feat(work-orders): add lifecycle, type mappers and derived field rules

This commit is contained in:
Arthur Bassi 2026-06-30 13:20:42 -03:00
parent 623810da45
commit 187d935da2
2 changed files with 103 additions and 0 deletions

View file

@ -0,0 +1,55 @@
using Data.SeaHavenIndustries;
using Data.SeaHavenIndustries.Enums;
namespace SeaHaven.Services.Helpers
{
public static class WorkOrderDerivedFields
{
/// <summary>
/// Past due overlay — never a WorkOrderType. Matches SHOC board design.
/// </summary>
public static bool IsPastDue(WorkOrder workOrder, DateOnly? asOf = null)
{
var today = asOf ?? DateOnly.FromDateTime(DateTime.UtcNow);
if (workOrder.ScheduledDate == null)
return false;
if (LifecycleStatusMapper.IsTerminal(workOrder.LifecycleStatus))
return false;
return DateOnly.FromDateTime(workOrder.ScheduledDate.Value.Date) < today;
}
/// <summary>
/// Sets initial lifecycle on create. New WOs start Incomplete unless auto-scheduled.
/// </summary>
public static void SetInitialLifecycleStatus(WorkOrder workOrder)
{
workOrder.LifecycleStatus ??= LifecycleStatus.Incomplete;
ApplyAutoScheduleIfEligible(workOrder);
}
/// <summary>
/// SHOC rule: specific scheduled date + assignee + Incomplete → Scheduled.
/// Week-only targets do not auto-schedule.
/// </summary>
public static bool ApplyAutoScheduleIfEligible(WorkOrder workOrder)
{
if (workOrder.LifecycleStatus != LifecycleStatus.Incomplete)
return false;
if (workOrder.ScheduleWeekOnly == true)
return false;
if (workOrder.ScheduledDate == null)
return false;
if (string.IsNullOrWhiteSpace(workOrder.AssignTo))
return false;
workOrder.LifecycleStatus = LifecycleStatus.Scheduled;
return true;
}
}
}

View file

@ -0,0 +1,48 @@
using Data.SeaHavenIndustries.Enums;
namespace SeaHaven.Services.Helpers
{
public static class WorkOrderTypeMapper
{
/// <summary>Board FE types. Overdue is not a type — use <see cref="WorkOrderDerivedFields.IsPastDue"/>.</summary>
public static bool TryParseFeLabel(string? label, out WorkOrderType type)
{
type = default;
if (string.IsNullOrWhiteSpace(label)) return false;
return label.Trim().ToLowerInvariant() switch
{
"pm" => Set(WorkOrderType.PM, out type),
"reactive" => Set(WorkOrderType.Reactive, out type),
"emergency" => Set(WorkOrderType.Emergency, out type),
"add-on" or "addon" => Set(WorkOrderType.AddOn, out type),
"po" => Set(WorkOrderType.PO, out type),
"project" => Set(WorkOrderType.Project, out type),
"inspection" => Set(WorkOrderType.Inspection, out type),
"other" => Set(WorkOrderType.Other, out type),
"overdue" => false,
_ => Enum.TryParse(label, true, out type)
};
}
public static string ToFeLabel(WorkOrderType type) => type switch
{
WorkOrderType.PM => "PM",
WorkOrderType.Reactive => "Reactive",
WorkOrderType.Emergency => "Emergency",
WorkOrderType.AddOn => "Add-On",
WorkOrderType.PO => "PO",
WorkOrderType.Project => "Project",
WorkOrderType.Inspection => "Inspection",
WorkOrderType.Other => "Other",
_ => type.ToString()
};
private static bool Set(WorkOrderType value, out WorkOrderType type)
{
type = value;
return true;
}
}
}