mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 06:03:12 +00:00
feat(work-orders): apply schedule lifecycle promote and demote
This commit is contained in:
parent
335390f746
commit
e12b3ea54b
2 changed files with 87 additions and 22 deletions
|
|
@ -50,25 +50,50 @@ namespace SeaHaven.Services.Helpers
|
|||
}
|
||||
|
||||
/// <summary>
|
||||
/// SHOC rule: specific scheduled date + assignee + Incomplete → Scheduled.
|
||||
/// Week-only targets do not auto-schedule.
|
||||
/// Promote Incomplete/Pending to Scheduled, or demote Scheduled to Pending, from Schedule On.
|
||||
/// Assignee is not required. Week-only is not a concrete date.
|
||||
/// </summary>
|
||||
public static List<WorkOrderBoardFieldMutations.BoardFieldChange> ApplyLifecycleFromSchedule(WorkOrder workOrder)
|
||||
{
|
||||
var changes = new List<WorkOrderBoardFieldMutations.BoardFieldChange>();
|
||||
LifecycleStatus? next = null;
|
||||
if (WorkOrderBoardMutationRules.ShouldPromoteToScheduled(
|
||||
workOrder.LifecycleStatus,
|
||||
workOrder.ScheduledDate,
|
||||
workOrder.ScheduleWeekOnly))
|
||||
{
|
||||
next = LifecycleStatus.Scheduled;
|
||||
}
|
||||
else if (WorkOrderBoardMutationRules.ShouldDemoteFromScheduled(
|
||||
workOrder.LifecycleStatus,
|
||||
workOrder.ScheduledDate,
|
||||
workOrder.ScheduleWeekOnly))
|
||||
{
|
||||
next = LifecycleStatus.Pending;
|
||||
}
|
||||
|
||||
if (next == null || workOrder.LifecycleStatus == next)
|
||||
return changes;
|
||||
|
||||
var old = workOrder.LifecycleStatus?.ToString();
|
||||
workOrder.LifecycleStatus = next;
|
||||
workOrder.Status = GetLifecycleStatusLabel(next);
|
||||
changes.Add(WorkOrderBoardFieldMutations.BoardFieldChange.StatusChanged(
|
||||
"LifecycleStatus",
|
||||
old,
|
||||
next.Value.ToString()));
|
||||
return changes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies schedule-driven lifecycle (promote or demote). True when the row becomes Scheduled.
|
||||
/// </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;
|
||||
var before = workOrder.LifecycleStatus;
|
||||
ApplyLifecycleFromSchedule(workOrder);
|
||||
return before != LifecycleStatus.Scheduled
|
||||
&& workOrder.LifecycleStatus == LifecycleStatus.Scheduled;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -83,19 +83,48 @@ public class WorkOrderDerivedFieldsTests
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyAutoSchedule_WhenDateAndAssignee_PromotesToScheduled()
|
||||
public void ApplyAutoSchedule_WhenDateWithoutAssignee_PromotesToScheduled()
|
||||
{
|
||||
var wo = new WorkOrder
|
||||
{
|
||||
LifecycleStatus = LifecycleStatus.Incomplete,
|
||||
ScheduledDate = new DateTime(2026, 6, 25),
|
||||
AssignTo = "dispatcher-1"
|
||||
ScheduledDate = new DateTime(2026, 6, 25)
|
||||
};
|
||||
|
||||
Assert.True(WorkOrderDerivedFields.ApplyAutoScheduleIfEligible(wo));
|
||||
Assert.Equal(LifecycleStatus.Scheduled, wo.LifecycleStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyLifecycleFromSchedule_PendingWithDate_PromotesToScheduled()
|
||||
{
|
||||
var wo = new WorkOrder
|
||||
{
|
||||
LifecycleStatus = LifecycleStatus.Pending,
|
||||
ScheduledDate = new DateTime(2026, 6, 25)
|
||||
};
|
||||
|
||||
var changes = WorkOrderDerivedFields.ApplyLifecycleFromSchedule(wo);
|
||||
Assert.Equal(LifecycleStatus.Scheduled, wo.LifecycleStatus);
|
||||
Assert.Single(changes);
|
||||
Assert.Equal(AuditActionType.StatusChanged, changes[0].Action);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyLifecycleFromSchedule_ScheduledWithoutDate_DemotesToPending()
|
||||
{
|
||||
var wo = new WorkOrder
|
||||
{
|
||||
LifecycleStatus = LifecycleStatus.Scheduled,
|
||||
ScheduledDate = null
|
||||
};
|
||||
|
||||
var changes = WorkOrderDerivedFields.ApplyLifecycleFromSchedule(wo);
|
||||
Assert.Equal(LifecycleStatus.Pending, wo.LifecycleStatus);
|
||||
Assert.Single(changes);
|
||||
Assert.Equal(LifecycleStatus.Pending.ToString(), changes[0].NewValue);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyAutoSchedule_WeekOnly_DoesNotPromote()
|
||||
{
|
||||
|
|
@ -103,7 +132,6 @@ public class WorkOrderDerivedFieldsTests
|
|||
{
|
||||
LifecycleStatus = LifecycleStatus.Incomplete,
|
||||
ScheduledDate = new DateTime(2026, 6, 25),
|
||||
AssignTo = "dispatcher-1",
|
||||
ScheduleWeekOnly = true,
|
||||
TargetWeek = new DateOnly(2026, 6, 22)
|
||||
};
|
||||
|
|
@ -112,13 +140,25 @@ public class WorkOrderDerivedFieldsTests
|
|||
Assert.Equal(LifecycleStatus.Incomplete, wo.LifecycleStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ApplyLifecycleFromSchedule_InProgress_UnchangedWhenDateCleared()
|
||||
{
|
||||
var wo = new WorkOrder
|
||||
{
|
||||
LifecycleStatus = LifecycleStatus.InProgress,
|
||||
ScheduledDate = null
|
||||
};
|
||||
|
||||
Assert.Empty(WorkOrderDerivedFields.ApplyLifecycleFromSchedule(wo));
|
||||
Assert.Equal(LifecycleStatus.InProgress, wo.LifecycleStatus);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetInitialLifecycleStatus_NewWo_StartsIncompleteThenAutoSchedules()
|
||||
{
|
||||
var wo = new WorkOrder
|
||||
{
|
||||
ScheduledDate = new DateTime(2026, 6, 25),
|
||||
AssignTo = "dispatcher-1"
|
||||
ScheduledDate = new DateTime(2026, 6, 25)
|
||||
};
|
||||
|
||||
WorkOrderDerivedFields.SetInitialLifecycleStatus(wo);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue