shoc-backend/SeaHaven.DataServices/Helpers/WorkOrderBoardProjection.cs
Arthur Bassi 97e042f552 feat(work-orders): persist IsAddOn frozen at create (SH-126)
Add set-once IsAddOn with server cutoff at create, board DTO exposure, legacy type-7 backfill, and Types=AddOn search compat. Aligns with FE PR #61 frozen contract.
2026-08-13 13:30:09 -03:00

143 lines
6.1 KiB
C#

using Data.SeaHavenIndustries;
using Microsoft.EntityFrameworkCore;
using SeaHaven.DataServices.Interfaces;
namespace SeaHaven.DataServices.Helpers
{
public static class WorkOrderBoardProjection
{
public static async Task<IReadOnlyList<WorkOrderBoardRawRow>> ProjectRowsAsync(
ApplicationDbContext context,
IQueryable<WorkOrder> query,
bool isUnscheduled)
{
var rows = await query
.Select(w => new
{
w.Id,
w.InternalWONumber,
w.RescheduleCount,
w.CarriedOver,
w.IsAddOn,
w.WorkOrderType,
w.SiteCode,
LocationName = w.Locations != null ? w.Locations.Name : null,
WoPocName = w.PocName,
WoPocPhone = w.PocPhone,
WoPocNotes = w.PocNotes,
ContactPoc = w.WorkOrderContacts!
.OrderBy(c => c.Id)
.Select(c => new
{
Name = c.POC != null
? ((c.POC.FirstName ?? "") + " " + (c.POC.LastName ?? "")).Trim()
: null,
PhoneNumber = c.POC != null ? c.POC.PhoneNumber : null,
c.Notes
})
.FirstOrDefault(),
w.LifecycleStatus,
w.LegacyStatus,
w.Status,
w.AssignTo,
w.AssignToUser!.FirstName,
w.AssignToUser!.LastName,
w.AssignToUser!.Initials,
w.AssignToUser!.Color,
w.DueDate,
w.ScheduledDate,
w.ScheduledStart,
w.ScheduledEnd,
w.TargetWeek,
w.ScheduleWeekOnly,
VendorId = w.PrimaryDispatch != null ? (int?)w.PrimaryDispatch.VendorId : null,
VendorName = w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null
? w.PrimaryDispatch.Vendor.CompanyName
: null,
TechName = w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null
? w.PrimaryDispatch.Vendor.ContactName
: null,
DispatchTechPhone = w.PrimaryDispatch != null ? w.PrimaryDispatch.TechPhone : null,
WoTechPhone = w.TechPhone,
VendorPhone = w.PrimaryDispatch != null && w.PrimaryDispatch.Vendor != null
? w.PrimaryDispatch.Vendor.Phone
: null,
DispatchApptDate = w.PrimaryDispatch != null ? w.PrimaryDispatch.ScheduledDate : null,
w.Trade,
w.Problem,
w.ServiceNotes,
w.ExtraServices,
w.DocStatus,
w.CompletedDate,
w.FlagColor,
w.PrimaryDispatchId,
w.RowVersion,
DispatchRowVersion = w.PrimaryDispatch != null ? w.PrimaryDispatch.RowVersion : null,
// SH-188: aggregate Pending uplifts on every live dispatch tied to this WO
// (primary WorkOrderId and multi-WO DispatchWorkOrders links).
PendingUpliftCount = context.DispatchUpliftRequests.Count(u =>
u.Status == "Pending"
&& (u.IsDeleted == null || u.IsDeleted == false)
&& u.Dispatch != null
&& (u.Dispatch.IsDeleted == null || u.Dispatch.IsDeleted == false)
&& (
u.Dispatch.WorkOrderId == w.Id
|| u.Dispatch.DispatchWorkOrders!.Any(link => link.WorkOrderId == w.Id)))
})
.ToListAsync();
return rows.Select(w =>
{
var pocName = !string.IsNullOrWhiteSpace(w.WoPocName) ? w.WoPocName : w.ContactPoc?.Name;
var pocPhone = !string.IsNullOrWhiteSpace(w.WoPocPhone) ? w.WoPocPhone : w.ContactPoc?.PhoneNumber;
var pocNotes = !string.IsNullOrWhiteSpace(w.WoPocNotes) ? w.WoPocNotes : w.ContactPoc?.Notes;
var techPhone = !string.IsNullOrWhiteSpace(w.DispatchTechPhone)
? w.DispatchTechPhone
: (!string.IsNullOrWhiteSpace(w.WoTechPhone) ? w.WoTechPhone : w.VendorPhone);
return new WorkOrderBoardRawRow(
w.Id,
w.InternalWONumber,
w.RescheduleCount,
w.CarriedOver,
w.IsAddOn,
w.WorkOrderType,
w.SiteCode,
w.LocationName,
pocName,
pocPhone,
pocNotes,
w.LifecycleStatus,
w.LegacyStatus ?? w.Status,
w.AssignTo,
w.FirstName,
w.LastName,
w.Initials,
w.Color,
w.DueDate,
w.ScheduledDate,
w.ScheduledStart,
w.ScheduledEnd,
w.TargetWeek,
w.ScheduleWeekOnly,
w.VendorId,
w.VendorName,
w.TechName,
techPhone,
w.DispatchApptDate,
w.Trade ?? w.Problem,
w.Problem,
w.ServiceNotes,
w.ExtraServices,
w.DocStatus,
w.CompletedDate,
w.FlagColor,
w.PrimaryDispatchId,
w.RowVersion,
w.DispatchRowVersion,
w.PendingUpliftCount,
isUnscheduled);
}).ToList();
}
}
}