Enhance clearance milestone management and introduce new contract actions

- Added new milestones for 'Transit Permit Uploaded' and 'Export Transport Document Issued' in the clearance milestone catalog.
- Implemented methods in ClearanceMilestoneService to skip milestones and complete them with metadata.
- Updated ContractBookingService to check boundary conditions before booking creation.
- Introduced new endpoints in ContractsController for uploading customs declarations, advising duty, and handling various document uploads.
- Enhanced the UI to support new clearance actions and display relevant components based on milestone statuses.
This commit is contained in:
marshal
2026-07-01 10:20:16 +03:00
parent ccd5d6de31
commit 612df8daff
36 changed files with 3018 additions and 57 deletions

View File

@@ -4,6 +4,7 @@ import {
Logger,
NotFoundException,
OnModuleInit,
Optional,
} from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { Cron, SchedulerRegistry } from '@nestjs/schedule';
@@ -34,6 +35,7 @@ import {
wagonTypeDimensionsFromEntity,
} from './train-capacity.util';
import { WagonType } from '../wagon-types/entities/wagon-type.entity';
import { ClearanceMilestoneService } from '../contracts/clearance-milestone.service';
/** A train's remaining capacity along the three physical limits the batch enforces. */
interface Capacity {
@@ -179,6 +181,7 @@ export class BookingBatchService implements OnModuleInit {
private readonly notifier: BookingNotifierService,
private readonly scheduler: SchedulerRegistry,
private readonly trainSchedulingService: TrainSchedulingService,
@Optional() private readonly milestoneService?: ClearanceMilestoneService,
) {}
/** On boot, reconcile OPEN route-days and re-arm settle timers. */
@@ -1002,6 +1005,16 @@ export class BookingBatchService implements OnModuleInit {
});
this.notifier.secured(booking, reason);
void this.triggerWagonAllocation(scheduleId);
void this.markWagonAllocatedMilestone(booking.id);
}
private async markWagonAllocatedMilestone(bookingId: string): Promise<void> {
if (!this.milestoneService) return;
try {
await this.milestoneService.completeForBooking(bookingId, 'WAGON_ALLOCATED');
} catch {
// Booking may have no milestone rows (non-contract path).
}
}
/**