package models import ( "errors" "time" "gorm.io/gorm" ) // Schedule represents available time slots type Schedule struct { gorm.Model StartTime time.Time `json:"start_time" gorm:"not null;index" validate:"required"` EndTime time.Time `json:"end_time" gorm:"not null;index" validate:"required"` IsAvailable bool `json:"is_available" gorm:"default:true"` MaxBookings int `json:"max_bookings" gorm:"default:1;check:max_bookings > 0" validate:"min=1,max=100"` BookedCount int `json:"booked_count" gorm:"default:0;check:booked_count >= 0" validate:"min=0"` } // BeforeCreate is a GORM hook that runs before creating a schedule record func (s *Schedule) BeforeCreate(tx *gorm.DB) error { // Validate that end time is after start time if !s.EndTime.After(s.StartTime) { return errors.New("end time must be after start time") } // Validate minimum duration (15 minutes) if s.EndTime.Sub(s.StartTime) < 15*time.Minute { return errors.New("schedule slot must be at least 15 minutes long") } // Validate that start time is in the future if s.StartTime.Before(time.Now()) { return errors.New("schedule slot cannot be created in the past") } // Set default values if s.MaxBookings == 0 { s.MaxBookings = 1 } return nil } // BeforeUpdate is a GORM hook that runs before updating a schedule record func (s *Schedule) BeforeUpdate(tx *gorm.DB) error { // Validate that end time is after start time if !s.EndTime.After(s.StartTime) { return errors.New("end time must be after start time") } // Validate that booked count doesn't exceed max bookings if s.BookedCount > s.MaxBookings { return errors.New("booked count cannot exceed max bookings") } return nil } // IsAvailableForBooking checks if the schedule slot has availability func (s *Schedule) IsAvailableForBooking() bool { return s.IsAvailable && s.BookedCount < s.MaxBookings && s.StartTime.After(time.Now()) } // GetRemainingSlots returns the number of remaining booking slots func (s *Schedule) GetRemainingSlots() int { remaining := s.MaxBookings - s.BookedCount if remaining < 0 { return 0 } return remaining } // Duration returns the duration of the schedule slot func (s *Schedule) Duration() time.Duration { return s.EndTime.Sub(s.StartTime) }