mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-27 22:30:55 +00:00
fix transi permit file upload
This commit is contained in:
@@ -863,14 +863,14 @@ export class ContractsController {
|
||||
|
||||
@Post('bookings/:bookingId/transport-document')
|
||||
@BookingStaff(FREIGHT_PERMS.contracts.clearanceEtActions)
|
||||
@UseInterceptors(FileInterceptor('file'))
|
||||
@UseInterceptors(AnyFilesInterceptor())
|
||||
@ApiConsumes('multipart/form-data')
|
||||
@ApiOperation({ summary: 'GL ET uploads export transport document after wagon allocation' })
|
||||
@ApiOperation({ summary: 'GL ET uploads export transit permit documents (multi-file)' })
|
||||
uploadTransportDocument(
|
||||
@Param('bookingId', ParseUUIDPipe) bookingId: string,
|
||||
@UploadedFile() file: Express.Multer.File,
|
||||
@UploadedFiles() files: Express.Multer.File[],
|
||||
) {
|
||||
return this.glOperationsService.uploadTransportDocument(bookingId, file);
|
||||
return this.glOperationsService.uploadTransportDocument(bookingId, files ?? []);
|
||||
}
|
||||
|
||||
@Post('bookings/:bookingId/documents')
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
IncidentType,
|
||||
} from './entities/clearance-incident.entity';
|
||||
import { ClearanceMilestoneService } from './clearance-milestone.service';
|
||||
import { persistExportTransportUploads } from './phased-clearance.util';
|
||||
|
||||
/**
|
||||
* Maps a GL post-booking document `code` to the milestone it auto-completes when
|
||||
@@ -165,7 +166,7 @@ export class GlOperationsService {
|
||||
*/
|
||||
async uploadTransportDocument(
|
||||
bookingId: string,
|
||||
file: Express.Multer.File,
|
||||
files: Express.Multer.File[],
|
||||
): Promise<{ uploaded: boolean; milestoneCompleted: boolean }> {
|
||||
const booking = await this.getBooking(bookingId);
|
||||
if (booking.tradeDirection !== 'EXPORT') {
|
||||
@@ -182,14 +183,11 @@ export class GlOperationsService {
|
||||
);
|
||||
}
|
||||
|
||||
if (!file) throw new BadRequestException('No transport document uploaded');
|
||||
if (files.length === 0) {
|
||||
throw new BadRequestException('No transit permit documents uploaded');
|
||||
}
|
||||
|
||||
await this.filesService.upsertByCode({
|
||||
resourceId: bookingId,
|
||||
resource: 'bookings',
|
||||
code: 'export_transport_document',
|
||||
file,
|
||||
});
|
||||
await persistExportTransportUploads(this.filesService, bookingId, files);
|
||||
|
||||
if (wagonAllocated && wagonAllocated.status !== 'COMPLETED') {
|
||||
await this.milestoneService.completeForBooking(bookingId, 'WAGON_ALLOCATED');
|
||||
|
||||
@@ -4,6 +4,8 @@ import {
|
||||
declarationFileLabel,
|
||||
isDeclarationFileCode,
|
||||
isImportTransitPermitFileCode,
|
||||
isExportTransportFileCode,
|
||||
exportTransportFileLabel,
|
||||
transitPermitFileLabel,
|
||||
type ClearanceWorkflowFile,
|
||||
} from '@edr/types';
|
||||
@@ -114,6 +116,50 @@ export async function persistTransitPermitUploads(
|
||||
);
|
||||
}
|
||||
|
||||
/** Require at least one export transport document in the upload batch. */
|
||||
export function assertExportTransportFiles(files: Express.Multer.File[]): void {
|
||||
if (files.length === 0) {
|
||||
throw new BadRequestException('No transit permit documents uploaded');
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeExportTransportFieldNames(
|
||||
files: Express.Multer.File[],
|
||||
): Express.Multer.File[] {
|
||||
return files.map((file, index) => ({
|
||||
...file,
|
||||
fieldname: `export_transport_document_${index}`,
|
||||
}));
|
||||
}
|
||||
|
||||
/** Replace all export transport documents on a booking with a new multi-file batch. */
|
||||
export async function persistExportTransportUploads(
|
||||
store: DeclarationFileStore,
|
||||
bookingId: string,
|
||||
files: Express.Multer.File[],
|
||||
): Promise<void> {
|
||||
const normalized = normalizeExportTransportFieldNames(files);
|
||||
assertExportTransportFiles(normalized);
|
||||
|
||||
const existing = await store.findByResource(bookingId, 'bookings');
|
||||
await Promise.all(
|
||||
existing
|
||||
.filter((f) => f.code && isExportTransportFileCode(f.code))
|
||||
.map((f) => store.deleteByCode(bookingId, 'bookings', f.code!)),
|
||||
);
|
||||
|
||||
await Promise.all(
|
||||
normalized.map((file, index) =>
|
||||
store.upload({
|
||||
resourceId: bookingId,
|
||||
resource: 'bookings',
|
||||
code: `export_transport_document_${index}`,
|
||||
file,
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
export function parseDutyRequiredForm(value: string | boolean | undefined): boolean {
|
||||
if (typeof value === 'boolean') return value;
|
||||
if (value === undefined || value === '') return false;
|
||||
@@ -251,5 +297,23 @@ export function buildWorkflowFiles(
|
||||
});
|
||||
}
|
||||
|
||||
if (tradeDirection === 'EXPORT') {
|
||||
const extraExportTransport = files
|
||||
.filter((f) => f.code && isExportTransportFileCode(f.code) && !included.has(f.code))
|
||||
.sort((a, b) => (a.code ?? '').localeCompare(b.code ?? ''));
|
||||
|
||||
extraExportTransport.forEach((file, index) => {
|
||||
if (!file.code) return;
|
||||
included.add(file.code);
|
||||
out.push({
|
||||
code: file.code,
|
||||
label: exportTransportFileLabel(file.code, index),
|
||||
uploadedBy: 'gl_et',
|
||||
category: 'transit',
|
||||
file: { id: file.id, name: file.name, url: file.url },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ export class PaymentClientService {
|
||||
private readonly logger = new Logger(PaymentClientService.name);
|
||||
private readonly baseUrl = (
|
||||
// process.env.PAYMENT_API_URL ??
|
||||
// "https://paymentcallback.triaplc.com"
|
||||
"http://localhost:3003"
|
||||
"https://paymentcallback.triaplc.com"
|
||||
// "http://localhost:3003"
|
||||
).replace(/\/$/, "");
|
||||
private readonly serviceToken = process.env.SERVICE_AUTH_TOKEN ?? "";
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@ import { PaymentEntity } from "./entities/payment.entity";
|
||||
import { PaymentRepository } from "./payment.repository";
|
||||
import { PaymentClientService } from "./payment-client.service";
|
||||
import { BillingService } from "../billing/billing.service";
|
||||
import { FirstMileService } from "../first-mile/first-mile.service";
|
||||
import { BookingBatchService } from "../train-scheduling/booking-batch.service";
|
||||
|
||||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
@@ -108,9 +106,6 @@ export class PaymentService {
|
||||
private readonly paymentClient: PaymentClientService,
|
||||
@Inject(forwardRef(() => BillingService))
|
||||
private readonly billing: BillingService,
|
||||
@Inject(forwardRef(() => BookingBatchService))
|
||||
private readonly bookingBatchService: BookingBatchService,
|
||||
private readonly firstMileService: FirstMileService,
|
||||
) { }
|
||||
|
||||
async getAll(filters: {
|
||||
|
||||
Reference in New Issue
Block a user