Preserve existing order metadata on empty upserts
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m21s

This commit is contained in:
Cauê Faleiros
2026-06-22 15:15:44 -03:00
parent 3568e48ce9
commit bd98348989
2 changed files with 92 additions and 35 deletions

View File

@@ -26,13 +26,13 @@ const upsertOrders = async (payload) => {
produto_descricao = EXCLUDED.produto_descricao,
quantidade = EXCLUDED.quantidade,
valor_unitario = EXCLUDED.valor_unitario,
cliente_fone = EXCLUDED.cliente_fone,
cliente_nome_fantasia = EXCLUDED.cliente_nome_fantasia,
id_vendedor = EXCLUDED.id_vendedor,
nome_vendedor = EXCLUDED.nome_vendedor,
marketplace = EXCLUDED.marketplace,
canal_venda = EXCLUDED.canal_venda,
numero_ecommerce = EXCLUDED.numero_ecommerce,
cliente_fone = COALESCE(NULLIF(EXCLUDED.cliente_fone, ''), orders.cliente_fone),
cliente_nome_fantasia = COALESCE(NULLIF(EXCLUDED.cliente_nome_fantasia, ''), orders.cliente_nome_fantasia),
id_vendedor = COALESCE(NULLIF(EXCLUDED.id_vendedor, ''), orders.id_vendedor),
nome_vendedor = COALESCE(NULLIF(EXCLUDED.nome_vendedor, ''), orders.nome_vendedor),
marketplace = COALESCE(NULLIF(EXCLUDED.marketplace, ''), orders.marketplace),
canal_venda = COALESCE(NULLIF(EXCLUDED.canal_venda, ''), orders.canal_venda),
numero_ecommerce = COALESCE(NULLIF(EXCLUDED.numero_ecommerce, ''), orders.numero_ecommerce),
created_at = CURRENT_TIMESTAMP
`;

View File

@@ -1,7 +1,7 @@
const assert = require('node:assert/strict');
const test = require('node:test');
test('upsertOrders persists Tiny ERP metadata columns', async () => {
const runUpsertWithPayload = async (payload) => {
const queries = [];
const client = {
query: async (sql, params) => {
@@ -31,24 +31,7 @@ test('upsertOrders persists Tiny ERP metadata columns', async () => {
try {
const { upsertOrders } = require('../services/ordersService');
await upsertOrders([{
Nome_Cliente: 'Cliente Teste',
Data_Pedido: '28/05/2026',
Valor_Pedido: '120.50',
ID_Produto: 'SKU-1',
Descricao_Produto: 'Produto',
Quantidade: '2',
Valor_Unitario: '60.25',
ID_Pedido: 'ORDER-1',
Fone_Cliente: '(16) 99999-9999',
cliente_nome_fantasia: 'Cliente Fantasia',
id_vendedor: 'VEN-1',
nome_vendedor: 'Maria',
marketplace: 'Mercado Livre',
canal_venda: 'Online',
numero_ecommerce: 'EC-987'
}]);
await upsertOrders(payload);
} finally {
delete require.cache[servicePath];
if (originalServiceCache) {
@@ -61,18 +44,39 @@ test('upsertOrders persists Tiny ERP metadata columns', async () => {
}
}
const insert = queries.find(query => query.sql.includes('INSERT INTO orders'));
return queries.find(query => query.sql.includes('INSERT INTO orders'));
};
const assertPreservesEmptyConflictValue = (sql, fieldName) => {
assert.match(
sql,
new RegExp(`${fieldName} = COALESCE\\(NULLIF\\(EXCLUDED\\.${fieldName}, ''\\), orders\\.${fieldName}\\)`)
);
};
test('upsertOrders persists non-empty Tiny ERP metadata columns', async () => {
const insert = await runUpsertWithPayload([{
Nome_Cliente: 'Cliente Teste',
Data_Pedido: '28/05/2026',
Valor_Pedido: '120.50',
ID_Produto: 'SKU-1',
Descricao_Produto: 'Produto',
Quantidade: '2',
Valor_Unitario: '60.25',
ID_Pedido: 'ORDER-1',
Fone_Cliente: '(16) 99999-9999',
cliente_nome_fantasia: 'Cliente Fantasia',
id_vendedor: 'VEN-1',
nome_vendedor: 'Maria',
marketplace: 'Mercado Livre',
canal_venda: 'Online',
numero_ecommerce: 'EC-987'
}]);
assert.ok(insert);
assert.match(insert.sql, /cliente_nome_fantasia/);
assert.match(insert.sql, /id_vendedor/);
assert.match(insert.sql, /nome_vendedor/);
assert.match(insert.sql, /marketplace/);
assert.match(insert.sql, /canal_venda/);
assert.match(insert.sql, /numero_ecommerce/);
assert.match(insert.sql, /cliente_nome_fantasia = EXCLUDED\.cliente_nome_fantasia/);
assert.equal(insert.params.length, 16);
assert.deepEqual(insert.params.slice(10), [
assert.deepEqual(insert.params.slice(9), [
'(16) 99999-9999',
'Cliente Fantasia',
'VEN-1',
'Maria',
@@ -81,3 +85,56 @@ test('upsertOrders persists Tiny ERP metadata columns', async () => {
'EC-987'
]);
});
test('upsertOrders preserves existing phone and metadata when incoming values are empty', async () => {
const insert = await runUpsertWithPayload([{
Nome_Cliente: 'Cliente Teste',
Data_Pedido: '28/05/2026',
Valor_Pedido: '120.50',
ID_Produto: 'SKU-1',
Descricao_Produto: 'Produto',
Quantidade: '2',
Valor_Unitario: '60.25',
ID_Pedido: 'ORDER-1',
Fone_Cliente: '',
cliente_nome_fantasia: '',
id_vendedor: '',
nome_vendedor: '',
marketplace: '',
canal_venda: '',
numero_ecommerce: ''
}]);
assert.ok(insert);
[
'cliente_fone',
'cliente_nome_fantasia',
'id_vendedor',
'nome_vendedor',
'marketplace',
'canal_venda',
'numero_ecommerce'
].forEach(fieldName => assertPreservesEmptyConflictValue(insert.sql, fieldName));
assert.deepEqual(insert.params.slice(9), ['', '', '', '', '', '', '']);
});
test('upsertOrders keeps existing payloads without Tiny ERP metadata working', async () => {
const insert = await runUpsertWithPayload([{
Nome_Cliente: 'Cliente Teste',
Data_Pedido: '28/05/2026',
Valor_Pedido: '120.50',
ID_Produto: 'SKU-1',
Descricao_Produto: 'Produto',
Quantidade: '2',
Valor_Unitario: '60.25',
ID_Pedido: 'ORDER-1'
}]);
assert.ok(insert);
assert.equal(insert.params.length, 16);
assert.deepEqual(insert.params.slice(9), ['', '', '', '', '', '', '']);
assert.match(insert.sql, /quantidade = EXCLUDED\.quantidade/);
assert.match(insert.sql, /valor_unitario = EXCLUDED\.valor_unitario/);
assertPreservesEmptyConflictValue(insert.sql, 'cliente_fone');
assertPreservesEmptyConflictValue(insert.sql, 'cliente_nome_fantasia');
});