shoc-backend/SeaHaven.Services/Helpers/WorkOrderUpliftContractMapper.cs
Alexandre Brandizzi eb2b442775 fix(uplifts): one per-path uplift amount for queue, approval and exposure
Work-order requests store the requested increase in RequestedNTE; vendor
portal requests store the requested NTE total. The queue Delta, the
pending and approved exposure totals, the work-order uplift list, the
board summary and the notification Delta now all read one definition
(UpliftAmount) that honours both meanings and translates to SQL.

Approving a work-order request now adds its increase to the dispatch NTE
instead of replacing the NTE with the increase; vendor requests still end
at their requested total.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-25 02:32:58 -03:00

101 lines
3.7 KiB
C#

using Data.SeaHavenIndustries;
using SeaHaven.DataServices.Helpers;
using SeaHaven.DataServices.Interfaces;
using SeaHaven.Services.DTOs;
using SeaHaven.Services.Implementation;
namespace SeaHaven.Services.Helpers
{
public static class WorkOrderUpliftContractMapper
{
public static WorkOrderUpliftSummaryDto MapSummary(
bool hasUplift,
int pendingCount,
string? primaryStatus,
decimal? amount)
{
var summary = new WorkOrderUpliftSummaryDto
{
HasUplift = hasUplift || pendingCount > 0,
PendingCount = pendingCount,
};
if (!string.IsNullOrWhiteSpace(primaryStatus))
{
summary.PrimaryStatus = ToFrontendStatus(primaryStatus);
}
if (amount.HasValue)
{
summary.Amount = amount.Value;
}
return summary;
}
public static WorkOrderUpliftSummaryDto MapSummary(WorkOrderBoardRawRow row)
=> MapSummary(row.HasUplift, row.PendingUpliftCount, row.PrimaryUpliftStatus, row.PrimaryUpliftAmount);
public static WorkOrderUpliftDto MapItem(UpliftForWorkOrderData row)
{
var decidedByName = FormatName(row.DecidedByFirstName, row.DecidedByLastName);
return new WorkOrderUpliftDto
{
Id = row.Id,
Status = ToFrontendStatus(row.Status),
Amount = row.Amount,
Notes = row.VendorReason ?? "",
RequestedAt = row.CreatedDate,
RequestedById = row.CreatedByUserId,
RequestedByName = row.RequestedByVendorName ?? "",
DecidedAt = row.DecidedAt,
DecidedByName = decidedByName,
DecisionNote = row.DecisionNote ?? "",
};
}
public static WorkOrderUpliftDto MapItem(DispatchUpliftRequest request, string? requestedByName, string? decidedByName)
=> new()
{
Id = request.Id,
Status = ToFrontendStatus(request.Status),
Amount = UpliftAmount.Of(request),
Notes = request.VendorReason ?? "",
RequestedAt = request.CreatedDate,
RequestedById = request.createdby,
RequestedByName = requestedByName ?? request.RequestedByVendorName ?? "",
DecidedAt = request.DecidedAt,
DecidedByName = decidedByName ?? "",
DecisionNote = request.DecisionNote ?? "",
};
public static WorkOrderUpliftDto MapRevokedItem(
DispatchUpliftRequest request,
string? requestedByName,
string decidedByName)
{
var dto = MapItem(request, requestedByName, decidedByName);
dto.Status = "revoked";
return dto;
}
public static string ToFrontendStatus(string? backendStatus)
{
return UpliftStatus.ToCanonical(backendStatus) switch
{
UpliftStatus.Pending => "pending",
UpliftStatus.Approved => "approved",
UpliftStatus.NoApprovalRequired => "auto_approved",
UpliftStatus.Rejected => "rejected",
UpliftStatus.Withdrawn => "cancelled",
UpliftStatus.Revoked => "revoked",
UpliftStatus.ChangesRequested => "pending",
UpliftStatus.Expired => "cancelled",
_ => "pending",
};
}
private static string FormatName(string? firstName, string? lastName)
=> $"{firstName ?? ""} {lastName ?? ""}".Trim();
}
}