// monorepo/cloud/maplefile-backend/internal/maplefile/service/storagedailyusage/get_trend.go package storagedailyusage import ( "context" "time" "go.uber.org/zap" "github.com/gocql/gocql" "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config" "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/config/constants" uc_storagedailyusage "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/internal/usecase/storagedailyusage" "codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/httperror" ) type GetStorageDailyUsageTrendRequestDTO struct { TrendPeriod string `json:"trend_period"` // "7days", "monthly", "yearly" Year *int `json:"year,omitempty"` Month *time.Month `json:"month,omitempty"` } type StorageDailyUsageResponseDTO struct { UserID gocql.UUID `json:"user_id"` UsageDay time.Time `json:"usage_day"` TotalBytes int64 `json:"total_bytes"` TotalAddBytes int64 `json:"total_add_bytes"` TotalRemoveBytes int64 `json:"total_remove_bytes"` } type StorageUsageTrendResponseDTO struct { UserID gocql.UUID `json:"user_id"` StartDate time.Time `json:"start_date"` EndDate time.Time `json:"end_date"` DailyUsages []*StorageDailyUsageResponseDTO `json:"daily_usages"` TotalAdded int64 `json:"total_added"` TotalRemoved int64 `json:"total_removed"` NetChange int64 `json:"net_change"` AverageDailyAdd int64 `json:"average_daily_add"` PeakUsageDay *time.Time `json:"peak_usage_day,omitempty"` PeakUsageBytes int64 `json:"peak_usage_bytes"` } type GetStorageDailyUsageTrendResponseDTO struct { TrendPeriod string `json:"trend_period"` Trend *StorageUsageTrendResponseDTO `json:"trend"` Success bool `json:"success"` Message string `json:"message"` } type GetStorageDailyUsageTrendService interface { Execute(ctx context.Context, req *GetStorageDailyUsageTrendRequestDTO) (*GetStorageDailyUsageTrendResponseDTO, error) } type getStorageDailyUsageTrendServiceImpl struct { config *config.Configuration logger *zap.Logger getStorageDailyUsageTrendUseCase uc_storagedailyusage.GetStorageDailyUsageTrendUseCase } func NewGetStorageDailyUsageTrendService( config *config.Configuration, logger *zap.Logger, getStorageDailyUsageTrendUseCase uc_storagedailyusage.GetStorageDailyUsageTrendUseCase, ) GetStorageDailyUsageTrendService { logger = logger.Named("GetStorageDailyUsageTrendService") return &getStorageDailyUsageTrendServiceImpl{ config: config, logger: logger, getStorageDailyUsageTrendUseCase: getStorageDailyUsageTrendUseCase, } } func (svc *getStorageDailyUsageTrendServiceImpl) Execute(ctx context.Context, req *GetStorageDailyUsageTrendRequestDTO) (*GetStorageDailyUsageTrendResponseDTO, error) { // // STEP 1: Validation // if req == nil { svc.logger.Warn("Failed validation with nil request") return nil, httperror.NewForBadRequestWithSingleField("non_field_error", "Request details are required") } // // STEP 2: Get user ID from context // userID, ok := ctx.Value(constants.SessionUserID).(gocql.UUID) if !ok { svc.logger.Error("Failed getting user ID from context") return nil, httperror.NewForInternalServerErrorWithSingleField("message", "Authentication context error") } // // STEP 3: Build use case request // useCaseReq := &uc_storagedailyusage.GetStorageDailyUsageTrendRequest{ UserID: userID, TrendPeriod: req.TrendPeriod, Year: req.Year, Month: req.Month, } // // STEP 4: Execute use case // trend, err := svc.getStorageDailyUsageTrendUseCase.Execute(ctx, useCaseReq) if err != nil { svc.logger.Error("Failed to get storage daily usage trend", zap.String("user_id", userID.String()), zap.String("trend_period", req.TrendPeriod), zap.Error(err)) return nil, err } // // STEP 5: Map domain models to response DTOs // dailyUsages := make([]*StorageDailyUsageResponseDTO, len(trend.DailyUsages)) for i, usage := range trend.DailyUsages { dailyUsages[i] = &StorageDailyUsageResponseDTO{ UserID: usage.UserID, UsageDay: usage.UsageDay, TotalBytes: usage.TotalBytes, TotalAddBytes: usage.TotalAddBytes, TotalRemoveBytes: usage.TotalRemoveBytes, } } trendResponse := &StorageUsageTrendResponseDTO{ UserID: trend.UserID, StartDate: trend.StartDate, EndDate: trend.EndDate, DailyUsages: dailyUsages, TotalAdded: trend.TotalAdded, TotalRemoved: trend.TotalRemoved, NetChange: trend.NetChange, AverageDailyAdd: trend.AverageDailyAdd, PeakUsageDay: trend.PeakUsageDay, PeakUsageBytes: trend.PeakUsageBytes, } response := &GetStorageDailyUsageTrendResponseDTO{ TrendPeriod: req.TrendPeriod, Trend: trendResponse, Success: true, Message: "Storage daily usage trend retrieved successfully", } svc.logger.Debug("Storage daily usage trend retrieved successfully", zap.String("user_id", userID.String()), zap.String("trend_period", req.TrendPeriod), zap.Int("daily_usages_count", len(dailyUsages)), zap.Int64("net_change", trend.NetChange)) return response, nil }