mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-29 12:58:13 +00:00
Merge pull request #719 from Tria-plc/freight_feature/usermanagement
implement empty-container return service: add return quantity handlin…
This commit is contained in:
@@ -97,6 +97,7 @@ interface LineErrors {
|
||||
quantity?: string;
|
||||
hazardousQuantity?: string;
|
||||
reeferQuantity?: string;
|
||||
returnQuantity?: string;
|
||||
units?: string;
|
||||
}
|
||||
|
||||
@@ -135,6 +136,8 @@ interface ContainerLineDraft {
|
||||
quantity: string;
|
||||
hazardousQuantity: string;
|
||||
reeferQuantity: string;
|
||||
/** Units of this line shipping with empty-container return (contract WITH_RETURN only). */
|
||||
returnQuantity: string;
|
||||
units: UnitDraft[];
|
||||
}
|
||||
|
||||
@@ -155,6 +158,7 @@ function emptyLine(size: string): ContainerLineDraft {
|
||||
quantity: "1",
|
||||
hazardousQuantity: "0",
|
||||
reeferQuantity: "0",
|
||||
returnQuantity: "0",
|
||||
units: [emptyUnit()],
|
||||
};
|
||||
}
|
||||
@@ -272,6 +276,14 @@ export default function GlCreateBookingForm() {
|
||||
}, [contract]);
|
||||
|
||||
const isContainer = contract?.freightType === "CONTAINER";
|
||||
// The contract gates the empty-container return service — like hazardous.
|
||||
// WITH_RETURN contracts capture a per-line return quantity instead of the
|
||||
// legacy booking-level toggle; other contracts cannot switch it on.
|
||||
const contractWithReturn =
|
||||
isContainer && contract?.equipmentReturn === "WITH_RETURN";
|
||||
// Legacy contracts (no equipment return chosen at creation) keep the old
|
||||
// booking-level toggle.
|
||||
const legacyReturnToggle = isContainer && !contract?.equipmentReturn;
|
||||
// Intercity shipments ride a passing import/export train staff pick at
|
||||
// finalize time — no shipment day is chosen and no window gate applies.
|
||||
const isIntercity = contract?.tradeDirection === "DOMESTIC";
|
||||
@@ -354,6 +366,7 @@ export default function GlCreateBookingForm() {
|
||||
quantity: String(Math.max(1, c.quantity)),
|
||||
hazardousQuantity: String(c.hazardousQuantity ?? 0),
|
||||
reeferQuantity: String(c.reeferQuantity ?? 0),
|
||||
returnQuantity: "0",
|
||||
units: Array.from({ length: Math.max(1, c.quantity) }, emptyUnit),
|
||||
})),
|
||||
);
|
||||
@@ -390,6 +403,7 @@ export default function GlCreateBookingForm() {
|
||||
quantity: String(qty),
|
||||
hazardousQuantity: "0",
|
||||
reeferQuantity: "0",
|
||||
returnQuantity: "0",
|
||||
units: Array.from({ length: qty }, emptyUnit),
|
||||
};
|
||||
}),
|
||||
@@ -542,6 +556,8 @@ export default function GlCreateBookingForm() {
|
||||
quantity: String(imported.length),
|
||||
hazardousQuantity: String(imported.filter((r) => r.hazardous).length),
|
||||
reeferQuantity: String(imported.filter((r) => r.reefer).length),
|
||||
returnQuantity:
|
||||
prev.find((l) => l.containerSize === size)?.returnQuantity ?? "0",
|
||||
units: imported.map((r) => ({
|
||||
containerNumber: r.containerNumber,
|
||||
sealNumber: r.sealNumber,
|
||||
@@ -614,9 +630,17 @@ export default function GlCreateBookingForm() {
|
||||
errs.reeferQuantity = `Can't exceed the ${qty} container(s) in this line.`;
|
||||
}
|
||||
}
|
||||
if (contractWithReturn) {
|
||||
const w = Number(line.returnQuantity || 0);
|
||||
if (Number.isNaN(w) || w < 0) {
|
||||
errs.returnQuantity = "Enter a valid return quantity.";
|
||||
} else if (w > qty) {
|
||||
errs.returnQuantity = `Can't exceed the ${qty} container(s) in this line.`;
|
||||
}
|
||||
}
|
||||
return errs;
|
||||
});
|
||||
}, [isContainer, contract, containerLines]);
|
||||
}, [isContainer, contract, containerLines, contractWithReturn]);
|
||||
|
||||
const bulkUom = contract ? bulkUnitOfMeasure(contract) : "PER_TON";
|
||||
|
||||
@@ -653,7 +677,11 @@ export default function GlCreateBookingForm() {
|
||||
const cargoValid = isContainer
|
||||
? lineErrors.every(
|
||||
(e) =>
|
||||
!e.quantity && !e.units && !e.hazardousQuantity && !e.reeferQuantity,
|
||||
!e.quantity &&
|
||||
!e.units &&
|
||||
!e.hazardousQuantity &&
|
||||
!e.reeferQuantity &&
|
||||
!e.returnQuantity,
|
||||
) &&
|
||||
unitErrors.every((line) =>
|
||||
line.every((e) => !e.containerNumber && !e.vgmTons),
|
||||
@@ -675,8 +703,10 @@ export default function GlCreateBookingForm() {
|
||||
? { scheduledDate: new Date(scheduledDate).toISOString() }
|
||||
: {}),
|
||||
...(notes.trim() ? { notes: notes.trim() } : {}),
|
||||
// Equipment return is a container concern — bulk keeps the contract default.
|
||||
...(isContainer
|
||||
// Equipment return: WITH_RETURN contracts derive it server-side from the
|
||||
// per-line return quantities; only legacy contracts (no value chosen at
|
||||
// creation) still send the booking-level toggle. Bulk keeps the default.
|
||||
...(legacyReturnToggle
|
||||
? { equipmentReturn: withReturn ? "WITH_RETURN" : "WITHOUT_RETURN" }
|
||||
: {}),
|
||||
};
|
||||
@@ -689,6 +719,9 @@ export default function GlCreateBookingForm() {
|
||||
quantity: Number(l.quantity),
|
||||
hazardousQuantity: Number(l.hazardousQuantity || 0) || undefined,
|
||||
reeferQuantity: Number(l.reeferQuantity || 0) || undefined,
|
||||
...(contractWithReturn
|
||||
? { returnQuantity: Number(l.returnQuantity || 0) }
|
||||
: {}),
|
||||
units: l.units.map((u) => ({
|
||||
containerNumber: u.containerNumber.trim().toUpperCase(),
|
||||
...(u.sealNumber ? { sealNumber: u.sealNumber } : {}),
|
||||
@@ -1168,6 +1201,28 @@ export default function GlCreateBookingForm() {
|
||||
styles={fieldStyles}
|
||||
/>
|
||||
)}
|
||||
{contractWithReturn && (
|
||||
<TextInput
|
||||
type="number"
|
||||
onKeyDown={blockNegative}
|
||||
label="With return qty"
|
||||
description="Containers EDR returns empty"
|
||||
min={0}
|
||||
value={line.returnQuantity}
|
||||
error={
|
||||
showErrors
|
||||
? lineErrors[lineIdx]?.returnQuantity
|
||||
: undefined
|
||||
}
|
||||
onChange={(e) =>
|
||||
patchLine(lineIdx, {
|
||||
returnQuantity: e.currentTarget.value,
|
||||
})
|
||||
}
|
||||
radius={10}
|
||||
styles={fieldStyles}
|
||||
/>
|
||||
)}
|
||||
</Group>
|
||||
|
||||
<StepLabel>Per-container details</StepLabel>
|
||||
@@ -1323,7 +1378,9 @@ export default function GlCreateBookingForm() {
|
||||
</StepCard>
|
||||
)}
|
||||
|
||||
{isContainer ? (
|
||||
{/* Legacy contracts only — WITH_RETURN contracts capture per-line
|
||||
return quantities above, WITHOUT_RETURN contracts locked it off. */}
|
||||
{legacyReturnToggle ? (
|
||||
<StepCard>
|
||||
<StepHeader
|
||||
icon={<Repeat size={22} />}
|
||||
|
||||
Reference in New Issue
Block a user