diff --git a/SeaHaven.DataServices/Helpers/WorkOrderBoardProjection.cs b/SeaHaven.DataServices/Helpers/WorkOrderBoardProjection.cs index cd4122f..9446621 100644 --- a/SeaHaven.DataServices/Helpers/WorkOrderBoardProjection.cs +++ b/SeaHaven.DataServices/Helpers/WorkOrderBoardProjection.cs @@ -8,6 +8,8 @@ namespace SeaHaven.DataServices.Helpers { public static class WorkOrderBoardProjection { + private static readonly string[] CompletedLegacyStatuses = { "completed", "complete", "done", "closed" }; + private static readonly JsonSerializerOptions SnapshotJsonOptions = new(JsonSerializerDefaults.Web); @@ -37,11 +39,15 @@ namespace SeaHaven.DataServices.Helpers w.ServiceId, w.ServiceNameSnapshot, ServiceDisplayName = w.ServiceId.HasValue - ? (w.ServiceDefinition != null - && w.ServiceDefinition.IsActive - && w.ServiceDefinition.IsDeleted != true - ? w.ServiceDefinition.Name - : w.ServiceNameSnapshot ?? w.Trade ?? w.Problem) + ? (w.LifecycleStatus == LifecycleStatus.Completed + || (w.LifecycleStatus == null + && CompletedLegacyStatuses.Contains(((w.LegacyStatus ?? w.Status) ?? "").Trim().ToLower())) + ? w.ServiceNameSnapshot ?? w.Trade ?? w.Problem + : (w.ServiceDefinition != null + && w.ServiceDefinition.IsActive + && w.ServiceDefinition.IsDeleted != true + ? w.ServiceDefinition.Name + : w.ServiceNameSnapshot ?? w.Trade ?? w.Problem)) : w.Trade ?? w.Problem, w.SiteCode, LocationName = w.Locations != null ? w.Locations.Name : null, diff --git a/SeaHaven.DataServices/Helpers/WorkOrderBoardQueryFilters.cs b/SeaHaven.DataServices/Helpers/WorkOrderBoardQueryFilters.cs index 0b63ac5..27f88f1 100644 --- a/SeaHaven.DataServices/Helpers/WorkOrderBoardQueryFilters.cs +++ b/SeaHaven.DataServices/Helpers/WorkOrderBoardQueryFilters.cs @@ -5,6 +5,8 @@ namespace SeaHaven.DataServices.Helpers { public static class WorkOrderBoardQueryFilters { + private static readonly string[] CompletedLegacyStatuses = { "completed", "complete", "done", "closed" }; + /// /// The window the Work Orders board searches when no date range is selected /// (client ADVANCED_SEARCH_ALL_WEEKS_FROM/TO), used with includeDateless. @@ -268,6 +270,9 @@ namespace SeaHaven.DataServices.Helpers ? (w.ServiceDefinition != null && w.ServiceDefinition.IsActive && w.ServiceDefinition.IsDeleted != true + && !(w.LifecycleStatus == LifecycleStatus.Completed + || (w.LifecycleStatus == null + && CompletedLegacyStatuses.Contains(((w.LegacyStatus ?? w.Status) ?? "").Trim().ToLower()))) ? (w.ServiceDefinition.Name ?? "").ToLower().Contains(pm) : ((w.ServiceDefinition != null && (w.ServiceDefinition.Name ?? "").ToLower().Contains(pm)) diff --git a/SeaHavenIndustries.Tests/WorkOrderServiceRegistryFilterRelationalTests.cs b/SeaHavenIndustries.Tests/WorkOrderServiceRegistryFilterRelationalTests.cs index 60a1016..1f81bcc 100644 --- a/SeaHavenIndustries.Tests/WorkOrderServiceRegistryFilterRelationalTests.cs +++ b/SeaHavenIndustries.Tests/WorkOrderServiceRegistryFilterRelationalTests.cs @@ -1,4 +1,5 @@ using Data.SeaHavenIndustries; +using Data.SeaHavenIndustries.Enums; using Microsoft.Data.Sqlite; using Microsoft.EntityFrameworkCore; using SeaHaven.DataServices.Helpers; @@ -9,7 +10,7 @@ namespace SeaHavenIndustries.Tests; public sealed class WorkOrderServiceRegistryFilterRelationalTests { [Fact] - public async Task ServiceDisplayAndFilter_UseCurrentActiveNameAndKeepHistoricalAndLegacyLabels() + public async Task ServiceDisplayAndFilter_RespectCompletedSnapshotsAndKeepCurrentAliases() { await using var connection = new SqliteConnection("Data Source=:memory:;Foreign Keys=True"); await connection.OpenAsync(); @@ -59,6 +60,22 @@ public sealed class WorkOrderServiceRegistryFilterRelationalTests Id = 3, Trade = "Legacy Cooling", Problem = "Legacy Leak" + }, + new WorkOrder + { + Id = 4, + ServiceId = 10, + ServiceNameSnapshot = "Completed Archive Alpha", + Trade = "Completed Archive Alpha", + LifecycleStatus = LifecycleStatus.Completed + }, + new WorkOrder + { + Id = 5, + ServiceId = 10, + ServiceNameSnapshot = "Completed Archive Beta", + Trade = "Completed Archive Beta", + Status = "Done" }); await context.SaveChangesAsync(); @@ -87,6 +104,18 @@ public sealed class WorkOrderServiceRegistryFilterRelationalTests isUnscheduled: true); var legacyDisplay = WorkOrderBoardService.MapRawRow(Assert.Single(legacyRows), DateTime.UtcNow); + var completedRows = await WorkOrderBoardProjection.ProjectRowsAsync( + context, + context.workOrders.AsNoTracking().Where(w => w.Id == 4), + isUnscheduled: true); + var completedDisplay = WorkOrderBoardService.MapRawRow(Assert.Single(completedRows), DateTime.UtcNow); + + var legacyCompletedRows = await WorkOrderBoardProjection.ProjectRowsAsync( + context, + context.workOrders.AsNoTracking().Where(w => w.Id == 5), + isUnscheduled: true); + var legacyCompletedDisplay = WorkOrderBoardService.MapRawRow(Assert.Single(legacyCompletedRows), DateTime.UtcNow); + var currentActiveNameMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Current Active Name" }) .Select(w => w.Id) @@ -102,6 +131,22 @@ public sealed class WorkOrderServiceRegistryFilterRelationalTests .Select(w => w.Id) .ToListAsync(); + var completedSnapshotMatches = await WorkOrderBoardQueryFilters + .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Completed Archive Alpha" }) + .Select(w => w.Id) + .ToListAsync(); + + var legacyCompletedSnapshotMatches = await WorkOrderBoardQueryFilters + .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Completed Archive Beta" }) + .Select(w => w.Id) + .ToListAsync(); + + var currentNameAliasMatches = await WorkOrderBoardQueryFilters + .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Current Active Name" }) + .Select(w => w.Id) + .OrderBy(id => id) + .ToListAsync(); + var legacyTradeMatches = await WorkOrderBoardQueryFilters .ApplyPmTypeFilter(context.workOrders.AsNoTracking(), new[] { "Legacy Cooling" }) .Select(w => w.Id) @@ -117,9 +162,14 @@ public sealed class WorkOrderServiceRegistryFilterRelationalTests $"active-display={activeDisplay.Pm}", $"inactive-display={inactiveDisplay.Pm}", $"legacy-display={legacyDisplay.Pm}", + $"completed-display={completedDisplay.Pm}", + $"legacy-completed-display={legacyCompletedDisplay.Pm}", $"active-filter={string.Join(',', currentActiveNameMatches)}", $"inactive-snapshot-filter={string.Join(',', historicalInactiveNameMatches)}", $"inactive-current-name-filter={string.Join(',', inactiveRegistryNameMatches)}", + $"completed-snapshot-filter={string.Join(',', completedSnapshotMatches)}", + $"legacy-completed-snapshot-filter={string.Join(',', legacyCompletedSnapshotMatches)}", + $"current-name-alias-filter={string.Join(',', currentNameAliasMatches)}", $"legacy-trade-filter={string.Join(',', legacyTradeMatches)}", $"legacy-problem-filter={string.Join(',', legacyProblemMatches)}" }); @@ -128,9 +178,14 @@ public sealed class WorkOrderServiceRegistryFilterRelationalTests "active-display=Current Active Name", "inactive-display=Historical Inactive Name", "legacy-display=Legacy Cooling", - "active-filter=1", + "completed-display=Completed Archive Alpha", + "legacy-completed-display=Completed Archive Beta", + "active-filter=1,4,5", "inactive-snapshot-filter=2", "inactive-current-name-filter=2", + "completed-snapshot-filter=4", + "legacy-completed-snapshot-filter=5", + "current-name-alias-filter=1,4,5", "legacy-trade-filter=3", "legacy-problem-filter=3" });