188 lines
7.0 KiB
JavaScript
188 lines
7.0 KiB
JavaScript
import { workflow, trigger, node } from 'n8n-workflow-sdk';
|
|
|
|
export default workflow('Supabase → Sheet VENDAS', {
|
|
description: 'Busca fechamentos_web do Supabase e append na Sheet VENDAS (incremental por atualizado_em UTC)',
|
|
|
|
nodes: [
|
|
// ── TRIGGER: 20h BRT (23h UTC) ──────────────────────────────────
|
|
trigger('Schedule Daily 20h', {
|
|
type: 'n8n-nodes-base.scheduleTrigger',
|
|
typeVersion: 1.2,
|
|
position: [100, 300],
|
|
parameters: {
|
|
rule: { interval: [{ field: 'cron', expression: '0 20 * * *' }] }
|
|
}
|
|
}),
|
|
|
|
// ── READ LAST SYNC from Sheet Sincronizacao A1 ───────────────────
|
|
node('Read Last Sync', {
|
|
type: 'n8n-nodes-base.googleSheets',
|
|
typeVersion: 4.2,
|
|
position: [340, 300],
|
|
credentials: { googleSheetsOAuth2Api: { id: 'qVVlfm46BZ6tX5VX', name: 'Google Sheets account' } },
|
|
parameters: {
|
|
operation: 'read',
|
|
documentId: { __rl: true, mode: 'id', value: '1RGa7Qigu5kWJGCOx3kJ3Oa8wTTJeD-CzGjBYazrjsWk' },
|
|
sheetName: { __rl: true, mode: 'list', value: 'Sincronizacao' },
|
|
cellSelection: { __rl: true, mode: 'list', value: 'A1' },
|
|
options: { cellFormat: 'USER_ENTERED' }
|
|
}
|
|
}),
|
|
|
|
// ── FETCH fechamentos_web from Supabase ──────────────────────────
|
|
node('Fetch from Supabase', {
|
|
type: 'n8n-nodes-base.httpRequest',
|
|
typeVersion: 4.2,
|
|
position: [600, 300],
|
|
credentials: { supabaseApi: { id: 'Tw9r35a9Iz3P9q7x', name: 'Supabase account 2 (self-hosted)' } },
|
|
parameters: {
|
|
method: 'GET',
|
|
url: '=https://supabase.ofrangao.com.br/rest/v1/fechamentos_web',
|
|
queryParameters: {
|
|
parameters: [
|
|
{
|
|
name: 'select',
|
|
value: '=id_fechamento,data,loja,turno,operador,fechamento_dinheiro,fechamento_cartoes,total_sangrias,total_despesas,total_vales,total_pixcnpj,saldo_pixcnpj,total_areceber,total_cartao_credito,total_cartao_debito,total_cartao_alimentacao,total_cancelamentos,diferenca,status_diferenca,atualizado_em'
|
|
},
|
|
{ name: 'order', value: '=atualizado_em.asc' },
|
|
{ name: 'limit', value: '=500' }
|
|
]
|
|
}
|
|
}
|
|
}),
|
|
|
|
// ── CODE: Filter by lastSync + Map to Sheet columns ─────────────
|
|
node('Filter + Map', {
|
|
type: 'n8n-nodes-base.code',
|
|
typeVersion: 2,
|
|
position: [860, 300],
|
|
parameters: {
|
|
jsCode: `
|
|
// 1. lastSync da Sheet
|
|
const lastSyncRaw = $input.first().json.value || null;
|
|
const lastSync = lastSyncRaw ? new Date(lastSyncRaw).toISOString() : null;
|
|
|
|
// 2. Todas as rows do Supabase
|
|
const allRows = $input.all().map(item => item.json);
|
|
|
|
// 3. Filtrar por lastSync
|
|
let filtered = lastSync ? allRows.filter(r => r.atualizado_em && r.atualizado_em > lastSync) : allRows;
|
|
|
|
if (filtered.length === 0) {
|
|
// Sem linhas novas —marker o sync point com lastSync antigo para não re-buscar
|
|
return [{
|
|
json: {
|
|
_action: 'noop',
|
|
_lastSync: lastSync,
|
|
_max_updated: lastSync,
|
|
DATA:'', EMPRESA:'', SANGRIA:0, DESPESAS:0, VALES:0,
|
|
DINHEIRO:0, PIX_TAXA:0, PIX_LOJA:0, PRAZO:0, P2:0,
|
|
CREDITO:0, DEBITO:0, VOUCHER:0, CARTAO:0,
|
|
T_VENDA:0, TX_CAIXA:0, CLIENTES:0, CANCELADOS:0,
|
|
SISTEMA:0, DIFERENCA:0, CAIXA:'', PG:false
|
|
}
|
|
}];
|
|
}
|
|
|
|
// 4. MAX(atualizado_em) do batch
|
|
const maxUpdated = filtered.reduce((m, r) =>
|
|
r.atualizado_em > m ? r.atualizado_em : m, filtered[0].atualizado_em);
|
|
|
|
// 5. Mapear para colunas Sheet
|
|
const LOJA_MAP = { alianca: 'Aliança', uniao: 'União' };
|
|
|
|
return filtered.map(r => ({
|
|
json: {
|
|
DATA: r.data,
|
|
EMPRESA: LOJA_MAP[r.loja] || r.loja,
|
|
SANGRIA: r.total_sangrias || 0,
|
|
DESPESAS: r.total_despesas || 0,
|
|
VALES: r.total_vales || 0,
|
|
DINHEIRO: r.fechamento_dinheiro || 0,
|
|
PIX_TAXA: r.total_pixcnpj || 0,
|
|
PIX_LOJA: r.saldo_pixcnpj || 0,
|
|
PRAZO: r.total_areceber || 0,
|
|
P2: 0,
|
|
CREDITO: r.total_cartao_credito || 0,
|
|
DEBITO: r.total_cartao_debito || 0,
|
|
VOUCHER: r.total_cartao_alimentacao || 0,
|
|
CARTAO: r.fechamento_cartoes || 0,
|
|
T_VENDA: 0, // fórmula na Sheet
|
|
TX_CAIXA: 0, // fórmula na Sheet
|
|
CLIENTES: 0,
|
|
CANCELADOS: r.total_cancelamentos || 0,
|
|
SISTEMA: 0, // fórmula na Sheet
|
|
DIFERENCA: r.diferenca || 0,
|
|
CAIXA: r.operador || '',
|
|
PG: r.status_diferenca === 'ok',
|
|
_action: 'append',
|
|
_max_updated: maxUpdated
|
|
}
|
|
}));
|
|
`
|
|
}
|
|
}),
|
|
|
|
// ── APPEND to Sheet VENDAS ──────────────────────────────────────
|
|
node('Append to VENDAS', {
|
|
type: 'n8n-nodes-base.googleSheets',
|
|
typeVersion: 4.2,
|
|
position: [1100, 200],
|
|
credentials: { googleSheetsOAuth2Api: { id: 'qVVlfm46BZ6tX5VX', name: 'Google Sheets account' } },
|
|
parameters: {
|
|
operation: 'append',
|
|
documentId: { __rl: true, mode: 'id', value: '1RGa7Qigu5kWJGCOx3kJ3Oa8wTTJeD-CzGjBYazrjsWk' },
|
|
sheetName: { __rl: true, mode: 'list', value: 'VENDAS' },
|
|
options: { cellFormat: 'USER_ENTERED' }
|
|
}
|
|
}),
|
|
|
|
// ── UPDATE LAST SYNC in Sincronizacao A1 ───────────────────────
|
|
// Recebe o primeiro item (com _max_updated) de Filter+Map
|
|
node('Update Last Sync', {
|
|
type: 'n8n-nodes-base.googleSheets',
|
|
typeVersion: 4.2,
|
|
position: [1100, 440],
|
|
credentials: { googleSheetsOAuth2Api: { id: 'qVVlfm46BZ6tX5VX', name: 'Google Sheets account' } },
|
|
parameters: {
|
|
operation: 'update',
|
|
documentId: { __rl: true, mode: 'id', value: '1RGa7Qigu5kWJGCOx3kJ3Oa8wTTJeD-CzGjBYazrjsWk' },
|
|
sheetName: { __rl: true, mode: 'list', value: 'Sincronizacao' },
|
|
cellSelection: { __rl: true, mode: 'list', value: 'A1' },
|
|
valueInputOption: 'USER_ENTERED',
|
|
options: { cellFormat: 'USER_ENTERED' }
|
|
}
|
|
}),
|
|
],
|
|
|
|
connections: {
|
|
'Schedule Daily 20h': {
|
|
main: [[{ node: 'Read Last Sync', type: 'main', index: 0 }]]
|
|
},
|
|
'Read Last Sync': {
|
|
main: [[{ node: 'Fetch from Supabase', type: 'main', index: 0 }]]
|
|
},
|
|
'Fetch from Supabase': {
|
|
main: [[{ node: 'Filter + Map', type: 'main', index: 0 }]]
|
|
},
|
|
'Filter + Map': {
|
|
main: [
|
|
// Branch 0: dados para Sheet
|
|
[{ node: 'Append to VENDAS', type: 'main', index: 0 }],
|
|
// Branch 1: marker sync (vai directo para Update Last Sync)
|
|
[{ node: 'Update Last Sync', type: 'main', index: 0 }]
|
|
]
|
|
},
|
|
'Append to VENDAS': {
|
|
main: [[{ node: 'Update Last Sync', type: 'main', index: 0 }]]
|
|
}
|
|
},
|
|
|
|
settings: {
|
|
executionOrder: 'v1',
|
|
saveExecutionProgress: true,
|
|
saveDataSuccessExecution: 'all',
|
|
saveDataErrorExecution: 'all'
|
|
}
|
|
});
|