fix: scope page insights to reporting periods

This commit is contained in:
2026-08-22 17:24:37 +08:00
parent 1b6ad4d095
commit 7f9c16be4b
13 changed files with 295 additions and 24 deletions

View File

@@ -244,6 +244,38 @@ func previousPersianSeason(year, startMonth int) (int, int) {
return year, startMonth
}
// PrecedingPeriodLabel returns the exact Persian label for the complete period
// immediately before start. The label follows the same vocabulary as Periods.
func PrecedingPeriodLabel(periodType string, start time.Time) (string, bool) {
location, err := time.LoadLocation("Asia/Tehran")
if err != nil {
return "", false
}
localStart := start.In(location)
switch periodType {
case "DAY":
day := localStart.AddDate(0, 0, -1)
year, month, dayOfMonth := gregorianToJalali(day.Year(), int(day.Month()), day.Day())
return fmt.Sprintf("روز %s %s %s", persianNumber(dayOfMonth), jalaliMonthNames[month-1], persianNumber(year)), true
case "WEEK":
weekStart := localStart.AddDate(0, 0, -7)
weekLastDay := localStart.AddDate(0, 0, -1)
_, startMonth, startDay := gregorianToJalali(weekStart.Year(), int(weekStart.Month()), weekStart.Day())
endYear, endMonth, endDay := gregorianToJalali(weekLastDay.Year(), int(weekLastDay.Month()), weekLastDay.Day())
return fmt.Sprintf("هفته %s %s تا %s %s %s", persianNumber(startDay), jalaliMonthNames[startMonth-1], persianNumber(endDay), jalaliMonthNames[endMonth-1], persianNumber(endYear)), true
case "JALALI_MONTH":
year, month, _ := gregorianToJalali(localStart.Year(), int(localStart.Month()), localStart.Day())
year, month = previousJalaliMonth(year, month)
return fmt.Sprintf("%s %s", jalaliMonthNames[month-1], persianNumber(year)), true
case "PERSIAN_SEASON":
year, month, _ := gregorianToJalali(localStart.Year(), int(localStart.Month()), localStart.Day())
year, month = previousPersianSeason(year, ((month-1)/3*3)+1)
return fmt.Sprintf("%s %s", persianSeasonNames[(month-1)/3], persianNumber(year)), true
default:
return "", false
}
}
func newPeriod(id, kind string, localStart, localEnd time.Time, label string, isDefault bool) Period {
return Period{
PeriodID: id, PeriodType: kind, StartAt: localStart.UTC(), EndAt: localEnd.UTC(),

View File

@@ -94,3 +94,29 @@ func TestCompletePeriods(t *testing.T) {
t.Fatalf("completePeriods() returned %d defaults, want 1", defaultCount)
}
}
func TestPrecedingPeriodLabelUsesExactJalaliPeriod(t *testing.T) {
location, err := time.LoadLocation("Asia/Tehran")
if err != nil {
t.Fatal(err)
}
tests := []struct {
name string
periodType string
start time.Time
want string
}{
{name: "day", periodType: "DAY", start: time.Date(2026, 7, 23, 0, 0, 0, 0, location), want: "روز ۳۱ تیر ۱۴۰۵"},
{name: "week", periodType: "WEEK", start: time.Date(2026, 8, 15, 0, 0, 0, 0, location), want: "هفته ۱۷ مرداد تا ۲۳ مرداد ۱۴۰۵"},
{name: "month", periodType: "JALALI_MONTH", start: time.Date(2026, 7, 23, 0, 0, 0, 0, location), want: "تیر ۱۴۰۵"},
{name: "season", periodType: "PERSIAN_SEASON", start: time.Date(2026, 6, 22, 0, 0, 0, 0, location), want: "بهار ۱۴۰۵"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, ok := PrecedingPeriodLabel(tt.periodType, tt.start)
if !ok || got != tt.want {
t.Fatalf("PrecedingPeriodLabel() = %q, %v; want %q, true", got, ok, tt.want)
}
})
}
}