fix: allow closing current week when future workdays are not yet closed
CloseWeek was requiring every workday in the ISO week to have a closed_days record, including days in the future. Now only workdays up to and including today are checked; future workdays are skipped. Adds TestCloseWeekMidWeek regression test.
This commit is contained in:
@@ -88,13 +88,18 @@ func (s *WeekService) CloseWeek(ctx context.Context, weekKey string) (*domain.Cl
|
|||||||
// Compute expected ms for the week (from settings frozen at week start)
|
// Compute expected ms for the week (from settings frozen at week start)
|
||||||
expectedMs := int64(set.HoursPerWeek * 3_600_000)
|
expectedMs := int64(set.HoursPerWeek * 3_600_000)
|
||||||
|
|
||||||
// Verify all workdays are closed; collect worked ms
|
// Verify all workdays up to and including today are closed; collect worked ms.
|
||||||
|
// Future workdays in the week (not yet reached) are skipped.
|
||||||
|
todayKey := time.Now().In(s.tz).Format("2006-01-02")
|
||||||
var totalWorkedMs int64
|
var totalWorkedMs int64
|
||||||
for _, dk := range dayKeys {
|
for _, dk := range dayKeys {
|
||||||
t, _ := time.ParseInLocation("2006-01-02", dk, s.tz)
|
t, _ := time.ParseInLocation("2006-01-02", dk, s.tz)
|
||||||
if !set.IsWorkday(int(t.Weekday())) {
|
if !set.IsWorkday(int(t.Weekday())) {
|
||||||
continue // weekend or non-workday — skip
|
continue // weekend or non-workday — skip
|
||||||
}
|
}
|
||||||
|
if dk > todayKey {
|
||||||
|
continue // future workday — skip
|
||||||
|
}
|
||||||
cd, err := s.closedDays.GetByDayKey(ctx, dk)
|
cd, err := s.closedDays.GetByDayKey(ctx, dk)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, sql.ErrNoRows) {
|
if errors.Is(err, sql.ErrNoRows) {
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ func TestCloseWeekBasic(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
entrySvc, daySvc, weekSvc, _ := newFullServices(t)
|
entrySvc, daySvc, weekSvc, _ := newFullServices(t)
|
||||||
|
|
||||||
// Find the ISO week for "this week" using a known Mon-Fri
|
|
||||||
// Use a fixed Monday to make the test deterministic
|
// Use a fixed Monday to make the test deterministic
|
||||||
monday := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC) // 2024-W03, Monday
|
monday := time.Date(2024, 1, 15, 10, 0, 0, 0, time.UTC) // 2024-W03, Monday
|
||||||
weekKey := "2024-W03"
|
weekKey := "2024-W03"
|
||||||
@@ -92,7 +91,7 @@ func TestCloseWeekMissingDayFails(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, daySvc, weekSvc, _ := newFullServices(t)
|
_, daySvc, weekSvc, _ := newFullServices(t)
|
||||||
|
|
||||||
// Only close Mon-Thu, leave Friday open
|
// Only close Mon-Thu, leave Friday open — all are in the past
|
||||||
monday := time.Date(2024, 1, 15, 0, 0, 0, 0, time.UTC)
|
monday := time.Date(2024, 1, 15, 0, 0, 0, 0, time.UTC)
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
dk := monday.AddDate(0, 0, i).Format("2006-01-02")
|
dk := monday.AddDate(0, 0, i).Format("2006-01-02")
|
||||||
@@ -101,7 +100,7 @@ func TestCloseWeekMissingDayFails(t *testing.T) {
|
|||||||
|
|
||||||
_, err := weekSvc.CloseWeek(ctx, "2024-W03")
|
_, err := weekSvc.CloseWeek(ctx, "2024-W03")
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("expected error closing week with unclosed day")
|
t.Fatal("expected error closing week with unclosed past day")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,3 +141,33 @@ func TestReopenWeek(t *testing.T) {
|
|||||||
t.Fatalf("CloseWeek after reopen: %v", err)
|
t.Fatalf("CloseWeek after reopen: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCloseWeekMidWeek(t *testing.T) {
|
||||||
|
// Regression: closing the current week mid-week should succeed when all
|
||||||
|
// past workdays are closed and future workdays are left open.
|
||||||
|
ctx := context.Background()
|
||||||
|
_, daySvc, weekSvc, _ := newFullServices(t)
|
||||||
|
|
||||||
|
tz, _ := time.LoadLocation("UTC")
|
||||||
|
now := time.Now().In(tz)
|
||||||
|
isoYear, isoWeek := now.ISOWeek()
|
||||||
|
weekKey := fmt.Sprintf("%d-W%02d", isoYear, isoWeek)
|
||||||
|
|
||||||
|
// Close every workday from Monday up to and including today.
|
||||||
|
monday := now.AddDate(0, 0, -int(now.Weekday()-time.Monday))
|
||||||
|
today := now.Format("2006-01-02")
|
||||||
|
for d := monday; d.Format("2006-01-02") <= today; d = d.AddDate(0, 0, 1) {
|
||||||
|
wd := d.Weekday()
|
||||||
|
if wd == time.Saturday || wd == time.Sunday {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dk := d.Format("2006-01-02")
|
||||||
|
if _, err := daySvc.MarkDay(ctx, dk, domain.DayKindHoliday); err != nil {
|
||||||
|
t.Fatalf("MarkDay %s: %v", dk, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := weekSvc.CloseWeek(ctx, weekKey); err != nil {
|
||||||
|
t.Fatalf("CloseWeek mid-week: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user