mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 12:41:04 +00:00
fix issue and add consolidation
This commit is contained in:
@@ -1536,4 +1536,72 @@ describe('BookingBatchService — physical wagon-type gate', () => {
|
||||
// Those 16 are now held, so the next booking in the pass cannot re-take them.
|
||||
expect(stock.availableFor([NW5], WHOLE_LEG)).toBe(0);
|
||||
});
|
||||
|
||||
it('sizes a capped-bulk partial on ONE type at the cargo cap, not the 70T rating', async () => {
|
||||
const svc = service();
|
||||
const inner = internals(svc);
|
||||
(inner as { isSplitEligible: unknown }).isSplitEligible = () => true;
|
||||
const dims = { lengthMeters: 14, tareWeightTons: 24, capacityTons: 70 };
|
||||
(inner as unknown as { loadWagonDims: unknown }).loadWagonDims = async () => ({
|
||||
container: dims,
|
||||
bulk: dims,
|
||||
byWagonTypeId: new Map([
|
||||
[NW5, dims],
|
||||
[PW2, dims],
|
||||
]),
|
||||
});
|
||||
const tryPartial = jest
|
||||
.fn()
|
||||
.mockResolvedValue({ wagons: 16, weightTons: 864, lengthMeters: 224 });
|
||||
(inner as { tryPartialOffer: unknown }).tryPartialOffer = tryPartial;
|
||||
|
||||
const stock = mixedStock();
|
||||
const candidate = {
|
||||
id: 'schedule-1',
|
||||
budget: {
|
||||
legOf: () => WHOLE_LEG,
|
||||
remainingFor: () => ({ wagons: 20, weightTons: 99_999, lengthMeters: 99_999 }),
|
||||
subtract: jest.fn(),
|
||||
},
|
||||
armed: false,
|
||||
stock,
|
||||
};
|
||||
const booking = {
|
||||
id: 'b2',
|
||||
reference: 'BK-2',
|
||||
originYardId: 'a',
|
||||
destinationYardId: 'b',
|
||||
freightType: 'BULK',
|
||||
cargoTotalWeightVgm: 695,
|
||||
cargoType: {
|
||||
id: 'cargo-perishable',
|
||||
wagonTypes: [
|
||||
{ id: NW5, capacityTons: 70 },
|
||||
{ id: PW2, capacityTons: 70 },
|
||||
],
|
||||
tonsPerWagonMap: { [NW5]: 30, [PW2]: 20 },
|
||||
},
|
||||
bookingContainers: [],
|
||||
} as unknown as Booking;
|
||||
|
||||
const offered = await inner.maybeOfferPartial(
|
||||
booking,
|
||||
false,
|
||||
[candidate],
|
||||
{ wagons: 24, weightTons: 1400, lengthMeters: 336 },
|
||||
[NW5, PW2],
|
||||
);
|
||||
|
||||
expect(offered).toBe(true);
|
||||
// Room capped to the 16 NW5 that exist (biggest capped take), and the seat
|
||||
// carries the 30T cargo cap — never the wagon's raw 70T rating.
|
||||
expect(tryPartial.mock.calls[0][2]).toMatchObject({ wagons: 16 });
|
||||
expect(tryPartial.mock.calls[0][4]).toMatchObject({
|
||||
wagonTypeId: NW5,
|
||||
perWagon: { capacityTons: 30 },
|
||||
});
|
||||
// Only the seated type is held; the PW2s stay free for bulk-only cargo.
|
||||
expect(stock.availableFor([NW5], WHOLE_LEG)).toBe(0);
|
||||
expect(stock.availableFor([PW2], WHOLE_LEG)).toBe(4);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2831,7 +2831,6 @@ export class BookingBatchService implements OnModuleInit {
|
||||
wagonTypeIds: string[] = [],
|
||||
): Promise<boolean> {
|
||||
if (!this.isSplitEligible(booking, isPair)) return false;
|
||||
const wagonDims = await this.loadWagonDims();
|
||||
// PER_TON bulk partials are sized on ONE concrete wagon type at the
|
||||
// cargo's per-wagon cap — sizing on the first type's raw 70T rating
|
||||
// offered tonnage the wagons could never carry (Perishable caps at
|
||||
@@ -2846,6 +2845,7 @@ export class BookingBatchService implements OnModuleInit {
|
||||
booking.freightType === "BULK" &&
|
||||
!perItemBulk &&
|
||||
wagonTypeIds.length > 0;
|
||||
const wagonDims = cappedBulk ? await this.loadWagonDims() : null;
|
||||
const target = candidates
|
||||
.map((c) => {
|
||||
const leg = c.budget.legOf(booking.originYardId, booking.destinationYardId);
|
||||
@@ -2856,7 +2856,7 @@ export class BookingBatchService implements OnModuleInit {
|
||||
// them NW5" into an offer for 16 — the customer pays for 16 and the
|
||||
// other 4 leave as the usual remainder booking, instead of paying for
|
||||
// 20 and stalling at allocation on wagon 17.
|
||||
if (cappedBulk) {
|
||||
if (cappedBulk && wagonDims) {
|
||||
const best = this.allowedDimsWithTypes(booking, wagonDims)
|
||||
.filter((o): o is { wagonTypeId: string; dims: PerWagonDims } =>
|
||||
o.wagonTypeId != null,
|
||||
|
||||
Reference in New Issue
Block a user