import path from 'node:path'; import { loadDotEnv, paths } from '../env.mjs'; import { openDb, transaction } from '../db.mjs'; import { createJobIO } from '../jobs/protocol.mjs'; import { exportExcel } from './excel.mjs'; import { exportOportunidades, exportBulkDataInput } from './zpro.mjs'; // Processo filho de exportacao: gera os arquivos do tipo pedido e, ao final, // numa unica transacao, registra os leads exportados (export_leads) e marca // exported_at (para o filtro "ainda nao exportado" excluir esses leads). await loadDotEnv(); const args = new Map( process.argv.slice(2).map((arg) => { const [key, value = 'true'] = arg.replace(/^--/, '').split('='); return [key, value]; }) ); const io = createJobIO(); const GENERATORS = { excel: exportExcel, 'zpro-oportunidades': exportOportunidades, 'zpro-bulk': exportBulkDataInput }; async function main() { const exportId = Number(args.get('export-id')); if (!exportId) throw new Error('export-job: --export-id obrigatorio'); const db = openDb(); const row = db.prepare('SELECT * FROM exports WHERE id = ?').get(exportId); if (!row) throw new Error(`export #${exportId} nao encontrado`); const generator = GENERATORS[row.tipo]; if (!generator) throw new Error(`tipo de exportacao desconhecido: ${row.tipo}`); const filtro = JSON.parse(row.filtro_json || '{}'); const params = JSON.parse(row.params_json || '{}'); db.prepare("UPDATE exports SET status = 'running' WHERE id = ?").run(exportId); io.emit({ phase: row.tipo, message: 'gerando arquivos...' }); const dir = path.join(paths.exports, `export-${exportId}`); const baseName = params.baseName || `leads-${row.tipo}`; const leadIds = []; try { const result = await generator({ db, filtro, params, dir, baseName, collectIds: leadIds, onProgress: (p) => io.emit({ phase: row.tipo, ...p }) }); const marcar = params.marcarExportado !== false; io.emit({ phase: row.tipo, message: `registrando ${leadIds.length} leads exportados...` }); transaction(db, () => { const insertLink = db.prepare('INSERT OR IGNORE INTO export_leads (export_id, lead_id) VALUES (?, ?)'); const mark = marcar ? db.prepare("UPDATE leads SET exported_at = COALESCE(exported_at, datetime('now')), updated_at = datetime('now') WHERE id = ?") : null; for (const leadId of leadIds) { insertLink.run(exportId, leadId); if (mark) mark.run(leadId); } db.prepare( "UPDATE exports SET status = 'done', total_leads = ?, arquivos_json = ?, finished_at = datetime('now') WHERE id = ?" ).run(result.total, JSON.stringify(result.files), exportId); }); io.done({ total: result.total, arquivos: result.files }); } catch (error) { db.prepare("UPDATE exports SET status = 'error', error = ?, finished_at = datetime('now') WHERE id = ?") .run(String(error.message || error), exportId); throw error; } finally { db.close(); } } main().catch((error) => { io.fail(error); process.exit(1); });