Add OP-aware cutting planning
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { buildCutPlan, classifyCutFamily } from './cutting.ts';
|
||||
import type { DateRange, ProductAnalyticsItem } from '../types.ts';
|
||||
import { buildCutPlan, buildOpenProductionByProductId, classifyCutFamily } from './cutting.ts';
|
||||
import type { DateRange, ProductAnalyticsItem, ProductionOrderItem } from '../types.ts';
|
||||
|
||||
const range: DateRange = {
|
||||
start: new Date(2026, 6, 1),
|
||||
@@ -22,6 +22,26 @@ const product = (overrides: Partial<ProductAnalyticsItem>): ProductAnalyticsItem
|
||||
...overrides
|
||||
});
|
||||
|
||||
const productionOrder = (overrides: Partial<ProductionOrderItem>): ProductionOrderItem => ({
|
||||
id: 1,
|
||||
tinyId: '',
|
||||
number: 'OP-1',
|
||||
status: 'in_progress',
|
||||
statusLabel: 'Em andamento',
|
||||
orderReference: '',
|
||||
issueDate: '2026-07-01',
|
||||
expectedDate: '2026-07-15',
|
||||
productSku: '',
|
||||
productDescription: 'BASE LISA CAMISETA COR PRETO TAMANHO - M',
|
||||
quantity: 40,
|
||||
unit: 'UN',
|
||||
integrationStatus: '',
|
||||
markers: [],
|
||||
createdAt: null,
|
||||
updatedAt: null,
|
||||
...overrides
|
||||
});
|
||||
|
||||
test('classifyCutFamily maps known product bases to internal cut families', () => {
|
||||
assert.equal(classifyCutFamily('BASE LISA CAMISETA').key, 'BLCS');
|
||||
assert.equal(classifyCutFamily('BASE LISA CAMISETA OVER').key, 'BLOS');
|
||||
@@ -37,6 +57,8 @@ test('buildCutPlan calculates projected cut need from sales pace and stock', ()
|
||||
assert.equal(row.projectedDemand, 140);
|
||||
assert.equal(row.availableQuantity, 20);
|
||||
assert.equal(row.suggestedCutQuantity, 120);
|
||||
assert.equal(row.estimatedRolls, null);
|
||||
assert.deepEqual(row.issues, ['missing_yield_rule']);
|
||||
assert.equal(plan.summary.suggestedCutQuantity, 120);
|
||||
});
|
||||
|
||||
@@ -48,6 +70,20 @@ test('buildCutPlan subtracts open production quantity from suggested cut need',
|
||||
assert.equal(row.suggestedCutQuantity, 20);
|
||||
});
|
||||
|
||||
test('buildOpenProductionByProductId matches open OPs by SKU and normalized product variant', () => {
|
||||
const products = [
|
||||
product({ id: 'SKU-1' }),
|
||||
product({ id: 'SKU-2', name: 'BASE LISA CAMISETA COR BRANCO TAMANHO - G' })
|
||||
];
|
||||
const totals = buildOpenProductionByProductId(products, [
|
||||
productionOrder({ productSku: 'SKU-1', productDescription: '', quantity: 10 }),
|
||||
productionOrder({ productSku: '', productDescription: 'Base Lisa Camiseta Cor Branco Tamanho - G', quantity: 20 }),
|
||||
productionOrder({ productSku: 'SKU-1', status: 'finished', quantity: 999 })
|
||||
]);
|
||||
|
||||
assert.deepEqual(totals, { 'SKU-1': 10, 'SKU-2': 20 });
|
||||
});
|
||||
|
||||
test('buildCutPlan marks products that cannot be planned cleanly for cutting', () => {
|
||||
const plan = buildCutPlan([
|
||||
product({
|
||||
|
||||
Reference in New Issue
Block a user