package service import ( "time" "laic-backend/common" "laic-backend/model" "laic-backend/vo" ) const bytesPerGB = 1024 * 1024 * 1024 func (s *AccountService) GetDownloadPage(userID int64, req *vo.UsagePageReq) (*common.PageResponse[vo.DownloadRecordVO], *common.BusiError) { type row struct { model.DownloadLog FileName string FileSize int64 DroneSN string ExecutionID int64 } db := common.DB.Table("download_log").Select("download_log.*, video.file_name, video.file_size, video.drone_sn, video.execution_id").Joins("JOIN video ON video.id = download_log.video_id").Where("download_log.user_id = ?", userID) var total int64 if err := db.Count(&total).Error; err != nil { return nil, common.ErrInternal } var rows []row if err := db.Scopes(req.Paginate).Order("download_log.created_at DESC, download_log.id DESC").Find(&rows).Error; err != nil { return nil, common.ErrInternal } list := make([]vo.DownloadRecordVO, 0, len(rows)) for _, row := range rows { list = append(list, vo.DownloadRecordVO{ID: row.ID, VideoID: row.VideoID, FileName: row.FileName, FileSize: row.FileSize, DroneSN: row.DroneSN, ExecutionID: row.ExecutionID, Bytes: row.Bytes, CreatedAt: row.CreatedAt}) } return common.Page(req.Pagination, total, list), nil } func (s *AccountService) GetResourceSummary(userID int64) (*vo.ResourceSummaryVO, *common.BusiError) { balance, busiErr := s.GetTrafficBalance(userID) if busiErr != nil { return nil, busiErr } now := time.Now() monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()) var usage struct{ Total, Live, Replay, Download int64 } if err := common.DB.Model(&model.TrafficUsageLog{}).Where("user_id = ? AND created_at >= ?", userID, monthStart).Select("COALESCE(SUM(bytes_used), 0) AS total, COALESCE(SUM(CASE WHEN source_type = 'live' THEN bytes_used ELSE 0 END), 0) AS live, COALESCE(SUM(CASE WHEN source_type = 'replay' THEN bytes_used ELSE 0 END), 0) AS replay, COALESCE(SUM(CASE WHEN source_type = 'download' THEN bytes_used ELSE 0 END), 0) AS download").Scan(&usage).Error; err != nil { return nil, common.ErrInternal } var simCount, dockCount, droneCount, videoCount, downloadCount int64 queries := []struct { model any target *int64 where string args []any }{ {&model.SimCard{}, &simCount, "user_id = ?", []any{userID}}, {&model.Dock{}, &dockCount, "user_id = ?", []any{userID}}, {&model.Drone{}, &droneCount, "user_id = ?", []any{userID}}, {&model.Video{}, &videoCount, "user_id = ?", []any{userID}}, {&model.DownloadLog{}, &downloadCount, "user_id = ? AND created_at >= ?", []any{userID, monthStart}}, } for _, query := range queries { if err := common.DB.Model(query.model).Where(query.where, query.args...).Count(query.target).Error; err != nil { return nil, common.ErrInternal } } toGB := func(value int64) float64 { return float64(value) / bytesPerGB } return &vo.ResourceSummaryVO{BalanceGb: balance.BalanceGb, MonthUsageGb: toGB(usage.Total), MonthLiveGb: toGB(usage.Live), MonthReplayGb: toGB(usage.Replay), MonthDownloadGb: toGB(usage.Download), SimCount: simCount, DockCount: dockCount, DroneCount: droneCount, VideoCount: videoCount, MonthDownloadCnt: downloadCount}, nil }