mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-10-04 13:42:14 +00:00
fix(completion-templates): read legacy status when counting open linked work orders
Work orders without a LifecycleStatus are open or closed according to their legacy status text. The linked work-order count now goes through the shared board status filter, so a legacy completed or cancelled row is no longer reported as depending on the template.
This commit is contained in:
parent
7c097c2750
commit
cd23ad5b68
2 changed files with 55 additions and 5 deletions
|
|
@ -8,6 +8,10 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
{
|
{
|
||||||
public class CompletionDocTemplateDataService : ICompletionDocTemplateDataService
|
public class CompletionDocTemplateDataService : ICompletionDocTemplateDataService
|
||||||
{
|
{
|
||||||
|
private static readonly LifecycleStatus[] OpenStatuses = Enum.GetValues<LifecycleStatus>()
|
||||||
|
.Where(status => !LifecycleStatusSets.Terminal.Contains(status))
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
private readonly ApplicationDbContext _context;
|
private readonly ApplicationDbContext _context;
|
||||||
|
|
||||||
public CompletionDocTemplateDataService(ApplicationDbContext context)
|
public CompletionDocTemplateDataService(ApplicationDbContext context)
|
||||||
|
|
@ -153,9 +157,12 @@ namespace SeaHaven.DataServices.Implementation
|
||||||
.Where(s => s.CompletionDocTemplateId == templateId)
|
.Where(s => s.CompletionDocTemplateId == templateId)
|
||||||
.Select(s => (int?)s.Id);
|
.Select(s => (int?)s.Id);
|
||||||
|
|
||||||
|
// Shared status filter so legacy rows without a LifecycleStatus are read
|
||||||
|
// through their legacy status text (a legacy "completed" row is not open).
|
||||||
|
workOrders = WorkOrderBoardQueryFilters.ApplyStatusFilter(workOrders, OpenStatuses);
|
||||||
|
|
||||||
return await workOrders
|
return await workOrders
|
||||||
.Where(w => w.ServiceId != null && linkedServiceIds.Contains(w.ServiceId))
|
.Where(w => w.ServiceId != null && linkedServiceIds.Contains(w.ServiceId))
|
||||||
.Where(w => !LifecycleStatusSets.Terminal.Contains(w.LifecycleStatus))
|
|
||||||
.OrderBy(w => w.Id)
|
.OrderBy(w => w.Id)
|
||||||
.Select(w => w.Id)
|
.Select(w => w.Id)
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
|
||||||
|
|
@ -376,6 +376,7 @@ public class CompletionDocTemplateServiceTests
|
||||||
new WorkOrder { Id = 107, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Scheduled, IsDeleted = true },
|
new WorkOrder { Id = 107, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Scheduled, IsDeleted = true },
|
||||||
new WorkOrder { Id = 108, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Scheduled, istemplate = true },
|
new WorkOrder { Id = 108, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Scheduled, istemplate = true },
|
||||||
new WorkOrder { Id = 205, ServiceId = 1, AccountId = 2, LifecycleStatus = LifecycleStatus.InProgress });
|
new WorkOrder { Id = 205, ServiceId = 1, AccountId = 2, LifecycleStatus = LifecycleStatus.InProgress });
|
||||||
|
context.workOrders.AddRange(LegacyStatusWorkOrders(serviceId: 1, accountId: 1));
|
||||||
await context.SaveChangesAsync();
|
await context.SaveChangesAsync();
|
||||||
var service = NewService(context);
|
var service = NewService(context);
|
||||||
|
|
||||||
|
|
@ -383,13 +384,21 @@ public class CompletionDocTemplateServiceTests
|
||||||
var tenantTwo = await service.GetLinkedWorkOrdersAsync(Admin(accountId: 2), 10, CancellationToken.None);
|
var tenantTwo = await service.GetLinkedWorkOrdersAsync(Admin(accountId: 2), 10, CancellationToken.None);
|
||||||
var orgWide = await service.GetLinkedWorkOrdersAsync(Admin(), 10, CancellationToken.None);
|
var orgWide = await service.GetLinkedWorkOrdersAsync(Admin(), 10, CancellationToken.None);
|
||||||
|
|
||||||
Assert.Equal(2, tenantOne.Count);
|
Assert.Equal(3, tenantOne.Count);
|
||||||
Assert.Equal(new[] { 101, 102 }, tenantOne.WorkOrderIds);
|
Assert.Equal(new[] { 101, 102, 111 }, tenantOne.WorkOrderIds);
|
||||||
Assert.Equal(new[] { 205 }, tenantTwo.WorkOrderIds);
|
Assert.Equal(new[] { 205 }, tenantTwo.WorkOrderIds);
|
||||||
Assert.Equal(new[] { 101, 102, 205 }, orgWide.WorkOrderIds);
|
Assert.Equal(new[] { 101, 102, 111, 205 }, orgWide.WorkOrderIds);
|
||||||
Assert.Equal(3, orgWide.Count);
|
Assert.Equal(4, orgWide.Count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Legacy rows carry no LifecycleStatus; their legacy status text decides whether they are open.
|
||||||
|
private static WorkOrder[] LegacyStatusWorkOrders(int serviceId, int accountId) => new[]
|
||||||
|
{
|
||||||
|
new WorkOrder { Id = 109, ServiceId = serviceId, AccountId = accountId, LegacyStatus = "Completed" },
|
||||||
|
new WorkOrder { Id = 110, ServiceId = serviceId, AccountId = accountId, Status = " Cancelled " },
|
||||||
|
new WorkOrder { Id = 111, ServiceId = serviceId, AccountId = accountId, LegacyStatus = "On Hold" }
|
||||||
|
};
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task LinkedWorkOrders_UnknownTemplateOrMissingScope_Throws()
|
public async Task LinkedWorkOrders_UnknownTemplateOrMissingScope_Throws()
|
||||||
{
|
{
|
||||||
|
|
@ -485,6 +494,40 @@ public class CompletionDocTemplateServiceTests
|
||||||
Assert.True((await context.CompletionDocTemplates.SingleAsync()).IsDeleted);
|
Assert.True((await context.CompletionDocTemplates.SingleAsync()).IsDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Relational_LinkedWorkOrdersExcludeTerminalAndLegacyTerminalRows()
|
||||||
|
{
|
||||||
|
await using var connection = new SqliteConnection("DataSource=:memory:");
|
||||||
|
await connection.OpenAsync();
|
||||||
|
await using var context = await NewSqliteContextAsync(connection);
|
||||||
|
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 1);
|
||||||
|
await WorkOrderAccountTestHelpers.EnsureAccountAsync(context, 2, "Other Corp");
|
||||||
|
context.CompletionDocTemplates.Add(new CompletionDocTemplate { Id = 10, Name = "Backflow" });
|
||||||
|
context.Services.Add(new Service
|
||||||
|
{
|
||||||
|
Id = 1,
|
||||||
|
Name = "Backflow",
|
||||||
|
NormalizedName = "BACKFLOW",
|
||||||
|
RequiresCompletionDocument = true,
|
||||||
|
CompletionDocTemplateId = 10
|
||||||
|
});
|
||||||
|
context.workOrders.AddRange(
|
||||||
|
new WorkOrder { Id = 101, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Scheduled },
|
||||||
|
new WorkOrder { Id = 102, ServiceId = 1, AccountId = 1 },
|
||||||
|
new WorkOrder { Id = 103, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Completed },
|
||||||
|
new WorkOrder { Id = 104, ServiceId = 1, AccountId = 1, LifecycleStatus = LifecycleStatus.Canceled },
|
||||||
|
new WorkOrder { Id = 205, ServiceId = 1, AccountId = 2, LifecycleStatus = LifecycleStatus.OnSite });
|
||||||
|
context.workOrders.AddRange(LegacyStatusWorkOrders(serviceId: 1, accountId: 1));
|
||||||
|
await context.SaveChangesAsync();
|
||||||
|
var data = new CompletionDocTemplateDataService(context);
|
||||||
|
|
||||||
|
var tenantOne = await data.GetOpenLinkedWorkOrderIdsAsync(10, 1, CancellationToken.None);
|
||||||
|
var orgWide = await data.GetOpenLinkedWorkOrderIdsAsync(10, null, CancellationToken.None);
|
||||||
|
|
||||||
|
Assert.Equal(new[] { 101, 102, 111 }, tenantOne);
|
||||||
|
Assert.Equal(new[] { 101, 102, 111, 205 }, orgWide);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Relational_UpdateReplacesProceduresInOrder()
|
public async Task Relational_UpdateReplacesProceduresInOrder()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue