diff --git a/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs b/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs
index 01dcc0e..13c7751 100644
--- a/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs
+++ b/Api.SeaHavenIndustries/Controllers/WorkOrderController.cs
@@ -22,7 +22,7 @@ using SeaHaven.DataServices.Interfaces;
namespace Api.SeaHavenIndustries.Controllers
{
- // [Authorize]
+ [Authorize]
[ApiController]
[Route("api/WorkOrder")]
[Route("api/workorders")]
diff --git a/Data.SeaHavenIndustries/Enums/WorkOrderEnums.cs b/Data.SeaHavenIndustries/Enums/WorkOrderEnums.cs
index 65fcb06..dabc6a2 100644
--- a/Data.SeaHavenIndustries/Enums/WorkOrderEnums.cs
+++ b/Data.SeaHavenIndustries/Enums/WorkOrderEnums.cs
@@ -10,21 +10,22 @@ namespace Data.SeaHavenIndustries.Enums
OnHold = 5
}
- /// 10 operational lifecycle values aligned with SHOC board.
+ /// 10 operational lifecycle values aligned with SHOC board (FE labels).
public enum LifecycleStatus
{
Incomplete = 1,
- Scheduled = 2,
- InProgress = 3,
- Complete = 4,
- Canceled = 5,
- OnHold = 6,
- PendingVendor = 7,
- PendingApproval = 8,
- NeedsReview = 9,
- Closed = 10
+ Pending = 2,
+ Scheduled = 3,
+ EnRoute = 4,
+ OnSite = 5,
+ InProgress = 6,
+ Completed = 7,
+ Rescheduled = 8,
+ Canceled = 9,
+ PendingQuote = 10
}
+ /// Board work-order types. Legacy values retained for backward compatibility.
public enum WorkOrderType
{
PO = 1,
@@ -32,6 +33,8 @@ namespace Data.SeaHavenIndustries.Enums
Emergency = 3,
Project = 4,
Inspection = 5,
+ Reactive = 6,
+ AddOn = 7,
Other = 99
}
diff --git a/SeaHaven.DataServices/Implementation/WorkOrderBoardDataService.cs b/SeaHaven.DataServices/Implementation/WorkOrderBoardDataService.cs
index 5a29f24..a25aa35 100644
--- a/SeaHaven.DataServices/Implementation/WorkOrderBoardDataService.cs
+++ b/SeaHaven.DataServices/Implementation/WorkOrderBoardDataService.cs
@@ -35,9 +35,8 @@ namespace SeaHaven.DataServices.Implementation
var unscheduledBase = baseQuery.Where(w =>
w.ScheduledDate == null
- && w.LifecycleStatus != LifecycleStatus.Complete
- && w.LifecycleStatus != LifecycleStatus.Canceled
- && w.LifecycleStatus != LifecycleStatus.Closed);
+ && w.LifecycleStatus != LifecycleStatus.Completed
+ && w.LifecycleStatus != LifecycleStatus.Canceled);
var scheduledTotal = await scheduledBase.CountAsync();
diff --git a/SeaHaven.Services/Helpers/LifecycleStatusMapper.cs b/SeaHaven.Services/Helpers/LifecycleStatusMapper.cs
index 348048f..551fa66 100644
--- a/SeaHaven.Services/Helpers/LifecycleStatusMapper.cs
+++ b/SeaHaven.Services/Helpers/LifecycleStatusMapper.cs
@@ -10,25 +10,76 @@ namespace SeaHaven.Services.Helpers
return status.Trim().ToLowerInvariant() switch
{
- "open" => LifecycleStatus.Incomplete,
- "inprogress" or "in progress" => LifecycleStatus.InProgress,
- "completed" or "complete" => LifecycleStatus.Complete,
- "cancelled" or "canceled" => LifecycleStatus.Canceled,
- "onhold" or "on hold" => LifecycleStatus.OnHold,
+ "open" or "incomplete" => LifecycleStatus.Incomplete,
+ "pending" or "onhold" or "on hold" => LifecycleStatus.Pending,
"scheduled" => LifecycleStatus.Scheduled,
- "pendingvendor" or "pending vendor" => LifecycleStatus.PendingVendor,
- "pendingapproval" or "pending approval" => LifecycleStatus.PendingApproval,
- "needsreview" or "needs review" => LifecycleStatus.NeedsReview,
- "closed" => LifecycleStatus.Closed,
- _ => LifecycleStatus.NeedsReview
+ "en route" or "enroute" => LifecycleStatus.EnRoute,
+ "on site" or "onsite" => LifecycleStatus.OnSite,
+ "inprogress" or "in progress" => LifecycleStatus.InProgress,
+ "completed" or "complete" or "done" or "closed" => LifecycleStatus.Completed,
+ "rescheduled" => LifecycleStatus.Rescheduled,
+ "cancelled" or "canceled" => LifecycleStatus.Canceled,
+ "pending quote" or "pendingquote" or "pendingapproval" or "pending approval" => LifecycleStatus.PendingQuote,
+ _ => null
};
}
public static LifecycleStatus? ParseLifecycleStatus(string? value)
{
if (string.IsNullOrWhiteSpace(value)) return null;
- if (Enum.TryParse(value, true, out var parsed)) return parsed;
+
+ if (TryParseFeLabel(value, out var fromLabel))
+ return fromLabel;
+
+ if (Enum.TryParse(value, true, out var parsed))
+ return parsed;
+
return FromLegacyStatus(value);
}
+
+ public static bool TryParseFeLabel(string? label, out LifecycleStatus status)
+ {
+ status = default;
+ if (string.IsNullOrWhiteSpace(label)) return false;
+
+ return label.Trim().ToLowerInvariant() switch
+ {
+ "incomplete" => Set(LifecycleStatus.Incomplete, out status),
+ "pending" => Set(LifecycleStatus.Pending, out status),
+ "scheduled" => Set(LifecycleStatus.Scheduled, out status),
+ "en route" => Set(LifecycleStatus.EnRoute, out status),
+ "on site" => Set(LifecycleStatus.OnSite, out status),
+ "in progress" => Set(LifecycleStatus.InProgress, out status),
+ "completed" => Set(LifecycleStatus.Completed, out status),
+ "rescheduled" => Set(LifecycleStatus.Rescheduled, out status),
+ "canceled" => Set(LifecycleStatus.Canceled, out status),
+ "pending quote" => Set(LifecycleStatus.PendingQuote, out status),
+ _ => false
+ };
+ }
+
+ public static string ToFeLabel(LifecycleStatus status) => status switch
+ {
+ LifecycleStatus.Incomplete => "Incomplete",
+ LifecycleStatus.Pending => "Pending",
+ LifecycleStatus.Scheduled => "Scheduled",
+ LifecycleStatus.EnRoute => "En Route",
+ LifecycleStatus.OnSite => "On Site",
+ LifecycleStatus.InProgress => "In Progress",
+ LifecycleStatus.Completed => "Completed",
+ LifecycleStatus.Rescheduled => "Rescheduled",
+ LifecycleStatus.Canceled => "Canceled",
+ LifecycleStatus.PendingQuote => "Pending Quote",
+ _ => status.ToString()
+ };
+
+ public static bool IsTerminal(LifecycleStatus? status)
+ => status is LifecycleStatus.Completed or LifecycleStatus.Canceled;
+
+ private static bool Set(LifecycleStatus value, out LifecycleStatus status)
+ {
+ status = value;
+ return true;
+ }
}
}
diff --git a/SeaHaven.Services/Helpers/WorkOrderBoardMutationRules.cs b/SeaHaven.Services/Helpers/WorkOrderBoardMutationRules.cs
index 7a3a59a..0f2be7e 100644
--- a/SeaHaven.Services/Helpers/WorkOrderBoardMutationRules.cs
+++ b/SeaHaven.Services/Helpers/WorkOrderBoardMutationRules.cs
@@ -7,8 +7,7 @@ namespace SeaHaven.Services.Helpers
private static readonly HashSet ReadOnlyStatuses = new()
{
LifecycleStatus.Canceled,
- LifecycleStatus.Closed,
- LifecycleStatus.Complete
+ LifecycleStatus.Completed
};
public static bool IsReadOnly(LifecycleStatus? status) => ReadOnlyStatuses.Contains(status);
diff --git a/SeaHaven.Services/Helpers/WorkOrderDerivedFields.cs b/SeaHaven.Services/Helpers/WorkOrderDerivedFields.cs
index 382ecae..b349a0e 100644
--- a/SeaHaven.Services/Helpers/WorkOrderDerivedFields.cs
+++ b/SeaHaven.Services/Helpers/WorkOrderDerivedFields.cs
@@ -4,13 +4,6 @@ namespace SeaHaven.Services.Helpers
{
public static class WorkOrderDerivedFields
{
- private static readonly HashSet TerminalStatuses = new()
- {
- LifecycleStatus.Complete,
- LifecycleStatus.Canceled,
- LifecycleStatus.Closed
- };
-
public static bool IsPastDue(
DateTime? scheduledDate,
LifecycleStatus? lifecycleStatus,
@@ -19,7 +12,7 @@ namespace SeaHaven.Services.Helpers
if (!scheduledDate.HasValue)
return false;
- if (TerminalStatuses.Contains(lifecycleStatus))
+ if (LifecycleStatusMapper.IsTerminal(lifecycleStatus))
return false;
var today = (utcNow ?? DateTime.UtcNow).Date;
@@ -27,7 +20,7 @@ namespace SeaHaven.Services.Helpers
}
public static bool IsTerminal(LifecycleStatus? lifecycleStatus)
- => TerminalStatuses.Contains(lifecycleStatus);
+ => LifecycleStatusMapper.IsTerminal(lifecycleStatus);
public static string? GetDayGroup(DateTime? scheduledDate)
{
@@ -57,24 +50,6 @@ namespace SeaHaven.Services.Helpers
}
public static string GetLifecycleStatusLabel(LifecycleStatus? status)
- {
- if (!status.HasValue)
- return "";
-
- return status.Value switch
- {
- LifecycleStatus.Incomplete => "Incomplete",
- LifecycleStatus.Scheduled => "Scheduled",
- LifecycleStatus.InProgress => "In Progress",
- LifecycleStatus.Complete => "Complete",
- LifecycleStatus.Canceled => "Canceled",
- LifecycleStatus.OnHold => "On Hold",
- LifecycleStatus.PendingVendor => "Pending Vendor",
- LifecycleStatus.PendingApproval => "Pending Approval",
- LifecycleStatus.NeedsReview => "Needs Review",
- LifecycleStatus.Closed => "Closed",
- _ => status.Value.ToString()
- };
- }
+ => status.HasValue ? LifecycleStatusMapper.ToFeLabel(status.Value) : "";
}
}
diff --git a/SeaHaven.Services/Helpers/WorkOrderTypeMapper.cs b/SeaHaven.Services/Helpers/WorkOrderTypeMapper.cs
new file mode 100644
index 0000000..4eda69f
--- /dev/null
+++ b/SeaHaven.Services/Helpers/WorkOrderTypeMapper.cs
@@ -0,0 +1,47 @@
+using Data.SeaHavenIndustries.Enums;
+
+namespace SeaHaven.Services.Helpers
+{
+ public static class WorkOrderTypeMapper
+ {
+ /// Board FE types. Overdue is not a type — use .
+ 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;
+ }
+ }
+}
diff --git a/SeaHaven.Services/Implementation/WorkOrderBoardUpdateService.cs b/SeaHaven.Services/Implementation/WorkOrderBoardUpdateService.cs
index 038f8b8..98239bb 100644
--- a/SeaHaven.Services/Implementation/WorkOrderBoardUpdateService.cs
+++ b/SeaHaven.Services/Implementation/WorkOrderBoardUpdateService.cs
@@ -222,7 +222,7 @@ namespace SeaHaven.Services.Implementation
if (string.IsNullOrWhiteSpace(value))
throw new WorkOrderBoardValidationException("InvalidValue", "workOrderType value is required.");
- if (!Enum.TryParse(value, true, out var parsed))
+ if (!WorkOrderTypeMapper.TryParseFeLabel(value, out var parsed))
throw new WorkOrderBoardValidationException("InvalidValue", $"Invalid workOrderType: {value}");
var old = workOrder.WorkOrderType?.ToString();
diff --git a/SeaHavenIndustries.Tests/LifecycleStatusMapperTests.cs b/SeaHavenIndustries.Tests/LifecycleStatusMapperTests.cs
index db7b4be..bf99a85 100644
--- a/SeaHavenIndustries.Tests/LifecycleStatusMapperTests.cs
+++ b/SeaHavenIndustries.Tests/LifecycleStatusMapperTests.cs
@@ -9,9 +9,9 @@ public class LifecycleStatusMapperTests
[InlineData("Open", LifecycleStatus.Incomplete)]
[InlineData("InProgress", LifecycleStatus.InProgress)]
[InlineData("In Progress", LifecycleStatus.InProgress)]
- [InlineData("Completed", LifecycleStatus.Complete)]
+ [InlineData("Completed", LifecycleStatus.Completed)]
[InlineData("Cancelled", LifecycleStatus.Canceled)]
- [InlineData("On Hold", LifecycleStatus.OnHold)]
+ [InlineData("On Hold", LifecycleStatus.Pending)]
[InlineData("Scheduled", LifecycleStatus.Scheduled)]
public void FromLegacyStatus_MapsKnownValues(string input, LifecycleStatus expected)
{
@@ -19,10 +19,31 @@ public class LifecycleStatusMapperTests
Assert.Equal(expected, result);
}
+ [Theory]
+ [InlineData("Incomplete", LifecycleStatus.Incomplete)]
+ [InlineData("En Route", LifecycleStatus.EnRoute)]
+ [InlineData("On Site", LifecycleStatus.OnSite)]
+ [InlineData("Rescheduled", LifecycleStatus.Rescheduled)]
+ [InlineData("Pending Quote", LifecycleStatus.PendingQuote)]
+ public void ParseLifecycleStatus_MapsFeLabels(string input, LifecycleStatus expected)
+ {
+ var result = LifecycleStatusMapper.ParseLifecycleStatus(input);
+ Assert.Equal(expected, result);
+ }
+
+ [Theory]
+ [InlineData(LifecycleStatus.EnRoute, "En Route")]
+ [InlineData(LifecycleStatus.OnSite, "On Site")]
+ [InlineData(LifecycleStatus.PendingQuote, "Pending Quote")]
+ public void ToFeLabel_ReturnsFrontendLabels(LifecycleStatus status, string expected)
+ {
+ Assert.Equal(expected, LifecycleStatusMapper.ToFeLabel(status));
+ }
+
[Fact]
- public void FromLegacyStatus_Unknown_ReturnsNeedsReview()
+ public void FromLegacyStatus_Unknown_ReturnsNull()
{
var result = LifecycleStatusMapper.FromLegacyStatus("MysteryStatus");
- Assert.Equal(LifecycleStatus.NeedsReview, result);
+ Assert.Null(result);
}
}
diff --git a/SeaHavenIndustries.Tests/WorkOrderBoardMutationRulesTests.cs b/SeaHavenIndustries.Tests/WorkOrderBoardMutationRulesTests.cs
index d57c27a..34509ce 100644
--- a/SeaHavenIndustries.Tests/WorkOrderBoardMutationRulesTests.cs
+++ b/SeaHavenIndustries.Tests/WorkOrderBoardMutationRulesTests.cs
@@ -7,8 +7,7 @@ public class WorkOrderBoardMutationRulesTests
{
[Theory]
[InlineData(LifecycleStatus.Canceled, true)]
- [InlineData(LifecycleStatus.Closed, true)]
- [InlineData(LifecycleStatus.Complete, true)]
+ [InlineData(LifecycleStatus.Completed, true)]
[InlineData(LifecycleStatus.Scheduled, false)]
[InlineData(LifecycleStatus.Incomplete, false)]
public void IsReadOnly_ReflectsTerminalStatuses(LifecycleStatus status, bool expected)
diff --git a/SeaHavenIndustries.Tests/WorkOrderBoardServiceTests.cs b/SeaHavenIndustries.Tests/WorkOrderBoardServiceTests.cs
index 587f8ec..9319831 100644
--- a/SeaHavenIndustries.Tests/WorkOrderBoardServiceTests.cs
+++ b/SeaHavenIndustries.Tests/WorkOrderBoardServiceTests.cs
@@ -193,7 +193,7 @@ public class WorkOrderBoardServiceTests
Assert.Equal(1, response.Counts.Total);
Assert.Single(response.Scheduled);
Assert.True(response.Scheduled[0].IsPastDue);
- Assert.Equal("wednesday", response.Scheduled[0].DayGroup);
+ Assert.Equal("monday", response.Scheduled[0].DayGroup);
}
[Fact]
diff --git a/SeaHavenIndustries.Tests/WorkOrderDerivedFieldsTests.cs b/SeaHavenIndustries.Tests/WorkOrderDerivedFieldsTests.cs
index 21423c9..2dc86da 100644
--- a/SeaHavenIndustries.Tests/WorkOrderDerivedFieldsTests.cs
+++ b/SeaHavenIndustries.Tests/WorkOrderDerivedFieldsTests.cs
@@ -34,7 +34,7 @@ public class WorkOrderDerivedFieldsTests
{
var result = WorkOrderDerivedFields.IsPastDue(
Today.AddDays(-3),
- LifecycleStatus.Complete,
+ LifecycleStatus.Completed,
Today);
Assert.False(result);