feat(train-scheduling): implement container movement between wagons

- Added functionality to move containers between wagons in the train scheduling system.
- Introduced  API endpoint and service method to handle container movement.
- Updated  component to support drag-and-drop for rearranging containers.
- Enhanced  to allow moving containers to other wagons via a context menu.
- Implemented UI feedback for container movement actions, including loading states and success/error notifications.
- Updated relevant types and constants to accommodate new container movement logic.
- Added tests for the rule engine to ensure proper handling of hazardous bookings.
This commit is contained in:
Marshal
2026-07-21 23:02:06 +00:00
parent 00a81fda15
commit 835c9e111c
35 changed files with 1896 additions and 154 deletions

View File

@@ -584,6 +584,15 @@ export function ScheduleWorkspacePanel({
customer={b.customer}
weightTons={b.weightTons}
status={b.status}
intercity={b.tradeDirection === "DOMESTIC"}
leg={
b.origin &&
b.destination &&
(b.originYardId !== schedule.originStation?.id ||
b.destinationYardId !== schedule.destinationStation?.id)
? `${b.origin}${b.destination}`
: null
}
loadingStatus={b.wagonAssigned ? b.loadingStatus ?? "UNLOADED" : undefined}
right={
canManage ? (
@@ -840,6 +849,8 @@ function BookingCard({
status,
loadingStatus,
waitingForWagon,
intercity,
leg,
right,
}: {
reference: string;
@@ -849,6 +860,10 @@ function BookingCard({
loadingStatus?: "LOADED" | "UNLOADED";
/** Paid, but no wagon of the required type was free — waiting for one. */
waitingForWagon?: boolean;
/** DOMESTIC ride-along riding only part of this train's corridor. */
intercity?: boolean;
/** "Origin → Destination" when the booking rides a sub-corridor leg. */
leg?: string | null;
right?: React.ReactNode;
}) {
return (
@@ -874,6 +889,16 @@ function BookingCard({
{reference}
</Text>
{status ? <BookingStatusBadge status={status} /> : null}
{intercity ? (
<Tooltip
label="Intercity ride-along — rides only its own leg of this train's corridor"
withArrow
>
<Badge size="sm" radius="sm" variant="filled" color="indigo">
Intercity
</Badge>
</Tooltip>
) : null}
{waitingForWagon ? (
<Tooltip
label="Paid, but no wagon of the required type was free. Free a wagon or assign it to a same-day train that has one."
@@ -907,6 +932,11 @@ function BookingCard({
</Text>
</Group>
) : null}
{leg ? (
<Text size="xs" c="indigo.7" fw={600} style={{ whiteSpace: "nowrap" }}>
{leg}
</Text>
) : null}
</Group>
</Stack>
{right ? <Box style={{ flexShrink: 0 }}>{right}</Box> : null}