Skip to content

Commit dc97ff8

Browse files
committed
update pageCount constraint with duplex and sides
1 parent 9f02fcb commit dc97ff8

2 files changed

Lines changed: 231 additions & 26 deletions

File tree

lambdas/supplier-allocator/src/services/__tests__/supplier-config.test.ts

Lines changed: 161 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,8 @@ describe("supplier-config service", () => {
483483

484484
expect(result).toEqual(["spec1"]);
485485
});
486-
it("throws when no eligible packs found for letter", async () => {
486+
487+
it("throws when no eligible packs found for letter based on sheets", async () => {
487488
const deps = makeDeps();
488489
deps.supplierConfigRepo.getPackSpecification = jest
489490
.fn()
@@ -505,11 +506,15 @@ describe("supplier-config service", () => {
505506
"No eligible pack specifications found for letter variant id undefined and pack specification ids spec1",
506507
);
507508
expect(deps.logger.info).toHaveBeenCalledWith({
508-
description: "Pack specification filtered out based on constraints",
509+
description: "Pack specification spec1 filtered out based on pageCount constraints",
509510
packSpecId: "spec1",
510511
pageCount: 3,
511-
constraintValue: 2,
512-
constraintOperator: "LESS_THAN",
512+
violatedConstraints: expect.arrayContaining([expect.objectContaining({
513+
actualValue: 3,
514+
constraint: "sheets",
515+
constraintValue: 2,
516+
operator: "LESS_THAN",
517+
})]),
513518
});
514519
expect(deps.logger.error).toHaveBeenCalledWith(
515520
expect.objectContaining({
@@ -519,6 +524,158 @@ describe("supplier-config service", () => {
519524
}),
520525
);
521526
});
527+
528+
it("does not filter pack specification when duplex reduces sheets and constraint is LESS_THAN_OR_EQUAL", async () => {
529+
const deps = makeDeps();
530+
deps.supplierConfigRepo.getPackSpecification = jest
531+
.fn()
532+
.mockResolvedValue({
533+
id: "spec1",
534+
assembly: { duplex: true },
535+
constraints: {
536+
sheets: { operator: "LESS_THAN_OR_EQUAL", value: 2 },
537+
},
538+
} as any);
539+
540+
const letterEvent = {
541+
data: {
542+
pageCount: 3,
543+
letterVariantId: "variant-1",
544+
},
545+
} as any;
546+
547+
const result = await filterPacksForLetter(letterEvent, ["spec1"], deps);
548+
549+
expect(result).toEqual(["spec1"]);
550+
expect(deps.logger.info).not.toHaveBeenCalled();
551+
});
552+
553+
it("filters pack specification when sides fail LESS_THAN_OR_EQUAL", async () => {
554+
const deps = makeDeps();
555+
deps.supplierConfigRepo.getPackSpecification = jest.fn().mockResolvedValue({
556+
id: "spec1",
557+
constraints: {
558+
sides: { operator: "LESS_THAN_OR_EQUAL", value: 2 },
559+
},
560+
} as any);
561+
562+
const letterEvent = {
563+
data: {
564+
pageCount: 3,
565+
letterVariantId: "variant-1",
566+
},
567+
} as any;
568+
569+
await expect(
570+
filterPacksForLetter(letterEvent, ["spec1"], deps),
571+
).rejects.toThrow(/No eligible pack specifications found/);
572+
573+
expect(deps.logger.info).toHaveBeenCalledWith({
574+
description:
575+
"Pack specification spec1 filtered out based on pageCount constraints",
576+
packSpecId: "spec1",
577+
pageCount: 3,
578+
violatedConstraints: expect.arrayContaining([
579+
expect.objectContaining({
580+
constraint: "sides",
581+
actualValue: 3,
582+
constraintValue: 2,
583+
operator: "LESS_THAN_OR_EQUAL",
584+
}),
585+
]),
586+
});
587+
});
588+
589+
it("filters by sides using page count even when duplex is enabled", async () => {
590+
const deps = makeDeps();
591+
deps.supplierConfigRepo.getPackSpecification = jest.fn().mockResolvedValue({
592+
id: "spec1",
593+
assembly: { duplex: true },
594+
constraints: {
595+
sheets: { operator: "LESS_THAN_OR_EQUAL", value: 2 },
596+
sides: { operator: "LESS_THAN_OR_EQUAL", value: 2 },
597+
},
598+
} as any);
599+
600+
const letterEvent = {
601+
data: {
602+
pageCount: 3,
603+
letterVariantId: "variant-1",
604+
},
605+
} as any;
606+
607+
await expect(
608+
filterPacksForLetter(letterEvent, ["spec1"], deps),
609+
).rejects.toThrow(/No eligible pack specifications found/);
610+
611+
expect(deps.logger.info).toHaveBeenCalledWith({
612+
description:
613+
"Pack specification spec1 filtered out based on pageCount constraints",
614+
packSpecId: "spec1",
615+
pageCount: 3,
616+
violatedConstraints: expect.arrayContaining([
617+
expect.objectContaining({
618+
constraint: "sides",
619+
actualValue: 3,
620+
constraintValue: 2,
621+
operator: "LESS_THAN_OR_EQUAL",
622+
}),
623+
]),
624+
});
625+
});
626+
627+
it("does not filter pack specification when sides is valid", async () => {
628+
const deps = makeDeps();
629+
deps.supplierConfigRepo.getPackSpecification = jest
630+
.fn()
631+
.mockResolvedValue({
632+
id: "spec1",
633+
assembly: { duplex: true },
634+
constraints: {
635+
sheets: { operator: "LESS_THAN_OR_EQUAL", value: 4 },
636+
},
637+
} as any);
638+
639+
const letterEvent = {
640+
data: {
641+
pageCount: 3,
642+
letterVariantId: "variant-1",
643+
},
644+
} as any;
645+
646+
const result = await filterPacksForLetter(letterEvent, ["spec1"], deps);
647+
648+
expect(result).toEqual(["spec1"]);
649+
expect(deps.logger.info).not.toHaveBeenCalled();
650+
});
651+
652+
it("keeps pack specification when sides constraint passes", async () => {
653+
const deps = makeDeps();
654+
deps.supplierConfigRepo.getPackSpecification = jest
655+
.fn()
656+
.mockResolvedValue({
657+
id: "spec1",
658+
constraints: {
659+
sides: { operator: "LESS_THAN_OR_EQUAL", value: 3 },
660+
},
661+
} as any);
662+
663+
const letterEvent = {
664+
data: {
665+
pageCount: 3,
666+
letterVariantId: "variant-1",
667+
},
668+
} as any;
669+
670+
const result = await filterPacksForLetter(letterEvent, ["spec1"], deps);
671+
672+
expect(result).toEqual(["spec1"]);
673+
expect(deps.logger.info).not.toHaveBeenCalled();
674+
expect(deps.logger.error).not.toHaveBeenCalled();
675+
});
676+
677+
678+
522679
it("returns eligible packs for all constraint types", async () => {
523680
const deps = makeDeps();
524681
const constraints: { operator: string; value: number }[] = [

lambdas/supplier-allocator/src/services/supplier-config.ts

Lines changed: 70 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -218,35 +218,83 @@ export async function filterPacksForLetter(
218218
deps: Deps,
219219
): Promise<string[]> {
220220
const filteredPackIds: string[] = [];
221+
221222
for (const packSpecId of packSpecificationIds) {
223+
let isValid = true;
224+
const violatedConstraints: Array<{
225+
constraint: "sheets" | "sides";
226+
actualValue: number;
227+
constraintValue: number;
228+
operator: string;
229+
}> = [];
230+
222231
const packSpec =
223232
await deps.supplierConfigRepo.getPackSpecification(packSpecId);
224-
if (
225-
!packSpec.constraints ||
226-
!packSpec.constraints.sheets ||
227-
!packSpec.constraints.sheets.value ||
228-
!packSpec.constraints.sheets.operator
229-
) {
233+
234+
if (packSpec.constraints) {
235+
// Evaluate sheets constraint if present
236+
if (
237+
packSpec.constraints.sheets &&
238+
packSpec.constraints.sheets.value !== undefined &&
239+
packSpec.constraints.sheets.operator
240+
) {
241+
const sheetCount = packSpec?.assembly?.duplex
242+
? Math.ceil(letterEvent.data.pageCount / 2)
243+
: letterEvent.data.pageCount;
244+
245+
const passesSheetsConstraint = evaluateContraint(
246+
sheetCount,
247+
packSpec.constraints.sheets.value,
248+
packSpec.constraints.sheets.operator,
249+
);
250+
251+
if (!passesSheetsConstraint) {
252+
isValid = false;
253+
violatedConstraints.push({
254+
constraint: "sheets",
255+
actualValue: sheetCount,
256+
constraintValue: packSpec.constraints.sheets.value,
257+
operator: packSpec.constraints.sheets.operator,
258+
});
259+
}
260+
}
261+
262+
// Evaluate sides constraint if present
263+
if (
264+
packSpec.constraints.sides &&
265+
packSpec.constraints.sides.value !== undefined &&
266+
packSpec.constraints.sides.operator
267+
) {
268+
const passesSidesConstraint = evaluateContraint(
269+
letterEvent.data.pageCount,
270+
packSpec.constraints.sides.value,
271+
packSpec.constraints.sides.operator,
272+
);
273+
274+
if (!passesSidesConstraint) {
275+
isValid = false;
276+
violatedConstraints.push({
277+
constraint: "sides",
278+
actualValue: letterEvent.data.pageCount,
279+
constraintValue: packSpec.constraints.sides.value,
280+
operator: packSpec.constraints.sides.operator,
281+
});
282+
}
283+
}
284+
}
285+
286+
if (isValid) {
230287
filteredPackIds.push(packSpecId);
231288
} else {
232-
const isValid = evaluateContraint(
233-
letterEvent.data.pageCount,
234-
packSpec.constraints.sheets.value,
235-
packSpec.constraints.sheets.operator,
236-
);
237-
if (isValid) {
238-
filteredPackIds.push(packSpecId);
239-
} else {
240-
deps.logger.info({
241-
description: "Pack specification filtered out based on constraints",
242-
packSpecId,
243-
pageCount: letterEvent.data.pageCount,
244-
constraintValue: packSpec.constraints.sheets.value,
245-
constraintOperator: packSpec.constraints.sheets.operator,
246-
});
247-
}
289+
deps.logger.info({
290+
description: `Pack specification ${packSpecId} filtered out based on pageCount constraints`,
291+
packSpecId,
292+
pageCount: letterEvent.data.pageCount,
293+
violatedConstraints,
294+
});
248295
}
249296
}
297+
250298
if (filteredPackIds.length === 0) {
251299
deps.logger.error({
252300
description: "No eligible pack specifications found for letter",

0 commit comments

Comments
 (0)