shoc-backend/SeaHaven.Services/Helpers/WorkOrderCompletionSnapshotMapper.cs
Arthur Bassi deeb29b512 fix(work-orders): allow Complete without a linked site
Snapshot whatever Site/Vendor/POC data exists instead of gating completion on Locations.
2026-09-10 17:56:00 -03:00

151 lines
5.8 KiB
C#

using System.Globalization;
using System.Text.Json;
using Data.SeaHavenIndustries;
using SeaHaven.DataServices.Helpers;
using SeaHaven.Services.DTOs;
namespace SeaHaven.Services.Helpers
{
public static class WorkOrderCompletionSnapshotMapper
{
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
public static void Capture(WorkOrder workOrder)
{
var location = workOrder.Locations;
var contact = workOrder.WorkOrderContacts?
.OrderBy(item => item.Id)
.FirstOrDefault();
var pocName = FirstNotBlank(
workOrder.PocName,
JoinName(contact?.POC?.FirstName, contact?.POC?.MiddleName, contact?.POC?.LastName));
var pocPhone = FirstNotBlank(workOrder.PocPhone, contact?.POC?.PhoneNumber);
var pocNotes = FirstNotBlank(workOrder.PocNotes, contact?.Notes);
var contacts = new List<WorkOrderFrozenPocContact>();
AddContact(contacts, pocName, pocPhone);
foreach (var additional in WorkOrderAdditionalContactsMapper.ParseJson(workOrder.AdditionalContacts)
?? Enumerable.Empty<WorkOrderAdditionalContactDto>())
{
AddContact(contacts, additional.Name, additional.Phone);
}
workOrder.FrozenSite = JsonSerializer.Serialize(
new WorkOrderFrozenSite
{
Code = workOrder.SiteCode,
Label = FirstNotBlank(location?.Name, location?.Title, workOrder.SiteCode),
Address = JoinAddress(location?.Address1, location?.Address2),
City = location?.City,
State = location?.State,
Zip = location?.Zip,
Phone = location?.PhoneNumber,
Email = location?.Email,
Maps = location == null ? null : BuildMapsUrl(location)
},
JsonOptions);
var liveVendor = ResolveLiveVendor(workOrder.PrimaryDispatch);
workOrder.FrozenCompany = liveVendor == null
? null
: JsonSerializer.Serialize(
new WorkOrderFrozenCompany
{
Name = liveVendor.CompanyName,
ContactName = liveVendor.ContactName,
Address = liveVendor.Address,
City = liveVendor.City,
State = liveVendor.State,
Zip = liveVendor.Zip,
Phone = FirstNotBlank(liveVendor.CompanyPhone, liveVendor.Phone),
Email = liveVendor.Email,
Maps = liveVendor.GoogleMapsUrl
},
JsonOptions);
workOrder.FrozenPoc = JsonSerializer.Serialize(
new WorkOrderFrozenPoc
{
Contacts = contacts,
Notes = pocNotes
},
JsonOptions);
}
public static WorkOrderFrozenSite? ParseSite(string? json)
=> Deserialize<WorkOrderFrozenSite>(json);
public static WorkOrderFrozenCompany? ParseCompany(string? json)
=> Deserialize<WorkOrderFrozenCompany>(json);
public static WorkOrderFrozenPoc? ParsePoc(string? json)
=> Deserialize<WorkOrderFrozenPoc>(json);
private static Vendor? ResolveLiveVendor(Dispatch? dispatch)
{
var (vendorId, _) = WorkOrderBoardDispatchAssignment.LiveVendor(
dispatch?.VendorId,
dispatch?.Vendor?.CompanyName,
dispatch?.Status);
return vendorId.HasValue ? dispatch?.Vendor : null;
}
private static string? BuildMapsUrl(Locations location)
{
if (!double.TryParse(location.Latitude, NumberStyles.Float, CultureInfo.InvariantCulture, out var latitude)
|| !double.TryParse(location.Longitude, NumberStyles.Float, CultureInfo.InvariantCulture, out var longitude))
{
return null;
}
return FormattableString.Invariant(
$"https://www.google.com/maps/search/?api=1&query={latitude},{longitude}");
}
private static string? JoinAddress(params string?[] parts)
{
var value = string.Join(", ", parts.Where(part => !string.IsNullOrWhiteSpace(part)));
return string.IsNullOrWhiteSpace(value) ? null : value;
}
private static string? JoinName(params string?[] parts)
{
var value = string.Join(" ", parts.Where(part => !string.IsNullOrWhiteSpace(part)));
return string.IsNullOrWhiteSpace(value) ? null : value;
}
private static string? FirstNotBlank(params string?[] values)
=> values.FirstOrDefault(value => !string.IsNullOrWhiteSpace(value))?.Trim();
private static void AddContact(
ICollection<WorkOrderFrozenPocContact> contacts,
string? name,
string? phone)
{
if (string.IsNullOrWhiteSpace(name) && string.IsNullOrWhiteSpace(phone))
return;
contacts.Add(new WorkOrderFrozenPocContact
{
Name = name?.Trim(),
Phone = phone?.Trim()
});
}
private static T? Deserialize<T>(string? json)
{
if (string.IsNullOrWhiteSpace(json))
return default;
try
{
return JsonSerializer.Deserialize<T>(json, JsonOptions);
}
catch (JsonException)
{
return default;
}
}
}
}