mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-07 16:19:07 +00:00
Compare commits
1 commit
cae22bce0d
...
deb02c99f8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
deb02c99f8 |
2 changed files with 11 additions and 51 deletions
|
|
@ -369,14 +369,9 @@ public class DashboardServiceTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTrendAsync_DailyBucketsClassifyByCalendarScheduledDate()
|
||||
public async Task GetTrendAsync_DailyBucketsClassifyByNewYorkScheduledDate()
|
||||
{
|
||||
using var ctx = NewContext();
|
||||
// ScheduledDate is a stored calendar value (board writes persist `.Date`), so a work
|
||||
// order buckets on its own calendar day regardless of the time-of-day component. The
|
||||
// UTC hours below were previously shifted a full day by an America/New_York conversion
|
||||
// (03:00 UTC -> prior evening), so they double as a regression guard: each row must now
|
||||
// stay on the calendar date it was scheduled for.
|
||||
ctx.workOrders.AddRange(
|
||||
new WorkOrder
|
||||
{
|
||||
|
|
@ -431,21 +426,17 @@ public class DashboardServiceTests
|
|||
trend.Buckets.Select(bucket => bucket.Label).Should().Equal(
|
||||
"2026-01-14", "2026-01-15", "2026-01-16");
|
||||
|
||||
// 01-14: only the canceled row scheduled that calendar day.
|
||||
trend.Buckets[0].Total.Should().Be(1);
|
||||
trend.Buckets[0].Open.Should().Be(0);
|
||||
trend.Buckets[0].Total.Should().Be(2);
|
||||
trend.Buckets[0].Open.Should().Be(1);
|
||||
trend.Buckets[0].Canceled.Should().Be(1);
|
||||
trend.Buckets[0].Completed.Should().Be(0);
|
||||
trend.Buckets[0].Overdue.Should().Be(0);
|
||||
trend.Buckets[0].Overdue.Should().Be(1);
|
||||
|
||||
// 01-15: the 03:00 UTC scheduled row (no longer shifted to 01-14) plus the completed row.
|
||||
trend.Buckets[1].Total.Should().Be(2);
|
||||
trend.Buckets[1].Open.Should().Be(1);
|
||||
trend.Buckets[1].Completed.Should().Be(1);
|
||||
trend.Buckets[1].Canceled.Should().Be(0);
|
||||
trend.Buckets[1].Overdue.Should().Be(1);
|
||||
|
||||
// 01-16: the 03:00 UTC scheduled row that stays on its own day.
|
||||
trend.Buckets[2].Total.Should().Be(1);
|
||||
trend.Buckets[2].Open.Should().Be(1);
|
||||
trend.Buckets[2].Overdue.Should().Be(1);
|
||||
|
|
@ -453,38 +444,6 @@ public class DashboardServiceTests
|
|||
trend.Buckets.Should().OnlyContain(bucket => !bucket.IsCurrent);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTrendAsync_MidnightScheduledDateStaysInTodayBucketAndIsNotOverdue()
|
||||
{
|
||||
using var ctx = NewContext();
|
||||
var today = DashboardBusinessTime.Today();
|
||||
// A board-scheduled work order for today is stored as midnight (`.Date`). It must land
|
||||
// in the Today bucket and count as open, not roll back to yesterday and read as overdue.
|
||||
ctx.workOrders.Add(new WorkOrder
|
||||
{
|
||||
AccountId = 1,
|
||||
LifecycleStatus = Data.SeaHavenIndustries.Enums.LifecycleStatus.Scheduled,
|
||||
ScheduledDate = today.ToDateTime(TimeOnly.MinValue)
|
||||
});
|
||||
ctx.SaveChanges();
|
||||
|
||||
var query = new DashboardTrendQueryDTO
|
||||
{
|
||||
DateFrom = today.AddDays(-1),
|
||||
DateTo = today.AddDays(1)
|
||||
};
|
||||
var trend = await NewService(ctx).GetTrendAsync(
|
||||
AccountUser(1), query, CancellationToken.None);
|
||||
|
||||
var todayBucket = trend.Buckets.Single(bucket => bucket.Date == today);
|
||||
todayBucket.Total.Should().Be(1);
|
||||
todayBucket.Open.Should().Be(1);
|
||||
todayBucket.Overdue.Should().Be(0);
|
||||
|
||||
var yesterdayBucket = trend.Buckets.Single(bucket => bucket.Date == today.AddDays(-1));
|
||||
yesterdayBucket.Total.Should().Be(0);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTrendAsync_ThreeMonthRangeUsesWeeklyMondayBuckets()
|
||||
{
|
||||
|
|
@ -556,8 +515,6 @@ public class DashboardServiceTests
|
|||
LifecycleStatus = Data.SeaHavenIndustries.Enums.LifecycleStatus.Scheduled,
|
||||
ScheduledDate = new DateTime(2025, 12, 31, 20, 0, 0, DateTimeKind.Utc)
|
||||
},
|
||||
// 2027-01-01 by calendar: outside the 2026 window. Previously an
|
||||
// America/New_York conversion pulled it back to 2026-12-31 and into December.
|
||||
new WorkOrder
|
||||
{
|
||||
AccountId = 1,
|
||||
|
|
@ -578,10 +535,10 @@ public class DashboardServiceTests
|
|||
trend.Buckets[2].Label.Should().Be("2026-03-01");
|
||||
trend.Buckets[2].Total.Should().Be(1);
|
||||
trend.Buckets[2].Completed.Should().Be(1);
|
||||
// December stays empty: the 2027-01-01 row is no longer pulled inside the window.
|
||||
trend.Buckets[11].Label.Should().Be("2026-12-01");
|
||||
trend.Buckets[11].Total.Should().Be(0);
|
||||
trend.Buckets[11].Open.Should().Be(0);
|
||||
trend.Buckets[11].Total.Should().Be(1);
|
||||
trend.Buckets[11].Open.Should().Be(1);
|
||||
trend.Buckets[11].Overdue.Should().Be(0);
|
||||
trend.Today.Should().Be(DashboardBusinessTime.Today());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -196,6 +196,7 @@ namespace SeaHaven.Services.Implementation
|
|||
|
||||
var today = DashboardBusinessTime.Today();
|
||||
var (windowFrom, windowTo, granularity) = ResolveTrendWindow(query, today);
|
||||
var timezone = TimeZoneInfo.FindSystemTimeZoneById(DashboardBusinessTime.TimeZoneId);
|
||||
var firstBucketStart = BucketStart(windowFrom, granularity);
|
||||
var lastBucketStart = BucketStart(windowTo, granularity);
|
||||
var lastBucketEnd = BucketEnd(lastBucketStart, granularity);
|
||||
|
|
@ -216,7 +217,9 @@ namespace SeaHaven.Services.Implementation
|
|||
{
|
||||
if (workOrder.ScheduledDate is not DateTime scheduled)
|
||||
continue;
|
||||
var businessDate = DateOnly.FromDateTime(scheduled.Date);
|
||||
var businessDate = DateOnly.FromDateTime(
|
||||
TimeZoneInfo.ConvertTimeFromUtc(
|
||||
DateTime.SpecifyKind(scheduled, DateTimeKind.Utc), timezone));
|
||||
if (businessDate < firstBucketStart || businessDate > lastBucketEnd)
|
||||
continue;
|
||||
var bucket = buckets[LocateBucket(bucketStarts, businessDate)];
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue