shoc-backend/SeaHaven.Services/Helpers/WorkOrderBoardFieldMutations.cs

122 lines
5.5 KiB
C#

using Data.SeaHavenIndustries;
using Data.SeaHavenIndustries.Enums;
using SeaHaven.Services.Exceptions;
namespace SeaHaven.Services.Helpers
{
public static class WorkOrderBoardFieldMutations
{
public static List<BoardFieldChange> ApplyAssignTo(WorkOrder workOrder, string? value, string auditField = "AssignTo")
{
var normalized = string.IsNullOrWhiteSpace(value) ? null : value.Trim();
var old = workOrder.AssignTo;
var changes = new List<BoardFieldChange>();
if (old != normalized)
{
workOrder.AssignTo = normalized;
changes.Add(BoardFieldChange.AssignmentChanged(auditField, old, normalized));
}
changes.AddRange(ApplyAutoScheduleSideEffects(workOrder));
return changes;
}
public static List<BoardFieldChange> ApplyScheduledDate(
WorkOrder workOrder,
DateTime? parsed,
string auditField = "ScheduledDate",
bool incrementRescheduleOnChange = true)
{
var previousDate = workOrder.ScheduledDate;
var changes = new List<BoardFieldChange>();
var oldFormatted = FormatDate(previousDate);
var newFormatted = FormatDate(parsed);
if (oldFormatted == newFormatted)
return changes;
workOrder.ScheduledDate = parsed;
changes.Add(BoardFieldChange.Changed(auditField, oldFormatted, newFormatted));
if (!workOrder.OriginalDate.HasValue && parsed.HasValue)
{
workOrder.OriginalDate = DateOnly.FromDateTime(parsed.Value);
var originalWeek = WorkOrderBoardMutationRules.ComputeOriginalWeek(parsed);
if (originalWeek.HasValue)
workOrder.OriginalWeek = originalWeek;
}
if (incrementRescheduleOnChange && WorkOrderBoardMutationRules.IsReschedule(previousDate, parsed))
{
var oldCount = workOrder.RescheduleCount.ToString();
workOrder.RescheduleCount++;
changes.Add(BoardFieldChange.Changed(
WorkOrderBoardFieldNames.RescheduleCount,
oldCount,
workOrder.RescheduleCount.ToString()));
}
changes.AddRange(ApplyAutoScheduleSideEffects(workOrder));
return changes;
}
public static List<BoardFieldChange> ApplyAutoScheduleSideEffects(WorkOrder workOrder)
=> WorkOrderDerivedFields.ApplyLifecycleFromSchedule(workOrder);
public static BoardFieldChange ApplyApptTime(WorkOrder workOrder, Dispatch dispatch, string? value)
{
if (!WorkOrderBoardApptTimeParser.TryParse(value, out var start, out var end, out var error))
throw new WorkOrderBoardValidationException("InvalidValue", error ?? "Invalid apptTime.");
var apptDate = dispatch.ScheduledDate ?? workOrder.ScheduledDate;
var oldStart = FormatDateTime(workOrder.ScheduledStart);
var oldEnd = FormatDateTime(workOrder.ScheduledEnd);
workOrder.ScheduledStart = WorkOrderBoardApptTimeParser.ToScheduledInstant(apptDate, start);
workOrder.ScheduledEnd = WorkOrderBoardApptTimeParser.ToScheduledInstant(apptDate, end);
var newStart = FormatDateTime(workOrder.ScheduledStart);
var newEnd = FormatDateTime(workOrder.ScheduledEnd);
var oldCombined = FormatApptRange(oldStart, oldEnd);
var newCombined = FormatApptRange(newStart, newEnd);
if (oldCombined == newCombined)
return BoardFieldChange.Unchanged("ApptTime", dispatch.Id);
return BoardFieldChange.Changed("ApptTime", oldCombined, newCombined, dispatch.Id);
}
public static void SetInitialLifecycleStatus(WorkOrder workOrder)
{
workOrder.LifecycleStatus = LifecycleStatus.Incomplete;
workOrder.Status = WorkOrderDerivedFields.GetLifecycleStatusLabel(LifecycleStatus.Incomplete);
}
private static string? FormatDate(DateTime? value) => value?.ToString("yyyy-MM-dd");
private static string? FormatDateTime(DateTime? value) => value?.ToString("O");
private static string? FormatApptRange(string? start, string? end)
=> start == null && end == null ? null : $"{start}|{end}";
public sealed record BoardFieldChange(
string FieldName,
string? OldValue,
string? NewValue,
AuditActionType Action,
int? DispatchId,
bool HasChanged)
{
public static BoardFieldChange Unchanged(string fieldName, int? dispatchId = null)
=> new(fieldName, null, null, AuditActionType.FieldChanged, dispatchId, false);
public static BoardFieldChange Changed(string fieldName, string? oldValue, string? newValue, int? dispatchId = null)
=> new(fieldName, oldValue, newValue, AuditActionType.FieldChanged, dispatchId, true);
public static BoardFieldChange StatusChanged(string fieldName, string? oldValue, string? newValue)
=> new(fieldName, oldValue, newValue, AuditActionType.StatusChanged, null, true);
public static BoardFieldChange AssignmentChanged(string fieldName, string? oldValue, string? newValue)
=> new(fieldName, oldValue, newValue, AuditActionType.AssignmentChanged, null, true);
}
}
}