shoc-backend/SeaHaven.Services/DTOs/WorkOrderBoardRequestDTOs.cs
Alexandre Brandizzi 3019e71093 feat(workorders): filter board search to an exact work-order id set
GET /board/search accepts ids=1,2,3 (positive ints, deduplicated, at most
200). When present the result is exactly those work orders inside the
caller's tenant and base scope; date, status, dispatcher, facet and text
filters are ignored so none of them can hide a listed work order.
Malformed or oversized lists are a 400.
2026-09-25 10:56:47 -03:00

128 lines
6.4 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Data.SeaHavenIndustries.Enums;
using SeaHaven.Services.Helpers;
namespace SeaHaven.Services.DTOs
{
/// <summary>
/// Payload for creating a board work order (SHOC create wizard).
/// FE follow-up: extend WorkOrderBoardCreatePayload + mapper with PrimaryService,
/// ExtraServices, ServiceNotes, PocName, PocPhone, VendorNotes, TechPhone; stop embedding
/// POC/vendor/service notes in description (pocNotes already exists). Prefer structured
/// fields; keep Trade+Description temporarily for legacy clients.
/// </summary>
public class WorkOrderBoardCreateRequestDto
{
public string? WoNumber { get; set; }
public WorkOrderType WorkOrderType { get; set; }
/// <summary>
/// Manual Add-On override when unscheduled. Ignored when ScheduledDate or TargetWeek is set
/// (server computes from cutoff).
/// </summary>
public bool? IsAddOn { get; set; }
public string? SiteCode { get; set; }
/// <summary>
/// Optional display customer name. Ignored when stamping AccountId
/// (board create resolves from Location.AccountId).
/// </summary>
public string? Customer { get; set; }
public string? Description { get; set; }
/// <summary>Legacy alias for primary service; prefer <see cref="PrimaryService"/>.</summary>
public string? Trade { get; set; }
/// <summary>Primary service label; persisted as Trade / board pm.</summary>
public string? PrimaryService { get; set; }
public int? ServiceId { get; set; }
public List<string>? ExtraServices { get; set; }
public string? ServiceNotes { get; set; }
/// <summary>Per-WO Aveta compliance. Omit or false = not required.</summary>
public bool? AvetaRequired { get; set; }
public int? LocationId { get; set; }
public DateTime? DueDate { get; set; }
public string? AssignTo { get; set; }
public DateTime? ScheduledDate { get; set; }
public DateOnly? TargetWeek { get; set; }
public bool? ScheduleWeekOnly { get; set; }
public DocStatus? DocStatus { get; set; }
/// <summary>Optional create-time lifecycle. When omitted, server defaults to Incomplete.</summary>
public LifecycleStatus? LifecycleStatus { get; set; }
public int? VendorId { get; set; }
public DateTime? ApptDate { get; set; }
public string? ApptTime { get; set; }
public int? PocContactId { get; set; }
public string? PocName { get; set; }
public string? PocPhone { get; set; }
public string? PocNotes { get; set; }
public List<WorkOrderAdditionalContactDto>? AdditionalContacts { get; set; }
public string? TechPhone { get; set; }
public string? VendorNotes { get; set; }
/// <summary>Severity 1–5 for Emergency/Reactive. Ignored for other types.</summary>
public int? Severity { get; set; }
}
/// <summary>
/// SH-379: replaces the work-order-level POC override (PocName/PocPhone/PocNotes).
/// Blank name and phone clear the override so the work order follows the Site's
/// live contact again. An edit equal to a live Site contact does not lock (SH-190).
/// </summary>
public class WorkOrderPocUpdateRequestDto
{
public string? PocName { get; set; }
public string? PocPhone { get; set; }
public string? PocNotes { get; set; }
/// <summary>Base64 row version, same concurrency token as the board patch.</summary>
public string? WorkOrderVersion { get; set; }
}
/// <summary>Advanced search / filter query for the board.</summary>
public class WorkOrderAdvancedSearchQueryDto
{
public int Page { get; set; } = 0;
public int PageSize { get; set; } = 50;
public string? Search { get; set; }
public WorkOrderAdvancedSearchDatePreset? DatePreset { get; set; }
public DateOnly? DateFrom { get; set; }
public DateOnly? DateTo { get; set; }
/// <summary>
/// When true, only unscheduled rows (ScheduledDate is null) are returned.
/// Takes precedence over DatePreset/DateFrom/DateTo for the scheduled-date
/// filter; every other facet still applies.
/// </summary>
public bool UnscheduledOnly { get; set; }
/// <summary>
/// When true, rows with no date (no Schedule On) are returned alongside
/// the in-range rows. Sent for searches with no date range selected; an
/// explicit range leaves it unset or false so the range strictly narrows
/// (SH-391). When it is omitted, clients that predate the flag keep their
/// undated rows: see <see cref="WorkOrderSearchDateRangeResolver.ResolveIncludeDateless"/>.
/// </summary>
public bool? IncludeDateless { get; set; }
public List<string>? Sites { get; set; }
public List<string>? Regions { get; set; }
public List<WorkOrderType>? Types { get; set; }
/// <summary>When true, include past-due (isPastDue) rows. Combined with Types via OR.</summary>
public bool Overdue { get; set; }
public List<string>? Dispatchers { get; set; }
public List<LifecycleStatus>? Statuses { get; set; }
public List<string>? PmTypes { get; set; }
public List<int>? VendorIds { get; set; }
public List<DocStatus>? DocStatuses { get; set; }
public List<int>? Severities { get; set; }
public bool Rescheduled { get; set; }
public bool CarriedOver { get; set; }
public bool AddOn { get; set; }
/// <summary>When true, only rows with AvetaRequired.</summary>
public bool AvetaOnly { get; set; }
public List<string>? FlagColors { get; set; }
public bool InternalOnly { get; set; }
public bool HasUplift { get; set; }
public List<string>? UpliftStatuses { get; set; }
public bool MyWorkOrders { get; set; }
/// <summary>
/// Comma-separated work-order ids, at most <see cref="WorkOrderIdSet.MaxCount"/> distinct.
/// When present the result is exactly those work orders inside the caller's tenant scope,
/// and every other filter (dates, statuses, dispatchers, facets, search) is ignored.
/// </summary>
public string? Ids { get; set; }
public string? SortBy { get; set; }
public string? SortDir { get; set; }
}
}