Add inferred product classification
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m36s

This commit is contained in:
Cauê Faleiros
2026-07-16 10:15:24 -03:00
parent 5e81a8f2c3
commit 422828f343
7 changed files with 274 additions and 16 deletions

View File

@@ -80,11 +80,11 @@ test('buildCutPlan estimates rolls when a family yield is configured', () => {
assert.equal(plan.summary.estimatedRolls, 3);
});
test('buildCutPlan applies per-product planning overrides', () => {
test('buildCutPlan applies per-product planning overrides to finished apparel', () => {
const plan = buildCutPlan([
product({
id: 'SKU-2',
name: 'BONÉ PRETO',
name: 'CAMISETA SEM PADRAO',
quantitySold: 70,
stock: 0
})
@@ -102,6 +102,26 @@ test('buildCutPlan applies per-product planning overrides', () => {
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' }),
@@ -116,11 +136,11 @@ test('buildOpenProductionByProductId matches open OPs by SKU and normalized prod
assert.deepEqual(totals, { 'SKU-1': 10, 'SKU-2': 20 });
});
test('buildCutPlan marks products that cannot be planned cleanly for cutting', () => {
test('buildCutPlan marks apparel products that cannot be planned cleanly for cutting', () => {
const plan = buildCutPlan([
product({
id: 'SKU-2',
name: 'BONÉ PRETO',
name: 'VESTUARIO SEM PADRAO',
quantitySold: 70,
stock: 0
})

View File

@@ -1,5 +1,6 @@
import type { CutFamilyKey, CutProductOverride, DateRange, ProductAnalyticsItem, ProductionOrderItem } from '../types';
import { normalizeProductText, parseProductName, sortProductSizes } from '../productParsing.ts';
import { classifyProductType } from '../productClassification.ts';
export type { CutFamilyKey, CutProductOverride };
@@ -201,8 +202,9 @@ export const buildCutPlan = (
options: CutPlanOptions = {}
): CutPlan => {
const rangeDays = getRangeDays(dateRange);
const cuttableProducts = products.filter(product => classifyProductType(product.name) === 'finished_apparel');
const rows = products.map<CutPlanSkuRow>(product => {
const rows = cuttableProducts.map<CutPlanSkuRow>(product => {
const metadata = parseProductName(product.name);
const override = options.productOverrides?.[product.id];
const overrideRule = override?.familyKey ? FAMILY_RULES_BY_KEY.get(override.familyKey) : undefined;