mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 23:35:42 +00:00
fix(mile): only send bookings that bought EDR haulage to the mile queues
The rule that a customer's own truck and an EDR road leg are alternatives existed on the truck side only (CustomerTruckService.assertSelfHaulPaid). LastMileService had no counterpart: create checked payment and nothing else, so any paid booking could be accepted into the queue. A booking took a customer truck at 06:42 and an EDR last-mile leg with a real EDR truck at 06:47, neither side aware of the other, on a contract that had chosen no road legs at all. The road legs are chosen on the contract and copied onto the booking, and the pickup/delivery address is the only per-booking record of that choice. service_types cannot serve: every type ships with includes_first_mile and includes_last_mile set to true, so reading them would mean no booking could ever self-haul. That same always-true flag had already killed the first-mile guard, whose `address || serviceType.includesFirstMile` admitted every paid export booking. One shared rule now answers it for both sides, so the two halves cannot drift apart again: last-mile create rejects a booking that chose no road legs and one already carrying a customer truck; first-mile no longer honours the service-type flag; the customer-truck guard reads the same helper. Existing legs are untouched — the guards are on creation, so the one booking already carrying both needs a human to reconcile it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,10 @@ import { AddCustomerTruckDto } from './dto/add-customer-truck.dto';
|
||||
import { DepartCustomerTruckDto } from './dto/depart-customer-truck.dto';
|
||||
import { CustomerTruckAssignment } from './entities/customer-truck-assignment.entity';
|
||||
import { CustomerTruckContainer } from './entities/customer-truck-container.entity';
|
||||
import {
|
||||
EDR_HAULAGE_CONFLICT_MESSAGE,
|
||||
usesEdrMileService,
|
||||
} from '../../common/mile-haulage.util';
|
||||
import { CustomerTruckAssignmentsRepository } from './customer-truck-assignments.repository';
|
||||
import { NotificationInboxService } from '../notification-inbox/notification-inbox.service';
|
||||
import { NotificationsService } from '../notifications/notifications.service';
|
||||
@@ -534,18 +538,11 @@ export class CustomerTruckService {
|
||||
}
|
||||
|
||||
private assertSelfHaulPaid(booking: BookingGuardRow): void {
|
||||
const hasFirstMile = Boolean(booking.firstMile?.trim());
|
||||
const hasLastMile = Boolean(booking.lastMile?.trim());
|
||||
const usesMileService =
|
||||
booking.tradeDirection === 'IMPORT'
|
||||
? hasLastMile
|
||||
: booking.tradeDirection === 'EXPORT'
|
||||
? hasFirstMile
|
||||
: hasFirstMile || hasLastMile;
|
||||
if (usesMileService) {
|
||||
throw new BadRequestException(
|
||||
'Customer truck assignment is only allowed when first/last mile delivery is not selected',
|
||||
);
|
||||
// Shared with the EDR side (LastMileService.assertNoCustomerTruck) so the two
|
||||
// halves of this rule cannot drift apart — they did, and a booking ended up
|
||||
// with a customer truck and an EDR leg at once.
|
||||
if (usesEdrMileService(booking)) {
|
||||
throw new BadRequestException(EDR_HAULAGE_CONFLICT_MESSAGE);
|
||||
}
|
||||
if (booking.paymentStatus !== 'PAID') {
|
||||
throw new BadRequestException(
|
||||
|
||||
Reference in New Issue
Block a user