implement update train details feature: add DTO, service method, and UI modal for editing train name and run numbers

This commit is contained in:
Marshal
2026-07-15 20:14:39 +00:00
parent d7d9db9c3a
commit fc44eee25e
44 changed files with 970 additions and 14 deletions

View File

@@ -24,6 +24,7 @@ import { SignaturesService } from '../signatures/signatures.service';
import { OtpService } from '../otp/otp.service';
import { ContractTemplatesService } from '../contract-templates/contract-templates.service';
import { ContractPricingService } from './contract-pricing.service';
import { ClearanceFeeService } from './clearance-fee.service';
import { ContractNotifierService } from './contract-notifier.service';
import { ClearanceMilestoneService } from './clearance-milestone.service';
import { ContractsRepository } from './contracts.repository';
@@ -89,6 +90,7 @@ export class ContractTransitionService {
private readonly otpService: OtpService,
private readonly notifier: ContractNotifierService,
private readonly contractTemplates: ContractTemplatesService,
private readonly clearanceFeeService: ClearanceFeeService,
) {}
/** Customer submits the contract for approval → SUBMITTED; freeze unit rates. */
@@ -866,8 +868,17 @@ export class ContractTransitionService {
const cycleNumber = (contract.clearanceCycleNumber ?? 0) + 1;
const cycle = await this.contractsRepository.openCycle(contractId, cycleNumber);
await this.milestoneService.seedPreBookingMilestones(contract, cycle.id);
updates.status = 'AWAITING_CLEARANCE_DOCUMENTS';
updates.clearanceStatus = 'AWAITING_DOCUMENTS';
// Path B prepay gate: the customs clearance service fee is invoiced here
// and must settle before the document step opens (the paid event advances
// to AWAITING_CLEARANCE_DOCUMENTS). Path A (self-clearance) has no GL fee.
if (await this.clearanceFeeService.gateApplies(contract)) {
await this.clearanceFeeService.issueForContract(contract);
updates.status = 'AWAITING_CLEARANCE_PAYMENT';
updates.clearanceStatus = 'AWAITING_PAYMENT';
} else {
updates.status = 'AWAITING_CLEARANCE_DOCUMENTS';
updates.clearanceStatus = 'AWAITING_DOCUMENTS';
}
updates.clearanceCycleNumber = cycleNumber;
} else {
// No contract-level clearance gate — DOMESTIC, or any GENERAL contract