exclude self from container clash

This commit is contained in:
Marshal
2026-08-06 22:34:53 +00:00
parent 1b8c7e4296
commit 96a4dd2e7f
7 changed files with 37 additions and 8 deletions

View File

@@ -1882,6 +1882,9 @@ export class ContractBookingService {
async validateShipment(
contractId: string,
dto: CreateBookingUnderContractDto,
// Completion/resubmit preview: the booking being completed must not clash
// with its own persisted containers.
excludeBookingId?: string,
): Promise<{
overweightLines: Array<{
containerTypeCode: string;
@@ -2043,6 +2046,7 @@ export class ContractBookingService {
originYardId: route?.originYardId,
destinationYardId: route?.destinationYardId,
},
excludeBookingId,
);
containerClashErrors = clashes.map(
(c) =>

View File

@@ -1124,8 +1124,11 @@ export class ContractsController {
validateShipment(
@Param('id', ParseUUIDPipe) id: string,
@Body() dto: CreateBookingUnderContractDto,
// Completion/resubmit preview: exclude this booking's own persisted
// containers from the same-train clash check.
@Query('bookingId') bookingId?: string,
) {
return this.contractBookingService.validateShipment(id, dto);
return this.contractBookingService.validateShipment(id, dto, bookingId);
}
@Get(':id/capacity')

View File

@@ -961,7 +961,7 @@ export default function GlCreateBookingForm() {
// modal falls back to the contract unit-rate estimate while it loads.
const validateShipmentMutation = useMutation({
mutationFn: (dto: Freight.CreateBookingUnderContractDto) =>
contractsService.validateShipment(id ?? "", dto),
contractsService.validateShipment(id ?? "", dto, completeBookingId),
});
const validation = validateShipmentMutation.data ?? null;

View File

@@ -673,8 +673,16 @@ export const contractsService = {
validateShipment: (
id: string,
payload: Freight.CreateBookingUnderContractDto,
// Completion/resubmit preview: exclude this booking's own containers from
// the same-train clash check.
excludeBookingId?: string,
) =>
postContract<ShipmentValidation>(C.VALIDATE_SHIPMENT(id), payload),
postContract<ShipmentValidation>(
excludeBookingId
? `${C.VALIDATE_SHIPMENT(id)}?bookingId=${excludeBookingId}`
: C.VALIDATE_SHIPMENT(id),
payload,
),
/** Remaining bookable quantity per cargo line (GENERAL draw-down cap). */
getCapacity: async (id: string): Promise<Freight.ContractCapacityLine[]> => {

View File

@@ -483,7 +483,12 @@ function NewShipmentBookingForm({
// price modal opens so re-reviewing after an edit re-checks.
const validateMutation = useMutation({
mutationFn: (dto: Freight.CreateBookingUnderContractDto) =>
api.contracts.validateShipment.call({ id: contractId, dto }),
api.contracts.validateShipment.call({
id: contractId,
dto,
// Resubmit preview must not clash with this booking's own containers.
excludeBookingId: completeBookingId,
}),
});
function buildDto(

View File

@@ -610,10 +610,14 @@ export const api = {
),
validateShipment: endpoint<
{ id: string; dto: Freight.CreateBookingUnderContractDto },
{
id: string;
dto: Freight.CreateBookingUnderContractDto;
excludeBookingId?: string;
},
ShipmentValidation
>("contracts", "validateShipment", ({ id, dto }) =>
contractsService.validateShipment(id, dto),
>("contracts", "validateShipment", ({ id, dto, excludeBookingId }) =>
contractsService.validateShipment(id, dto, excludeBookingId),
),
getContractMilestones: endpoint<

View File

@@ -400,8 +400,13 @@ export const contractsService = {
validateShipment: async (
id: string,
dto: Freight.CreateBookingUnderContractDto,
// Completion/resubmit: exclude this booking's own containers from the
// same-train clash check.
excludeBookingId?: string,
): Promise<ShipmentValidation> => {
const { data } = await client.post(C.VALIDATE_SHIPMENT(id), dto);
const { data } = await client.post(C.VALIDATE_SHIPMENT(id), dto, {
params: excludeBookingId ? { bookingId: excludeBookingId } : undefined,
});
return data.data ?? data;
},