fix issue

This commit is contained in:
Marshal
2026-08-22 01:29:44 +00:00
parent 1ab2cfdb3b
commit 3455c1b3b4
2 changed files with 39 additions and 12 deletions

View File

@@ -1516,6 +1516,7 @@ export class BookingBatchService implements OnModuleInit {
stock,
leg,
this.scarcityRankForPool([primary], allowedWagonTypes),
wagonTypeIds,
)
: null;
const seated = useSmart
@@ -2357,7 +2358,7 @@ export class BookingBatchService implements OnModuleInit {
!perItemBulk &&
wagonTypeIds.length > 0;
const smart = useSmart
? this.smartBulkNeed(booking, wagonDims, stock, leg, scarcityRank)
? this.smartBulkNeed(booking, wagonDims, stock, leg, scarcityRank, wagonTypeIds)
: null;
const admitted = useSmart
? smart != null && budget.fits(smart.need, leg)
@@ -2653,7 +2654,14 @@ export class BookingBatchService implements OnModuleInit {
const leg = legOn(t);
if (leg == null) continue;
if (useSmart) {
const probe = this.smartBulkNeed(booking, wagonDims, t.stock, leg, scarcityRank);
const probe = this.smartBulkNeed(
booking,
wagonDims,
t.stock,
leg,
scarcityRank,
wagonTypeIds,
);
if (probe != null && t.budget.fits(probe.need, leg)) {
smart = probe;
target = t;
@@ -2858,10 +2866,14 @@ export class BookingBatchService implements OnModuleInit {
// other 4 leave as the usual remainder booking, instead of paying for
// 20 and stalling at allocation on wagon 17.
if (cappedBulk && wagonDims) {
const best = this.allowedDimsWithTypes(booking, wagonDims)
.filter((o): o is { wagonTypeId: string; dims: PerWagonDims } =>
o.wagonTypeId != null,
)
// Types resolved from the id list (join tables), never the pool
// entity's unloaded cargoType.wagonTypes relation — see smartBulkNeed.
const best = [...new Set(wagonTypeIds)]
.map((wagonTypeId) => ({
wagonTypeId,
dims: wagonDims.byWagonTypeId.get(wagonTypeId),
}))
.filter((o): o is { wagonTypeId: string; dims: PerWagonDims } => o.dims != null)
.map((o) => ({
...o,
free: c.stock?.availableFor([o.wagonTypeId], leg) ?? 0,
@@ -5074,7 +5086,7 @@ export class BookingBatchService implements OnModuleInit {
Number(b.bulkTotalWeightTons ?? 0) > 0 &&
Number(b.cargoTotalWeightVgm ?? 0) > 0;
if (b.freightType === "BULK" && !perItemBulk && typeIds.length) {
const smart = this.smartBulkNeed(b, wagonDims, ledger, leg, rank);
const smart = this.smartBulkNeed(b, wagonDims, ledger, leg, rank, typeIds);
if (smart) {
for (const part of smart.perType) {
ledger.consume([part.wagonTypeId], part.wagons, leg);
@@ -5168,9 +5180,19 @@ export class BookingBatchService implements OnModuleInit {
stock: WagonStockLedger,
leg: CorridorLeg,
scarcityRank: Map<string, number>,
/**
* Wagon-type ids this booking may ride, from {@link loadAllowedWagonTypeIds}
* — NEVER from `booking.cargoType.wagonTypes`. The batch pool finders
* deliberately do not join that relation (hot path), so on a pool entity
* it is always empty; resolving through it made every PER_TON bulk booking
* unseatable — no whole fit and no partial offer, silently READY forever
* (the S-2026-00020 / BK-2026-000036 incident).
*/
wagonTypeIds: readonly string[],
): { need: Capacity; perType: Array<{ wagonTypeId: string; wagons: number }> } | null {
const options = this.allowedDimsWithTypes(booking, wagonDims)
.filter((o): o is { wagonTypeId: string; dims: PerWagonDims } => o.wagonTypeId != null)
const options = [...new Set(wagonTypeIds)]
.map((wagonTypeId) => ({ wagonTypeId, dims: wagonDims.byWagonTypeId.get(wagonTypeId) }))
.filter((o): o is { wagonTypeId: string; dims: PerWagonDims } => o.dims != null)
.map((o) => ({
...o,
free: stock.availableFor([o.wagonTypeId], leg),