From 7e3d0be595e956a865a6fee0e15d0c370b9ef7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Wed, 10 Jun 2026 16:00:59 -0300 Subject: [PATCH] fix: format campaign product list for whatsapp --- backend/services/campaignFormatter.js | 16 +++++++++------ backend/test/campaignFormatter.test.js | 27 ++++++++++++++++++++------ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/backend/services/campaignFormatter.js b/backend/services/campaignFormatter.js index d044943..4f0edd5 100644 --- a/backend/services/campaignFormatter.js +++ b/backend/services/campaignFormatter.js @@ -1,5 +1,13 @@ +const applyProductDisplayAlias = (name) => { + const productName = String(name || '').trim(); + return productName + .replace(/^BASE LISA CAMISETA\b/i, 'CAMISETA PREMIUM') + .replace(/^BASE LISA OVER SIZE\b/i, 'CAMISETA PREMIUM OVER SIZE') + .replace(/^BASE LISA MOLETOM CANGURU\b/i, 'MOLETOM CANGURU PREMIUM'); +}; + const formatProductNameForDisplay = (name) => { - return String(name || '') + return applyProductDisplayAlias(name) .toLocaleLowerCase('pt-BR') .replace(/(^|[\s/-])(\p{L})/gu, (_, separator, letter) => { return `${separator}${letter.toLocaleUpperCase('pt-BR')}`; @@ -9,11 +17,7 @@ const formatProductNameForDisplay = (name) => { const formatProductList = (productNames) => { const displayNames = productNames.map(formatProductNameForDisplay); - if (displayNames.length <= 2) { - return displayNames.join(' e '); - } - - return `${displayNames.slice(0, -1).join(', ')} e ${displayNames[displayNames.length - 1]}`; + return displayNames.map(name => `• ${name}`).join(' '); }; const groupCampaignRowsByBaseProduct = (rows) => { diff --git a/backend/test/campaignFormatter.test.js b/backend/test/campaignFormatter.test.js index 7a5adc4..3378a86 100644 --- a/backend/test/campaignFormatter.test.js +++ b/backend/test/campaignFormatter.test.js @@ -25,24 +25,39 @@ const row = (overrides) => ({ ...overrides }); -test('formatProductList uses Portuguese list joining', () => { +test('formatProductList uses inline bullet separators', () => { assert.equal(formatProductList([]), ''); - assert.equal(formatProductList(['BONÉ - PRETO']), 'Boné - Preto'); - assert.equal(formatProductList(['BONÉ - PRETO', 'BASE BRANCA']), 'Boné - Preto e Base Branca'); + assert.equal(formatProductList(['BONÉ - PRETO']), '• Boné - Preto'); + assert.equal(formatProductList(['BONÉ - PRETO', 'BASE BRANCA']), '• Boné - Preto • Base Branca'); assert.equal( formatProductList(['BONÉ - PRETO', 'BASE BRANCA', 'BASE PRETA']), - 'Boné - Preto, Base Branca e Base Preta' + '• Boné - Preto • Base Branca • Base Preta' ); }); test('formatProductNameForDisplay converts campaign product names to title case', () => { assert.equal( formatProductNameForDisplay('BASE LISA MOLETOM CANGURU COR PRETO'), - 'Base Lisa Moletom Canguru Cor Preto' + 'Moletom Canguru Premium Cor Preto' ); assert.equal(formatProductNameForDisplay('BONÉ - BRANCO'), 'Boné - Branco'); }); +test('formatProductNameForDisplay applies customer-facing campaign aliases', () => { + assert.equal( + formatProductNameForDisplay('BASE LISA CAMISETA COR AZUL'), + 'Camiseta Premium Cor Azul' + ); + assert.equal( + formatProductNameForDisplay('BASE LISA OVER SIZE COR PRETO'), + 'Camiseta Premium Over Size Cor Preto' + ); + assert.equal( + formatProductNameForDisplay('BASE LISA MOLETOM CANGURU COR PRETO'), + 'Moletom Canguru Premium Cor Preto' + ); +}); + test('mapCampaignProducts accumulates split deltas by base product', () => { const groups = groupCampaignRowsByBaseProduct([ row({ id: 1, delta_estoque: 10, produto_id: 'SKU-P', nome: 'Produto Split TAMANHO - P' }), @@ -79,7 +94,7 @@ test('buildWhatsappCampaignPayload combines multiple ready products into one mes ])); const payload = buildWhatsappCampaignPayload(products, [{ nome: 'Cliente', fone: '5511999999999' }]); - assert.equal(payload.productsText, 'Boné - Preto e Base Lisa Camiseta Cor Branco'); + assert.equal(payload.productsText, '• Boné - Preto • Camiseta Premium Cor Branco'); assert.equal(payload.baseProduct, payload.productsText); assert.equal(payload.total_delta, 200); assert.equal(payload.products.length, 2);