package report import ( "context" "fmt" "github.com/SamuelTariku/FortuneBet-Backend/internal/domain" "go.uber.org/zap" ) type WalletIntervalRow struct { Period string `csv:"Period"` WalletUserFirstName string `csv:"User First Name"` WalletUserLastName string `csv:"User Last Name"` WalletID int64 `csv:"Wallet Id"` WalletType string `csv:"Wallet Type"` NumberOfTransactions int64 `csv:"Number Of Transactions"` TotalTransactions float32 `csv:"Total Transactions"` NumberOfDeposits int64 `csv:"Number Of Deposits"` TotalDepositsAmount float32 `csv:"Total Deposits Amount"` NumberOfWithdraws int64 `csv:"Number Of Withdraws"` TotalWithdrawsAmount float32 `csv:"Total Withdraws Amount"` NumberOfTransfers int64 `csv:"Number Of Transfers"` TotalTransfersAmount float32 `csv:"Total Transfers Amount"` } func (s *Service) GenerateWalletIntervalReport(ctx context.Context, request domain.ReportRequestDetail) (string, error) { // Only a super-admin is allowed to generate this type of report if request.RequesterRole.Valid && request.RequesterRole.Value != domain.RoleSuperAdmin { s.mongoLogger.Error("[GenerateWalletIntervalReport] Unauthorized user report") return "", ErrUnauthorizedUserReport } if request.Metadata.Interval == nil { s.mongoLogger.Error("[GenerateWalletIntervalReport] Metadata interval is empty") return "", domain.ErrInvalidInterval } interval, err := domain.ParseDateInterval(*request.Metadata.Interval) if err != nil { s.mongoLogger.Error("[GenerateWalletIntervalReport] Failed to parse date interval", zap.String("interval", *request.Metadata.Interval), zap.Error(err), ) return "", domain.ErrInvalidInterval } stats, err := s.statService.GetWalletStatsByInterval(ctx, domain.WalletStatFilter{ Interval: domain.ValidDateInterval{ Value: interval, Valid: true, }, }) if err != nil { s.mongoLogger.Error("[GenerateWalletIntervalReport] Failed to fetch wallet stats", zap.String("interval", string(interval)), zap.Error(err), ) return "", fmt.Errorf("fetching wallet stats: %w", err) } var rows [][]string var headers []string for _, stat := range stats { endDate, err := domain.GetEndDateFromInterval(interval, stat.IntervalStart) if err != nil { s.mongoLogger.Error("[GenerateWalletIntervalReport] Failed to get end date from interval", zap.String("interval", string(interval)), zap.Error(err), ) return "", fmt.Errorf("invalid interval end date: %w", err) } period := fmt.Sprintf("%s to %s", stat.IntervalStart.Format("2006-01-02"), endDate.Format("2006-01-02"), ) r := WalletIntervalRow{ Period: period, WalletUserFirstName: stat.WalletUserFirstName, WalletUserLastName: stat.WalletUserLastName, WalletID: stat.WalletID, WalletType: stat.WalletType, NumberOfTransactions: stat.NumberOfTransactions, TotalTransactions: stat.TotalTransactions.Float32(), NumberOfDeposits: stat.NumberOfDeposits, TotalDepositsAmount: stat.TotalDepositsAmount.Float32(), NumberOfWithdraws: stat.NumberOfWithdraws, TotalWithdrawsAmount: stat.TotalWithdrawsAmount.Float32(), NumberOfTransfers: stat.NumberOfTransfers, TotalTransfersAmount: stat.TotalTransfersAmount.Float32(), } if headers == nil { headers, _ = StructToCSVRow(r) rows = append(rows, headers) } _, row := StructToCSVRow(r) rows = append(rows, row) } return s.WriteCSV(rows, "wallet_interval") }