cab-backend/internal/models/models.go
2026-03-30 21:00:35 +03:00

439 lines
21 KiB
Go

package models
import (
"time"
"github.com/uptrace/bun"
)
// ─── Roles ──────────────────────────────────────────────────
type Role string
const (
RoleAdmin Role = "admin"
RoleModerator Role = "moderator"
RoleUser Role = "user"
)
// ─── User ───────────────────────────────────────────────────
type User struct {
bun.BaseModel `bun:"table:users,alias:u"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
Email string `bun:"email,notnull,unique" json:"email"`
Username string `bun:"username,notnull,unique" json:"username"`
Password string `bun:"password,notnull" json:"-"`
Role Role `bun:"role,notnull,default:'user'" json:"role"`
IsActive bool `bun:"is_active,notnull,default:true" json:"is_active"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
UserGames []*UserGame `bun:"rel:has-many,join:id=user_id" json:"user_games,omitempty"`
}
// ─── Game ───────────────────────────────────────────────────
type Game struct {
bun.BaseModel `bun:"table:games,alias:g"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
Name string `bun:"name,notnull,unique" json:"name"`
Slug string `bun:"slug,notnull,unique" json:"slug"`
Description string `bun:"description" json:"description"`
ImageURL string `bun:"image_url" json:"image_url"`
IsActive bool `bun:"is_active,notnull,default:true" json:"is_active"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Variables []*GameVariable `bun:"rel:has-many,join:id=game_id" json:"variables,omitempty"`
Notifications []Notification `bun:"rel:has-many,join:id=game_id" json:"notifications,omitempty"`
Leaderboards []Leaderboard `bun:"rel:has-many,join:id=game_id" json:"leaderboards,omitempty"`
Modules []Module `bun:"-" json:"modules,omitempty"`
}
type GameVariableType string
const (
GameVariableTypeNumber GameVariableType = "number"
GameVariableTypeString GameVariableType = "string"
GameVariableTypeTable GameVariableType = "table"
GameVariableTypeVector GameVariableType = "vector"
)
type GameVariableTableValueType string
const (
GameVariableTableValueTypeNumber GameVariableTableValueType = "number"
GameVariableTableValueTypeString GameVariableTableValueType = "string"
)
type GameVariable struct {
bun.BaseModel `bun:"table:game_variables,alias:gv"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
GameID int64 `bun:"game_id,notnull" json:"game_id"`
Key string `bun:"key,notnull" json:"key"`
Type GameVariableType `bun:"type,notnull" json:"type"`
NumberValue *float64 `bun:"number_value" json:"number_value,omitempty"`
StringValue *string `bun:"string_value" json:"string_value,omitempty"`
TableValueType *GameVariableTableValueType `bun:"table_value_type" json:"table_value_type,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Game *Game `bun:"rel:belongs-to,join:game_id=id" json:"game,omitempty"`
Items []*GameVariableItem `bun:"rel:has-many,join:id=game_variable_id" json:"items,omitempty"`
}
type GameVariableItem struct {
bun.BaseModel `bun:"table:game_variable_items,alias:gvi"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
GameVariableID int64 `bun:"game_variable_id,notnull" json:"game_variable_id"`
Key string `bun:"item_key,notnull" json:"key,omitempty"`
Index *int64 `bun:"-" json:"index,omitempty"`
NumberValue *float64 `bun:"number_value" json:"number_value,omitempty"`
StringValue *string `bun:"string_value" json:"string_value,omitempty"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Variable *GameVariable `bun:"rel:belongs-to,join:game_variable_id=id" json:"-"`
}
type Module struct {
bun.BaseModel `bun:"table:modules,alias:m"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
Key string `bun:"key,notnull,unique" json:"key"`
Name string `bun:"name,notnull" json:"name"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
}
type Language struct {
bun.BaseModel `bun:"table:languages,alias:l"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
Code string `bun:"code,notnull,unique" json:"code"`
Name string `bun:"name,notnull" json:"name"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
}
type GameModule struct {
bun.BaseModel `bun:"table:game_modules,alias:gm"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
GameID int64 `bun:"game_id,notnull" json:"game_id"`
ModuleID int64 `bun:"module_id,notnull" json:"module_id"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
Game *Game `bun:"rel:belongs-to,join:game_id=id" json:"-"`
Module *Module `bun:"rel:belongs-to,join:module_id=id" json:"module,omitempty"`
}
type Notification struct {
bun.BaseModel `bun:"table:notifications,alias:n"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
GameID int64 `bun:"game_id,notnull" json:"game_id"`
Name string `bun:"name,notnull" json:"name"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Game *Game `bun:"rel:belongs-to,join:game_id=id" json:"game,omitempty"`
Descriptions []NotificationDescription `bun:"rel:has-many,join:id=notification_id" json:"descriptions,omitempty"`
Variables []NotificationVariableDef `bun:"rel:has-many,join:id=notification_id" json:"variables,omitempty"`
Entries []NotificationEntry `bun:"rel:has-many,join:id=notification_id" json:"entries,omitempty"`
Macros []string `bun:"-" json:"macros,omitempty"`
}
type NotificationDescription struct {
bun.BaseModel `bun:"table:notification_descriptions,alias:nd"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
NotificationID int64 `bun:"notification_id,notnull" json:"notification_id"`
LanguageID int64 `bun:"language_id,notnull" json:"language_id"`
Description string `bun:"description,notnull" json:"description"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Language *Language `bun:"rel:belongs-to,join:language_id=id" json:"language,omitempty"`
Notification *Notification `bun:"rel:belongs-to,join:notification_id=id" json:"-"`
}
type NotificationVariableDef struct {
bun.BaseModel `bun:"table:notification_variable_defs,alias:nvd"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
NotificationID int64 `bun:"notification_id,notnull" json:"notification_id"`
Key string `bun:"key,notnull" json:"key"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Notification *Notification `bun:"rel:belongs-to,join:notification_id=id" json:"-"`
}
type NotificationEntry struct {
bun.BaseModel `bun:"table:notification_entries,alias:ne"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
NotificationID int64 `bun:"notification_id,notnull" json:"notification_id"`
TimeSecond int64 `bun:"time_second,notnull" json:"time_second"`
Image string `bun:"image,notnull" json:"image"`
Login string `bun:"login,notnull" json:"login"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Notification *Notification `bun:"rel:belongs-to,join:notification_id=id" json:"-"`
Variables []NotificationEntryVariable `bun:"rel:has-many,join:id=notification_entry_id" json:"variables,omitempty"`
}
type NotificationEntryVariable struct {
bun.BaseModel `bun:"table:notification_entry_variables,alias:nev"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
NotificationEntryID int64 `bun:"notification_entry_id,notnull" json:"notification_entry_id"`
NotificationVariableID int64 `bun:"notification_variable_id,notnull" json:"notification_variable_id"`
Value string `bun:"value,notnull" json:"value"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Key string `bun:"-" json:"key,omitempty"`
Entry *NotificationEntry `bun:"rel:belongs-to,join:notification_entry_id=id" json:"-"`
Variable *NotificationVariableDef `bun:"rel:belongs-to,join:notification_variable_id=id" json:"-"`
}
type LeaderboardSortOrder string
const (
LeaderboardSortOrderDesc LeaderboardSortOrder = "desc"
LeaderboardSortOrderAsc LeaderboardSortOrder = "asc"
)
type LeaderboardPeriodType string
const (
LeaderboardPeriodAllTime LeaderboardPeriodType = "all_time"
LeaderboardPeriodDaily LeaderboardPeriodType = "daily"
LeaderboardPeriodWeekly LeaderboardPeriodType = "weekly"
LeaderboardPeriodMonthly LeaderboardPeriodType = "monthly"
)
type Leaderboard struct {
bun.BaseModel `bun:"table:leaderboards,alias:lb"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
GameID int64 `bun:"game_id,notnull" json:"game_id"`
Key string `bun:"key,notnull" json:"key"`
Name string `bun:"name,notnull" json:"name"`
SortOrder LeaderboardSortOrder `bun:"sort_order,notnull" json:"sort_order"`
PeriodType LeaderboardPeriodType `bun:"period_type,notnull" json:"period_type"`
IsActive bool `bun:"is_active,notnull,default:true" json:"is_active"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Game *Game `bun:"rel:belongs-to,join:game_id=id" json:"game,omitempty"`
Groups []LeaderboardGroup `bun:"rel:has-many,join:id=leaderboard_id" json:"groups,omitempty"`
}
type LeaderboardGroup struct {
bun.BaseModel `bun:"table:leaderboard_groups,alias:lbg"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
LeaderboardID int64 `bun:"leaderboard_id,notnull" json:"leaderboard_id"`
Key string `bun:"key,notnull" json:"key"`
Name string `bun:"name,notnull" json:"name"`
IsDefault bool `bun:"is_default,notnull,default:false" json:"is_default"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Leaderboard *Leaderboard `bun:"rel:belongs-to,join:leaderboard_id=id" json:"leaderboard,omitempty"`
Members []LeaderboardGroupMember `bun:"rel:has-many,join:id=group_id" json:"members,omitempty"`
}
type LeaderboardGroupMember struct {
bun.BaseModel `bun:"table:leaderboard_group_members,alias:lbgm"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
GroupID int64 `bun:"group_id,notnull" json:"group_id"`
UserID int64 `bun:"user_id,notnull" json:"user_id"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
Group *LeaderboardGroup `bun:"rel:belongs-to,join:group_id=id" json:"-"`
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
}
type LeaderboardScore struct {
bun.BaseModel `bun:"table:leaderboard_scores,alias:lbs"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
LeaderboardID int64 `bun:"leaderboard_id,notnull" json:"leaderboard_id"`
UserGameID int64 `bun:"user_game_id,notnull" json:"user_game_id"`
Score float64 `bun:"score,notnull" json:"score"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
Leaderboard *Leaderboard `bun:"rel:belongs-to,join:leaderboard_id=id" json:"leaderboard,omitempty"`
UserGame *UserGame `bun:"rel:belongs-to,join:user_game_id=id" json:"user_game,omitempty"`
}
type LeaderboardRankItem struct {
Rank int64 `json:"rank"`
UserID int64 `json:"user_id"`
UserGameID int64 `json:"user_game_id"`
Username string `json:"username"`
Score float64 `json:"score"`
}
// ─── UserGame (pivot — user's connected games + balance) ────
type UserGame struct {
bun.BaseModel `bun:"table:user_games,alias:ug"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
UserID int64 `bun:"user_id,notnull" json:"user_id"`
GameID int64 `bun:"game_id,notnull" json:"game_id"`
Balance float64 `bun:"balance,notnull,default:0" json:"balance"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:current_timestamp" json:"updated_at"`
User *User `bun:"rel:belongs-to,join:user_id=id" json:"user,omitempty"`
Game *Game `bun:"rel:belongs-to,join:game_id=id" json:"game,omitempty"`
}
// ─── Invite Link ────────────────────────────────────────────
type InviteLink struct {
bun.BaseModel `bun:"table:invite_links,alias:il"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
Code string `bun:"code,notnull,unique" json:"code"`
Role Role `bun:"role,notnull,default:'user'" json:"role"`
MaxUses int `bun:"max_uses,notnull,default:1" json:"max_uses"`
UsedCount int `bun:"used_count,notnull,default:0" json:"used_count"`
CreatedByID int64 `bun:"created_by_id,notnull" json:"created_by_id"`
ExpiresAt *time.Time `bun:"expires_at" json:"expires_at"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
CreatedBy *User `bun:"rel:belongs-to,join:created_by_id=id" json:"created_by,omitempty"`
}
// ─── Balance Transaction Log ────────────────────────────────
type BalanceTransaction struct {
bun.BaseModel `bun:"table:balance_transactions,alias:bt"`
ID int64 `bun:"id,pk,autoincrement" json:"id"`
UserGameID int64 `bun:"user_game_id,notnull" json:"user_game_id"`
Amount float64 `bun:"amount,notnull" json:"amount"`
Type string `bun:"type,notnull" json:"type"` // "topup" | "withdraw"
Comment string `bun:"comment" json:"comment"`
AdminID int64 `bun:"admin_id,notnull" json:"admin_id"`
CreatedAt time.Time `bun:"created_at,nullzero,notnull,default:current_timestamp" json:"created_at"`
}
// ─── Request / Response DTOs ────────────────────────────────
type LoginRequest struct {
Email string `json:"email" binding:"required,email"`
Password string `json:"password" binding:"required,min=6"`
}
type RegisterRequest struct {
Email string `json:"email" binding:"required,email"`
Username string `json:"username" binding:"required,min=3"`
Password string `json:"password" binding:"required,min=6"`
InviteCode string `json:"invite_code"`
}
type TopUpRequest struct {
Amount float64 `json:"amount" binding:"required,gt=0"`
Comment string `json:"comment"`
}
type CreateInviteRequest struct {
Role Role `json:"role" binding:"required"`
MaxUses int `json:"max_uses" binding:"required,gt=0"`
}
type CreateGameRequest struct {
Name string `json:"name" binding:"required"`
Slug string `json:"slug" binding:"required"`
Description string `json:"description"`
ImageURL string `json:"image_url"`
}
type GameVariableItemRequest struct {
Key string `json:"key"`
Index *int64 `json:"index"`
NumberValue *float64 `json:"number_value"`
StringValue *string `json:"string_value"`
}
type UpsertGameVariableRequest struct {
Key string `json:"key" binding:"required"`
Type GameVariableType `json:"type" binding:"required"`
NumberValue *float64 `json:"number_value"`
StringValue *string `json:"string_value"`
TableValueType *GameVariableTableValueType `json:"table_value_type"`
Items []GameVariableItemRequest `json:"items"`
}
type ConnectGameModuleRequest struct {
ModuleKey string `json:"module_key" binding:"required"`
}
type UpsertLanguageRequest struct {
Code string `json:"code" binding:"required"`
Name string `json:"name" binding:"required"`
}
type NotificationDescriptionRequest struct {
LanguageID int64 `json:"language_id" binding:"required"`
Description string `json:"description" binding:"required"`
}
type NotificationVariableRequest struct {
Key string `json:"key" binding:"required"`
}
type NotificationEntryVariableRequest struct {
Key string `json:"key" binding:"required"`
Value string `json:"value"`
}
type NotificationEntryRequest struct {
TimeSecond int64 `json:"time_second"`
Image string `json:"image" binding:"required"`
Login string `json:"login" binding:"required"`
Variables []NotificationEntryVariableRequest `json:"variables"`
}
type UpsertNotificationRequest struct {
Name string `json:"name" binding:"required"`
Descriptions []NotificationDescriptionRequest `json:"descriptions" binding:"required"`
Variables []NotificationVariableRequest `json:"variables"`
Entries []NotificationEntryRequest `json:"entries" binding:"required"`
}
type UpsertLeaderboardRequest struct {
Key string `json:"key" binding:"required"`
Name string `json:"name" binding:"required"`
SortOrder LeaderboardSortOrder `json:"sort_order" binding:"required"`
PeriodType LeaderboardPeriodType `json:"period_type" binding:"required"`
IsActive *bool `json:"is_active"`
}
type UpsertLeaderboardGroupRequest struct {
Key string `json:"key" binding:"required"`
Name string `json:"name" binding:"required"`
IsDefault *bool `json:"is_default"`
}
type AddLeaderboardGroupMemberRequest struct {
UserID int64 `json:"user_id" binding:"required"`
}
type UpsertLeaderboardScoreRequest struct {
UserGameID int64 `json:"user_game_id" binding:"required"`
Score float64 `json:"score" binding:"required"`
}
type ConnectGameRequest struct {
GameID int64 `json:"game_id" binding:"required"`
}
type UpdateUserRoleRequest struct {
Role Role `json:"role" binding:"required"`
}