This commit is contained in:
marshal
2026-07-01 20:55:17 +03:00
parent 612df8daff
commit 9c18d086d7
112 changed files with 5654 additions and 1370 deletions

View File

@@ -1,4 +1,4 @@
import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common';
import { Injectable, NotFoundException } from '@nestjs/common';
import { DataSource } from 'typeorm';
import {
@@ -39,6 +39,15 @@ export class ClearanceMilestoneService {
});
}
/** Seed pre-booking milestones on a booking (GENERAL + customs per-shipment clearance). */
async seedPreBookingMilestonesOnBooking(
bookingId: string,
tradeDirection: string,
): Promise<void> {
const { preBooking } = splitMilestones(tradeDirection);
await this.seed(preBooking, { bookingId });
}
/** Seed the post-booking milestones onto a freshly created booking. */
async seedPostBookingMilestones(
bookingId: string,
@@ -94,7 +103,7 @@ export class ClearanceMilestoneService {
throw new NotFoundException(`Milestone ${code} not found for booking ${bookingId}`);
}
if (milestone.status === 'COMPLETED') {
throw new BadRequestException(`Milestone ${code} is already completed.`);
return milestone;
}
milestone.status = 'COMPLETED';
milestone.triggeredAt = new Date();
@@ -178,7 +187,7 @@ export class ClearanceMilestoneService {
throw new NotFoundException(`Milestone ${code} not found for contract ${contractId}`);
}
if (milestone.status === 'COMPLETED') {
throw new BadRequestException(`Milestone ${code} is already completed.`);
return milestone;
}
milestone.status = 'COMPLETED';
milestone.triggeredAt = new Date();
@@ -199,6 +208,27 @@ export class ClearanceMilestoneService {
return this.repo.save(milestone);
}
async skipForBooking(bookingId: string, code: string): Promise<ClearanceMilestone> {
const milestone = await this.repo.findOne({ where: { bookingId, milestoneCode: code } });
if (!milestone) {
throw new NotFoundException(`Milestone ${code} not found for booking ${bookingId}`);
}
if (milestone.status === 'COMPLETED') return milestone;
milestone.status = 'SKIPPED';
milestone.triggeredAt = new Date();
return this.repo.save(milestone);
}
async completeWithMetadataForBooking(
bookingId: string,
code: string,
metadata: MilestoneMetadata,
userId?: string,
note?: string,
): Promise<ClearanceMilestone> {
return this.completeWithMetadata(bookingId, code, metadata, userId, note);
}
/** Complete a contract milestone with structured metadata (duty advice, etc.). */
async completeWithMetadataForContract(
contractId: string,
@@ -212,7 +242,7 @@ export class ClearanceMilestoneService {
throw new NotFoundException(`Milestone ${code} not found for contract ${contractId}`);
}
if (milestone.status === 'COMPLETED') {
throw new BadRequestException(`Milestone ${code} is already completed.`);
return milestone;
}
milestone.status = 'COMPLETED';
milestone.triggeredAt = new Date();