mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 09:33:13 +00:00
180 lines
6 KiB
C#
180 lines
6 KiB
C#
using Data.SeaHavenIndustries;
|
|
using Data.SeaHavenIndustries.Enums;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using SeaHaven.DataServices.Implementation;
|
|
using SeaHaven.Services.DTOs;
|
|
using SeaHaven.Services.Exceptions;
|
|
using SeaHaven.Services.Implementation;
|
|
using SeaHaven.Services.Validation;
|
|
|
|
namespace SeaHavenIndustries.Tests;
|
|
|
|
public class WorkOrderBoardCreateServiceTests
|
|
{
|
|
private static (ApplicationDbContext Context, WorkOrderBoardCreateService Service) CreateSut()
|
|
{
|
|
var options = new DbContextOptionsBuilder<ApplicationDbContext>()
|
|
.UseInMemoryDatabase(Guid.NewGuid().ToString())
|
|
.Options;
|
|
var context = new ApplicationDbContext(options);
|
|
var boardData = new WorkOrderBoardDataService(context);
|
|
var boardService = new WorkOrderBoardService(boardData);
|
|
var fieldLocks = new WorkOrderFieldLockService(context);
|
|
var audit = new WorkOrderAuditService(context, fieldLocks);
|
|
var validator = new WorkOrderBoardCreateValidation();
|
|
var service = new WorkOrderBoardCreateService(context, boardData, boardService, audit, validator);
|
|
return (context, service);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_Minimal_ReturnsIncomplete()
|
|
{
|
|
var (_, service) = CreateSut();
|
|
|
|
var result = await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5"
|
|
}, "actor-1");
|
|
|
|
Assert.Equal(LifecycleStatus.Incomplete, result.LifecycleStatus);
|
|
Assert.Equal("BK5", result.SiteCode);
|
|
Assert.Equal(WorkOrderType.PM, result.WorkOrderType);
|
|
Assert.False(string.IsNullOrWhiteSpace(result.WoNumber));
|
|
Assert.Equal(11, result.WoNumber!.Length);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_WithManualWoNumber_NormalizesTo11Digits()
|
|
{
|
|
var (_, service) = CreateSut();
|
|
|
|
var result = await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WoNumber = "12345",
|
|
WorkOrderType = WorkOrderType.PO,
|
|
SiteCode = "DAL"
|
|
}, "actor-1");
|
|
|
|
Assert.Equal("00000012345", result.WoNumber);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_DuplicateWoNumber_Throws()
|
|
{
|
|
var (context, service) = CreateSut();
|
|
context.workOrders.Add(new WorkOrder { InternalWONumber = "00000099999", WorkerOrderNumber = "00000099999" });
|
|
await context.SaveChangesAsync();
|
|
|
|
var ex = await Assert.ThrowsAsync<WorkOrderBoardValidationException>(() =>
|
|
service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WoNumber = "99999",
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5"
|
|
}, "actor-1"));
|
|
|
|
Assert.Equal("DuplicateWoNumber", ex.Code);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_AutoSchedulesWhenDateAndAssignee()
|
|
{
|
|
var (_, service) = CreateSut();
|
|
|
|
var result = await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5",
|
|
AssignTo = "dispatcher-1",
|
|
ScheduledDate = new DateTime(2026, 6, 25)
|
|
}, "actor-1");
|
|
|
|
Assert.Equal(LifecycleStatus.Scheduled, result.LifecycleStatus);
|
|
Assert.Equal(new DateTime(2026, 6, 25), result.ScheduledDate);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_WeekOnlyScheduling_SetsTargetWeek()
|
|
{
|
|
var (_, service) = CreateSut();
|
|
|
|
var result = await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5",
|
|
ScheduleWeekOnly = true,
|
|
TargetWeek = new DateOnly(2026, 6, 22)
|
|
}, "actor-1");
|
|
|
|
Assert.True(result.ScheduleWeekOnly);
|
|
Assert.Equal(new DateOnly(2026, 6, 22), result.TargetWeek);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_WeekOnlyWithoutTargetWeek_ThrowsValidation()
|
|
{
|
|
var (_, service) = CreateSut();
|
|
|
|
await Assert.ThrowsAsync<FluentValidation.ValidationException>(() =>
|
|
service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5",
|
|
ScheduleWeekOnly = true
|
|
}, "actor-1"));
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_WithVendor_CreatesPrimaryDispatch()
|
|
{
|
|
var (context, service) = CreateSut();
|
|
context.Vendors.Add(new Vendor { Id = 5, CompanyName = "Acme HVAC" });
|
|
await context.SaveChangesAsync();
|
|
|
|
var result = await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5",
|
|
VendorId = 5,
|
|
ApptDate = new DateTime(2026, 6, 26)
|
|
}, "actor-1");
|
|
|
|
Assert.Equal(5, result.VendorId);
|
|
Assert.NotNull(result.PrimaryDispatchId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_CreatesFieldLocksForPopulatedFields()
|
|
{
|
|
var (context, service) = CreateSut();
|
|
|
|
await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5",
|
|
Description = "Test WO"
|
|
}, "actor-1");
|
|
|
|
var locks = await context.WorkOrderFieldLocks.ToListAsync();
|
|
Assert.Contains(locks, l => l.FieldName == "SiteCode");
|
|
Assert.Contains(locks, l => l.FieldName == "WorkOrderType");
|
|
Assert.Contains(locks, l => l.FieldName == "Description");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task Create_WritesCreateAuditEvent()
|
|
{
|
|
var (context, service) = CreateSut();
|
|
|
|
await service.CreateAsync(new WorkOrderBoardCreateRequestDto
|
|
{
|
|
WorkOrderType = WorkOrderType.PM,
|
|
SiteCode = "BK5"
|
|
}, "actor-1");
|
|
|
|
var logs = await context.WorkOrderAuditLogs.ToListAsync();
|
|
Assert.Contains(logs, l => l.Action == "Create");
|
|
Assert.Contains(logs, l => l.Action == "FieldChanged" && l.FieldName == "SiteCode");
|
|
}
|
|
}
|