mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 13:03:12 +00:00
fix(work-orders): process all WeekRolled candidates across batches
Offset paging skipped remaining WOs after ledger writes; always refetch the first page of unprocessed candidates and cover with a >BatchSize test.
This commit is contained in:
parent
8c33eb7f9a
commit
f977483c17
4 changed files with 41 additions and 7 deletions
|
|
@ -24,12 +24,13 @@ namespace SeaHaven.DataServices.Implementation
|
|||
DateOnly sourceWeekStart,
|
||||
DateOnly sourceWeekEnd,
|
||||
int batchSize = 500,
|
||||
int skip = 0,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var weekStartDate = sourceWeekStart.ToDateTime(TimeOnly.MinValue);
|
||||
var weekEndDate = sourceWeekEnd.ToDateTime(TimeOnly.MinValue);
|
||||
|
||||
// Always return the first page of remaining unprocessed candidates.
|
||||
// Callers must not offset-page: ledger writes shrink this set after each batch.
|
||||
return await _context.workOrders
|
||||
.AsNoTracking()
|
||||
.Where(w => w.IsDeleted != true)
|
||||
|
|
@ -42,7 +43,6 @@ namespace SeaHaven.DataServices.Implementation
|
|||
.Where(w => !_context.WorkOrderWeekRolledLedgers.Any(l =>
|
||||
l.WorkOrderId == w.Id && l.SourceWeekStart == sourceWeekStart))
|
||||
.OrderBy(w => w.Id)
|
||||
.Skip(skip)
|
||||
.Take(batchSize)
|
||||
.Select(w => w.Id)
|
||||
.ToListAsync(cancellationToken);
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ namespace SeaHaven.DataServices.Interfaces
|
|||
DateOnly sourceWeekStart,
|
||||
DateOnly sourceWeekEnd,
|
||||
int batchSize = 500,
|
||||
int skip = 0,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<WeekRolledProcessOutcome> TryProcessWeekRolledAsync(
|
||||
|
|
|
|||
|
|
@ -36,16 +36,17 @@ namespace SeaHaven.Services.Implementation
|
|||
var processed = 0;
|
||||
var skipped = 0;
|
||||
var failed = 0;
|
||||
var skip = 0;
|
||||
|
||||
_logger.LogInformation(
|
||||
"WeekRolled job started. CorrelationId={CorrelationId}, SourceWeekStart={SourceWeekStart}, SourceWeekEnd={SourceWeekEnd}",
|
||||
correlationId, sourceWeekStart, sourceWeekEnd);
|
||||
|
||||
// Always fetch the first page of remaining candidates. Processed rows write ledger
|
||||
// entries that exclude them from the next query; offset paging would skip unprocessed rows.
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
var candidates = await _dataService.GetWeekRolledCandidatesAsync(
|
||||
sourceWeekStart, sourceWeekEnd, BatchSize, skip, cancellationToken);
|
||||
sourceWeekStart, sourceWeekEnd, BatchSize, cancellationToken);
|
||||
|
||||
if (candidates.Count == 0)
|
||||
break;
|
||||
|
|
@ -84,8 +85,6 @@ namespace SeaHaven.Services.Implementation
|
|||
|
||||
if (candidates.Count < BatchSize)
|
||||
break;
|
||||
|
||||
skip += BatchSize;
|
||||
}
|
||||
|
||||
stopwatch.Stop();
|
||||
|
|
|
|||
|
|
@ -193,6 +193,42 @@ public class WorkOrderWeekRolledTests
|
|||
Assert.Equal(1, wo!.CarriedOver);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WeekRolled_ProcessesAllEligible_WhenMoreThanBatchSize()
|
||||
{
|
||||
// WorkOrderWeekRolledService.BatchSize is 500; more than one page must all be carried over.
|
||||
const int eligibleCount = 501;
|
||||
|
||||
await using var context = CreateContext();
|
||||
for (var i = 1; i <= eligibleCount; i++)
|
||||
{
|
||||
context.workOrders.Add(new WorkOrder
|
||||
{
|
||||
Id = i,
|
||||
ScheduledDate = new DateTime(2026, 6, 18),
|
||||
LifecycleStatus = LifecycleStatus.Scheduled,
|
||||
CarriedOver = 0
|
||||
});
|
||||
}
|
||||
await context.SaveChangesAsync();
|
||||
|
||||
var service = CreateService(context);
|
||||
var result = await service.ProcessWeekRolledAsync(SourceWeekStart);
|
||||
|
||||
Assert.Equal(eligibleCount, result.Processed);
|
||||
Assert.Equal(0, result.Skipped);
|
||||
Assert.Equal(0, result.Failed);
|
||||
|
||||
var carriedOverCount = await context.workOrders.CountAsync(w => w.CarriedOver == 1);
|
||||
Assert.Equal(eligibleCount, carriedOverCount);
|
||||
|
||||
var ledgerCount = await context.WorkOrderWeekRolledLedgers.CountAsync();
|
||||
Assert.Equal(eligibleCount, ledgerCount);
|
||||
|
||||
var auditCount = await context.WorkOrderAuditLogs.CountAsync(l => l.Action == "WeekRolled");
|
||||
Assert.Equal(eligibleCount, auditCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PastDueCache_SyncsOperationalFlags()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue