shoc-backend/SeaHaven.DataServices/Interfaces/WorkOrderBoardModels.cs
Alexandre Brandizzi cbecc7b4ea fix(workorders): persist manual POC override with audit and site-follow (SH-379)
Editing a work order's POC never reached the backend: no update path wrote
PocName/PocPhone/PocNotes, so the optimistic UI edit was lost on refetch and
the completion freeze captured the Site contact instead of the manual value,
and nothing was audited.

- Add tenant-scoped PATCH api/workorders/{id}/poc via new WorkOrderPocService
  + WorkOrderPocDataService: persists the override, stages FieldChanged audit
  entries (which also write field locks so sync never overwrites a manual POC),
  and enforces row-version concurrency and terminal-status read-only rules.
- Lock semantics (SH-190): a manual POC away from the Site's live contacts is
  stored WO-level; an edit equal to a live Site contact (or blanking name+phone)
  stores nothing so the WO follows the Site. PocCustomized exposes the state.
- Board projection, completion freeze and create now share one Site-contact
  fallback (first non-deleted contact by SiteContactOrder) so a never-overridden
  WO keeps following the Site, including at create when the wizard prefills it.
- Route contract baseline gains PATCH {id:int}/poc.
2026-09-18 14:30:54 -03:00

89 lines
2.6 KiB
C#

using Data.SeaHavenIndustries;
using Data.SeaHavenIndustries.Enums;
namespace SeaHaven.DataServices.Interfaces
{
public record WorkOrderBoardQuery(
DateOnly WeekStart,
DateOnly WeekEnd,
IReadOnlyList<string>? Dispatchers,
bool MyWorkOrders,
IReadOnlyList<WorkOrderType>? Types,
bool Overdue,
string? Search,
string? CurrentUserId,
int? AccountId = null);
public record WorkOrderBoardRawRow(
int Id,
string? InternalWONumber,
int RescheduleCount,
int CarriedOver,
bool IsAddOn,
WorkOrderType? WorkOrderType,
int? ServiceId,
string? ServiceNameSnapshot,
string? SiteCode,
string? LocationName,
string? PocName,
string? PocPhone,
string? PocNotes,
LifecycleStatus? LifecycleStatus,
string? LegacyStatus,
string? AssignTo,
string? DispatcherFirstName,
string? DispatcherLastName,
string? Initials,
string? Color,
DateTime? DueDate,
DateTime? ScheduledDate,
DateTime? ScheduledStart,
DateTime? ScheduledEnd,
DateOnly? TargetWeek,
bool? ScheduleWeekOnly,
int? VendorId,
string? VendorName,
string? TechName,
string? TechPhone,
DateTime? DispatchApptDate,
string? Trade,
string? Problem,
string? ServiceNotes,
string? ExtraServices,
string? AdditionalContacts,
DocStatus? DocStatus,
DateTime? CompletedDate,
string? FlagColor,
int? PrimaryDispatchId,
byte[]? RowVersion,
byte[]? DispatchRowVersion,
int PendingUpliftCount,
bool HasUplift,
string? PrimaryUpliftStatus,
decimal? PrimaryUpliftAmount,
string? PrimaryDispatchStatus,
bool AvetaRequired,
bool HasAvetaDocument,
DateOnly? OriginalDate,
DateOnly? OriginalWeek,
bool IsUnscheduled,
string? Severity = null,
int MediaCount = 0,
WorkOrderFrozenSite? FrozenSite = null,
WorkOrderFrozenCompany? FrozenCompany = null,
WorkOrderFrozenPoc? FrozenPoc = null,
string? WoPocName = null,
string? WoPocPhone = null);
public record WorkOrderBoardQueryResult(
IReadOnlyList<WorkOrderBoardRawRow> ScheduledRows,
IReadOnlyList<WorkOrderBoardRawRow> UnscheduledRows,
int ScheduledTotalBeforeSearch);
public record DispatcherLookupRow(
string Id,
string FirstName,
string? LastName,
string? Initials,
string? Color);
}