mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-07 20:05:41 +00:00
fix(freight): gate loading on booking paymentStatus only; default schedule voyage no. to train's voyage number
This commit is contained in:
@@ -442,8 +442,11 @@ export class TrainSchedulingService {
|
||||
relations: { company: true },
|
||||
});
|
||||
for (const b of bookings) {
|
||||
if (event === 'dispatched') this.bookingNotifier.dispatched(b, origin, destination);
|
||||
else this.bookingNotifier.arrived(b, origin, destination);
|
||||
if (event === 'dispatched') {
|
||||
this.bookingNotifier.dispatched(b, origin, destination, schedule);
|
||||
} else {
|
||||
this.bookingNotifier.arrived(b, origin, destination, schedule);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
this.logger.warn(`Failed to notify schedule bookings (${event}): ${(err as Error).message}`);
|
||||
@@ -1169,7 +1172,7 @@ export class TrainSchedulingService {
|
||||
});
|
||||
for (const booking of allocatedBookings) {
|
||||
if (['CANCELLED', 'EXPIRED', 'REJECTED'].includes(booking.status)) continue;
|
||||
this.bookingNotifier.rescheduled(booking, departure);
|
||||
this.bookingNotifier.rescheduled(booking, departure, schedule);
|
||||
notifiedCount += 1;
|
||||
}
|
||||
}
|
||||
@@ -1374,7 +1377,7 @@ export class TrainSchedulingService {
|
||||
.getRepository(Booking)
|
||||
.update(aboard.map((b) => b.id), { scheduledDate: departure } as never);
|
||||
for (const booking of aboard) {
|
||||
this.bookingNotifier.maintenanceMoved(booking, departure);
|
||||
this.bookingNotifier.maintenanceMoved(booking, departure, schedule, dto.reason);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1871,6 +1874,10 @@ export class TrainSchedulingService {
|
||||
status: TrainScheduleStatusEnum.Scheduled,
|
||||
direction,
|
||||
trainNumber: pairTrainNumber ?? undefined,
|
||||
// Staff-entered at creation; the UI defaults it to the built train's
|
||||
// own voyage number (Train.trainName). Fall back to the pair train
|
||||
// number here only for non-UI callers that send none.
|
||||
voyageNumber: dto.voyageNumber?.trim() || pairTrainNumber || null,
|
||||
maxWagons,
|
||||
plannedWagonYards,
|
||||
reverseWagonOrder: dto.reverseWagonOrder ?? false,
|
||||
@@ -2530,7 +2537,8 @@ export class TrainSchedulingService {
|
||||
.getRepository(Booking)
|
||||
.findOne({ where: { id: bookingId }, relations: { company: true } });
|
||||
if (removedBooking && opts.notifyCustomer !== false) {
|
||||
this.bookingNotifier.removedFromTrain(removedBooking);
|
||||
// The booking's train_schedule_id is already cleared — name the run explicitly.
|
||||
this.bookingNotifier.removedFromTrain(removedBooking, schedule);
|
||||
}
|
||||
this.logger.log(
|
||||
`Booking ${bookingReference} removed from schedule ${scheduleId} by user ${userId ?? 'unknown'} — customer notified to reschedule or cancel.`,
|
||||
@@ -3101,7 +3109,7 @@ export class TrainSchedulingService {
|
||||
AND b.deleted_at IS NULL
|
||||
AND b.origin_yard_id = $2
|
||||
AND b.loaded_at IS NULL
|
||||
AND (b.status = 'PAID' OR (b.is_government = true AND b.status = 'APPROVED'))
|
||||
AND (b.payment_status = 'PAID' OR (b.is_government = true AND b.status = 'APPROVED'))
|
||||
AND ($4::uuid[] IS NULL OR b.id = ANY($4::uuid[]))`,
|
||||
[
|
||||
scheduleId,
|
||||
@@ -3318,7 +3326,7 @@ export class TrainSchedulingService {
|
||||
AND b.loading_started_at IS NULL
|
||||
AND COALESCE(tsb.loading_status, 'UNLOADED') <> 'LOADED'
|
||||
AND b.is_government = false
|
||||
AND (b.status = 'PAID'
|
||||
AND (b.payment_status = 'PAID'
|
||||
OR (b.shipping_line_company_id IS NOT NULL AND b.status = 'FULLY_EXECUTED'))`,
|
||||
[scheduleId, originYardId],
|
||||
);
|
||||
@@ -3432,7 +3440,7 @@ export class TrainSchedulingService {
|
||||
// milestone still counts as paid — the clearance views self-heal the row on
|
||||
// read, and the gate pass must not lag behind that.
|
||||
for (const booking of bookings) {
|
||||
if (booking.paymentStatus === 'PAID' || booking.status === 'PAID') {
|
||||
if (booking.paymentStatus === 'PAID') {
|
||||
paidBookingIds.add(booking.id);
|
||||
}
|
||||
}
|
||||
@@ -5667,7 +5675,8 @@ export class TrainSchedulingService {
|
||||
const booking = await this.bookingsRepository
|
||||
.findByIdWithFiles(sb.bookingId)
|
||||
.catch(() => null);
|
||||
if (booking) this.bookingNotifier.scheduleCancelled(booking);
|
||||
// Detached above, so pass the cancelled schedule for its train/voyage numbers.
|
||||
if (booking) this.bookingNotifier.scheduleCancelled(booking, schedule);
|
||||
}
|
||||
|
||||
// Window retired (DONE) — remove the card from portal/GL lists right away.
|
||||
@@ -10271,6 +10280,8 @@ export class TrainSchedulingService {
|
||||
// without the wagons' tare. The legs tab shows this per booking.
|
||||
cargoWeightTons: sb.booking ? bookingCargoTons(sb.booking) : 0,
|
||||
status: sb.booking?.status ?? null,
|
||||
// Loadability is decided by the payment status, not `status`.
|
||||
paymentStatus: sb.booking?.paymentStatus ?? null,
|
||||
schedulingStatus: sb.booking?.schedulingStatus ?? null,
|
||||
freightType: sb.booking?.freightType ?? null,
|
||||
// Which leg of the corridor this booking rides — the workspace can't
|
||||
@@ -11584,7 +11595,11 @@ export class TrainSchedulingService {
|
||||
return assignability.shortage;
|
||||
}
|
||||
|
||||
/** Paid (or government) bookings that may be loaded onto wagons — excludes expired / awaiting payment. */
|
||||
/**
|
||||
* Paid (or government) bookings that may be loaded onto wagons — excludes
|
||||
* expired / awaiting payment. "Paid" is read from the PAYMENT status only;
|
||||
* the booking status is not a reliable payment signal.
|
||||
*/
|
||||
private isReadyToLoadBooking(booking: {
|
||||
status: string;
|
||||
paymentStatus?: string | null;
|
||||
@@ -11594,7 +11609,7 @@ export class TrainSchedulingService {
|
||||
if (booking.status === 'SELECTED_FOR_BATCH' || booking.status === 'AWAITING_PAYMENT') {
|
||||
return false;
|
||||
}
|
||||
if (booking.status === 'PAID' || booking.paymentStatus === 'PAID') return true;
|
||||
if (booking.paymentStatus === 'PAID') return true;
|
||||
if (booking.isGovernment) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user