mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 08:23:12 +00:00
fix(work-orders): address PR #13 review feedback
Return BadRequest for invalid board week window, remove duplicate unused board types, fix POC null guard, and document appt precedence and UTC Phase 1 assumptions.
This commit is contained in:
parent
8efe4460bb
commit
c2d0bd45e3
12 changed files with 42 additions and 67 deletions
|
|
@ -17,6 +17,7 @@ using System.Security.Claims;
|
|||
using static System.Runtime.InteropServices.JavaScript.JSType;
|
||||
using SeaHaven.Services.Interfaces;
|
||||
using SeaHaven.Services.DTOs;
|
||||
using SeaHaven.Services.Helpers;
|
||||
using SeaHaven.DataServices.Interfaces;
|
||||
|
||||
namespace Api.SeaHavenIndustries.Controllers
|
||||
|
|
@ -89,6 +90,11 @@ namespace Api.SeaHavenIndustries.Controllers
|
|||
[FromQuery] List<WorkOrderType>? types = null,
|
||||
[FromQuery] string? search = null)
|
||||
{
|
||||
var resolvedWeekEnd = weekEnd ?? weekStart.AddDays(4);
|
||||
var weekValidationError = WorkOrderOperationalWeek.ValidateWeekWindow(weekStart, resolvedWeekEnd);
|
||||
if (weekValidationError != null)
|
||||
return BadRequest(weekValidationError);
|
||||
|
||||
var userId = User.FindFirstValue(ClaimTypes.NameIdentifier);
|
||||
var query = new WorkOrderBoardQueryDto
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
namespace SeaHaven.DataServices.Board
|
||||
{
|
||||
public static class WorkOrderBoardConstants
|
||||
{
|
||||
public const int ClientSideThreshold = 300;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
namespace SeaHaven.DataServices.DTOs
|
||||
{
|
||||
public record WorkOrderBoardQuery(
|
||||
DateOnly ScheduledFrom,
|
||||
DateOnly ScheduledTo,
|
||||
string? Search,
|
||||
IReadOnlyList<string>? AssigneeIds,
|
||||
IReadOnlyList<string>? DbStatuses,
|
||||
int? LocationId);
|
||||
}
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
namespace SeaHaven.DataServices.DTOs
|
||||
{
|
||||
public record WorkOrderBoardRowData(
|
||||
int Id,
|
||||
string? WoNumber,
|
||||
string? SiteCode,
|
||||
string? LocationLabel,
|
||||
DateTime? ScheduledDate,
|
||||
DateTime? ScheduledStart,
|
||||
DateTime? DueDate,
|
||||
string? WorkOrderType,
|
||||
string? ServiceType,
|
||||
string? AssigneeId,
|
||||
string? AssigneeName,
|
||||
string? VendorCompany,
|
||||
string? VendorTechnician,
|
||||
string? Status,
|
||||
string? PocName,
|
||||
string? PocPhone);
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
namespace SeaHaven.DataServices.Exceptions
|
||||
{
|
||||
public class BoardQueryException : Exception
|
||||
{
|
||||
public BoardQueryException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -27,7 +27,7 @@ namespace SeaHaven.DataServices.Helpers
|
|||
Name = c.POC != null
|
||||
? ((c.POC.FirstName ?? "") + " " + (c.POC.LastName ?? "")).Trim()
|
||||
: null,
|
||||
c.POC!.PhoneNumber,
|
||||
PhoneNumber = c.POC != null ? c.POC.PhoneNumber : null,
|
||||
c.Notes
|
||||
})
|
||||
.FirstOrDefault(),
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ namespace SeaHaven.DataServices.Helpers
|
|||
return query.Where(w => w.WorkOrderType != null && types.Contains(w.WorkOrderType.Value));
|
||||
}
|
||||
|
||||
#region Phase 2 filter helpers (not wired in Phase 1 board API)
|
||||
|
||||
public static IQueryable<WorkOrder> ApplySiteFilter(
|
||||
IQueryable<WorkOrder> query,
|
||||
IReadOnlyList<string>? sites)
|
||||
|
|
@ -135,6 +137,8 @@ namespace SeaHaven.DataServices.Helpers
|
|||
&& w.TargetWeek <= dateTo));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static IQueryable<WorkOrder> ApplySearchFilter(IQueryable<WorkOrder> query, string? search)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(search))
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
namespace SeaHaven.DataServices.Interfaces
|
||||
{
|
||||
public record PrimaryDispatchProjection(
|
||||
int WorkOrderId,
|
||||
int? DispatchId,
|
||||
string? VendorName,
|
||||
DateTime? ApptDate,
|
||||
string? DispatchStatus);
|
||||
}
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
namespace SeaHaven.Services.Board
|
||||
{
|
||||
/// <summary>
|
||||
/// Shared board constants for Phase 2+ features. Not referenced in Phase 1.
|
||||
/// </summary>
|
||||
public static class WorkOrderBoardConstants
|
||||
{
|
||||
public const int MaxWindowDays = 90;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,10 @@ namespace SeaHaven.Services.Helpers
|
|||
return DateOnly.FromDateTime(workOrder.ScheduledDate.Value.Date) < today;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Board read-model past-due check. Phase 1 compares UTC calendar dates;
|
||||
/// business/location timezone support is planned for a later phase.
|
||||
/// </summary>
|
||||
public static bool IsPastDue(
|
||||
DateTime? scheduledDate,
|
||||
LifecycleStatus? lifecycleStatus,
|
||||
|
|
@ -66,6 +70,10 @@ namespace SeaHaven.Services.Helpers
|
|||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Maps scheduled date to Mon–Fri board column. Phase 1 uses the stored
|
||||
/// date's day-of-week (UTC); timezone-aware grouping is planned for a later phase.
|
||||
/// </summary>
|
||||
public static string? GetDayGroup(DateTime? scheduledDate)
|
||||
{
|
||||
if (!scheduledDate.HasValue)
|
||||
|
|
|
|||
|
|
@ -16,5 +16,20 @@ namespace SeaHaven.Services.Helpers
|
|||
|
||||
public static string BuildWeekCorrelationId(DateOnly sourceWeekStart)
|
||||
=> $"week:{sourceWeekStart:yyyy-MM-dd}";
|
||||
|
||||
/// <summary>
|
||||
/// Returns a validation error message when the week window is invalid; otherwise null.
|
||||
/// </summary>
|
||||
public static string? ValidateWeekWindow(DateOnly weekStart, DateOnly weekEnd)
|
||||
{
|
||||
if (weekEnd < weekStart)
|
||||
return "weekEnd must be on or after weekStart.";
|
||||
|
||||
var spanDays = weekEnd.DayNumber - weekStart.DayNumber;
|
||||
if (spanDays > 6)
|
||||
return "Week window cannot exceed 7 days.";
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,9 @@ namespace SeaHaven.Services.Implementation
|
|||
var weekStart = query.WeekStart;
|
||||
var weekEnd = query.WeekEnd ?? weekStart.AddDays(4);
|
||||
|
||||
ValidateWeekWindow(weekStart, weekEnd);
|
||||
var validationError = WorkOrderOperationalWeek.ValidateWeekWindow(weekStart, weekEnd);
|
||||
if (validationError != null)
|
||||
throw new ArgumentException(validationError);
|
||||
|
||||
var dataQuery = new WorkOrderBoardQuery(
|
||||
weekStart,
|
||||
|
|
@ -62,18 +64,10 @@ namespace SeaHaven.Services.Implementation
|
|||
}).ToList();
|
||||
}
|
||||
|
||||
private static void ValidateWeekWindow(DateOnly weekStart, DateOnly weekEnd)
|
||||
{
|
||||
if (weekEnd < weekStart)
|
||||
throw new ArgumentException("weekEnd must be on or after weekStart.");
|
||||
|
||||
var spanDays = weekEnd.DayNumber - weekStart.DayNumber;
|
||||
if (spanDays > 6)
|
||||
throw new ArgumentException("Week window cannot exceed 7 days.");
|
||||
}
|
||||
|
||||
private static WorkOrderBoardRowDto MapRow(WorkOrderBoardRawRow row, DateTime utcNow)
|
||||
{
|
||||
// Appt column: date prefers dispatch appointment (vendor slot), then WO ScheduledDate.
|
||||
// Time prefers WO ScheduledStart/End (dispatcher window), then dispatch datetime.
|
||||
var apptStart = row.ScheduledStart ?? row.DispatchApptDate;
|
||||
var apptEnd = row.ScheduledEnd;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue