mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
feat(freight): add company logo setting applied to every generated document
New logo-settings module (mirrors stamp-settings): single uploaded logo, stored via FilesService/MinIO, injected as a data URL into invoice/receipt, contract, warehouse, train-scheduling, and payment-receipt PDFs. Adds a matching backoffice settings page and settings:logo:view/manage permissions. >
This commit is contained in:
@@ -181,6 +181,7 @@ describe('TrainSchedulingService', () => {
|
||||
autoArriveAtFinalYard: jest.fn().mockResolvedValue([]),
|
||||
} as never, // bookingJourneyService
|
||||
{ dispatched: jest.fn(), arrived: jest.fn() } as never, // bookingNotifier
|
||||
{ getLogoImageUrl: jest.fn().mockResolvedValue(null) } as never, // logoSettings
|
||||
);
|
||||
|
||||
const defaultFleetWagons = [
|
||||
|
||||
@@ -177,6 +177,8 @@ import { RouteMilestone } from '../../routes/entities/route-milestone.entity';
|
||||
import { deriveTradeDirection } from '../../../common/derive-trade-direction.util';
|
||||
import { WarehouseInventoryService } from '../../warehouses/warehouse-inventory.service';
|
||||
import { WarehouseReleaseDocumentService } from '../../warehouses/warehouse-release-document.service';
|
||||
import { LogoSettingsService } from '../../logo-settings/logo-settings.service';
|
||||
import { logoImageCss, logoMarkup } from '../../billing/documents/logo-markup.util';
|
||||
import {
|
||||
autoFillPlacements,
|
||||
findMissingContainerNumberIssues,
|
||||
@@ -376,6 +378,7 @@ export class TrainSchedulingService {
|
||||
private readonly bookingWindowGateway: BookingWindowGateway,
|
||||
private readonly bookingJourneyService: BookingJourneyService,
|
||||
private readonly bookingNotifier: BookingNotifierService,
|
||||
private readonly logoSettings: LogoSettingsService,
|
||||
@Optional() private readonly milestoneService?: ClearanceMilestoneService,
|
||||
private readonly configService?: ConfigService,
|
||||
// forwardRef: BookingBatchService injects this service back; @Optional so
|
||||
@@ -3025,7 +3028,7 @@ export class TrainSchedulingService {
|
||||
const loadList = await this.generateImportLoadList(scheduleId, {
|
||||
performedBy: 'DOCUMENT_GENERATION',
|
||||
});
|
||||
const html = this.buildImportLoadListHtml(loadList);
|
||||
const html = this.buildImportLoadListHtml(loadList, await this.logoSettings.getLogoImageUrl());
|
||||
// Styled table-aware fallback (marshalling grid) when Chromium is unavailable —
|
||||
// NOT the release-order fallback (would mislabel this as a gate-clearance order).
|
||||
const buffer = await this.pdfDocuments.renderTabularDocument(html, 'Import marshalling / load list');
|
||||
@@ -3045,7 +3048,9 @@ export class TrainSchedulingService {
|
||||
throw new BadRequestException('Export marshalling document applies only to EXPORT schedules');
|
||||
}
|
||||
|
||||
const html = this.buildExportLoadListHtml(schedule);
|
||||
const html = this.buildExportLoadListHtml(schedule, {
|
||||
logoImageUrl: await this.logoSettings.getLogoImageUrl(),
|
||||
});
|
||||
// Styled table-aware fallback (marshalling grid) — see importLoadListDocument.
|
||||
const buffer = await this.pdfDocuments.renderTabularDocument(html, 'Export marshalling / load list');
|
||||
const reference = schedule.trainNumber ?? schedule.id;
|
||||
@@ -3117,6 +3122,7 @@ export class TrainSchedulingService {
|
||||
positionLabel,
|
||||
wagons,
|
||||
unassignedBookings,
|
||||
logoImageUrl: await this.logoSettings.getLogoImageUrl(),
|
||||
});
|
||||
// Styled table-aware fallback (marshalling grid) — see importLoadListDocument.
|
||||
const buffer = await this.pdfDocuments.renderTabularDocument(html, 'Intercity marshalling / load list');
|
||||
@@ -3160,6 +3166,7 @@ export class TrainSchedulingService {
|
||||
positionLabel?: string;
|
||||
wagons?: TrainSetWagon[];
|
||||
unassignedBookings?: Booking[];
|
||||
logoImageUrl?: string | null;
|
||||
},
|
||||
): string {
|
||||
const esc = (value: unknown) =>
|
||||
@@ -3278,6 +3285,7 @@ export class TrainSchedulingService {
|
||||
.tile { border: 1px solid #cbd5e1; padding: 8px; min-height: 50px; }
|
||||
.tile span { display: block; color: #64748b; font-size: 9px; text-transform: uppercase; letter-spacing: .05em; margin-bottom: 4px; }
|
||||
.tile strong { font-size: 11px; }
|
||||
${logoImageCss()}
|
||||
table { width: 100%; border-collapse: collapse; }
|
||||
th { background: #f8fafc; color: #475569; text-align: left; }
|
||||
th, td { border: 1px solid #cbd5e1; padding: 5px 6px; font-size: 9.5px; vertical-align: top; }
|
||||
@@ -3292,6 +3300,7 @@ export class TrainSchedulingService {
|
||||
<body>
|
||||
<div class="top">
|
||||
<div>
|
||||
${logoMarkup(opts?.logoImageUrl)}
|
||||
<div class="brand">Ethio-Djibouti Railway S.C.</div>
|
||||
<h1>${esc(opts?.title ?? 'Export Marshalling Document / Load List')}</h1>
|
||||
</div>
|
||||
@@ -3471,7 +3480,10 @@ export class TrainSchedulingService {
|
||||
}
|
||||
}
|
||||
|
||||
private buildImportLoadListHtml(loadList: Awaited<ReturnType<TrainSchedulingService['generateImportLoadList']>>): string {
|
||||
private buildImportLoadListHtml(
|
||||
loadList: Awaited<ReturnType<TrainSchedulingService['generateImportLoadList']>>,
|
||||
logoImageUrl?: string | null,
|
||||
): string {
|
||||
const esc = (value: unknown) =>
|
||||
String(value ?? '-')
|
||||
.replace(/&/g, '&')
|
||||
@@ -3562,6 +3574,7 @@ export class TrainSchedulingService {
|
||||
.tile { border: 1px solid #cbd5e1; padding: 10px; min-height: 58px; }
|
||||
.tile span { display: block; color: #64748b; font-size: 10px; text-transform: uppercase; letter-spacing: .05em; margin-bottom: 5px; }
|
||||
.tile strong { font-size: 13px; }
|
||||
${logoImageCss()}
|
||||
.status { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; margin-top: 14px; }
|
||||
.step { border: 1px solid #cbd5e1; padding: 8px; font-size: 10px; text-align: center; min-height: 48px; }
|
||||
.done { background: #ecfdf5; border-color: #22c55e; color: #14532d; font-weight: 700; }
|
||||
@@ -3583,6 +3596,7 @@ export class TrainSchedulingService {
|
||||
<div class="doc">
|
||||
<div class="top">
|
||||
<div>
|
||||
${logoMarkup(logoImageUrl)}
|
||||
<div class="brand">Ethio-Djibouti Railway S.C.</div>
|
||||
<h1>Import Load List /<br />Marshalling Document</h1>
|
||||
<div class="subtitle">Djibouti-side gatepass, loading, and departure manifest</div>
|
||||
|
||||
Reference in New Issue
Block a user