package duty_schedule import ( "encoding/json" "time" ) type Group struct { ID string `json:"id" gorm:"type:uuid;primaryKey"` Name string `json:"name" gorm:"size:128;not null;uniqueIndex"` Timezone string `json:"timezone" gorm:"size:64;not null"` Enabled bool `json:"enabled" gorm:"not null;default:true;index"` Version int `json:"version" gorm:"not null;default:1"` CreatedBy int `json:"createdBy" gorm:"not null"` UpdatedBy int `json:"updatedBy" gorm:"not null"` CreatedAt time.Time `json:"createdAt" gorm:"type:timestamptz;not null"` UpdatedAt time.Time `json:"updatedAt" gorm:"type:timestamptz;not null"` } func (Group) TableName() string { return "bell_duty_groups" } type Member struct { GroupID string `json:"groupId" gorm:"type:uuid;primaryKey"` ContactID string `json:"contactId" gorm:"type:uuid;primaryKey"` Role string `json:"role" gorm:"size:16;not null"` CreatedBy int `json:"createdBy" gorm:"not null"` CreatedAt time.Time `json:"createdAt" gorm:"type:timestamptz;not null"` } func (Member) TableName() string { return "bell_duty_members" } type ScheduleVersion struct { ID string `json:"id" gorm:"type:uuid;primaryKey"` GroupID string `json:"groupId" gorm:"type:uuid;not null;index"` Version int `json:"version" gorm:"not null"` Timezone string `json:"timezone" gorm:"size:64;not null"` EffectiveFrom time.Time `json:"effectiveFrom" gorm:"type:timestamptz;not null"` EffectiveTo *time.Time `json:"effectiveTo,omitempty" gorm:"type:timestamptz"` Status string `json:"status" gorm:"size:16;not null"` CreatedBy int `json:"createdBy" gorm:"not null"` CreatedAt time.Time `json:"createdAt" gorm:"type:timestamptz;not null"` PublishedBy *int `json:"publishedBy,omitempty"` PublishedAt *time.Time `json:"publishedAt,omitempty" gorm:"type:timestamptz"` } func (ScheduleVersion) TableName() string { return "bell_duty_schedule_versions" } type RotationSlot struct { ID string `json:"id" gorm:"type:uuid;primaryKey"` ScheduleVersionID string `json:"scheduleVersionId" gorm:"type:uuid;not null;index"` Weekday int `json:"weekday" gorm:"not null"` StartMinute int `json:"startMinute" gorm:"not null"` EndMinute int `json:"endMinute" gorm:"not null"` PrimaryContactID string `json:"primaryContactId" gorm:"type:uuid;not null"` BackupContactID string `json:"backupContactId" gorm:"type:uuid;not null"` } func (RotationSlot) TableName() string { return "bell_duty_rotation_slots" } type Override struct { ID string `json:"id" gorm:"type:uuid;primaryKey"` GroupID string `json:"groupId" gorm:"type:uuid;not null;index"` OriginalContactID string `json:"originalContactId" gorm:"type:uuid;not null"` ReplacementContactID string `json:"replacementContactId" gorm:"type:uuid;not null"` StartsAt time.Time `json:"startsAt" gorm:"type:timestamptz;not null;index"` EndsAt time.Time `json:"endsAt" gorm:"type:timestamptz;not null"` Reason string `json:"reason" gorm:"size:256;not null"` CreatedBy int `json:"createdBy" gorm:"not null"` CreatedAt time.Time `json:"createdAt" gorm:"type:timestamptz;not null"` } func (Override) TableName() string { return "bell_duty_overrides" } type AuditFact struct { ID string `json:"id" gorm:"type:uuid;primaryKey"` GroupID string `json:"groupId" gorm:"type:uuid;not null;index"` Action string `json:"action" gorm:"size:32;not null"` Snapshot json.RawMessage `json:"snapshot" gorm:"type:jsonb;not null"` ActorID int `json:"actorId" gorm:"not null"` CreatedAt time.Time `json:"createdAt" gorm:"type:timestamptz;not null"` } func (AuditFact) TableName() string { return "bell_duty_audit_facts" } type GroupView struct { Group Members []Member `json:"members"` Schedules []ScheduleView `json:"schedules"` Overrides []Override `json:"overrides"` } type ScheduleView struct { ScheduleVersion Slots []RotationSlot `json:"slots"` }