fix: title case campaign product names

This commit is contained in:
Cauê Faleiros
2026-06-01 09:47:35 -03:00
parent a1aa071e1d
commit fce7bbf975
2 changed files with 28 additions and 8 deletions

View File

@@ -1,9 +1,19 @@
const formatProductNameForDisplay = (name) => {
return String(name || '')
.toLocaleLowerCase('pt-BR')
.replace(/(^|[\s/-])(\p{L})/gu, (_, separator, letter) => {
return `${separator}${letter.toLocaleUpperCase('pt-BR')}`;
});
};
const formatProductList = (productNames) => {
if (productNames.length <= 2) {
return productNames.join(' e ');
const displayNames = productNames.map(formatProductNameForDisplay);
if (displayNames.length <= 2) {
return displayNames.join(' e ');
}
return `${productNames.slice(0, -1).join(', ')} e ${productNames[productNames.length - 1]}`;
return `${displayNames.slice(0, -1).join(', ')} e ${displayNames[displayNames.length - 1]}`;
};
const groupCampaignRowsByBaseProduct = (rows) => {
@@ -23,7 +33,7 @@ const mapCampaignProducts = (groups) => {
const sortedItems = [...items].sort((a, b) => String(a.nome).localeCompare(String(b.nome), 'pt-BR'));
return {
baseProduct: baseProductName,
baseProduct: formatProductNameForDisplay(baseProductName),
total_delta: sortedItems.reduce((sum, item) => sum + Number(item.delta_estoque || 0), 0),
sizes: sortedItems.map(item => ({
id: item.produto_id,
@@ -85,6 +95,7 @@ const groupCampaignRows = (rows) => {
module.exports = {
buildWhatsappCampaignPayload,
formatProductNameForDisplay,
formatProductList,
groupCampaignRows,
groupCampaignRowsByBaseProduct,

View File

@@ -3,6 +3,7 @@ const assert = require('node:assert/strict');
const {
buildWhatsappCampaignPayload,
formatProductList,
formatProductNameForDisplay,
groupCampaignRows,
groupCampaignRowsByBaseProduct,
mapCampaignProducts
@@ -26,14 +27,22 @@ const row = (overrides) => ({
test('formatProductList uses Portuguese list joining', () => {
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 e Base Branca');
assert.equal(
formatProductList(['BONÉ - PRETO', 'BASE BRANCA', 'BASE PRETA']),
'BONÉ - PRETO, BASE BRANCA e BASE PRETA'
'Boné - Preto, Base Branca e 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'
);
assert.equal(formatProductNameForDisplay('BONÉ - BRANCO'), 'Boné - Branco');
});
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' }),
@@ -70,7 +79,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 e Base Lisa Camiseta Cor Branco');
assert.equal(payload.baseProduct, payload.productsText);
assert.equal(payload.total_delta, 200);
assert.equal(payload.products.length, 2);