package model import ( "encoding/json" "time" ) const ( RoleAdmin = "ADMIN" RoleStaff = "STAFF" // SuperAdminUsername identifies the permanent production owner account. SuperAdminUsername = "xqkwljtadmin" // PublicVisitorUsername is a non-login system actor used for anonymous // visitor-created tickets so existing foreign keys and idempotency records // remain attributable without borrowing a real staff account. PublicVisitorUsername = "public-visitor" ProjectNotOpen = "NOT_OPEN" ProjectRunning = "RUNNING" ProjectPaused = "PAUSED" ProjectEnded = "ENDED" ETAFixedBatch = "FIXED_BATCH" ETAContinuous = "CONTINUOUS" CallModeTicket = "TICKET" CallModePeople = "PEOPLE" CallModeBoth = "BOTH" TicketWaiting = "WAITING" TicketCalled = "CALLED" TicketArrived = "ARRIVED" TicketCompleted = "COMPLETED" TicketMissed = "MISSED" TicketCanceled = "CANCELED" DefaultVisitorNotice = "请您在景区附近等候,注意听从工作人员指引。" ) type User struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` Username string `gorm:"size:80;not null;uniqueIndex"` PasswordHash string `gorm:"not null"` Role string `gorm:"size:16;not null"` Active bool `gorm:"not null"` CreatedAt time.Time UpdatedAt time.Time } type Project struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` Code string `gorm:"size:24;not null;uniqueIndex"` Name string `gorm:"size:120;not null"` Status string `gorm:"size:16;not null"` Timezone string `gorm:"size:64;not null"` TicketPrefix string `gorm:"size:8;not null"` CallBatchSize int `gorm:"column:call_batch_size;not null"` CallMode string `gorm:"column:call_mode;size:16;not null;default:BOTH"` MaxCallTicketCount int `gorm:"column:max_call_ticket_count;not null;default:100"` DefaultCallPeopleCount int `gorm:"column:default_call_people_count;not null;default:1"` MaxCallPeopleCount int `gorm:"column:max_call_people_count;not null;default:100"` MinPartySize int `gorm:"column:min_party_size;not null;default:1"` MaxPartySize int `gorm:"column:max_party_size;not null;default:10"` GracePeriodMinutes int `gorm:"not null"` ETAMode string `gorm:"column:eta_mode;size:24;not null"` AverageBatchIntervalSeconds int `gorm:"not null"` ContinuousRatePerMinute float64 `gorm:"type:numeric(10,2);not null"` ETABufferMinutes int `gorm:"column:eta_buffer_minutes;not null"` ETAIntervalSeconds int `gorm:"column:eta_interval_seconds;not null;default:60"` VisitorNotice string `gorm:"column:visitor_notice;size:240;not null"` ExperiencedPeopleStart int `gorm:"column:experienced_people_start;not null;default:0"` DisplayTokenHash *string `gorm:"type:char(64)"` DeviceSimulationMode string `gorm:"size:16;not null"` CreatedAt time.Time UpdatedAt time.Time } type UserProject struct { UserID string `gorm:"type:uuid;primaryKey"` ProjectID string `gorm:"type:uuid;primaryKey"` CreatedAt time.Time } type AuthSession struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` UserID string `gorm:"type:uuid;not null;index"` TokenHash string `gorm:"type:char(64);not null;uniqueIndex"` ExpiresAt time.Time `gorm:"not null"` LastSeenAt time.Time `gorm:"not null"` RevokedAt *time.Time CreatedIP *string `gorm:"type:inet"` UserAgent string `gorm:"size:512;not null"` CreatedAt time.Time User User `gorm:"foreignKey:UserID"` } type QueueSession struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` ProjectID string `gorm:"type:uuid;not null;index"` BusinessDate time.Time `gorm:"type:date;not null"` Status string `gorm:"size:16;not null"` NextTicketNumber int `gorm:"not null"` Revision int64 `gorm:"not null"` OpenedAt time.Time `gorm:"not null"` ClosedAt *time.Time CreatedAt time.Time UpdatedAt time.Time } type QueueTicket struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` ProjectID string `gorm:"type:uuid;not null;index"` QueueSessionID string `gorm:"type:uuid;not null;index"` ReissuedFromTicketID *string `gorm:"type:uuid;uniqueIndex"` TicketNumber int `gorm:"not null"` DisplayNumber string `gorm:"size:24;not null"` PartySize int `gorm:"column:party_size;not null;default:1"` PublicTokenHash string `gorm:"type:char(64);not null;uniqueIndex"` PhoneCiphertext []byte `gorm:"type:bytea"` PhoneNonce []byte `gorm:"type:bytea"` PhoneHMAC *string `gorm:"type:char(64);index"` LastNameCiphertext []byte LastNameNonce []byte Honorific string `gorm:"size:16;not null"` Status string `gorm:"size:16;not null;index"` JoinedAt time.Time `gorm:"not null"` CalledAt *time.Time ArrivedAt *time.Time CompletedAt *time.Time MissedAt *time.Time PersonalDataPurgedAt *time.Time PersonalDataPurgeAt time.Time `gorm:"not null"` HistoryAnonymizedAt *time.Time CreatedBy string `gorm:"type:uuid;not null"` CreatedAt time.Time UpdatedAt time.Time } type CallBatch struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` ProjectID string `gorm:"type:uuid;not null;index"` QueueSessionID string `gorm:"type:uuid;not null;index"` BatchSequence int `gorm:"not null"` Revision int64 `gorm:"not null"` Status string `gorm:"size:16;not null"` CallMode string `gorm:"column:call_mode;size:16;not null;default:TICKET"` RequestedCount int `gorm:"column:requested_count;not null;default:1"` TicketCount int `gorm:"column:ticket_count;not null;default:1"` PeopleCount int `gorm:"column:people_count;not null;default:1"` RequestedBy string `gorm:"type:uuid;not null"` CalledAt time.Time `gorm:"not null"` CompletedAt *time.Time CreatedAt time.Time } type CallBatchTicket struct { CallBatchID string `gorm:"type:uuid;primaryKey"` TicketID string `gorm:"type:uuid;primaryKey"` ProjectID string `gorm:"type:uuid;not null"` Position int `gorm:"not null"` CreatedAt time.Time } type AuditEntry struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` ProjectID *string `gorm:"type:uuid;index"` ActorUserID *string `gorm:"type:uuid;index"` Action string `gorm:"size:64;not null"` EntityType string `gorm:"size:64;not null"` EntityID *string `gorm:"type:uuid"` Details json.RawMessage `gorm:"type:jsonb;not null"` RequestID string `gorm:"size:80;not null"` IPAddress *string `gorm:"type:inet"` UserAgent string `gorm:"size:512;not null"` RetainUntil time.Time `gorm:"not null"` CreatedAt time.Time } type IdempotencyKey struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` ProjectID string `gorm:"type:uuid;not null"` UserID string `gorm:"type:uuid;not null"` Scope string `gorm:"size:40;not null"` Key string `gorm:"size:128;not null"` RequestHash string `gorm:"type:char(64);not null"` ResponseCode int `gorm:"not null"` ResponseBody json.RawMessage `gorm:"type:jsonb;not null"` ResourceID *string `gorm:"type:uuid"` ExpiresAt time.Time `gorm:"not null"` CreatedAt time.Time } type DeviceSimulation struct { ID string `gorm:"type:uuid;primaryKey;default:gen_random_uuid()"` ProjectID string `gorm:"type:uuid;not null;index"` CallBatchID string `gorm:"type:uuid;not null;uniqueIndex"` Adapter string `gorm:"size:40;not null"` Outcome string `gorm:"size:16;not null"` Detail string `gorm:"size:500;not null"` AttemptedAt time.Time `gorm:"not null"` CompletedAt time.Time `gorm:"not null"` CreatedAt time.Time }