mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 00:38:11 +00:00
Fix customer_truck_containers status
This commit is contained in:
@@ -1424,12 +1424,14 @@ export class BookingsService {
|
||||
schedule?.status ?? null;
|
||||
}
|
||||
|
||||
// A generated-but-unsigned handover means the customer must approve delivery.
|
||||
// Surfaced so the portal shows "Approve delivery" as soon as the handover
|
||||
// exists, independent of the truck-arrival flag.
|
||||
// A generated-but-unsigned SELF_HAUL handover means the customer must approve
|
||||
// delivery from the portal (booking-based, one per booking). EDR last-mile
|
||||
// handovers are per delivering truck and signed by the receiver at the door,
|
||||
// so they never surface the portal "Approve delivery" action.
|
||||
const [pendingHandover] = await this.dataSource.query(
|
||||
`SELECT 1 FROM freight.booking_handovers
|
||||
WHERE booking_id = $1 AND signed_at IS NULL AND deleted_at IS NULL
|
||||
AND mile_type = 'SELF_HAUL'
|
||||
LIMIT 1`,
|
||||
[id],
|
||||
);
|
||||
|
||||
@@ -312,6 +312,13 @@ export class CustomerTruckService {
|
||||
if (assignment.departedAt) {
|
||||
throw new ConflictException('This truck has already left — its load is locked');
|
||||
}
|
||||
// Containers can only be loaded after the truck has physically arrived at the
|
||||
// warehouse (arrival weighing recorded). Assignment alone is just planning.
|
||||
if (!assignment.arrivedAt) {
|
||||
throw new BadRequestException(
|
||||
'Record the truck arrival before loading — containers can only be loaded onto an arrived truck',
|
||||
);
|
||||
}
|
||||
|
||||
const requested = (dto.containerNumbers ?? []).map((n) => n.trim().toUpperCase());
|
||||
if (!requested.length) {
|
||||
@@ -333,12 +340,16 @@ export class CustomerTruckService {
|
||||
const grossTons = await this.vgmTonsForContainers(bookingId, requested);
|
||||
await this.dataSource.transaction(async (manager) => {
|
||||
await manager.getRepository(CustomerTruckContainer).softDelete({ assignmentId });
|
||||
// Operator loading the truck: stamp loaded_at so these containers move to
|
||||
// the LOADED stage (customer assignment alone leaves loaded_at null).
|
||||
const loadedAt = new Date();
|
||||
await manager.getRepository(CustomerTruckContainer).save(
|
||||
requested.map((containerNumber) =>
|
||||
manager.getRepository(CustomerTruckContainer).create({
|
||||
assignmentId,
|
||||
bookingId,
|
||||
containerNumber,
|
||||
loadedAt,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -23,4 +23,12 @@ export class CustomerTruckContainer extends BaseEntity {
|
||||
|
||||
@Column({ name: 'container_number', type: 'varchar', length: 64 })
|
||||
containerNumber!: string;
|
||||
|
||||
/**
|
||||
* When the container was actually loaded onto the truck by the operator.
|
||||
* Null = customer-assigned (planned) but not yet loaded. Stage LOADED requires
|
||||
* this to be set, so customer assignment alone does not mark a container loaded.
|
||||
*/
|
||||
@Column({ name: 'loaded_at', type: 'timestamptz', nullable: true })
|
||||
loadedAt?: Date | null;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user