add carriage acceptance sheet PDF per booking

Lists every wagon allocated to a booking with tare, equated length,
capacity, container and seal numbers, plus footer totals and signature
lines. Issued on cargo acceptance (export) and on allocation before
marshalling (import), so the endpoint rejects bookings with no wagon
allocations. Price per wagon splits the booking amount by allocated
weight, with the last row absorbing rounding so the column sums to the
total. Reuses the existing marshalling document renderer and its
Chromium-less tabular fallback.
This commit is contained in:
Hagernesh
2026-07-31 07:02:11 +00:00
parent 08e0fe2db2
commit 341c2b3742

View File

@@ -0,0 +1,26 @@
import { BookingsService } from './bookings.service';
// The split is a pure helper on the prototype (never touches `this`), so it can be
// exercised without constructing the service and its dependency graph.
const split = (total: number, weights: number[]): number[] =>
(
BookingsService.prototype as unknown as {
splitAmountAcrossWagons(total: number, weights: number[]): number[];
}
).splitAmountAcrossWagons(total, weights);
describe('carriage acceptance sheet — price split', () => {
it('splits proportionally to allocated weight', () => {
expect(split(100, [30, 10])).toEqual([75, 25]);
});
it('splits equally when no weights are recorded', () => {
expect(split(90, [0, 0, 0])).toEqual([30, 30, 30]);
});
it('always sums back to the booking total despite rounding', () => {
const shares = split(100, [1, 1, 1]);
expect(shares.reduce((a, b) => a + b, 0)).toBe(100);
expect(shares).toEqual([33.33, 33.33, 33.34]);
});
});