sno-quiz/backend/internal/models/models.go

231 lines
7.2 KiB
Go

package models
import "time"
// --- Enums (matches DB types) ---
type QuestionType string
const (
Single QuestionType = "single"
Multiple QuestionType = "multiple"
)
type DeliveryType string
const (
Physical DeliveryType = "physical"
Digital DeliveryType = "digital"
)
type PurchaseStatus string
const (
Pending PurchaseStatus = "pending"
Delivered PurchaseStatus = "delivered"
Cancelled PurchaseStatus = "cancelled"
)
type QRScanType string
const (
QRReward QRScanType = "reward"
QRQuiz QRScanType = "quiz"
QRShop QRScanType = "shop"
)
type QRScanSource string
const (
InApp QRScanSource = "in_app"
External QRScanSource = "external"
)
type AdminRole string
const (
RoleAdmin AdminRole = "admin"
RoleOperator AdminRole = "operator"
)
// --- Model Structs ---
type User struct {
TelegramID int64 `json:"telegram_id"`
Username *string `json:"username,omitempty"`
FirstName *string `json:"first_name,omitempty"`
LastName *string `json:"last_name,omitempty"`
PhotoURL *string `json:"photo_url,omitempty"`
StarsBalance int `json:"stars_balance"`
CreatedAt time.Time `json:"created_at"`
}
type Quiz struct {
ID int `json:"id"`
Title string `json:"title"`
Description *string `json:"description,omitempty"`
ImageURL *string `json:"image_url,omitempty"`
RewardStars int `json:"reward_stars"`
HasTimer bool `json:"has_timer"`
TimerPerQuestion *int `json:"timer_per_question,omitempty"`
CanRepeat bool `json:"can_repeat"`
RepeatCooldownHours *int `json:"repeat_cooldown_hours,omitempty"`
IsActive bool `json:"is_active"`
CreatedBy *int64 `json:"created_by,omitempty"`
CreatedAt time.Time `json:"created_at"`
Questions []Question `json:"questions,omitempty"` // This field is for API responses, not DB storage
}
type Question struct {
ID int `json:"id"`
QuizID int `json:"quiz_id"`
Text string `json:"text"`
Type QuestionType `json:"type"`
Options []Option `json:"options"` // Stored as JSONB
OrderIndex int `json:"order_index"`
}
type Option struct {
ID int `json:"id"`
Text string `json:"text"`
IsCorrect bool `json:"is_correct"`
}
type QuizAttempt struct {
ID int `json:"id"`
UserID int64 `json:"user_id"`
QuizID int `json:"quiz_id"`
Score int `json:"score"`
StarsEarned int `json:"stars_earned"`
CompletedAt time.Time `json:"completed_at"`
Answers []UserAnswer `json:"answers"` // Stored as JSONB
// Additional fields for response
CorrectAnswers int `json:"correct_answers"`
TotalQuestions int `json:"total_questions"`
}
type Reward struct {
ID int `json:"id"`
Title string `json:"title"`
Description *string `json:"description,omitempty"`
ImageURL *string `json:"image_url,omitempty"`
PriceStars int `json:"price_stars"`
DeliveryType DeliveryType `json:"delivery_type"`
Instructions *string `json:"instructions,omitempty"`
Stock int `json:"stock"`
IsActive bool `json:"is_active"`
CreatedBy *int64 `json:"created_by,omitempty"`
CreatedAt time.Time `json:"created_at"`
}
type Purchase struct {
ID int `json:"id"`
UserID int64 `json:"user_id"`
RewardID int `json:"reward_id"`
StarsSpent int `json:"stars_spent"`
PurchasedAt time.Time `json:"purchased_at"`
Status PurchaseStatus `json:"status"`
}
type QRScan struct {
ID int `json:"id"`
UserID int64 `json:"user_id"`
Type QRScanType `json:"type"`
Value *string `json:"value,omitempty"`
ScannedAt time.Time `json:"scanned_at"`
Source QRScanSource `json:"source"`
}
type Admin struct {
TelegramID int64 `json:"telegram_id"`
Role AdminRole `json:"role"`
Name *string `json:"name,omitempty"`
AddedBy *int64 `json:"added_by,omitempty"`
AddedAt time.Time `json:"added_at"`
}
// --- API Request/Response Structs ---
// TransactionType defines whether stars were earned or spent.
type TransactionType string
const (
TransactionEarned TransactionType = "earned"
TransactionSpent TransactionType = "spent"
)
// Transaction represents a single entry in the user's balance history.
type Transaction struct {
Type TransactionType `json:"type"`
Amount int `json:"amount"`
Description string `json:"description"`
CreatedAt time.Time `json:"created_at"`
}
// SubmissionRequest defines the structure for a user submitting quiz answers.
type SubmissionRequest struct {
Answers []UserAnswer `json:"answers"`
}
// UserAnswer defines a single answer provided by the user.
type UserAnswer struct {
QuestionID int `json:"question_id"`
OptionIDs []int `json:"option_ids"`
}
// GrantStarsRequest defines the structure for an admin to grant stars to a user.
type GrantStarsRequest struct {
UserID int64 `json:"user_id"`
Amount int `json:"amount"`
}
// CanRepeatResponse defines the response for the can-repeat check.
type CanRepeatResponse struct {
CanRepeat bool `json:"can_repeat"`
NextAvailableAt *time.Time `json:"next_available_at,omitempty"`
}
// QRValidateRequest defines the structure for a QR validation request.
type QRValidateRequest struct {
Payload string `json:"payload"`
}
// QRValidateResponse defines the structure for a QR validation response.
type QRValidateResponse struct {
Type string `json:"type"` // e.g., "REWARD", "OPEN_QUIZ"
Data interface{} `json:"data"`
}
// GenerateQRCodesRequest defines the structure for generating unique QR codes.
type GenerateQRCodesRequest struct {
Type string `json:"type"` // e.g., "reward", "quiz"
Value string `json:"value"` // e.g., "50" for reward, "1" for quiz
Count int `json:"count"` // Number of codes to generate
}
// QRTokenData represents the data stored for a unique QR token
type QRTokenData struct {
Type string `json:"type"` // "reward", "quiz", "shop"
Value string `json:"value"` // e.g., "50", "123"
Used bool `json:"used"` // Whether the token has been used
}
// GenerateQRCodesResponse defines the response for generating QR codes
type GenerateQRCodesResponse struct {
Tokens []string `json:"tokens"` // List of generated unique tokens
}
// CreateOperatorRequest defines the structure for creating a new operator
type CreateOperatorRequest struct {
TelegramID int64 `json:"telegram_id"`
Name string `json:"name"`
}
// Analytics represents various statistics and metrics for the admin dashboard
type Analytics struct {
TotalUsers int `json:"total_users"`
TotalQuizzes int `json:"total_quizzes"`
ActiveQuizzes int `json:"active_quizzes"`
TotalRewards int `json:"total_rewards"`
ActiveRewards int `json:"active_rewards"`
TotalAttempts int `json:"total_attempts"`
TotalPurchases int `json:"total_purchases"`
TotalQRScans int `json:"total_qr_scans"`
StarsDistributed int `json:"stars_distributed"`
StarsSpent int `json:"stars_spent"`
}