All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m36s
153 lines
4.8 KiB
TypeScript
153 lines
4.8 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import { buildCutPlan, buildOpenProductionByProductId, classifyCutFamily } from './cutting.ts';
|
|
import type { DateRange, ProductAnalyticsItem, ProductionOrderItem } from '../types.ts';
|
|
|
|
const range: DateRange = {
|
|
start: new Date(2026, 6, 1),
|
|
end: new Date(2026, 6, 7)
|
|
};
|
|
|
|
const product = (overrides: Partial<ProductAnalyticsItem>): ProductAnalyticsItem => ({
|
|
id: 'SKU-1',
|
|
name: 'BASE LISA CAMISETA COR PRETO TAMANHO - M',
|
|
quantitySold: 70,
|
|
revenue: 700,
|
|
orderLineCount: 10,
|
|
lastPrice: 10,
|
|
stock: 20,
|
|
firstSaleDate: '2026-07-01',
|
|
lastSaleDate: '2026-07-07',
|
|
...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');
|
|
assert.equal(classifyCutFamily('BASE LISA MOLETOM CANGURU').key, 'BLPM');
|
|
assert.equal(classifyCutFamily('BONÉ').key, 'OUTROS');
|
|
});
|
|
|
|
test('buildCutPlan calculates projected cut need from sales pace and stock', () => {
|
|
const plan = buildCutPlan([product({})], range, 14);
|
|
const [row] = plan.needRows;
|
|
|
|
assert.equal(row.dailySales, 10);
|
|
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);
|
|
});
|
|
|
|
test('buildCutPlan subtracts open production quantity from suggested cut need', () => {
|
|
const plan = buildCutPlan([product({ id: 'SKU-1' })], range, 14, { 'SKU-1': 100 });
|
|
const [row] = plan.needRows;
|
|
|
|
assert.equal(row.availableQuantity, 120);
|
|
assert.equal(row.suggestedCutQuantity, 20);
|
|
});
|
|
|
|
test('buildCutPlan estimates rolls when a family yield is configured', () => {
|
|
const plan = buildCutPlan([product({})], range, 14, {}, { familyYields: { BLCS: 50 } });
|
|
const [row] = plan.needRows;
|
|
|
|
assert.equal(row.suggestedCutQuantity, 120);
|
|
assert.equal(row.estimatedRolls, 3);
|
|
assert.deepEqual(row.issues, []);
|
|
assert.equal(plan.summary.estimatedRolls, 3);
|
|
});
|
|
|
|
test('buildCutPlan applies per-product planning overrides to finished apparel', () => {
|
|
const plan = buildCutPlan([
|
|
product({
|
|
id: 'SKU-2',
|
|
name: 'CAMISETA SEM PADRAO',
|
|
quantitySold: 70,
|
|
stock: 0
|
|
})
|
|
], range, 7, {}, {
|
|
familyYields: { BLCS: 35 },
|
|
productOverrides: {
|
|
'SKU-2': { familyKey: 'BLCS', color: 'Preto', size: 'M' }
|
|
}
|
|
});
|
|
|
|
assert.equal(plan.needRows[0].family.key, 'BLCS');
|
|
assert.equal(plan.needRows[0].color, 'Preto');
|
|
assert.equal(plan.needRows[0].size, 'M');
|
|
assert.equal(plan.needRows[0].estimatedRolls, 2);
|
|
assert.deepEqual(plan.needRows[0].issues, []);
|
|
});
|
|
|
|
test('buildCutPlan excludes non-apparel products from cut planning', () => {
|
|
const plan = buildCutPlan([
|
|
product({
|
|
id: 'SKU-2',
|
|
name: 'BONÉ PRETO',
|
|
quantitySold: 70,
|
|
stock: 0
|
|
}),
|
|
product({
|
|
id: 'SKU-3',
|
|
name: 'TRANSPARENTE PP MILHEIRO - 25x35',
|
|
quantitySold: 70,
|
|
stock: 0
|
|
})
|
|
], range, 7);
|
|
|
|
assert.equal(plan.rows.length, 0);
|
|
assert.equal(plan.summary.skuCount, 0);
|
|
});
|
|
|
|
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 apparel products that cannot be planned cleanly for cutting', () => {
|
|
const plan = buildCutPlan([
|
|
product({
|
|
id: 'SKU-2',
|
|
name: 'VESTUARIO SEM PADRAO',
|
|
quantitySold: 70,
|
|
stock: 0
|
|
})
|
|
], range, 7);
|
|
|
|
assert.equal(plan.needRows[0].family.key, 'OUTROS');
|
|
assert.deepEqual(plan.needRows[0].issues, ['missing_family_rule', 'missing_color', 'missing_size']);
|
|
assert.equal(plan.summary.rowsWithIssues, 1);
|
|
});
|