diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts
index c167e3077..dc3719207 100644
--- a/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts
+++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-inventory.service.ts
@@ -1736,6 +1736,7 @@ export class WarehouseInventoryService {
const [row] = await this.dataSource.query(
`SELECT inv.id,
inv.release_date AS "releaseDate",
+ inv.release_order_reference AS "releaseOrderReference",
inv.quantity,
inv.weight,
inv.status,
@@ -1777,8 +1778,10 @@ export class WarehouseInventoryService {
throw new BadRequestException('A release order must be issued before downloading the exit paper');
}
- const reference = `REL-${id.slice(0, 8).toUpperCase()}`;
- const bookingReference = row?.bookingReference || row?.bookingId || 'N/A';
+ const bookingReference = row?.bookingReference || 'N/A';
+ const reference =
+ row?.releaseOrderReference ||
+ (row?.bookingReference ? `REL-${String(row.bookingReference).replace(/^BK-?/i, '')}` : 'REL-N/A');
const issuedAt = new Date(row.releaseDate);
const html = this.buildReleaseDocumentHtml({
reference,
@@ -1796,6 +1799,7 @@ export class WarehouseInventoryService {
yard: [row?.yardName, row?.yardCode].filter(Boolean).join(' / ') || null,
zone: [row?.zoneName, row?.zoneCode].filter(Boolean).join(' / ') || null,
inventoryStatus: row?.status ?? null,
+ clearanceStatus: 'CLEARED FOR WAREHOUSE EXIT',
});
return {
@@ -2300,6 +2304,7 @@ export class WarehouseInventoryService {
yard: string | null;
zone: string | null;
inventoryStatus: string | null;
+ clearanceStatus: string;
}): string {
const esc = (value: unknown) =>
String(value ?? '-')
@@ -2316,71 +2321,84 @@ export class WarehouseInventoryService {
minute: '2-digit',
});
const rows = [
- ['Booking reference', data.bookingReference],
- ['Customer', data.customerName],
- ['Booking status', data.bookingStatus],
- ['Freight type', data.freightType],
- ['Trade direction', data.tradeDirection],
- ['Container number', data.containerNumber],
- ['Cargo / goods', data.cargoDescription],
+ ['Booking Reference', data.bookingReference],
+ ['Customer / Consignee', data.customerName],
+ ['Booking Status', data.bookingStatus],
+ ['Freight Type', data.freightType],
+ ['Trade Direction', data.tradeDirection],
+ ['Container Number', data.containerNumber],
+ ['Cargo / Goods Description', data.cargoDescription],
['Quantity', data.quantity],
- ['Weight', `${data.weight.toLocaleString()} kg`],
+ ['Declared Weight', `${data.weight.toLocaleString()} kg`],
['Warehouse', data.warehouse],
['Yard', data.yard],
['Zone', data.zone],
- ['Inventory status', data.inventoryStatus],
+ ['Inventory Status', data.inventoryStatus],
+ ['Clearance Status', data.clearanceStatus],
];
return `
- Warehouse Release Exit Paper
+ Warehouse Gate Clearance / Release Order
-
EDR Warehouse Operations
-
Warehouse Release / Exit Paper
+
Ethio-Djibouti Railway S.C.
+
Warehouse Gate Clearance / Release Order
+
Official warehouse release and exit authorization
- Release reference
+ Document / Release No.
${esc(data.reference)}
Issued: ${esc(issuedAt)}
+
EDR
Warehouse
Cleared
- This document authorizes the listed booking/goods to leave the warehouse after release checks.
+ This clearance document confirms that the listed booking/goods are authorized for warehouse exit, subject to gate identity verification and confirmation that no blocking warehouse fees remain unpaid.
+
Release Particulars
${rows.map(([label, value]) => `| ${esc(label)} | ${esc(value)} |
`).join('')}
+
Authorization Clause
+
+ The warehouse officer and gate staff shall verify this document against the booking reference, customer or driver identity,
+ cargo details, clearance status, and payment records before permitting exit from the warehouse premises.
+
-
Warehouse officer name / signature / date
+
Authorized warehouse officer name / signature / date
Customer or driver name / signature / date
diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.service.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.service.ts
index 7ec13602d..45c471db1 100644
--- a/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.service.ts
+++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-invoice.service.ts
@@ -28,6 +28,22 @@ export interface PayInvoiceDto {
const BLOCKING_STATUSES: WarehouseInvoiceStatus[] = ['ISSUED', 'PARTIALLY_PAID'];
const ACTIVE_STATUSES: WarehouseInvoiceStatus[] = ['ISSUED', 'PARTIALLY_PAID', 'PAID'];
+export interface InvoiceDocumentDetails {
+ bookingReference: string | null;
+ customerName: string | null;
+ inventoryReference: string | null;
+ inventoryInfo: string | null;
+ inventoryStatus: string | null;
+ containerNumber: string | null;
+ cargoDescription: string | null;
+ clearanceStatus: string;
+ warehouseName: string | null;
+ yardName: string | null;
+ zoneName: string | null;
+}
+
+export type WarehouseFeeInvoiceWithDisplay = WarehouseFeeInvoice & Partial;
+
@Injectable()
export class WarehouseInvoiceService {
constructor(
@@ -152,16 +168,18 @@ export class WarehouseInvoiceService {
}
// ── Reads ────────────────────────────────────────────────────────────────
- async findById(id: string): Promise {
+ async findById(id: string): Promise {
const invoice = await this.invoiceRepository.findById(id);
if (!invoice) throw new NotFoundException(`Invoice ${id} not found`);
const items = await this.itemRepository.findAll({ where: { invoiceId: id } });
- return { ...invoice, items } as WarehouseFeeInvoice & { items: unknown[] };
+ const details = await this.getInvoiceDocumentDetails(invoice);
+ return { ...invoice, ...details, items } as WarehouseFeeInvoiceWithDisplay & { items: unknown[] };
}
async document(id: string): Promise<{ filename: string; buffer: Buffer }> {
const invoice = await this.findById(id);
- const html = this.buildInvoiceDocumentHtml(invoice, 'INVOICE');
+ const details = await this.getInvoiceDocumentDetails(invoice);
+ const html = this.buildInvoiceDocumentHtml(invoice, 'INVOICE', details);
return {
filename: `warehouse-invoice-${this.safeFilename(invoice.invoiceNumber)}.pdf`,
buffer: await this.documents.htmlToPdfBuffer(html),
@@ -173,7 +191,8 @@ export class WarehouseInvoiceService {
if (Number(invoice.paidAmount) <= 0) {
throw new BadRequestException('A receipt is available only after payment is recorded.');
}
- const html = this.buildInvoiceDocumentHtml(invoice, 'RECEIPT');
+ const details = await this.getInvoiceDocumentDetails(invoice);
+ const html = this.buildInvoiceDocumentHtml(invoice, 'RECEIPT', details);
return {
filename: `warehouse-receipt-${this.safeFilename(invoice.invoiceNumber)}.pdf`,
buffer: await this.documents.htmlToPdfBuffer(html),
@@ -257,9 +276,66 @@ export class WarehouseInvoiceService {
}
}
+ private async getInvoiceDocumentDetails(invoice: WarehouseFeeInvoice): Promise {
+ const [row] = await this.dataSource.query(
+ `SELECT b.reference AS "bookingReference",
+ company.name AS "customerName",
+ COALESCE(inv.release_order_reference, b.reference) AS "inventoryReference",
+ inv.status AS "inventoryStatus",
+ COALESCE(container.container_number, booking_container.container_number) AS "containerNumber",
+ COALESCE(cargo_type.cargo_type_name, b.cargo_free_text, cargo.description) AS "cargoDescription",
+ CONCAT_WS(
+ ' / ',
+ NULLIF(inv.status, ''),
+ NULLIF(COALESCE(container.container_number, booking_container.container_number), ''),
+ NULLIF(COALESCE(cargo_type.cargo_type_name, b.cargo_free_text, cargo.description), '')
+ ) AS "inventoryInfo",
+ wh.name AS "warehouseName",
+ yard.name AS "yardName",
+ zone.name AS "zoneName",
+ CASE
+ WHEN inv.release_date IS NOT NULL THEN 'RELEASE ISSUED'
+ WHEN $2 = 'PAID' THEN 'FEE PAID - READY FOR RELEASE'
+ ELSE 'PENDING PAYMENT'
+ END AS "clearanceStatus"
+ FROM freight.warehouse_fee_invoices fee
+ LEFT JOIN freight.warehouse_inventory inv ON inv.id = fee.inventory_id AND inv.deleted_at IS NULL
+ LEFT JOIN freight.bookings b ON b.id = fee.booking_id AND b.deleted_at IS NULL
+ LEFT JOIN freight.companies company ON company.id = COALESCE(fee.customer_id, b.company_id)
+ LEFT JOIN freight.containers container ON container.id = inv.container_id AND container.deleted_at IS NULL
+ LEFT JOIN freight.booking_container booking_container ON (
+ booking_container.booking_id = b.id
+ AND booking_container.deleted_at IS NULL
+ )
+ LEFT JOIN freight.cargoes cargo ON cargo.id = inv.cargo_id AND cargo.deleted_at IS NULL
+ LEFT JOIN freight.cargo_types cargo_type ON cargo_type.id = COALESCE(cargo.cargo_type_id, b.cargo_type_id)
+ LEFT JOIN freight.warehouses wh ON wh.id = fee.warehouse_id
+ LEFT JOIN freight.warehouse_yards yard ON yard.id = fee.yard_id
+ LEFT JOIN freight.warehouse_zones zone ON zone.id = fee.zone_id
+ WHERE fee.id = $1
+ LIMIT 1`,
+ [invoice.id, invoice.status],
+ );
+
+ return {
+ bookingReference: row?.bookingReference ?? null,
+ customerName: row?.customerName ?? null,
+ inventoryReference: row?.inventoryReference ?? null,
+ inventoryInfo: row?.inventoryInfo ?? null,
+ inventoryStatus: row?.inventoryStatus ?? null,
+ containerNumber: row?.containerNumber ?? null,
+ cargoDescription: row?.cargoDescription ?? null,
+ warehouseName: row?.warehouseName ?? null,
+ yardName: row?.yardName ?? null,
+ zoneName: row?.zoneName ?? null,
+ clearanceStatus: row?.clearanceStatus ?? (invoice.status === 'PAID' ? 'FEE PAID - READY FOR RELEASE' : 'PENDING PAYMENT'),
+ };
+ }
+
private buildInvoiceDocumentHtml(
- invoice: WarehouseFeeInvoice & { items: unknown[] },
+ invoice: WarehouseFeeInvoiceWithDisplay & { items: unknown[] },
kind: 'INVOICE' | 'RECEIPT',
+ details: InvoiceDocumentDetails,
): string {
const esc = (value: unknown) =>
String(value ?? '-')
@@ -329,8 +405,13 @@ export class WarehouseInvoiceService {
Status${esc(invoice.status.replace(/_/g, ' '))}
Invoice type${esc(invoice.invoiceType.replace(/_/g, ' '))}
-
Booking ID${esc(invoice.bookingId)}
-
Inventory ID${esc(invoice.inventoryId)}
+
Booking reference${esc(details.bookingReference)}
+
Customer${esc(details.customerName)}
+
Inventory reference${esc(details.inventoryReference)}
+
Inventory info${esc(details.inventoryInfo)}
+
Clearance${esc(details.clearanceStatus)}
+
Warehouse${esc(details.warehouseName)}
+
Yard / Zone${esc([details.yardName, details.zoneName].filter(Boolean).join(' / ') || null)}
Period${esc(date(invoice.periodStart))} - ${esc(date(invoice.periodEnd))}
Payment${esc(lastPayment ? `${lastPayment.method ?? 'MANUAL'} / ${date(lastPayment.paidAt)}` : '-')}
diff --git a/apps/edr-freight-api/src/modules/warehouses/warehouse-release-document.service.ts b/apps/edr-freight-api/src/modules/warehouses/warehouse-release-document.service.ts
index de9fac6e6..6b78d05bd 100644
--- a/apps/edr-freight-api/src/modules/warehouses/warehouse-release-document.service.ts
+++ b/apps/edr-freight-api/src/modules/warehouses/warehouse-release-document.service.ts
@@ -100,20 +100,33 @@ export class WarehouseReleaseDocumentService {
private htmlToBasicPdfBuffer(html: string): Buffer {
const text = this.htmlToPlainText(html);
- const lines = this.wrapLines(text, 92).slice(0, 72);
+ const lines = this.wrapLines(text, 86).slice(0, 52);
const body = lines
.map((line, index) => {
- const prefix = index === 0 ? '50 790 Td' : '0 -12 Td';
- return `${prefix} (${this.escapePdfText(line)}) Tj`;
+ const y = 770 - index * 12;
+ const isTitle = index < 2 || /clearance|release order/i.test(line);
+ const size = index === 0 ? 13 : isTitle ? 11 : 9.6;
+ const font = isTitle ? 'F2' : 'F1';
+ return this.textOp(line, 48, y, size, font);
})
.join('\n');
- const stream = `BT\n/F1 10 Tf\n12 TL\n${body}\nET`;
+ const stream = [
+ this.lineOp(48, 752, 548, 752),
+ this.circularSealOps(470, 690),
+ body,
+ this.lineOp(48, 126, 238, 126, '0 0 0'),
+ this.textOp('Authorized warehouse officer name / signature / date', 48, 110, 9, 'F1'),
+ this.lineOp(312, 126, 548, 126, '0 0 0'),
+ this.textOp('Customer or driver name / signature / date', 312, 110, 9, 'F1'),
+ this.textOp('OFFICIAL WAREHOUSE GATE CLEARANCE DOCUMENT', 145, 52, 9, 'F2', '0.08 0.32 0.18'),
+ ].join('\n');
const objects = [
'<< /Type /Catalog /Pages 2 0 R >>',
'<< /Type /Pages /Kids [3 0 R] /Count 1 >>',
- '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >>',
- '<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>',
+ '<< /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R /F2 5 0 R >> >> /Contents 6 0 R >>',
+ '<< /Type /Font /Subtype /Type1 /BaseFont /Times-Roman >>',
+ '<< /Type /Font /Subtype /Type1 /BaseFont /Times-Bold >>',
`<< /Length ${Buffer.byteLength(stream, 'latin1')} >>\nstream\n${stream}\nendstream`,
];
@@ -178,4 +191,50 @@ export class WarehouseReleaseDocumentService {
private escapePdfText(value: string): string {
return value.replace(/\\/g, '\\\\').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
}
+
+ private textOp(
+ text: string,
+ x: number,
+ y: number,
+ size: number,
+ font: 'F1' | 'F2' = 'F1',
+ color = '0 0 0',
+ ): string {
+ return `BT\n${color} rg\n/${font} ${size} Tf\n${x} ${y} Td\n(${this.escapePdfText(text)}) Tj\nET`;
+ }
+
+ private lineOp(x1: number, y1: number, x2: number, y2: number, color = '0.08 0.32 0.18'): string {
+ return `q\n${color} RG\n0.8 w\n${x1} ${y1} m\n${x2} ${y2} l\nS\nQ`;
+ }
+
+ private circularSealOps(cx: number, cy: number): string {
+ return [
+ 'q',
+ '0.08 0.32 0.18 RG',
+ '0.08 0.32 0.18 rg',
+ '2.2 w',
+ this.circlePath(cx, cy, 51),
+ 'S',
+ '0.8 w',
+ this.circlePath(cx, cy, 41),
+ 'S',
+ this.textOp('EDR', cx - 14, cy + 18, 14, 'F2', '0.08 0.32 0.18'),
+ this.textOp('WAREHOUSE', cx - 31, cy + 2, 9, 'F2', '0.08 0.32 0.18'),
+ this.textOp('CLEARED', cx - 27, cy - 16, 11, 'F2', '0.08 0.32 0.18'),
+ 'Q',
+ ].join('\n');
+ }
+
+ private circlePath(cx: number, cy: number, r: number): string {
+ const k = 0.5522847498;
+ const c = r * k;
+ return [
+ `${cx + r} ${cy} m`,
+ `${cx + r} ${cy + c} ${cx + c} ${cy + r} ${cx} ${cy + r} c`,
+ `${cx - c} ${cy + r} ${cx - r} ${cy + c} ${cx - r} ${cy} c`,
+ `${cx - r} ${cy - c} ${cx - c} ${cy - r} ${cx} ${cy - r} c`,
+ `${cx + c} ${cy - r} ${cx + r} ${cy - c} ${cx + r} ${cy} c`,
+ 'h',
+ ].join('\n');
+ }
}
diff --git a/apps/edr-freight-web/backoffice/package.json b/apps/edr-freight-web/backoffice/package.json
index 8f0e233b4..67fe4e9cb 100644
--- a/apps/edr-freight-web/backoffice/package.json
+++ b/apps/edr-freight-web/backoffice/package.json
@@ -5,6 +5,7 @@
"type": "module",
"scripts": {
"dev": "vite --port 5183",
+ "prebuild": "node -e \"const fs=require('fs'); fs.rmSync('dist',{recursive:true,force:true});\"",
"build": "vite build",
"preview": "vite preview --port 5183",
"lint": "eslint src",
diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryDetailModal.tsx b/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryDetailModal.tsx
index ad079577b..b0b864e4d 100644
--- a/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryDetailModal.tsx
+++ b/apps/edr-freight-web/backoffice/src/components/warehouses/InventoryDetailModal.tsx
@@ -24,6 +24,15 @@ function DetailRow({ label, value }: { label: string; value: React.ReactNode })
}
export function InventoryDetailModal({ opened, onClose, item }: InventoryDetailModalProps) {
+ const bookingReference = item?.booking?.reference ?? '-';
+ const inventorySummary = [
+ item?.status?.replace(/_/g, ' '),
+ item?.releaseOrderReference ? `Release ${item.releaseOrderReference}` : null,
+ item?.warehouse ? `${item.warehouse.name} (${item.warehouse.code})` : null,
+ ]
+ .filter(Boolean)
+ .join(' / ');
+
return (
{!item ? (
@@ -33,10 +42,10 @@ export function InventoryDetailModal({ opened, onClose, item }: InventoryDetailM
- {item.booking?.reference ?? item.bookingId ?? item.id}
+ {bookingReference}
- Inventory ID: {item.id}
+ {inventorySummary || 'Inventory information'}
@@ -51,12 +60,12 @@ export function InventoryDetailModal({ opened, onClose, item }: InventoryDetailM
+
-
-
-
+
+
diff --git a/apps/edr-freight-web/backoffice/src/components/warehouses/warehousePdf.ts b/apps/edr-freight-web/backoffice/src/components/warehouses/warehousePdf.ts
index b64ae9384..9f91456c8 100644
--- a/apps/edr-freight-web/backoffice/src/components/warehouses/warehousePdf.ts
+++ b/apps/edr-freight-web/backoffice/src/components/warehouses/warehousePdf.ts
@@ -130,12 +130,22 @@ function buildSimplePdf(lines: PdfLine[], rawOps: string[] = []): Blob {
export function buildWarehouseInvoicePdf(invoice: WarehouseFeeInvoice, kind: 'INVOICE' | 'RECEIPT') {
const paid = kind === 'RECEIPT' || invoice.status === 'PAID';
const title = `Warehouse Fee ${kind === 'RECEIPT' ? 'Receipt' : 'Invoice'}`;
+ const bookingReference = firstText(invoice.bookingReference);
+ const customerName = firstText(invoice.customerName);
+ const inventoryReference = firstText(invoice.inventoryReference);
+ const inventoryInfo = firstText(invoice.inventoryInfo, invoice.containerNumber, invoice.cargoDescription);
+ const clearanceStatus = firstText(
+ invoice.clearanceStatus,
+ paid ? 'FEE PAID - READY FOR RELEASE' : 'PENDING PAYMENT',
+ );
const lines: PdfLine[] = [
{ text: 'Ethio-Djibouti Railway S.C.', size: 12, bold: true, yGap: 0, align: 'center' },
{ text: title, size: 23, bold: true, yGap: 28, align: 'center' },
{ text: `Document No: ${invoice.invoiceNumber}`, size: 12, bold: true, yGap: 32, align: 'center' },
{ text: `Status: ${invoice.status.replace(/_/g, ' ')} Type: ${invoice.invoiceType.replace(/_/g, ' ')}`, align: 'center' },
- { text: `Booking: ${invoice.bookingId ?? '-'} Inventory: ${invoice.inventoryId}`, align: 'center' },
+ { text: `Booking Reference: ${bookingReference} Customer: ${customerName}`, align: 'center' },
+ { text: `Inventory Reference: ${inventoryReference} Inventory Info: ${inventoryInfo}`, align: 'center' },
+ { text: `Clearance: ${clearanceStatus}`, align: 'center' },
{ text: `Issued: ${fmtDate(invoice.issuedAt)} Paid At: ${fmtDate(invoice.paidAt)}`, align: 'center' },
{ text: 'ITEMS', size: 13, bold: true, yGap: 30, align: 'center' },
...(invoice.items ?? []).flatMap((item) => [
@@ -201,15 +211,33 @@ export function buildWarehouseExitPaperPdf(input: WarehouseFeeInvoice | Warehous
const releasedItem = context.releasedItem;
const inventory = context.inventory ?? releasedItem;
const releasedAt = context.releasedAt ?? new Date();
- const releaseReference = `REL-${invoice.inventoryId.slice(0, 8).toUpperCase()}`;
+ const releaseReference = firstText(
+ inventory?.releaseOrderReference,
+ releasedItem?.releaseOrderReference,
+ invoice.inventoryReference,
+ booking?.reference ? `REL-${booking.reference.replace(/^BK-?/i, '')}` : null,
+ );
const customerName = firstText(
booking?.company?.name,
booking?.company?.companyName,
booking?.company?.label,
booking?.company?.contactPersonName,
- invoice.customerId,
+ invoice.customerName,
);
const weightTons = firstText(tons(booking?.cargoTotalWeightVgm), tons(inventory?.weight));
+ const inventoryInfo = firstText(
+ invoice.inventoryInfo,
+ invoice.containerNumber,
+ invoice.cargoDescription,
+ inventory?.status,
+ releasedItem?.status,
+ );
+ const bookingReference = firstText(
+ booking?.reference,
+ (inventory as unknown as { bookingReference?: string })?.bookingReference,
+ invoice.bookingReference,
+ releasedItem?.booking?.reference,
+ );
return buildSimplePdf([
{ text: 'Ethio-Djibouti Railway S.C.', size: 12, bold: true, yGap: 0, align: 'center' },
@@ -217,16 +245,18 @@ export function buildWarehouseExitPaperPdf(input: WarehouseFeeInvoice | Warehous
{ text: '[ GATE CLEARANCE ]', size: 14, bold: true, color: 'green', yGap: 24, align: 'center' },
{ text: `Release Reference: ${releaseReference}`, bold: true, yGap: 30, align: 'center' },
{ text: `Invoice No: ${invoice.invoiceNumber}`, align: 'center' },
- { text: `Booking Reference: ${firstText(booking?.reference, (inventory as unknown as { bookingReference?: string })?.bookingReference, invoice.bookingId, releasedItem?.bookingId)}`, align: 'center' },
+ { text: `Booking Reference: ${bookingReference}`, align: 'center' },
{ text: `Customer: ${customerName}`, align: 'center' },
- { text: `Warehouse: ${firstText(inventory?.warehouse?.name, inventory?.warehouse?.code, invoice.warehouseId, releasedItem?.warehouseId)}`, align: 'center' },
- { text: `Yard: ${firstText(inventory?.yard?.name, inventory?.yard?.code, invoice.yardId, releasedItem?.yardId)}`, align: 'center' },
- { text: `Zone: ${firstText(inventory?.zone?.name, inventory?.zone?.code, invoice.zoneId, releasedItem?.zoneId)}`, align: 'center' },
+ { text: `Inventory Info: ${inventoryInfo}`, align: 'center' },
+ { text: `Warehouse: ${firstText(inventory?.warehouse?.name, inventory?.warehouse?.code)}`, align: 'center' },
+ { text: `Yard: ${firstText(inventory?.yard?.name, inventory?.yard?.code)}`, align: 'center' },
+ { text: `Zone: ${firstText(inventory?.zone?.name, inventory?.zone?.code)}`, align: 'center' },
{ text: `Booking Container: ${containerSummary(booking, inventory)}`, align: 'center' },
{ text: `Weight: ${weightTons}`, align: 'center' },
{ text: `Inventory Status: ${releasedItem?.status ?? inventory?.status ?? 'RELEASED'}`, align: 'center' },
+ { text: `Clearance: ${invoice.clearanceStatus ?? 'CLEARED FOR WAREHOUSE EXIT'}`, bold: true, color: 'green', align: 'center' },
{ text: `Release Date & Time: ${fmtDate(releasedAt)}`, align: 'center' },
- { text: 'This document authorizes the listed booking/goods to leave the warehouse gate.', yGap: 30, align: 'center' },
+ { text: 'This sealed document authorizes the listed booking/goods to leave the warehouse gate.', yGap: 30, align: 'center' },
], [
...buildAuthorizationBand('CLEARED'),
textOp('Warehouse officer name / signature / date:', 72, 190, 10),
diff --git a/apps/edr-freight-web/backoffice/src/constants/apiConfig.ts b/apps/edr-freight-web/backoffice/src/constants/apiConfig.ts
index 3f552ab15..061305b11 100644
--- a/apps/edr-freight-web/backoffice/src/constants/apiConfig.ts
+++ b/apps/edr-freight-web/backoffice/src/constants/apiConfig.ts
@@ -1,10 +1,6 @@
export const API_BASE_URL =
-<<<<<<< HEAD
- import.meta.env.VITE_API_URL?.replace(/\/+$/, '') || 'https://edrfreightapi.triaplc.com';
-=======
import.meta.env.VITE_BASE_API_URL ||
import.meta.env.VITE_API_URL ||
'https://edrfreightapi.triaplc.com';
//export const API_BASE_URL = 'http://localhost:3001';
->>>>>>> 2f06817e4811190cdc9ef8a2975aeca1e31c3484
diff --git a/apps/edr-freight-web/backoffice/src/types/warehouse.ts b/apps/edr-freight-web/backoffice/src/types/warehouse.ts
index 74008d81b..b935ac2ec 100644
--- a/apps/edr-freight-web/backoffice/src/types/warehouse.ts
+++ b/apps/edr-freight-web/backoffice/src/types/warehouse.ts
@@ -737,8 +737,16 @@ export interface WarehouseFeeInvoice {
id: string;
invoiceNumber: string;
bookingId?: string | null;
+ bookingReference?: string | null;
customerId?: string | null;
+ customerName?: string | null;
inventoryId: string;
+ inventoryReference?: string | null;
+ inventoryInfo?: string | null;
+ inventoryStatus?: string | null;
+ containerNumber?: string | null;
+ cargoDescription?: string | null;
+ clearanceStatus?: string | null;
facilityId?: string | null;
warehouseId?: string | null;
yardId?: string | null;