Files
XQKqueue/server/internal/model/models.go
2026-07-22 10:18:49 +08:00

204 lines
8.3 KiB
Go

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
}