fix: align report date defaults with recent periods
This commit is contained in:
@@ -137,23 +137,11 @@ func (uc *AnalyticsUsecase) list(ctx context.Context, kind AnalyticsKind, filter
|
||||
filter.PromoteName = ""
|
||||
filter.PromoteType = nil
|
||||
}
|
||||
if filter.EndDate == nil || kind == GameAnalytics && filter.StartDate == nil {
|
||||
now := uc.now().In(portraitLocation)
|
||||
day := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, portraitLocation)
|
||||
if kind == GameAnalytics && filter.StartDate == nil {
|
||||
filter.StartDate = &day
|
||||
}
|
||||
if filter.EndDate == nil {
|
||||
filter.EndDate = &day
|
||||
}
|
||||
}
|
||||
if filter.StartDate != nil && filter.EndDate.Before(*filter.StartDate) {
|
||||
filter.StartDate, filter.EndDate = reportDateDefaults(filter.StartDate, filter.EndDate, 30, uc.now())
|
||||
if filter.EndDate.Before(*filter.StartDate) {
|
||||
return nil, ErrAnalyticsDateOrder
|
||||
}
|
||||
filter.Begin = ""
|
||||
if filter.StartDate != nil {
|
||||
filter.Begin = filter.StartDate.Format("2006-01-02")
|
||||
}
|
||||
filter.Begin = filter.StartDate.Format("2006-01-02")
|
||||
filter.End = filter.EndDate.Format("2006-01-02")
|
||||
out := &AnalyticsPage{Rows: []*AnalyticsRow{}, Begin: filter.Begin, End: filter.End, Available: true}
|
||||
scope := AnalyticsScope{Viewer: viewer, IncludeSub: pref.IncludeSubPromote, IDCardDedup: pref.IDCardDedup}
|
||||
|
||||
@@ -63,8 +63,8 @@ func TestGameAnalyticsSummaryUsesAllRowsAndCorrectDenominators(t *testing.T) {
|
||||
if len(page.Rows) != 1 || page.Total != 2 || page.Rows[0].ID != 2 || page.Summary.Counts.Register != 5 || page.Summary.Pay != "50.00" || page.Summary.PayRate != "30.00" || page.Summary.ARPU != "5.00" || page.Summary.ARPPU != "16.67" {
|
||||
t.Fatalf("游戏汇总、分页或分母错误: %+v", page)
|
||||
}
|
||||
if page.Begin != "2026-11-04" || page.End != "2026-11-04" {
|
||||
t.Fatal("后台缺省统计日期应为当天")
|
||||
if page.Begin != "2026-10-06" || page.End != "2026-11-04" {
|
||||
t.Fatal("后台缺省统计日期应为含今天的近30天")
|
||||
}
|
||||
}
|
||||
func TestChannelAnalyticsSummaryDependsOnViewer(t *testing.T) {
|
||||
@@ -82,7 +82,7 @@ func TestChannelAnalyticsSummaryDependsOnViewer(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestChannelAnalyticsAllPagesSummaryAndOpenDateRange(t *testing.T) {
|
||||
func TestChannelAnalyticsAllPagesSummaryAndDefaultDateRange(t *testing.T) {
|
||||
uc, repo := analyticsFixture()
|
||||
repo.data.EffectiveCount = 3
|
||||
for _, pageNum := range []int{1, 2, 8} {
|
||||
@@ -90,8 +90,8 @@ func TestChannelAnalyticsAllPagesSummaryAndOpenDateRange(t *testing.T) {
|
||||
if err != nil || page.Total != 2 || page.Summary.Counts.Register != 5 || page.Summary.Counts.Active != 10 || page.Summary.Counts.Pay != 3 || page.Summary.Counts.NewPay != 2 || page.Summary.Pay != "50.00" || page.Summary.PayRate != "30.00" || page.EffectiveCount != 3 {
|
||||
t.Fatalf("翻页不能改变完整合计: page=%d %+v %v", pageNum, page, err)
|
||||
}
|
||||
if page.Begin != "" || page.End != "2026-11-04" || repo.filter.StartDate != nil {
|
||||
t.Fatalf("渠道统计缺省应从最早数据统计至今天: %+v", repo.filter)
|
||||
if page.Begin != "2026-10-06" || page.End != "2026-11-04" || repo.filter.StartDate == nil {
|
||||
t.Fatalf("渠道统计缺省应为含今天的近30天: %+v", repo.filter)
|
||||
}
|
||||
}
|
||||
for _, sample := range []struct {
|
||||
|
||||
@@ -119,18 +119,13 @@ func (uc *LedgerUsecase) prepare(ctx context.Context, filter LedgerFilter) (Ledg
|
||||
viewer := portraitUserScope(a)
|
||||
viewer.All = actor.AuthorityID == 888
|
||||
scope := LedgerScope{Viewer: viewer, IncludeSub: pref.IncludeSubPromote, Unrestricted: viewer.All && strings.TrimSpace(filter.BusierAccount) == ""}
|
||||
begin, end := filter.StartDate, filter.EndDate
|
||||
if begin == nil || end == nil {
|
||||
now := uc.now().In(portraitLocation)
|
||||
yesterday := time.Date(now.Year(), now.Month(), now.Day()-1, 0, 0, 0, 0, portraitLocation)
|
||||
first := yesterday.AddDate(0, 0, -6)
|
||||
begin, end = &first, &yesterday
|
||||
}
|
||||
begin, end := reportDateDefaults(filter.StartDate, filter.EndDate, 30, uc.now())
|
||||
if end.Before(*begin) {
|
||||
return scope, filter, ErrLedgerInput
|
||||
}
|
||||
filter.BeginUnix = begin.Unix()
|
||||
filter.EndUnix = end.AddDate(0, 0, 1).Unix() - 1
|
||||
filter.StartDate, filter.EndDate = begin, end
|
||||
return scope, filter, nil
|
||||
}
|
||||
func registrationSort(field string) string {
|
||||
|
||||
@@ -46,8 +46,8 @@ func TestLedgerDateDefaultsAndBusinessScope(t *testing.T) {
|
||||
if _, err := uc.Registrations(accountContext(7, 901), LedgerFilter{SortField: "payAmount"}, LedgerListOptions{Limit: 10}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if time.Unix(r.filter.BeginUnix, 0).In(portraitLocation).Format("2006-01-02 15:04:05") != "2026-10-28 00:00:00" || time.Unix(r.filter.EndUnix, 0).In(portraitLocation).Format("2006-01-02 15:04:05") != "2026-11-03 23:59:59" {
|
||||
t.Fatal("未传日期应取截至昨日的七天")
|
||||
if time.Unix(r.filter.BeginUnix, 0).In(portraitLocation).Format("2006-01-02 15:04:05") != "2026-10-06 00:00:00" || time.Unix(r.filter.EndUnix, 0).In(portraitLocation).Format("2006-01-02 15:04:05") != "2026-11-04 23:59:59" {
|
||||
t.Fatal("未传日期应取含今天的近30天")
|
||||
}
|
||||
if r.scope.Unrestricted || !r.scope.Viewer.IncludeSelf || r.filter.SortField != "totalPayAmount" {
|
||||
t.Fatal("商务范围或排序别名错误")
|
||||
|
||||
@@ -70,10 +70,7 @@ func (uc *RankingUsecase) List(ctx context.Context, kind RankingKind, f Analytic
|
||||
if kind != ChannelRanking && kind != BusinessRanking && kind != GameRanking {
|
||||
return nil, ErrAnalyticsInput
|
||||
}
|
||||
if f.StartDate == nil || f.EndDate == nil {
|
||||
day := workbenchWindow(uc.now()).Today
|
||||
f.StartDate, f.EndDate = &day, &day
|
||||
}
|
||||
f.StartDate, f.EndDate = reportDateDefaults(f.StartDate, f.EndDate, 7, uc.now())
|
||||
if f.EndDate.Before(*f.StartDate) {
|
||||
return nil, ErrAnalyticsDateOrder
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ func TestRankingComparisonsAndBusinessCountSemantics(t *testing.T) {
|
||||
if err != nil || p.Active[0].Value != "5" || p.PayRate[0].Value != "40.00" || p.Register[0].Name != "二级商务 (L2)" || p.Register[0].SourceDB != "" {
|
||||
t.Fatal("商务需加总各渠道人数,不全局去重")
|
||||
}
|
||||
if p.Begin != "2026-10-29" || p.End != "2026-11-04" || r.filter.PreviousBegin != "2026-10-22" || r.filter.PreviousEnd != "2026-10-28" {
|
||||
t.Fatal("排行榜缺省为含今天的近7天,上期范围应等长")
|
||||
}
|
||||
calls := r.calls
|
||||
p, err = uc.List(accountContext(9, 903), BusinessRanking, AnalyticsFilter{})
|
||||
if err != nil || len(p.Register) != 0 || r.calls != calls {
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package business
|
||||
|
||||
import "time"
|
||||
|
||||
// reportDateDefaults fills missing bounds without discarding an explicit date.
|
||||
// Reports include the end date, so a 30-day period starts 29 days earlier.
|
||||
func reportDateDefaults(begin, end *time.Time, days int, now time.Time) (*time.Time, *time.Time) {
|
||||
if end == nil {
|
||||
local := now.In(portraitLocation)
|
||||
day := time.Date(local.Year(), local.Month(), local.Day(), 0, 0, 0, 0, portraitLocation)
|
||||
end = &day
|
||||
}
|
||||
if begin == nil {
|
||||
first := end.AddDate(0, 0, 1-days)
|
||||
begin = &first
|
||||
}
|
||||
return begin, end
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package business
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestAnalyticsDefaultDatesBoundListAndExportQueries(t *testing.T) {
|
||||
date := func(value string) *time.Time {
|
||||
parsed, err := time.ParseInLocation("2006-01-02", value, portraitLocation)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
return &parsed
|
||||
}
|
||||
for _, kind := range []AnalyticsKind{ChannelAnalytics, GameAnalytics} {
|
||||
for _, sample := range []struct {
|
||||
name, start, end, wantStart, wantEnd string
|
||||
now time.Time
|
||||
}{
|
||||
{"empty", "", "", "2026-10-06", "2026-11-04", time.Date(2026, 11, 4, 9, 0, 0, 0, portraitLocation)},
|
||||
{"China day across UTC midnight", "", "", "2025-12-03", "2026-01-01", time.Date(2025, 12, 31, 17, 0, 0, 0, time.UTC)},
|
||||
{"only end across leap day", "", "2024-03-01", "2024-02-01", "2024-03-01", time.Now()},
|
||||
{"only start", "2026-01-01", "", "2026-01-01", "2026-11-04", time.Date(2026, 11, 4, 9, 0, 0, 0, portraitLocation)},
|
||||
{"explicit historical year", "2023-01-01", "2023-12-31", "2023-01-01", "2023-12-31", time.Now()},
|
||||
} {
|
||||
t.Run(string(kind)+"/"+sample.name, func(t *testing.T) {
|
||||
uc, repo := analyticsFixture()
|
||||
uc.now = func() time.Time { return sample.now }
|
||||
filter := AnalyticsFilter{}
|
||||
if sample.start != "" {
|
||||
filter.StartDate = date(sample.start)
|
||||
}
|
||||
if sample.end != "" {
|
||||
filter.EndDate = date(sample.end)
|
||||
}
|
||||
for _, export := range []bool{false, true} {
|
||||
var page *AnalyticsPage
|
||||
var err error
|
||||
if export {
|
||||
page, err = uc.ListAll(accountContext(7, 901), kind, filter)
|
||||
} else {
|
||||
page, err = uc.List(accountContext(7, 901), kind, filter, 1, 10)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if page.Begin != sample.wantStart || page.End != sample.wantEnd || repo.filter.Begin != page.Begin || repo.filter.End != page.End || repo.filter.StartDate == nil || repo.filter.EndDate == nil {
|
||||
t.Fatalf("export=%v expected %s..%s, got %+v", export, sample.wantStart, sample.wantEnd, repo.filter)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLedgerPartialDateDoesNotDiscardHistoricalEnd(t *testing.T) {
|
||||
uc, repo, _ := ledgerFixture()
|
||||
end := time.Date(2024, 3, 1, 0, 0, 0, 0, portraitLocation)
|
||||
for _, export := range []bool{false, true} {
|
||||
filter := LedgerFilter{EndDate: &end}
|
||||
var err error
|
||||
if export {
|
||||
_, err = uc.ExportSpends(accountContext(7, 901), filter)
|
||||
} else {
|
||||
_, err = uc.Registrations(accountContext(7, 901), filter, LedgerListOptions{Limit: 10})
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if time.Unix(repo.filter.BeginUnix, 0).In(portraitLocation).Format("2006-01-02 15:04:05") != "2024-02-01 00:00:00" || time.Unix(repo.filter.EndUnix, 0).In(portraitLocation).Format("2006-01-02 15:04:05") != "2024-03-01 23:59:59" {
|
||||
t.Fatalf("historical end date was discarded: %+v", repo.filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -89,11 +89,7 @@ func (uc *ServerAnalysisUsecase) List(ctx context.Context, f ServerAnalysisFilte
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.StartDate == nil || f.EndDate == nil {
|
||||
now := uc.now().In(portraitLocation)
|
||||
day := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, portraitLocation)
|
||||
f.StartDate, f.EndDate = &day, &day
|
||||
}
|
||||
f.StartDate, f.EndDate = reportDateDefaults(f.StartDate, f.EndDate, 30, uc.now())
|
||||
if f.EndDate.Before(*f.StartDate) {
|
||||
return nil, ErrAnalyticsDateOrder
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ func TestServerAnalysisSummaryZerosSortingAndLimits(t *testing.T) {
|
||||
uc.now = func() time.Time { return time.Date(2026, 11, 4, 9, 0, 0, 0, portraitLocation) }
|
||||
f := ServerAnalysisFilter{AnalyticsFilter: AnalyticsFilter{GameNames: []string{"游戏"}}}
|
||||
p, err := uc.List(accountContext(7, 901), f, 1, 1)
|
||||
if err != nil || p.Total != 2 || len(p.Rows) != 1 || p.Rows[0].ServerNum != "01" || p.Summary.Pay != "30.01" || p.Summary.Counts.Register != 5 || p.Summary.ARPU != "6.00" || p.Begin != "2026-11-04" {
|
||||
if err != nil || p.Total != 2 || len(p.Rows) != 1 || p.Rows[0].ServerNum != "01" || p.Summary.Pay != "30.01" || p.Summary.Counts.Register != 5 || p.Summary.ARPU != "6.00" || p.Begin != "2026-10-06" || p.End != "2026-11-04" {
|
||||
t.Fatalf("汇总、四舍五入或分页错误: %+v %v", p, err)
|
||||
}
|
||||
if !r.scope.IncludeSub || !r.scope.IDCardDedup || r.scope.Viewer.All {
|
||||
|
||||
Reference in New Issue
Block a user