Agregar República Dominicana y ajustes finales del portal

This commit is contained in:
2026-09-14 07:18:07 -04:00
parent 8ff13ceb9f
commit 57367628ec
27 changed files with 4859 additions and 572 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,164 @@
{
"name": "Portal de Verificación de Nómina República Dominicana - Históricos",
"nodes": [
{
"parameters": {
"path": "cruce-cuentas-rd-historicos",
"responseMode": "responseNode",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
304,
272
],
"id": "7550a9f8-2006-4330-8b6d-f0a99b53ba69",
"name": "Webhook Históricos RD",
"webhookId": "31b88d0c-ab11-4ff9-87c9-895b4fb6b097"
},
{
"parameters": {
"jsCode": "const items = $input.all();\n\nfunction formatDate(value) {\n if (!value) return '';\n const date = new Date(value);\n if (Number.isNaN(date.getTime())) return String(value).slice(0, 10);\n return date.toISOString().slice(0, 10);\n}\n\nfunction toNumber(value) {\n const parsed = Number(value);\n return Number.isFinite(parsed) ? parsed : 0;\n}\n\nfunction normalizeStatus(value, discrepancias) {\n const status = String(value || '').toLowerCase();\n\n if (status === 'resuelto') return 'resuelto';\n if (status === 'procesado' && toNumber(discrepancias) === 0) return 'procesado';\n\n return 'pendiente_revision';\n}\n\nfunction statusLabel(status) {\n if (status === 'resuelto') return 'RESUELTO';\n if (status === 'procesado') return 'PROCESADO';\n return 'PENDIENTE REVISIÓN';\n}\n\nconst reports = items.map((item) => {\n const row = item.json || {};\n\n const discrepancias = toNumber(row.discrepancias);\n const bancoSinNomina = toNumber(row.banco_sin_nomina);\n const nominaSinCuenta = toNumber(row.nomina_sin_cuenta);\n const bancoSinBamboo = toNumber(row.banco_sin_bamboo);\n const nominaSinBamboo = toNumber(row.nomina_sin_bamboo);\n const bambooSinNomina = toNumber(row.bamboo_sin_nomina);\n\n const diferenciasNombreBanco = toNumber(row.metadata?.diferencias_nombre_banco ?? row.summary?.diferenciasNombreBanco ?? row.diferencias_nombre_banco);\n const posiblesCuentasMalDigitadas = toNumber(row.metadata?.posibles_cuentas_mal_digitadas ?? row.summary?.posiblesCuentasMalDigitadas ?? row.posibles_cuentas_mal_digitadas);\n const fallbackPendientes = discrepancias + bancoSinNomina + nominaSinCuenta + diferenciasNombreBanco + posiblesCuentasMalDigitadas;\n const savedPendientes = Number(row.metadata?.pendientes_cruce_principal ?? row.summary?.pendientes ?? row.pendientes_cruce_principal);\n const totalPendientes = Number.isFinite(savedPendientes) ? savedPendientes : fallbackPendientes;\n\n const estado = normalizeStatus(row.estado, totalPendientes);\n\n return {\n id: row.id,\n\n fecha: formatDate(row.period_end || row.ejecutado_en || row.created_at),\n fechaEjecucion: row.ejecutado_en || row.created_at,\n\n periodo: row.period_label || '',\n year: row.year,\n month: row.month,\n periodType: row.period_type,\n periodStart: row.period_start,\n periodEnd: row.period_end,\n\n archivoNomina: row.payroll_file_name || '',\n archivosBanco: row.bank_file_names || [],\n\n coincidencias: toNumber(row.coincidencias),\n discrepancias,\n bancoSinNomina,\n nominaSinCuenta,\n bancoSinBamboo,\n nameDifferences: diferenciasNombreBanco,\n diferenciasNombreBanco,\n possibleWrongAccounts: posiblesCuentasMalDigitadas,\n posiblesCuentasMalDigitadas,\n pendientes: totalPendientes,\n totalPending: totalPendientes,\n nominaSinBamboo,\n bambooSinNomina,\n totalPendientes,\n\n totalNomina: toNumber(row.total_nomina),\n totalBanco: toNumber(row.total_banco),\n diferenciaTotal: toNumber(row.diferencia_total),\n\n estado,\n estadoLabel: statusLabel(estado),\n\n reportUrl: row.report_url || '',\n spreadsheetId: row.spreadsheet_id || '',\n\n ejecutadoPorNombre: row.ejecutado_por_nombre || '',\n ejecutadoPorEmail: row.ejecutado_por_email || '',\n\n resueltoPorNombre: row.resuelto_por_nombre || '',\n resueltoPorEmail: row.resuelto_por_email || '',\n resueltoEn: row.resuelto_en || null,\n comentarioResolucion: row.comentario_resolucion || '',\n };\n});\n\nreturn [\n {\n json: {\n ok: true,\n stage: 'historicos_rd_listos',\n count: reports.length,\n reports,\n },\n },\n];"
},
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
720,
272
],
"id": "bfa3bf09-7076-4322-9ea5-abde67baa069",
"name": "Normalizar históricos para app"
},
{
"parameters": {
"url": "https://dbit.digitalcompass.agency/rest/v1/cruces_cuentas_gt_reportes?select=*&country=eq.RD&order=ejecutado_en.desc&limit=100",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
},
{
"name": "Authorization",
"value": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.DaYlNEoUrrEn2Ig7tqibS-PHK5vgusbcbo7X36XVt4Q"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.4,
"position": [
512,
272
],
"id": "6ca12435-bafc-44ab-ba07-08d6a1d72cf4",
"name": "Consultar históricos Supabase"
},
{
"parameters": {
"respondWith": "json",
"responseBody": "={{ $json }}",
"options": {
"responseHeaders": {
"entries": [
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "Access-Control-Allow-Origin",
"value": "*"
},
{
"name": "Access-Control-Allow-Methods",
"value": "GET,POST,OPTIONS"
},
{
"name": "Access-Control-Allow-Headers",
"value": "Content-Type, Authorization"
}
]
}
}
},
"type": "n8n-nodes-base.respondToWebhook",
"typeVersion": 1.5,
"position": [
944,
272
],
"id": "c735659d-0fb1-452d-bb88-34d4076dbba9",
"name": "Responder históricos app"
},
{
"parameters": {
"content": "# 📚 HISTÓRICOS DE VERIFICACIÓN — REPÚBLICA DOMINICANA\n\nEntrega a la aplicación el historial de reportes procesados para República Dominicana.\n\n- Consulta únicamente registros con `country = RD`.\n- Supabase continúa usando la tabla histórica compartida `cruces_cuentas_gt_reportes`; el nombre de la tabla es legado y funciona como tabla multi-país.\n- Devuelve la misma estructura de históricos utilizada por los demás países.\n- Este webhook sirve como respaldo; la app intenta primero la RPC paginada de Supabase.",
"height": 496,
"width": 1360,
"color": 6
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
0,
0
],
"id": "b7b1d804-34f1-4da1-9cde-ac6aee727f02",
"name": "Sticky Note"
}
],
"pinData": {},
"connections": {
"Consultar históricos Supabase": {
"main": [
[
{
"node": "Normalizar históricos para app",
"type": "main",
"index": 0
}
]
]
},
"Normalizar históricos para app": {
"main": [
[
{
"node": "Responder históricos app",
"type": "main",
"index": 0
}
]
]
},
"Webhook Históricos RD": {
"main": [
[
{
"node": "Consultar históricos Supabase",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1",
"binaryMode": "separate"
},
"versionId": "47a1ec31-b680-45cf-98d5-9e9099779ccd",
"meta": {
"instanceId": "b4b77b17af092830e794eef639ce2f6d7daccf7eddc075060b03b3b6545aac70"
},
"id": "",
"tags": []
}