From 0d6ef40c8e18e4ffb679b186aa8038b4ed8ad052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Mon, 1 Jun 2026 09:54:30 -0300 Subject: [PATCH] fix: preserve etiqueta product variants --- backend/db.js | 10 ++++++++++ backend/mappers/stockMapper.js | 7 ++++++- backend/services/analyticsService.js | 7 ++++++- backend/test/stockMapper.test.js | 6 ++++++ src/analytics/orders.ts | 7 ++++++- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/backend/db.js b/backend/db.js index bae155e..1b59730 100644 --- a/backend/db.js +++ b/backend/db.js @@ -108,6 +108,16 @@ const initDB = async () => { console.error('Notice: Could not normalize queued campaign product names:', err.message); }); + await pool.query(` + UPDATE stock_campaign_queue + SET base_product_name = nome + WHERE status IN ('pending', 'failed', 'processing') + AND nome ILIKE 'ETIQUETA%' + AND base_product_name != nome; + `).catch(err => { + console.error('Notice: Could not restore queued etiqueta product names:', err.message); + }); + await pool.query(`CREATE INDEX IF NOT EXISTS idx_stock_campaign_queue_status ON stock_campaign_queue (status);`); await pool.query(`CREATE INDEX IF NOT EXISTS idx_orders_cliente_fone ON orders (cliente_fone);`); await pool.query(`CREATE INDEX IF NOT EXISTS idx_orders_produto_id ON orders (produto_id);`); diff --git a/backend/mappers/stockMapper.js b/backend/mappers/stockMapper.js index cf1a8ab..1f12065 100644 --- a/backend/mappers/stockMapper.js +++ b/backend/mappers/stockMapper.js @@ -1,7 +1,12 @@ const SIZE_SUFFIX_PATTERN = /\s+-\s+(?:(?:PP|P|M|G|GG|XG|XGG|EG|EGG|EXG|U|UNICO|ÚNICO|\d{2})(?:\/(?:PP|P|M|G|GG|XG|XGG|EG|EGG|EXG|U|UNICO|ÚNICO|\d{2}))*)$/i; const getBaseProductName = (name) => { - return String(name || 'Unknown') + const productName = String(name || 'Unknown').trim(); + if (productName.toLocaleUpperCase('pt-BR').startsWith('ETIQUETA')) { + return productName; + } + + return productName .split(' TAMANHO')[0] .replace(SIZE_SUFFIX_PATTERN, '') .trim(); diff --git a/backend/services/analyticsService.js b/backend/services/analyticsService.js index dc77c2e..46fd914 100644 --- a/backend/services/analyticsService.js +++ b/backend/services/analyticsService.js @@ -1,7 +1,12 @@ const { pool } = require('../db'); const SIZE_SUFFIX_SQL_PATTERN = '\\s+-\\s+(?:(?:PP|P|M|G|GG|XG|XGG|EG|EGG|EXG|U|UNICO|ÚNICO|\\d{2})(?:/(?:PP|P|M|G|GG|XG|XGG|EG|EGG|EXG|U|UNICO|ÚNICO|\\d{2}))*)$'; -const PRODUCT_NAME_SQL = `NULLIF(TRIM(regexp_replace(split_part(COALESCE(produto_descricao, 'Unknown'), ' TAMANHO', 1), '${SIZE_SUFFIX_SQL_PATTERN}', '', 'i')), '')`; +const PRODUCT_NAME_SQL = ` + CASE + WHEN COALESCE(produto_descricao, 'Unknown') ILIKE 'ETIQUETA%' THEN COALESCE(produto_descricao, 'Unknown') + ELSE NULLIF(TRIM(regexp_replace(split_part(COALESCE(produto_descricao, 'Unknown'), ' TAMANHO', 1), '${SIZE_SUFFIX_SQL_PATTERN}', '', 'i')), '') + END +`; const normalizeDateParam = (value) => { if (!value) return null; diff --git a/backend/test/stockMapper.test.js b/backend/test/stockMapper.test.js index 90aa337..8de3c6a 100644 --- a/backend/test/stockMapper.test.js +++ b/backend/test/stockMapper.test.js @@ -21,3 +21,9 @@ test('getBaseProductName strips trailing size suffixes without removing colors', ); assert.equal(getBaseProductName('BONÉ - BRANCO'), 'BONÉ - BRANCO'); }); + +test('getBaseProductName preserves etiqueta product variants', () => { + assert.equal(getBaseProductName('ETIQUETA 10X5 851UN'), 'ETIQUETA 10X5 851UN'); + assert.equal(getBaseProductName('ETIQUETA BRANCA TAMANHO 08'), 'ETIQUETA BRANCA TAMANHO 08'); + assert.equal(getBaseProductName('ETIQUETA BRANCA TAMANHO GG'), 'ETIQUETA BRANCA TAMANHO GG'); +}); diff --git a/src/analytics/orders.ts b/src/analytics/orders.ts index 6e56dec..971ccfc 100644 --- a/src/analytics/orders.ts +++ b/src/analytics/orders.ts @@ -4,7 +4,12 @@ import { parseOrderDate } from '../dataService'; const SIZE_SUFFIX_PATTERN = /\s+-\s+(?:(?:PP|P|M|G|GG|XG|XGG|EG|EGG|EXG|U|UNICO|ÚNICO|\d{2})(?:\/(?:PP|P|M|G|GG|XG|XGG|EG|EGG|EXG|U|UNICO|ÚNICO|\d{2}))*)$/i; export const getBaseProductName = (description: string): string => { - return description.split(' TAMANHO')[0].replace(SIZE_SUFFIX_PATTERN, '').trim(); + const productName = description.trim(); + if (productName.toLocaleUpperCase('pt-BR').startsWith('ETIQUETA')) { + return productName; + } + + return productName.split(' TAMANHO')[0].replace(SIZE_SUFFIX_PATTERN, '').trim(); }; export const getClientDisplayName = (order: OrderData): string => {