From 440c8cee1fcfaffc0ae3699877a10d6303fdfcfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Faleiros?= Date: Wed, 27 May 2026 16:31:26 -0300 Subject: [PATCH] combine ready products in campaign payload --- backend/services/campaignService.js | 84 +++++++++++++++++++---------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/backend/services/campaignService.js b/backend/services/campaignService.js index 1ec26da..ac99730 100644 --- a/backend/services/campaignService.js +++ b/backend/services/campaignService.js @@ -111,21 +111,51 @@ const updateCampaignItemsStatus = async (ids, status, errorMessage = null) => { `, [status, errorMessage, ids]); }; -const sendWhatsappCampaign = async (baseProductName, items, customers) => { - const totalDelta = items.reduce((sum, item) => sum + Number(item.delta_estoque || 0), 0); +const formatProductList = (productNames) => { + if (productNames.length <= 2) { + return productNames.join(' e '); + } + + return `${productNames.slice(0, -1).join(', ')} e ${productNames[productNames.length - 1]}`; +}; + +const mapCampaignProducts = (groups) => { + return Object.entries(groups) + .sort(([, aItems], [, bItems]) => { + return new Date(aItems[0].created_at).getTime() - new Date(bItems[0].created_at).getTime(); + }) + .map(([baseProductName, items]) => { + const sortedItems = [...items].sort((a, b) => String(a.nome).localeCompare(String(b.nome), 'pt-BR')); + + return { + baseProduct: baseProductName, + total_delta: sortedItems.reduce((sum, item) => sum + Number(item.delta_estoque || 0), 0), + sizes: sortedItems.map(item => ({ + id: item.produto_id, + nome: item.nome, + delta: item.delta_estoque, + saldo: item.saldo + })), + itemIds: sortedItems.map(item => item.id) + }; + }); +}; + +const sendWhatsappCampaign = async (products, customers) => { + const productNames = products.map(product => product.baseProduct); + const productsText = formatProductList(productNames); + const allSizes = products.flatMap(product => product.sizes); + const totalDelta = products.reduce((sum, product) => sum + product.total_delta, 0); const response = await fetch(N8N_WHATSAPP_TRIGGER_URL, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ - baseProduct: baseProductName, + baseProduct: productsText, + productsText, total_delta: totalDelta, - sizes: items.map(item => ({ - id: item.produto_id, - nome: item.nome, - delta: item.delta_estoque, - saldo: item.saldo - })), + sizes: allSizes, + products: products.map(({ itemIds, ...product }) => product), customers }) }); @@ -149,32 +179,30 @@ const processPendingStockCampaigns = async () => { return summary; } - const customers = await getTopBuyersAllTime(); const groups = rows.reduce((acc, row) => { if (!acc[row.base_product_name]) acc[row.base_product_name] = []; acc[row.base_product_name].push(row); return acc; }, {}); + const products = mapCampaignProducts(groups); + const ids = products.flatMap(product => product.itemIds); + const customers = await getTopBuyersAllTime(); - for (const [baseProductName, items] of Object.entries(groups)) { - const ids = items.map(item => item.id); + if (!customers.length) { + await updateCampaignItemsStatus(ids, 'skipped', 'No customers with valid phone numbers found.'); + summary.skippedGroups = products.length; + return summary; + } - if (!customers.length) { - await updateCampaignItemsStatus(ids, 'skipped', 'No customers with valid phone numbers found.'); - summary.skippedGroups += 1; - continue; - } - - try { - await sendWhatsappCampaign(baseProductName, items, customers); - await updateCampaignItemsStatus(ids, 'sent'); - summary.sentGroups += 1; - console.log(`[Campaign Queue] Sent ${baseProductName} campaign to ${customers.length} all-time top buyers.`); - } catch (error) { - await updateCampaignItemsStatus(ids, 'failed', error.message); - summary.failedGroups += 1; - console.error(`[Campaign Queue] Failed to send ${baseProductName} campaign:`, error); - } + try { + await sendWhatsappCampaign(products, customers); + await updateCampaignItemsStatus(ids, 'sent'); + summary.sentGroups = products.length; + console.log(`[Campaign Queue] Sent one campaign with ${products.length} products to ${customers.length} all-time top buyers.`); + } catch (error) { + await updateCampaignItemsStatus(ids, 'failed', error.message); + summary.failedGroups = products.length; + console.error('[Campaign Queue] Failed to send product list campaign:', error); } return summary;