diff --git a/apps/edr-freight-api/src/modules/billing/billing.service.ts b/apps/edr-freight-api/src/modules/billing/billing.service.ts index ab6b2f8c8..a334b5e28 100644 --- a/apps/edr-freight-api/src/modules/billing/billing.service.ts +++ b/apps/edr-freight-api/src/modules/billing/billing.service.ts @@ -957,7 +957,7 @@ export class BillingService { returnUrl: opts.returnUrl, failureUrl: opts.failureUrl, }); - +// // Link the intent to the invoice BEFORE any settlement can correlate against it. await this.dataSource .getRepository(Invoice) diff --git a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts index 240f7071f..265f9e676 100644 --- a/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts +++ b/apps/edr-freight-api/src/modules/train-scheduling/train-scheduling.service.ts @@ -20,6 +20,7 @@ import { DataSource, EntityManager, In, IsNull, Not } from 'typeorm'; import { BookingsRepository } from '../bookings/bookings.repository'; import { Booking } from '../bookings/entities/booking.entity'; import { BookingContainer } from '../bookings/entities/booking-container.entity'; +import { ClearanceMilestone } from '../contracts/entities/clearance-milestone.entity'; import { Container } from '../container-management/entities/container.entity'; import { Locomotive } from '../locomotives/entities/locomotive.entity'; import { LocomotivesRepository } from '../locomotives/locomotives.repository'; @@ -1168,12 +1169,47 @@ export class TrainSchedulingService { notes: dto.notes ?? operation.notes ?? null, }); + await this.completeGatepassMilestoneForSchedule(scheduleId, securedAt); + console.log( `[NOTIFY] Gate pass secured for train ${schedule.trainNumber ?? schedule.id}; Djibouti Port entry is allowed.`, ); return this.getImportDjiboutiOperation(schedule.id); } + /** + * Bridge write: also flips the legacy clearance-side GATEPASS_GRANTED + * milestone for every customs booking on this schedule, so contract/booking + * clearance views still reading that milestone (older deployed builds) see + * the gate pass as done. Drop once every clearance-api deployment reads + * ImportDjiboutiOperation.gatepassGrantedAt directly. + */ + private async completeGatepassMilestoneForSchedule( + scheduleId: string, + securedAt: Date, + ): Promise { + const bookings = await this.dataSource.getRepository(Booking).find({ + where: { trainScheduleId: scheduleId, customsClearingEnabled: true }, + }); + if (bookings.length === 0) return; + + const milestoneRepo = this.dataSource.getRepository(ClearanceMilestone); + const rows = await milestoneRepo.find({ + where: { + bookingId: In(bookings.map((b) => b.id)), + milestoneCode: 'GATEPASS_GRANTED', + }, + }); + + for (const row of rows) { + if (row.status === 'COMPLETED') continue; + row.status = 'COMPLETED'; + row.triggeredAt = securedAt; + row.metadata = { ...(row.metadata ?? {}), gatepassAt: securedAt.toISOString() }; + await milestoneRepo.save(row); + } + } + async markImportReadyForLoading(scheduleId: string, dto: ImportDjiboutiActionDto = {}) { const schedule = await this.getImportDjiboutiSchedule(scheduleId); const operation = await this.getOrCreateImportDjiboutiOperation(scheduleId);