package commission_stats import ( "context" "time" "github.com/break/junhong_cmp_fiber/internal/model" "github.com/break/junhong_cmp_fiber/internal/store/postgres" "github.com/break/junhong_cmp_fiber/pkg/errors" "gorm.io/gorm" ) type Service struct { statsStore *postgres.ShopSeriesCommissionStatsStore } func New(statsStore *postgres.ShopSeriesCommissionStatsStore) *Service { return &Service{ statsStore: statsStore, } } func (s *Service) GetCurrentStats(ctx context.Context, allocationID uint, periodType string) (*model.ShopSeriesCommissionStats, error) { now := time.Now() stats, err := s.statsStore.GetCurrent(ctx, allocationID, periodType, now) if err != nil { if err == gorm.ErrRecordNotFound { return nil, errors.New(errors.CodeNotFound, "统计数据不存在") } return nil, errors.Wrap(errors.CodeInternalError, err, "获取统计数据失败") } return stats, nil } func (s *Service) UpdateStats(ctx context.Context, allocationID uint, periodType string, salesCount int64, salesAmount int64) error { now := time.Now() periodStart, periodEnd := calculatePeriod(now, periodType) stats, err := s.statsStore.GetCurrent(ctx, allocationID, periodType, now) if err != nil && err != gorm.ErrRecordNotFound { return errors.Wrap(errors.CodeInternalError, err, "查询统计数据失败") } if stats == nil { stats = &model.ShopSeriesCommissionStats{ AllocationID: allocationID, PeriodType: periodType, PeriodStart: periodStart, PeriodEnd: periodEnd, TotalSalesCount: salesCount, TotalSalesAmount: salesAmount, Status: "active", LastUpdatedAt: now, Version: 1, } return s.statsStore.Create(ctx, stats) } return s.statsStore.IncrementSales(ctx, stats.ID, salesCount, salesAmount, stats.Version) } func (s *Service) ArchiveCompletedPeriod(ctx context.Context, allocationID uint, periodType string) error { now := time.Now() stats, err := s.statsStore.GetCurrent(ctx, allocationID, periodType, now) if err != nil { if err == gorm.ErrRecordNotFound { return nil } return errors.Wrap(errors.CodeInternalError, err, "查询统计数据失败") } return s.statsStore.CompletePeriod(ctx, stats.ID) } func calculatePeriod(now time.Time, periodType string) (time.Time, time.Time) { var periodStart, periodEnd time.Time switch periodType { case "monthly": periodStart = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()) periodEnd = periodStart.AddDate(0, 1, 0).Add(-time.Second) case "quarterly": quarter := (int(now.Month()) - 1) / 3 periodStart = time.Date(now.Year(), time.Month(quarter*3+1), 1, 0, 0, 0, 0, now.Location()) periodEnd = periodStart.AddDate(0, 3, 0).Add(-time.Second) case "yearly": periodStart = time.Date(now.Year(), 1, 1, 0, 0, 0, 0, now.Location()) periodEnd = periodStart.AddDate(1, 0, 0).Add(-time.Second) default: periodStart = time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location()) periodEnd = periodStart.AddDate(0, 1, 0).Add(-time.Second) } return periodStart, periodEnd }