shoc-backend/SeaHavenIndustries.Tests/WorkOrderTechnicianAssignmentRelationalTests.cs

217 lines
8.7 KiB
C#
Raw Permalink Normal View History

using Data.SeaHavenIndustries;
using Data.SeaHavenIndustries.Enums;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using SeaHaven.DataServices.Helpers;
using SeaHaven.DataServices.Implementation;
using SeaHaven.Services.DTOs;
using SeaHaven.Services.Helpers;
using SeaHaven.Services.Implementation;
namespace SeaHavenIndustries.Tests;
public class WorkOrderTechnicianAssignmentRelationalTests
{
[Fact]
public async Task ClearingTechnicianOnOneWorkOrder_PreservesSharedDispatchAndSiblingSelectionAfterReload()
{
await using var connection = new SqliteConnection("Data Source=:memory:;Foreign Keys=True");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseSqlite(connection)
.Options;
byte[] workOrderVersion = { 1, 0, 0, 0, 0, 0, 0, 1 };
byte[] dispatchVersion = { 1, 0, 0, 0, 0, 0, 0, 2 };
await using (var seed = new SqliteBoardTestDbContext(options))
{
await seed.Database.EnsureCreatedAsync();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(seed);
seed.Users.Add(new ApplicationUser
{
Id = "actor-1",
UserName = "actor-1",
NormalizedUserName = "ACTOR-1",
Email = "actor@test.local",
NormalizedEmail = "ACTOR@TEST.LOCAL"
});
seed.Vendors.Add(new Vendor
{
Id = 5,
CompanyName = "Acme HVAC",
ContactName = "Technician One",
CompanyPhone = "312-555-0100"
});
await seed.SaveChangesAsync();
var dispatch = new Dispatch
{
Id = 10,
VendorId = 5,
Status = "Sent",
TechPhone = "312-555-0199",
RowVersion = dispatchVersion
};
seed.Dispatches.Add(dispatch);
seed.workOrders.AddRange(
new WorkOrder
{
Id = 1,
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
ScheduledDate = new DateTime(2026, 9, 30),
PrimaryDispatchId = 10,
TechnicianAssigned = true,
RowVersion = workOrderVersion
},
new WorkOrder
{
Id = 2,
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
ScheduledDate = new DateTime(2026, 9, 30),
PrimaryDispatchId = 10,
RowVersion = new byte[] { 2, 0, 0, 0, 0, 0, 0, 1 }
});
await seed.SaveChangesAsync();
dispatch.WorkOrderId = 1;
seed.DispatchWorkOrders.Add(new DispatchWorkOrder { Id = 20, DispatchId = 10, WorkOrderId = 2 });
await seed.SaveChangesAsync();
}
await using (var context = new SqliteBoardTestDbContext(options))
{
var fieldLocks = new WorkOrderFieldLockService(new WorkOrderFieldLockDataService(context));
var audit = new WorkOrderAuditService(new WorkOrderAuditDataService(context), fieldLocks);
var service = WorkOrderAccountTestHelpers.BoardUpdateService(context, audit);
var updated = await service.PatchFieldAsync(1, new WorkOrderBoardPatchRequestDto
{
Field = WorkOrderBoardFieldNames.VendorId,
Value = "5",
TechnicianAssigned = false,
WorkOrderVersion = Convert.ToBase64String(workOrderVersion),
DispatchVersion = Convert.ToBase64String(dispatchVersion),
PrimaryDispatchId = 10
}, "actor-1");
Assert.False(updated.TechnicianAssigned);
Assert.Equal(10, updated.PrimaryDispatchId);
}
await using var verify = new SqliteBoardTestDbContext(options);
var data = new WorkOrderBoardDataService(verify);
var workOrderA = Assert.IsType<SeaHaven.DataServices.Interfaces.WorkOrderBoardRawRow>(
await data.GetBoardRowByIdAsync(1));
var workOrderB = Assert.IsType<SeaHaven.DataServices.Interfaces.WorkOrderBoardRawRow>(
await data.GetBoardRowByIdAsync(2));
Assert.False(workOrderA.TechnicianAssigned);
Assert.Null(workOrderA.TechName);
Assert.Null(workOrderA.TechPhone);
Assert.Equal("Technician One", workOrderB.TechName);
Assert.Equal("312-555-0199", workOrderB.TechPhone);
Assert.Equal(10, workOrderA.PrimaryDispatchId);
Assert.Equal(10, workOrderB.PrimaryDispatchId);
Assert.Equal(5, workOrderA.VendorId);
Assert.Equal(5, workOrderB.VendorId);
}
[Fact]
public async Task TechnicianNameSearch_MatchesLegacyAndAssignedRows_ButNotExplicitlyClearedRow()
{
await using var connection = new SqliteConnection("Data Source=:memory:;Foreign Keys=True");
await connection.OpenAsync();
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
.UseSqlite(connection)
.Options;
await using (var seed = new SqliteBoardTestDbContext(options))
{
await seed.Database.EnsureCreatedAsync();
await WorkOrderAccountTestHelpers.EnsureAccountAsync(seed);
seed.Vendors.Add(new Vendor
{
Id = 5,
CompanyName = "Acme HVAC",
ContactName = "Technician One",
CompanyPhone = "312-555-0100"
});
seed.Dispatches.AddRange(
new Dispatch { Id = 10, VendorId = 5, Status = "Sent", RowVersion = new byte[] { 1, 0, 0, 0, 0, 0, 0, 2 } },
new Dispatch { Id = 11, VendorId = 5, Status = "Sent", RowVersion = new byte[] { 2, 0, 0, 0, 0, 0, 0, 2 } },
new Dispatch { Id = 12, VendorId = 5, Status = "Sent", RowVersion = new byte[] { 3, 0, 0, 0, 0, 0, 0, 2 } });
seed.workOrders.AddRange(
new WorkOrder
{
Id = 1,
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
PrimaryDispatchId = 10,
TechnicianAssigned = null,
RowVersion = new byte[] { 1, 0, 0, 0, 0, 0, 0, 1 }
},
new WorkOrder
{
Id = 2,
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
PrimaryDispatchId = 11,
TechnicianAssigned = true,
RowVersion = new byte[] { 2, 0, 0, 0, 0, 0, 0, 1 }
},
new WorkOrder
{
Id = 3,
AccountId = 1,
LifecycleStatus = LifecycleStatus.Scheduled,
PrimaryDispatchId = 12,
TechnicianAssigned = false,
RowVersion = new byte[] { 3, 0, 0, 0, 0, 0, 0, 1 }
});
await seed.SaveChangesAsync();
}
await using var context = new SqliteBoardTestDbContext(options);
var technicianMatches = await WorkOrderBoardSearchFilter
.Apply(context.workOrders.AsQueryable(), "Technician One")
.Select(w => w.Id)
.OrderBy(id => id)
.ToListAsync();
Assert.Equal(new[] { 1, 2 }, technicianMatches);
var companyMatches = await WorkOrderBoardSearchFilter
.Apply(context.workOrders.AsQueryable(), "Acme HVAC")
.Select(w => w.Id)
.OrderBy(id => id)
.ToListAsync();
Assert.Equal(new[] { 1, 2, 3 }, companyMatches);
}
private sealed class SqliteBoardTestDbContext : ApplicationDbContext
{
public SqliteBoardTestDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
foreach (var index in builder.Model.GetEntityTypes().SelectMany(entity => entity.GetIndexes()))
{
if (index.GetFilter() != null)
index.SetFilter(null);
}
foreach (var entityType in new[] { typeof(WorkOrder), typeof(Dispatch) })
{
var property = builder.Entity(entityType).Property("RowVersion").Metadata;
property.ValueGenerated = Microsoft.EntityFrameworkCore.Metadata.ValueGenerated.Never;
property.IsConcurrencyToken = false;
}
}
}
}