using Data.SeaHavenIndustries; using Data.SeaHavenIndustries.Enums; using Microsoft.EntityFrameworkCore; using SeaHaven.DataServices.Implementation; using SeaHaven.Services.Constants; using SeaHaven.Services.DTOs; using SeaHaven.Services.Helpers; using SeaHaven.Services.Implementation; namespace SeaHavenIndustries.Tests; public class WorkOrderCompletionFreezeTests { [Fact] public async Task FirstCompletedTransitionCapturesSnapshotAndLaterPatchKeepsIt() { await using var context = CreateContext(); var service = CreateService(context); var location = new Locations { Id = 10, Name = "BK5 Chicago", Address1 = "100 Main St", City = "Chicago", State = "IL", Zip = "60601", PhoneNumber = "312-555-0100", Email = "site@example.com" }; var vendor = new Vendor { Id = 20, CompanyName = "Frozen Vendor", ContactName = "Frozen Tech", Address = "200 Vendor Ave", City = "Chicago", State = "IL", Zip = "60602", CompanyPhone = "312-555-0200", Email = "vendor@example.com" }; var contact = new Contacts { Id = 30, FirstName = "Frozen", LastName = "POC", PhoneNumber = "312-555-0300" }; var dispatch = new Dispatch { Id = 40, WorkOrderId = 1, VendorId = vendor.Id, Vendor = vendor, Status = "Sent" }; var workOrder = new WorkOrder { Id = 1, InternalWONumber = "00000012345", SiteCode = "BK5", LocationId = location.Id, Locations = location, LifecycleStatus = LifecycleStatus.Scheduled, ScheduledDate = DateTime.UtcNow.Date.AddDays(1), PrimaryDispatchId = dispatch.Id, PrimaryDispatch = dispatch, PocNotes = "Call first", AdditionalContacts = """[{"name":"Backup","phone":"312-555-0400"}]""", RowVersion = Version() }; var workOrderContact = new WorkOrderContacts { Id = 50, WorkorderId = workOrder.Id, WorkOrder = workOrder, ContactId = contact.Id, POC = contact }; workOrder.WorkOrderContacts = new[] { workOrderContact }; context.AddRange(location, vendor, contact, dispatch, workOrder, workOrderContact); await context.SaveChangesAsync(); var completed = await service.PatchFieldAsync( workOrder.Id, Patch(WorkOrderBoardFieldNames.LifecycleStatus, "Complete", workOrder), "actor-1"); var persisted = await context.workOrders.SingleAsync(); var frozenSiteJson = persisted.FrozenSite; var frozenCompanyJson = persisted.FrozenCompany; var frozenPocJson = persisted.FrozenPoc; Assert.Equal(LifecycleStatus.Completed, completed.LifecycleStatus); Assert.Equal("BK5 Chicago", completed.LocationName); Assert.Equal("Frozen Vendor", completed.VendorName); Assert.Equal("Frozen POC", completed.PocName); Assert.Equal("Chicago", completed.FrozenSite?.City); Assert.Equal("Frozen Vendor", completed.FrozenCompany?.Name); Assert.Equal(2, completed.FrozenPoc?.Contacts.Count); location.Name = "Changed Site"; location.City = "Milwaukee"; vendor.CompanyName = "Changed Vendor"; contact.FirstName = "Changed"; await context.SaveChangesAsync(); var afterFlag = await service.PatchFieldAsync( workOrder.Id, Patch(WorkOrderBoardFieldNames.FlagColor, "#EF4444", persisted), "actor-1"); Assert.Equal(frozenSiteJson, persisted.FrozenSite); Assert.Equal(frozenCompanyJson, persisted.FrozenCompany); Assert.Equal(frozenPocJson, persisted.FrozenPoc); Assert.Equal("BK5 Chicago", afterFlag.LocationName); Assert.Equal("Frozen Vendor", afterFlag.VendorName); Assert.Equal("Frozen POC", afterFlag.PocName); } [Fact] public async Task FirstCompletedTransitionWithoutSiteStillCapturesAvailableSnapshot() { await using var context = CreateContext(); var service = CreateService(context); var workOrder = new WorkOrder { Id = 1, InternalWONumber = "00000012345", SiteCode = "BK5", LifecycleStatus = LifecycleStatus.Scheduled, ScheduledDate = DateTime.UtcNow.Date.AddDays(1), RowVersion = Version() }; context.Add(workOrder); await context.SaveChangesAsync(); var completed = await service.PatchFieldAsync( workOrder.Id, Patch(WorkOrderBoardFieldNames.LifecycleStatus, "Complete", workOrder), "actor-1"); var persisted = await context.workOrders.SingleAsync(); Assert.Equal(LifecycleStatus.Completed, completed.LifecycleStatus); Assert.Equal("BK5", completed.FrozenSite?.Code); Assert.Equal("BK5", completed.FrozenSite?.Label); Assert.Null(completed.FrozenSite?.City); Assert.Null(completed.FrozenCompany); Assert.False(string.IsNullOrWhiteSpace(persisted.FrozenSite)); Assert.Null(persisted.FrozenCompany); } [Fact] public async Task OpenWorkOrderProjectionKeepsUsingLiveLocation() { await using var context = CreateContext(); var location = new Locations { Id = 10, Name = "Live Site", City = "Chicago" }; var workOrder = new WorkOrder { Id = 1, SiteCode = "BK5", LocationId = location.Id, Locations = location, LifecycleStatus = LifecycleStatus.Scheduled, ScheduledDate = DateTime.UtcNow.Date.AddDays(1), FrozenSite = """{"code":"BK5","label":"Frozen Site","city":"Old City"}""", RowVersion = Version() }; context.AddRange(location, workOrder); await context.SaveChangesAsync(); var raw = await new WorkOrderBoardDataService(context).GetBoardRowByIdAsync(workOrder.Id); var dto = WorkOrderBoardService.MapRawRow(Assert.IsType(raw), DateTime.UtcNow); Assert.Equal("Live Site", dto.LocationName); Assert.Null(dto.FrozenSite); } private static ApplicationDbContext CreateContext() { var options = new DbContextOptionsBuilder() .UseInMemoryDatabase(Guid.NewGuid().ToString()) .Options; return new ApplicationDbContext(options); } private static WorkOrderBoardUpdateService CreateService(ApplicationDbContext context) { var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context)); return WorkOrderAccountTestHelpers.BoardUpdateService( context, new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks)); } private static WorkOrderBoardPatchRequestDto Patch( string field, string value, WorkOrder workOrder) => new() { Field = field, Value = value, WorkOrderVersion = Convert.ToBase64String(workOrder.RowVersion ?? Version()) }; private static byte[] Version() => new byte[] { 1, 0, 0, 0, 0, 0, 0, 1 }; }