package console import ( "context" "os" "strings" "time" "github.com/perfect-panel/server/internal/svc" "github.com/perfect-panel/server/internal/types" "github.com/perfect-panel/server/pkg/logger" "github.com/perfect-panel/server/pkg/xerr" "github.com/pkg/errors" ) type QueryRevenueStatisticsLogic struct { logger.Logger ctx context.Context svcCtx *svc.ServiceContext } // NewQueryRevenueStatisticsLogic Query revenue statistics func NewQueryRevenueStatisticsLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryRevenueStatisticsLogic { return &QueryRevenueStatisticsLogic{ Logger: logger.WithContext(ctx), ctx: ctx, svcCtx: svcCtx, } } func (l *QueryRevenueStatisticsLogic) QueryRevenueStatistics() (resp *types.RevenueStatisticsResponse, err error) { if strings.ToLower(os.Getenv("PPANEL_MODE")) == "demo" { return l.mockRevenueStatistics(), nil } var today, monthly, all types.OrdersStatistics now := time.Now() // Get today's revenue statistics todayData, err := l.svcCtx.OrderModel.QueryDateOrders(l.ctx, now) if err != nil { l.Errorw("[QueryRevenueStatisticsLogic] QueryDateOrders error", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QueryDateOrders error: %v", err) } else { today = types.OrdersStatistics{ AmountTotal: todayData.AmountTotal, NewOrderAmount: todayData.NewOrderAmount, RenewalOrderAmount: todayData.RenewalOrderAmount, } } // Get monthly's revenue statistics monthlyData, err := l.svcCtx.OrderModel.QueryMonthlyOrders(l.ctx, now) if err != nil { l.Errorw("[QueryRevenueStatisticsLogic] QueryMonthlyOrders error", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QueryMonthlyOrders error: %v", err) } else { monthly = types.OrdersStatistics{ AmountTotal: monthlyData.AmountTotal, NewOrderAmount: monthlyData.NewOrderAmount, RenewalOrderAmount: monthlyData.RenewalOrderAmount, List: make([]types.OrdersStatistics, 0), } } // Get monthly daily list for the current month (from 1st to current date) monthlyListData, err := l.svcCtx.OrderModel.QueryDailyOrdersList(l.ctx, now) if err != nil { l.Errorw("[QueryRevenueStatisticsLogic] QueryDailyOrdersList error", logger.Field("error", err.Error())) // Don't return error, just log it and continue with empty list } else { monthlyList := make([]types.OrdersStatistics, len(monthlyListData)) for i, data := range monthlyListData { monthlyList[i] = types.OrdersStatistics{ Date: data.Date, AmountTotal: data.AmountTotal, NewOrderAmount: data.NewOrderAmount, RenewalOrderAmount: data.RenewalOrderAmount, } } monthly.List = monthlyList } // Get all revenue statistics allData, err := l.svcCtx.OrderModel.QueryTotalOrders(l.ctx) if err != nil { l.Errorw("[QueryRevenueStatisticsLogic] QueryTotalOrders error", logger.Field("error", err.Error())) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DatabaseQueryError), "QueryTotalOrders error: %v", err) } else { all = types.OrdersStatistics{ AmountTotal: allData.AmountTotal, NewOrderAmount: allData.NewOrderAmount, RenewalOrderAmount: allData.RenewalOrderAmount, List: make([]types.OrdersStatistics, 0), } } // Get all monthly list for the past 6 months allListData, err := l.svcCtx.OrderModel.QueryMonthlyOrdersList(l.ctx, now) if err != nil { l.Errorw("[QueryRevenueStatisticsLogic] QueryMonthlyOrdersList error", logger.Field("error", err.Error())) // Don't return error, just log it and continue with empty list } else { allList := make([]types.OrdersStatistics, len(allListData)) for i, data := range allListData { allList[i] = types.OrdersStatistics{ Date: data.Date, AmountTotal: data.AmountTotal, NewOrderAmount: data.NewOrderAmount, RenewalOrderAmount: data.RenewalOrderAmount, } } all.List = allList } return &types.RevenueStatisticsResponse{ Today: today, Monthly: monthly, All: all, }, nil } // mockRevenueStatistics is a mock function to simulate revenue statistics data. func (l *QueryRevenueStatisticsLogic) mockRevenueStatistics() *types.RevenueStatisticsResponse { now := time.Now() // Generate daily data for the current month (from 1st to current date) monthlyList := make([]types.OrdersStatistics, 7) for i := 0; i < 7; i++ { dayDate := now.AddDate(0, 0, -(6 - i)) baseAmount := int64(25000 + ((6 - i) * 3000) + ((6-i)%3)*8000) monthlyList[i] = types.OrdersStatistics{ Date: dayDate.Format("2006-01-02"), AmountTotal: baseAmount, NewOrderAmount: int64(float64(baseAmount) * 0.68), RenewalOrderAmount: int64(float64(baseAmount) * 0.32), } } // Generate monthly data for the past 6 months (oldest first) allList := make([]types.OrdersStatistics, 6) for i := 0; i < 6; i++ { monthDate := now.AddDate(0, -(5 - i), 0) baseAmount := int64(1800000 + ((5 - i) * 200000) + ((5-i)%2)*500000) allList[i] = types.OrdersStatistics{ Date: monthDate.Format("2006-01"), AmountTotal: baseAmount, NewOrderAmount: int64(float64(baseAmount) * 0.68), RenewalOrderAmount: int64(float64(baseAmount) * 0.32), } } return &types.RevenueStatisticsResponse{ Today: types.OrdersStatistics{ AmountTotal: 35888, NewOrderAmount: 22888, RenewalOrderAmount: 13000, }, Monthly: types.OrdersStatistics{ AmountTotal: 888888, NewOrderAmount: 588888, RenewalOrderAmount: 300000, List: monthlyList, }, All: types.OrdersStatistics{ AmountTotal: 12888888, NewOrderAmount: 8588888, RenewalOrderAmount: 4300000, List: allList, }, } }