mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-09-09 00:08:18 +00:00
feat: add wagon usage computation and maintenance logging features
- Implemented utility to calculate wagon usage metrics for train schedules. - Created for sending wagons to maintenance with optional notes. - Added unit tests for train builder maintenance functionalities, including formatting train run labels and building maintenance notes. - Developed component for merging train schedules with detailed previews and reasons for merging. - Introduced component for selecting wagons with search functionality and selection limits. - Created for displaying and filtering audit logs, including detailed views of individual log entries. - Added for handling API interactions related to audit logs, including fetching logs and entity types.
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import {
|
||||
ContractDocPhase,
|
||||
isDeliveryOrderFileCode,
|
||||
type ClearanceFinalInvoiceSummary,
|
||||
type ClearanceOffloadState,
|
||||
type ClearanceSecondDuty,
|
||||
@@ -36,7 +37,7 @@ import { Contract } from './entities/contract.entity';
|
||||
import { ContractDocReviewStatus } from './entities/contract-document-review.entity';
|
||||
import { FilterContractDto } from './dto/filter-contract.dto';
|
||||
import { AdviseContractDutyDto } from './dto/phased-clearance.dto';
|
||||
import { buildWorkflowFiles, persistDeclarationUploads, persistTransitPermitUploads, PHASED_CUSTOMS_CONTRACT_QUEUE_STATUSES } from './phased-clearance.util';
|
||||
import { buildWorkflowFiles, persistDeclarationUploads, persistDeliveryOrderUploads, persistReleaseOrderUploads, persistTransitPermitUploads, PHASED_CUSTOMS_CONTRACT_QUEUE_STATUSES } from './phased-clearance.util';
|
||||
|
||||
const RO_VESSEL_MIN_DAYS_CODE = 'ro_vessel_min_days';
|
||||
|
||||
@@ -1449,7 +1450,7 @@ export class ContractClearanceService {
|
||||
|
||||
// GL Djibouti may have uploaded the DO early (un-gated) — count it now.
|
||||
const files = await this.filesService.findByResource(contractId, 'contracts');
|
||||
if (files.some((f) => f.code === 'delivery_order')) {
|
||||
if (files.some((f) => isDeliveryOrderFileCode(f.code))) {
|
||||
await this.workflowService.completeMilestone(contractId, 'DO_COLLECTED');
|
||||
await this.workflowService.markReadyForBooking(contractId);
|
||||
}
|
||||
@@ -1460,7 +1461,7 @@ export class ContractClearanceService {
|
||||
|
||||
async uploadDeliveryOrder(
|
||||
contractId: string,
|
||||
file: Express.Multer.File,
|
||||
files: Express.Multer.File[],
|
||||
userId?: string,
|
||||
dates?: { vesselArrivalDate?: string; doCollectedDate?: string },
|
||||
): Promise<Contract> {
|
||||
@@ -1470,19 +1471,12 @@ export class ContractClearanceService {
|
||||
throw new BadRequestException('Delivery Order applies only to import contracts.');
|
||||
}
|
||||
|
||||
if (!file) throw new BadRequestException('No Delivery Order uploaded');
|
||||
|
||||
const { vesselArrivalDate, doCollectedDate } = assertDoCollectionDates(dates);
|
||||
|
||||
// DO upload is deliberately un-gated: GL Djibouti may attach it at any point,
|
||||
// any file type. The DO_COLLECTED milestone (and booking readiness) still waits
|
||||
// for GL Ethiopia to finalize pre-clearance so the workflow order holds.
|
||||
await this.filesService.upsertByCode({
|
||||
resourceId: contractId,
|
||||
resource: 'contracts',
|
||||
code: 'delivery_order',
|
||||
file,
|
||||
});
|
||||
await persistDeliveryOrderUploads(this.filesService, contractId, 'contracts', files ?? []);
|
||||
|
||||
const cycle = await this.contractsRepository.currentCycle(contractId);
|
||||
if (cycle) {
|
||||
@@ -1520,7 +1514,7 @@ export class ContractClearanceService {
|
||||
|
||||
async uploadReleaseOrder(
|
||||
contractId: string,
|
||||
file: Express.Multer.File,
|
||||
files: Express.Multer.File[],
|
||||
vesselDepartureDate: string,
|
||||
userId?: string,
|
||||
): Promise<{ contract: Contract; hold: boolean; holdReason?: string }> {
|
||||
@@ -1535,7 +1529,6 @@ export class ContractClearanceService {
|
||||
'RELEASE_ORDER_SECURED',
|
||||
);
|
||||
|
||||
if (!file) throw new BadRequestException('No Release Order uploaded');
|
||||
if (!vesselDepartureDate?.trim()) {
|
||||
throw new BadRequestException('Vessel departure date is required');
|
||||
}
|
||||
@@ -1545,12 +1538,7 @@ export class ContractClearanceService {
|
||||
const cycle = await this.contractsRepository.currentCycle(contractId);
|
||||
if (!cycle) throw new BadRequestException('No clearance cycle found');
|
||||
|
||||
await this.filesService.upsertByCode({
|
||||
resourceId: contractId,
|
||||
resource: 'contracts',
|
||||
code: 'release_order',
|
||||
file,
|
||||
});
|
||||
await persistReleaseOrderUploads(this.filesService, contractId, 'contracts', files ?? []);
|
||||
|
||||
await this.contractsRepository.updateCycle(cycle.id, {
|
||||
vesselDepartureDate,
|
||||
|
||||
Reference in New Issue
Block a user