mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-08 05:25:41 +00:00
Merge pull request #1472 from Tria-plc/freight_feature/usermanagement
feat: Implement handling for partially loaded bookings in train sched…
This commit is contained in:
@@ -139,8 +139,17 @@ export function WagonCancellationCard({
|
||||
// rows this booking opened itself can be paid/withdrawn/rebooked from here.
|
||||
const rows = data?.items ?? [];
|
||||
const ownRows = rows.filter((r) => r.bookingId === booking.id);
|
||||
const openRow = ownRows.find((r) => r.status === "FEE_PENDING");
|
||||
const creditRow = ownRows.find((r) => r.status === "CREDIT_AVAILABLE");
|
||||
// A cancellation owes its fee whenever a customer-fault fee is still
|
||||
// unsettled. FEE_PENDING is the customer-requested flow (cut applies at
|
||||
// payment); an AT-LOADING cut applies immediately and jumps straight to
|
||||
// CREDIT_AVAILABLE with its invoice left open — so status alone would hide
|
||||
// the fee and offer a "no further payment needed" rebook on money still owed.
|
||||
const owesFee = (r: (typeof ownRows)[number]) =>
|
||||
r.fault === "CUSTOMER" && Number(r.feeAmount ?? 0) > 0 && !r.feePaidAt;
|
||||
const openRow = ownRows.find((r) => r.status === "FEE_PENDING" || owesFee(r));
|
||||
const creditRow = ownRows.find(
|
||||
(r) => r.status === "CREDIT_AVAILABLE" && !owesFee(r),
|
||||
);
|
||||
|
||||
const feePay = useFeeInvoicePayment(booking.id);
|
||||
|
||||
@@ -237,7 +246,14 @@ export function WagonCancellationCard({
|
||||
toast.error(apiErrorMessage(e, "Could not rebook the wagons. Please try again.")),
|
||||
});
|
||||
|
||||
if (!eligible) return null;
|
||||
// Showing the card is NOT the same as allowing a new cut. A partial cancel at
|
||||
// loading leaves the kept wagons to ride, so the booking moves on to
|
||||
// IN_TRANSIT/ARRIVED/COMPLETED while its cancellation still owes a fee and
|
||||
// holds a rebookable credit. Gating on PAID/CANCELLED hid exactly that case —
|
||||
// the customer saw neither the cancelled wagons nor the fee they owe. Any
|
||||
// booking that HAS cancellation rows keeps the card, whatever its status;
|
||||
// `canRequest` still limits NEW cuts to a live PAID booking.
|
||||
if (!eligible && !ownRows.length) return null;
|
||||
if (!canRequest && !ownRows.length) return null;
|
||||
|
||||
return (
|
||||
@@ -265,8 +281,10 @@ export function WagonCancellationCard({
|
||||
{fmtMoney(openRow.feeAmount, openRow.feeCurrency)}
|
||||
</Text>
|
||||
. The cancelled wagons have left the train. Pay the fee to unlock
|
||||
the rebooking credit. The request cannot be withdrawn from here —
|
||||
if it was a mistake, contact EDR staff.
|
||||
the rebooking credit — the {Number(openRow.wagonsCancelled)} cancelled
|
||||
wagon(s) can then be rebooked on a coming train day. The request
|
||||
cannot be withdrawn from here — if it was a mistake, contact EDR
|
||||
staff.
|
||||
</Alert>
|
||||
<Group gap={8}>
|
||||
<Button
|
||||
|
||||
@@ -459,7 +459,15 @@ export default function BookingsListPage() {
|
||||
const creditByBooking = useMemo(() => {
|
||||
const m = new Map<string, WagonCancellation>();
|
||||
for (const r of myCancellations?.items ?? []) {
|
||||
if (r.status === "CREDIT_AVAILABLE" && !m.has(r.bookingId)) m.set(r.bookingId, r);
|
||||
// A customer-fault cut invoices a fee. An at-loading cut applies at once
|
||||
// and opens the credit with that invoice still OPEN, so CREDIT_AVAILABLE
|
||||
// alone never means the fee was settled — offering "Rebook" here would
|
||||
// let the customer redeem the wagons without ever paying. Those rows fall
|
||||
// through to the row's Pay button instead (the fee is on my-payables).
|
||||
const owesFee =
|
||||
r.fault === "CUSTOMER" && Number(r.feeAmount ?? 0) > 0 && !r.feePaidAt;
|
||||
if (r.status === "CREDIT_AVAILABLE" && !owesFee && !m.has(r.bookingId))
|
||||
m.set(r.bookingId, r);
|
||||
}
|
||||
return m;
|
||||
}, [myCancellations]);
|
||||
|
||||
@@ -282,6 +282,8 @@ export interface WagonCancellation {
|
||||
feeCurrency: string;
|
||||
feeInvoiceId?: string | null;
|
||||
feePaidAt?: string | null;
|
||||
/** Who caused the cut: CUSTOMER pays a fee, EDR never does. */
|
||||
fault?: "CUSTOMER" | "EDR" | null;
|
||||
status: WagonCancellationStatus;
|
||||
reason?: string | null;
|
||||
rebookedAt?: string | null;
|
||||
|
||||
Reference in New Issue
Block a user