package db import ( "time" "gorm.io/gorm" ) type PaginationParams struct { Page int Size int } func (p *PaginationParams) Normalize() { if p.Page < 1 { p.Page = 1 } if p.Size < 1 || p.Size > 100 { p.Size = 20 } } func (p *PaginationParams) Offset() int { return (p.Page - 1) * p.Size } type PaginatedResult struct { Items interface{} `json:"items"` Total int64 `json:"total"` Page int `json:"page"` Size int `json:"size"` } func Paginate(db *gorm.DB, p PaginationParams, dest interface{}) (*PaginatedResult, error) { p.Normalize() var total int64 if err := db.Count(&total).Error; err != nil { return nil, err } if err := db.Offset(p.Offset()).Limit(p.Size).Find(dest).Error; err != nil { return nil, err } return &PaginatedResult{ Items: dest, Total: total, Page: p.Page, Size: p.Size, }, nil } // Dashboard stats type DashboardStats struct { TotalAccounts int64 `json:"total_accounts"` PlusCount int64 `json:"plus_count"` TeamCount int64 `json:"team_count"` TodayRegistrations int64 `json:"today_registrations"` SuccessRate float64 `json:"success_rate"` ActiveTask *Task `json:"active_task"` RecentTasks []Task `json:"recent_tasks"` } func GetDashboardStats(db *gorm.DB) (*DashboardStats, error) { stats := &DashboardStats{} db.Model(&Account{}).Count(&stats.TotalAccounts) db.Model(&Account{}).Where("plan = ?", "plus").Count(&stats.PlusCount) db.Model(&Account{}).Where("plan IN ?", []string{"team_owner", "team_member"}).Count(&stats.TeamCount) today := time.Now().Truncate(24 * time.Hour) db.Model(&Account{}).Where("created_at >= ?", today).Count(&stats.TodayRegistrations) var totalLogs, successLogs int64 db.Model(&TaskLog{}).Count(&totalLogs) db.Model(&TaskLog{}).Where("status = ?", "success").Count(&successLogs) if totalLogs > 0 { stats.SuccessRate = float64(successLogs) / float64(totalLogs) * 100 } var activeTask Task if err := db.Where("status IN ?", []string{"running", "stopping"}).First(&activeTask).Error; err == nil { stats.ActiveTask = &activeTask } db.Order("created_at DESC").Limit(5).Find(&stats.RecentTasks) return stats, nil } // Card stats type CardStats struct { Total int64 `json:"total"` Available int64 `json:"available"` Active int64 `json:"active"` Exhausted int64 `json:"exhausted"` Rejected int64 `json:"rejected"` Expired int64 `json:"expired"` Disabled int64 `json:"disabled"` } func GetCardStats(db *gorm.DB) *CardStats { s := &CardStats{} db.Model(&Card{}).Count(&s.Total) db.Model(&Card{}).Where("status = ?", "available").Count(&s.Available) db.Model(&Card{}).Where("status = ?", "active").Count(&s.Active) db.Model(&Card{}).Where("status = ?", "exhausted").Count(&s.Exhausted) db.Model(&Card{}).Where("status = ?", "rejected").Count(&s.Rejected) db.Model(&Card{}).Where("status = ?", "expired").Count(&s.Expired) db.Model(&Card{}).Where("status = ?", "disabled").Count(&s.Disabled) return s } type CardCodeStats struct { Total int64 `json:"total"` Unused int64 `json:"unused"` Redeemed int64 `json:"redeemed"` Failed int64 `json:"failed"` } func GetCardCodeStats(db *gorm.DB) *CardCodeStats { s := &CardCodeStats{} db.Model(&CardCode{}).Count(&s.Total) db.Model(&CardCode{}).Where("status = ?", "unused").Count(&s.Unused) db.Model(&CardCode{}).Where("status = ?", "redeemed").Count(&s.Redeemed) db.Model(&CardCode{}).Where("status = ?", "failed").Count(&s.Failed) return s } type EmailRecordStats struct { Total int64 `json:"total"` Used int64 `json:"used"` UsedMember int64 `json:"used_member"` UsedFailed int64 `json:"used_failed"` } func GetEmailRecordStats(db *gorm.DB) *EmailRecordStats { s := &EmailRecordStats{} db.Model(&EmailRecord{}).Count(&s.Total) db.Model(&EmailRecord{}).Where("status = ?", "used").Count(&s.Used) db.Model(&EmailRecord{}).Where("status = ?", "used_member").Count(&s.UsedMember) db.Model(&EmailRecord{}).Where("status = ?", "used_failed").Count(&s.UsedFailed) return s }