{
  "updatedAt": "2026-04-13T20:30:55.076Z",
  "createdAt": "2026-04-09T15:54:00.901Z",
  "id": "OZXFFP7DW3Ba9gqT",
  "name": "Envio Nominas a Finanzas Webhook",
  "description": null,
  "active": true,
  "isArchived": false,
  "nodes": [
    {
      "id": "cd6ede2d-84c5-48f3-a8c0-b2cb4ae75ef8",
      "webhookId": "96aad650-ef8d-4b8c-a3f9-5b4288038d76",
      "name": "Webhook Vista Enviar",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -1136,
        64
      ],
      "parameters": {
        "path": "nominas-send-finanzas",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "c36b83f6-2ff5-401a-89a5-7777528fc575",
      "webhookId": "b7d989dc-2892-4089-9d86-4ceab3b49f69",
      "name": "Webhook Enviar Submit",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -1136,
        288
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "nominas-send-finanzas-submit",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "a748b1c7-477e-4bc0-8f11-85c86d428411",
      "name": "Parse Token Vista",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -912,
        64
      ],
      "parameters": {
        "jsCode": "function b64urlDecode(s){s=s.replace(/-/g,'+').replace(/_/g,'/');while(s.length%4)s+='=';return Buffer.from(s,'base64').toString('utf8');}const token=$json.token||$json.query?.token||'';if(!token||!token.includes('.')) throw new Error('Token invalido');const parts=token.split('.');const payloadStr=b64urlDecode(parts[0]);const payload=JSON.parse(payloadStr);if(payload.exp){const expMs=payload.exp<1e12?payload.exp*1000:payload.exp;if(Date.now()>expMs) throw new Error('Token expirado');}return [{json:{...payload,payloadStr,sigPart:parts[1],secret:'MyE_Fujo_2026..',mode:'preview',token}}];"
      }
    },
    {
      "id": "aa1b63cf-c69f-4041-a0b9-05ee8f3cd50d",
      "name": "Parse Token Submit",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -912,
        288
      ],
      "parameters": {
        "jsCode": "function b64urlDecode(s){s=s.replace(/-/g,'+').replace(/_/g,'/');while(s.length%4)s+='=';return Buffer.from(s,'base64').toString('utf8');}function readToken(src){const candidates=[src?.token,src?.query?.token,src?.body?.token,src?.form?.token,src?.params?.token,src?.headers?.token,src?.headers?.['x-token']].map(v=>(v??'').toString().trim()).filter(Boolean);if(candidates.length) return candidates[0];const raw=(src?.rawBody??src?.bodyRaw??'').toString();if(raw){const m=raw.match(/(?:^|[?&]|token=)([^&\\s]+)/);if(m&&m[1]) return decodeURIComponent(m[1].replace(/\\+/g,'%20')).trim();}return '';}const token=readToken($json);if(!token||!token.includes('.')) throw new Error('Token invalido');const parts=token.split('.');const payloadStr=b64urlDecode(parts[0]);const payload=JSON.parse(payloadStr);if(payload.exp){const expMs=payload.exp<1e12?payload.exp*1000:payload.exp;if(Date.now()>expMs) throw new Error('Token expirado');}return [{json:{...payload,payloadStr,sigPart:parts[1],secret:'MyE_Fujo_2026..',mode:'submit',token}}];"
      }
    },
    {
      "id": "83d4832b-09eb-4329-8e62-60ceeef75e36",
      "name": "HMAC Token Envio Vista",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        -688,
        64
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "hex"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "d14d2deb-1e70-4c16-b4b2-593b75c9375a",
      "name": "HMAC Token Envio Submit",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        -688,
        288
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "hex"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "de82590f-c6cd-476c-920a-f93806c6874c",
      "name": "Verificar Token Envio",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -448,
        176
      ],
      "parameters": {
        "jsCode": "function b64urlFromHexDouble(hex){const base64str=Buffer.from(hex,'hex').toString('base64');return Buffer.from(base64str,'utf8').toString('base64').replace(/=+$/,'').replace(/\\+/g,'-').replace(/\\//g,'_');}const expected=b64urlFromHexDouble($json.data);if(expected!==$json.sigPart) throw new Error('Firma invalida');const sd=$getWorkflowStaticData('global');if(!sd.nominaSendToFinanzasByToken||typeof sd.nominaSendToFinanzasByToken!=='object'){sd.nominaSendToFinanzasByToken={};}const now=Date.now();const TTL_MS=45*24*60*60*1000;for(const [key,value] of Object.entries(sd.nominaSendToFinanzasByToken)){const atMs=Number(value?.atMs||0);if(!atMs||(now-atMs)>TTL_MS) delete sd.nominaSendToFinanzasByToken[key];}const tokenKey=String($json.sigPart||'');if(!tokenKey) throw new Error('Token invalido');const existing=sd.nominaSendToFinanzasByToken[tokenKey];return [{json:{...$json,tokenKey,alreadyProcessed:Boolean(existing),existingAction:existing?.action||'',existingAtIso:existing?.atIso||''}}];"
      }
    },
    {
      "id": "0f95e9fd-6980-4784-97e9-6738ae809639",
      "name": "IF Envio Ya Procesado",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -208,
        176
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{$json.alreadyProcessed}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "04802be1-978c-4dd3-a115-aae6572ff57c",
      "name": "Respuesta Ya Enviada",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "jsCode": "const when = ($json.existingAtIso || '').toString();\nconst stage = ($json.stage || '').toString().toLowerCase();\nconst targetLabel = (($json.recipientLabel || $json.recipientEmail) || (stage === 'finanzas' ? 'Rodrigo Pulgar, Gerente de Administración y Finanzas' : 'Ximena Inostroza, Verificadora de Monto')).toString();\nconst whenLine = when ? '<p style=\"font-size:13px;color:#666;\">Fecha del envío: ' + when + '</p>' : '';\nreturn [{json:{body:'<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Nómina ya enviada</title><style>:root{--mye-red:#ff171a;--bg:#f4f6f8;}*{box-sizing:border-box;}body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222}.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{width:100%;max-width:680px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12)}.header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;font-size:20px;font-weight:700}.content{padding:28px;text-align:center}.firma{max-width:420px;width:100%;height:auto;margin-top:16px}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Nómina ya enviada</div><div class=\"content\"><p>Esta nómina ya fue remitida a '+targetLabel+' y no admite un nuevo envío.</p>'+whenLine+'<img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>'}}];"
      }
    },
    {
      "id": "5253b4ff-971d-45dd-9427-9049f8616478",
      "name": "Responder Ya Enviada",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        240,
        0
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "d5d073b8-cdac-4f30-8281-d04d8abeb630",
      "name": "IF Modo Preview",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        0,
        384
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{$json.mode}}",
              "rightValue": "preview",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "ee888cf7-2317-4698-ae8b-64998a619a69",
      "name": "Mostrar Confirmacion Enviar",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1552,
        144
      ],
      "parameters": {
        "jsCode": "const token = $json.token || $json.query?.token || '';\nconst actionUrl = '/webhook/nominas-send-finanzas-submit?token=' + encodeURIComponent(token);\nconst reloadUrl = '/webhook/nominas-send-finanzas?token=' + encodeURIComponent(token);\nconst bankType = ($json.bankType || 'No especificado').toString();\nconst monto = ($json.facturasTotalTexto || 'Calculando...').toString();\nconst carpeta = ($json.folderName || 'Sin carpeta').toString();\nconst fecha = ($json.fechaSolicitudTexto || 'No disponible').toString();\nconst stage = ($json.stage || '').toString().toLowerCase();\nconst targetLabel = (($json.recipientLabel || $json.recipientEmail) || (stage === 'finanzas' ? 'Rodrigo Pulgar, Gerente de Administración y Finanzas' : 'Ximena Inostroza, Verificadora de Monto')).toString();\nconst ready = $json.readyToSend === true;\nif(!ready){return [{json:{body:'<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><meta http-equiv=\"refresh\" content=\"15\"><title>Actualización en curso</title><style>:root{--mye-red:#ff171a;--bg:#f4f6f8;--muted:#666;}*{box-sizing:border-box;}body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222}.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{width:100%;max-width:720px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12)}.header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;font-size:20px;font-weight:700}.content{padding:28px;text-align:center}.meta{font-size:14px;color:#555;line-height:1.7;margin:18px 0}.actions{display:flex;justify-content:center}.btn{background:var(--mye-red);color:#fff;text-decoration:none;border:none;border-radius:10px;padding:12px 24px;font-size:14px;font-weight:700;display:inline-block}.note{margin-top:14px;font-size:12px;color:var(--muted)}.firma{max-width:420px;width:100%;height:auto;margin-top:20px}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Actualización en curso</div><div class=\"content\"><p>Las facturas aún se encuentran en proceso de incorporación al archivo de control.</p><p>Esta página se actualizará automáticamente hasta que el monto consolidado quede disponible para su revisión.</p><div class=\"meta\">Carpeta: <b>'+carpeta+'</b><br>Fecha: <b>'+fecha+'</b><br>Tipo de Banco: <b>'+bankType+'</b><br>Monto Excel actual: <b>'+monto+'</b></div><div class=\"actions\"><a class=\"btn\" href=\"'+reloadUrl+'\">Actualizar ahora</a></div><div class=\"note\">La actualización automática se ejecuta cada 15 segundos.</div><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>'}}];}const formLockScript='<script>(() => { const form=document.getElementById(\"send-form\"); const button=document.getElementById(\"send-submit\"); const note=document.getElementById(\"send-note\"); if(!form||!button) return; const storageKey=\"nomina:send:\" + encodeURIComponent(\"'+token+'\"); const ttlMs=2*60*1000; let submitting=false; try { const storedRaw=sessionStorage.getItem(storageKey); if(storedRaw){ const stored=JSON.parse(storedRaw); if(stored && typeof stored.ts === \"number\" && (Date.now()-stored.ts) < ttlMs){ button.disabled=true; button.textContent=\"Envío confirmado\"; if(note) note.textContent=\"Esta solicitud ya fue enviada. Espere la confirmación en pantalla.\"; } else { sessionStorage.removeItem(storageKey); } } } catch {} form.addEventListener(\"submit\", (event) => { if(submitting || button.disabled){ event.preventDefault(); return; } submitting=true; try { sessionStorage.setItem(storageKey, JSON.stringify({ ts: Date.now() })); } catch {} button.disabled=true; button.textContent=\"Enviando...\"; if(note) note.textContent=\"Estamos registrando el envío. No cierre esta ventana.\"; }); })();</script>';return [{json:{body:'<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Confirmación de envío</title><style>:root{--mye-red:#ff171a;--bg:#f4f6f8;--muted:#666;}*{box-sizing:border-box;}body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222}.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{width:100%;max-width:720px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12)}.header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;font-size:20px;font-weight:700}.content{padding:28px;text-align:center}.meta{font-size:14px;color:#555;line-height:1.7;margin:18px 0}.actions{display:flex;justify-content:center}.btn{background:var(--mye-red);color:#fff;border:none;border-radius:10px;padding:12px 24px;font-size:14px;font-weight:700;cursor:pointer}.btn:disabled{background:#d48d8e;cursor:not-allowed}.note{margin-top:14px;font-size:12px;color:var(--muted)}.firma{max-width:420px;width:100%;height:auto;margin-top:20px}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Confirmación de envío</div><div class=\"content\"><p>Por favor, revise la información consolidada y confirme el envío de esta nómina a '+targetLabel+'.</p><div class=\"meta\">Carpeta: <b>'+carpeta+'</b><br>Fecha: <b>'+fecha+'</b><br>Tipo de Banco: <b>'+bankType+'</b><br>Monto Excel actual: <b>'+monto+'</b></div><form id=\"send-form\" method=\"POST\" action=\"'+actionUrl+'\"><input type=\"hidden\" name=\"token\" value=\"'+token+'\" /><div class=\"actions\"><button id=\"send-submit\" class=\"btn\" type=\"submit\">Confirmar envío</button></div></form><div id=\"send-note\" class=\"note\">Previo al envío, el sistema valida que el archivo de control contenga la información necesaria.</div><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div>'+formLockScript+'</body></html>'}}];"
      }
    },
    {
      "id": "1151d2be-a242-4f77-b397-7917cbe51b18",
      "name": "Responder Confirmacion Enviar",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1744,
        144
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "9bbff07d-de95-487c-85fc-46b4818172ad",
      "name": "Buscar facturas_semana (Enviar)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        224,
        400
      ],
      "parameters": {
        "url": "=https://graph.microsoft.com/v1.0/me/drive/root:/{{$json.linkedFacturasFolderPathEncoded ? ($json.linkedFacturasFolderPathEncoded + \"/facturas_semana.xlsx\") : (\"Facturas/\" + ($json.facturasYearMonth || $json.yearMonth) + \"/\" + $json.weekFolder + \"/\" + ($json.linkedFacturasFolderName || $json.folderName) + \"/facturas_semana.xlsx\").split(\"/\").filter(Boolean).map(encodeURIComponent).join(\"/\")}}?$select=id,name,webUrl",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftOAuth2Api",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      },
      "credentials": {
        "microsoftOAuth2Api": {
          "id": "7pDFU0vOqasMJYBC",
          "name": "Microsoft account"
        }
      },
      "onError": "continueRegularOutput"
    },
    {
      "id": "1f96c8b9-3cd5-4a80-a52b-1c191e0b622d",
      "name": "Listar Archivos Facturas (Enviar)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        528,
        160
      ],
      "parameters": {
        "url": "=https://graph.microsoft.com/v1.0/me/drive/root:/{{$items(\"Verificar Token Envio\")[0].json.linkedFacturasFolderPathEncoded ? $items(\"Verificar Token Envio\")[0].json.linkedFacturasFolderPathEncoded : (\"Facturas/\" + ($items(\"Verificar Token Envio\")[0].json.facturasYearMonth || $items(\"Verificar Token Envio\")[0].json.yearMonth) + \"/\" + $items(\"Verificar Token Envio\")[0].json.weekFolder + \"/\" + ($items(\"Verificar Token Envio\")[0].json.linkedFacturasFolderName || $items(\"Verificar Token Envio\")[0].json.folderName)).split(\"/\").filter(Boolean).map(encodeURIComponent).join(\"/\")}}:/children?$top=999&$select=id,name,webUrl,file,folder,lastModifiedDateTime,createdDateTime",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftOAuth2Api",
        "options": {
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      },
      "credentials": {
        "microsoftOAuth2Api": {
          "id": "7pDFU0vOqasMJYBC",
          "name": "Microsoft account"
        }
      },
      "onError": "continueRegularOutput",
      "retryOnFail": true,
      "maxTries": 4,
      "waitBetweenTries": 4000
    },
    {
      "id": "775e94b0-5ae3-49ff-bfb5-2c9409bb2426",
      "name": "Leer filas facturas (Enviar)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        528,
        512
      ],
      "parameters": {
        "url": "=https://graph.microsoft.com/v1.0/me/drive/items/{{$json.id || 'SIN_EXCEL'}}/content",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftOAuth2Api",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          },
          "timeout": 180000
        }
      },
      "credentials": {
        "microsoftOAuth2Api": {
          "id": "7pDFU0vOqasMJYBC",
          "name": "Microsoft account"
        }
      },
      "onError": "continueRegularOutput",
      "retryOnFail": true,
      "maxTries": 4,
      "waitBetweenTries": 4000
    },
    {
      "id": "01a4d559-1468-4904-95f2-fab6f54ae485",
      "name": "Parsear Excel Facturas (Enviar)",
      "type": "n8n-nodes-base.spreadsheetFile",
      "typeVersion": 2,
      "position": [
        736,
        512
      ],
      "parameters": {
        "options": {}
      }
    },
    {
      "id": "7c4c5a5e-ba37-4ce4-a352-b7eabc8d50b1",
      "name": "Calcular total facturas (Enviar)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        944,
        512
      ],
      "parameters": {
        "jsCode": "function parseMonto(value){if(value===null||value===undefined||value==='') return 0;if(typeof value==='number'&&Number.isFinite(value)) return Math.max(0,Math.round(value));const raw=String(value).replace(/\\$/g,'').replace(/\\s/g,'').trim();if(!raw||raw==='-') return 0;if(/^\\d{1,3}(\\.\\d{3})+(,\\d+)?$/.test(raw)){const n=Number(raw.replace(/\\./g,'').replace(',','.'));return Number.isFinite(n)?Math.max(0,Math.round(n)):0;}if(/^\\d{1,3}(,\\d{3})+(\\.\\d+)?$/.test(raw)){const n=Number(raw.replace(/,/g,''));return Number.isFinite(n)?Math.max(0,Math.round(n)):0;}const fallback=Number(raw.replace(/\\./g,'').replace(',','.'));if(Number.isFinite(fallback)) return Math.max(0,Math.round(fallback));const digits=raw.replace(/[^\\d]/g,'');return digits?parseInt(digits,10):0;}function cleanText(value){return (value??'').toString().trim();}function normalizeUrl(value){return cleanText(value);}function isPdf(item){return item?.file&&/\\.pdf$/i.test(cleanText(item?.name));}function itemTs(item){return Date.parse(item?.lastModifiedDateTime||item?.createdDateTime||'')||0;}const QUIET_WINDOW_MS=60*1000;const tokenData=($items('Verificar Token Envio')[0]||{}).json||{};const folderResp=(($items('Listar Archivos Facturas (Enviar)')[0]||{}).json||{});const folderChildren=Array.isArray(folderResp.value)?folderResp.value:[];const pdfItems=folderChildren.filter(isPdf);const pdfUrls=pdfItems.map((item)=>normalizeUrl(item.webUrl)).filter(Boolean);const latestPdfTs=pdfItems.reduce((max,item)=>Math.max(max,itemTs(item)),0);const folderSettled=pdfUrls.length===0?true:(latestPdfTs>0&&(Date.now()-latestPdfTs)>=QUIET_WINDOW_MS);let facturasCount=0;let facturasTotal=0;const excelUrls=new Set();for(const rowItem of items){const row=rowItem.json||{};const excelUrl=normalizeUrl(row.url_documento);if(excelUrl) excelUrls.add(excelUrl);const numeroFactura=cleanText(row.numero_factura);const numeroOc=cleanText(row.numero_oc);if(!numeroFactura&&!numeroOc) continue;const monto=parseMonto(row.monto_total);if(!Number.isFinite(monto)||monto<=0) continue;facturasCount+=1;facturasTotal+=monto;}const pendingPdfItems=pdfItems.filter((item)=>{const url=normalizeUrl(item.webUrl);return url&&!excelUrls.has(url);});const facturasTotalTexto=facturasTotal>0?'$'+Number(facturasTotal).toLocaleString('es-CL'):'';let excelError='';if(facturasCount<1||facturasTotal<=0){excelError='El Excel aun no registra documentos validos.';}else if(pdfUrls.length>0&&!folderSettled){excelError='La carpeta de respaldo aun recibe archivos.';}else if(pdfUrls.length>0&&pendingPdfItems.length>0){excelError='Aun faltan '+pendingPdfItems.length+' PDF por consolidar en el Excel.';}const readyToSend=Boolean(facturasCount>0&&facturasTotal>0&&(pdfUrls.length===0||(folderSettled&&pendingPdfItems.length===0)));return [{json:{...tokenData,facturasCount,facturasTotal,facturasTotalTexto,readyToSend,pendingPdfCount:pendingPdfItems.length,pdfCount:pdfUrls.length,excelError}}];"
      }
    },
    {
      "id": "26527037-1e0d-4dee-bcc6-5c6dffca6c4c",
      "name": "IF Hay Facturas para Enviar",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1552,
        624
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{$json.readyToSend === true}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "183ba048-5ed3-4ea2-a0d3-74572d12c25e",
      "name": "IF Preview Confirmacion",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        1232,
        336
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "leftValue": "={{$json.mode}}",
              "rightValue": "preview",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "d95b73b5-b6b6-441f-83c9-aa4097f9fda0",
      "name": "Respuesta Sin Facturas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        736
      ],
      "parameters": {
        "jsCode": "const detalle=($json.excelError||'El archivo de control aún no registra facturas consolidadas.').toString();return [{json:{body:'<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Información aún no disponible</title><style>:root{--mye-red:#ff171a;--bg:#f4f6f8;}*{box-sizing:border-box;}body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222}.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{width:100%;max-width:680px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12)}.header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;font-size:20px;font-weight:700}.content{padding:28px;text-align:center}.firma{max-width:420px;width:100%;height:auto;margin-top:20px}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Información aún no disponible</div><div class=\"content\"><p>Por el momento no fue posible continuar con el envío de la nómina.</p><p>'+detalle+'</p><p>Por favor, espere unos instantes y vuelva a intentarlo.</p><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>'}}];"
      }
    },
    {
      "id": "ddd1745d-313a-48b5-9eb9-a9ad7b38921c",
      "name": "Responder Sin Facturas",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1968,
        736
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "2e538784-25cd-4517-88c1-5df9c180d001",
      "name": "Marcar Token Enviado",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1760,
        544
      ],
      "parameters": {
        "jsCode": "const sd=$getWorkflowStaticData('global');if(!sd.nominaSendToFinanzasByToken||typeof sd.nominaSendToFinanzasByToken!=='object'){sd.nominaSendToFinanzasByToken={};}const tokenKey=String($json.tokenKey||'');if(!tokenKey) throw new Error('Token invalido');const now=Date.now();const stage=($json.stage||'verificador').toString().toLowerCase();sd.nominaSendToFinanzasByToken[tokenKey]={action:'sent_to_'+stage,atMs:now,atIso:new Date(now).toISOString(),folderName:$json.folderName||''};return items;"
      }
    },
    {
      "id": "324eade4-320a-4e47-8e79-4084edf3ed02",
      "name": "Prep Payload Email Finanzas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1968,
        544
      ],
      "parameters": {
        "jsCode": "const nowText = new Intl.DateTimeFormat('es-CL', {\n  timeZone: 'America/Santiago',\n  year: 'numeric',\n  month: '2-digit',\n  day: '2-digit',\n}).format(new Date());\nconst facturasTotal = Number($json.facturasTotal || 0);\nconst facturasTotalTexto = ($json.facturasTotalTexto || ('$' + Number(facturasTotal).toLocaleString('es-CL'))).toString();\nconst excelWebUrl = (((($items('Buscar facturas_semana (Enviar)')[0] || {}).json || {}).webUrl) || '').toString();\nconst stage = ($json.stage || 'verificador').toString().toLowerCase();\n      const emailContador = ($json.emailContador || 'pagosproveedores@mye.cl').toString();\n      const emailVerificador = ($json.emailVerificador || 'xinostroza@mye.cl').toString();\n      const emailFinanzas = ($json.emailFinanzas || 'rpulgar@mye.cl').toString();\nconst recipientEmail = (stage === 'finanzas' ? emailFinanzas : emailVerificador).toString();\nconst recipientLabel = stage === 'finanzas' ? 'Rodrigo Pulgar' : 'Ximena Inostroza';\nconst recipientRole = stage === 'finanzas' ? 'Gerente de Administración y Finanzas' : 'Verificadora de Monto';\nconst recipientGreeting = stage === 'finanzas' ? 'Estimado Rodrigo Pulgar:' : 'Estimada Ximena Inostroza:';\nconst linkedFacturasFolderName = ($json.linkedFacturasFolderName || $json.folderName || '').toString();\nconst resolveBaseWebhookUrl = (value) => {\n  const raw = String(value ?? '').trim();\n  if (!raw) return '';\n  const withProtocol = /^[a-z]+:\\/\\//i.test(raw) ? raw : raw.startsWith('/') ? raw : 'https://' + raw;\n  return withProtocol.replace(/\\/+$/,'').replace(/\\/webhook$/,'');\n};\nconst baseWebhookUrl = (() => {\n  for (const candidate of [$json.baseWebhookUrl, $vars?.baseWebhookUrl, $vars?.BASE_WEBHOOK_URL, $vars?.WEBHOOK_URL]) {\n    const normalized = resolveBaseWebhookUrl(candidate);\n    if (normalized) return normalized;\n  }\n  return 'https://nonsuspended-worried-alyssa.ngrok-free.dev';\n})();\nconst payload = {driveId:$json.driveId,folderId:$json.folderId,folderName:$json.folderName,linkedFacturasFolderName,webUrl:$json.webUrl,excelWebUrl,weekFolder:$json.weekFolder,bankType:$json.bankType,fechaSolicitudTexto:($json.fechaSolicitudTexto||nowText).toString(),facturasTotal,facturasTotalTexto,facturasYearMonth:$json.facturasYearMonth||$json.yearMonth,facturasDriveId:$json.facturasDriveId||$json.driveId,yearMonth:$json.yearMonth,emailContador,emailVerificador,emailFinanzas,stage,exp:Date.now()+1000*60*60*48};\nreturn [{json:{...$json,linkedFacturasFolderName,excelWebUrl,baseWebhookUrl,secret:'MyE_Fujo_2026..',facturasTotal,facturasTotalTexto,emailContador,emailVerificador,emailFinanzas,recipientEmail,recipientLabel,recipientRole,recipientGreeting,stage,payloadStr:JSON.stringify(payload)}}];"
      }
    },
    {
      "id": "cca36093-4b0e-4453-8f2a-022f7562e24c",
      "name": "HMAC Token Email Finanzas",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        2144,
        544
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "base64"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "a045ae84-048f-4455-980a-3ee6a8530a08",
      "name": "Build Token Email Finanzas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2320,
        544
      ],
      "parameters": {
        "jsCode": "function b64url(s){return Buffer.from(s).toString('base64').replace(/=+$/,'').replace(/\\+/g,'-').replace(/\\//g,'_');}function resolveBaseWebhookUrl(value){const normalize=(candidate)=>{const raw=String(candidate??'').trim();if(!raw)return '';const withProtocol=/^[a-z]+:\\/\\//i.test(raw)||raw.startsWith('/')?raw:'https://'+raw;return withProtocol.replace(/\\/+$/,'').replace(/\\/webhook$/,'');};for(const candidate of [value,$vars?.baseWebhookUrl,$vars?.BASE_WEBHOOK_URL,$vars?.WEBHOOK_URL]){const normalized=normalize(candidate);if(normalized)return normalized;}return 'https://nonsuspended-worried-alyssa.ngrok-free.dev';}const sig=$json.data;const token=b64url($json.payloadStr)+'.'+b64url(sig);const baseWebhookUrl=resolveBaseWebhookUrl($json.baseWebhookUrl);const approveUrl=baseWebhookUrl+'/webhook/nominas-approve?token='+token;const rejectUrl=baseWebhookUrl+'/webhook/nominas-reject?token='+token;return [{json:{...$json,token,approveUrl,rejectUrl}}];"
      }
    },
    {
      "id": "d371c93b-dd73-4db6-87f3-2a2de3340c75",
      "webhookId": "1f3b15ca-1b57-4ec9-8173-33ed8c3abaf9",
      "name": "Email a Gerencia Finanzas",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        2496,
        544
      ],
      "parameters": {
        "toRecipients": "={{$json.recipientEmail || ($json.stage === \"finanzas\" ? ($json.emailFinanzas || \"rpulgar@mye.cl\") : ($json.emailVerificador || \"xinostroza@mye.cl\"))}}",
        "subject": "={{$json.stage === 'finanzas' ? 'Confirmar Aprobación Nomina ' + ($json.bankType || 'No especificado') + ' por ' + ($json.facturasTotalTexto || '$0') : 'Solicitud Validación Nomina ' + ($json.bankType || 'No especificado') + ' por ' + ($json.facturasTotalTexto || '$0')}}",
        "bodyContent": "={{ (() => { const v = $json || {}; const esc = (x) => String(x ?? '').replace(/[&<>]/g, (m) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[m])); const isFin = v.stage === 'finanzas'; const title = isFin ? 'Solicitud de aprobación de nómina' : 'Solicitud de validación de nómina'; const greeting = v.recipientGreeting || 'Estimado/a:'; const bank = v.bankType || 'No especificado'; const total = v.facturasTotalTexto || '$0'; const date = v.fechaSolicitudTexto || 'No disponible'; const folderUrl = v.webUrl || '#'; const excelUrl = v.excelWebUrl || '#'; const approveUrl = v.approveUrl || '#'; const rejectUrl = v.rejectUrl || '#'; const message = isFin ? 'Junto con saludar, la nomina fue validada correctamente, favor de dar por finalizada su revisión para Aprobar o Rechazar justificadamente la nomina adjunta' : 'Junto con saludar, la nómina está lista para ser validada. Una vez finalizada su revisión, favor aprobar o rechazar con justificación la siguiente nómina.'; return `<table role='presentation' width='100%' cellpadding='0' cellspacing='0' border='0' bgcolor='#f4f6f8' style='font-family: Arial, Helvetica, sans-serif;'><tr><td align='center' style='padding:20px;'><table role='presentation' width='600' cellpadding='0' cellspacing='0' border='0' bgcolor='#ffffff' style='border-radius:6px; overflow:hidden;'><tr><td bgcolor='#ff171a' style='color:#ffffff; padding:16px; font-size:18px;'>${esc(title)}</td></tr><tr><td style='padding:20px; color:#333333; font-size:14px; line-height:1.6;'><p>${esc(greeting)}</p><p>${esc(message)}</p><ul><li><b>Tipo de banco:</b> ${esc(bank)}</li><li><b>Monto informado en Excel:</b> ${esc(total)}</li><li><b>Carpeta de respaldo:</b> <a href='${folderUrl}'>Abrir carpeta</a></li><li><b>Archivo de control:</b> <a href='${excelUrl}'>Abrir facturas_semana.xlsx</a></li><li><b>Fecha:</b> ${esc(date)}</li></ul><p style='margin-top:20px;'><a href='${approveUrl}' style='background:#ff171a; color:#ffffff; text-decoration:none; padding:12px 18px; border-radius:4px; display:inline-block; margin-right:10px;'>Aprobar</a><a href='${rejectUrl}' style='background:#808080; color:#ffffff; text-decoration:none; padding:12px 18px; border-radius:4px; display:inline-block;'>Rechazar</a></p><hr style='border:none; border-top:1px solid #e0e0e0; margin:20px 0;'><div style='font-size:12px; color:#666;'><img src='https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif' alt='Firma MYE' style='max-width:420px; width:100%; height:auto;'></div></td></tr></table></td></tr></table>`; })() }}",
        "additionalFields": {
          "bodyContentType": "html"
        }
      },
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "id": "p4O6wj9qoVBj9C9X",
          "name": "Microsoft Outlook account"
        }
      }
    },
    {
      "id": "0fb9b248-fe5d-4269-bcf7-8a5f4861cb1d",
      "name": "Respuesta Enviado Finanzas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2672,
        544
      ],
      "parameters": {
        "jsCode": "const targetLabel = (($json.recipientLabel || $json.recipientEmail) || 'Rodrigo Pulgar, Gerente de Administración y Finanzas').toString();\nreturn [{json:{body:'<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Envío confirmado</title><style>:root{--mye-red:#ff171a;--bg:#f4f6f8;}*{box-sizing:border-box;}body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222}.wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px}.card{width:100%;max-width:680px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12)}.header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;font-size:20px;font-weight:700}.content{padding:28px;text-align:center}.firma{max-width:420px;width:100%;height:auto;margin-top:20px}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Envío confirmado</div><div class=\"content\"><p>La nómina fue enviada correctamente a '+targetLabel+' para su revisión.</p><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>'}}];"
      }
    },
    {
      "id": "c79d82c8-bce8-4806-ba74-8750aa65284d",
      "name": "Responder Enviado Finanzas",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        2848,
        544
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    }
  ],
  "connections": {
    "Webhook Vista Enviar": {
      "main": [
        [
          {
            "node": "Parse Token Vista",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Token Vista": {
      "main": [
        [
          {
            "node": "HMAC Token Envio Vista",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HMAC Token Envio Vista": {
      "main": [
        [
          {
            "node": "Verificar Token Envio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Enviar Submit": {
      "main": [
        [
          {
            "node": "Parse Token Submit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Token Submit": {
      "main": [
        [
          {
            "node": "HMAC Token Envio Submit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HMAC Token Envio Submit": {
      "main": [
        [
          {
            "node": "Verificar Token Envio",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar Token Envio": {
      "main": [
        [
          {
            "node": "IF Envio Ya Procesado",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Envio Ya Procesado": {
      "main": [
        [
          {
            "node": "Respuesta Ya Enviada",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF Modo Preview",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta Ya Enviada": {
      "main": [
        [
          {
            "node": "Responder Ya Enviada",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Modo Preview": {
      "main": [
        [
          {
            "node": "Buscar facturas_semana (Enviar)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar facturas_semana (Enviar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mostrar Confirmacion Enviar": {
      "main": [
        [
          {
            "node": "Responder Confirmacion Enviar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar facturas_semana (Enviar)": {
      "main": [
        [
          {
            "node": "Leer filas facturas (Enviar)",
            "type": "main",
            "index": 0
          },
          {
            "node": "Listar Archivos Facturas (Enviar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Leer filas facturas (Enviar)": {
      "main": [
        [
          {
            "node": "Parsear Excel Facturas (Enviar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsear Excel Facturas (Enviar)": {
      "main": [
        [
          {
            "node": "Calcular total facturas (Enviar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calcular total facturas (Enviar)": {
      "main": [
        [
          {
            "node": "IF Preview Confirmacion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Preview Confirmacion": {
      "main": [
        [
          {
            "node": "Mostrar Confirmacion Enviar",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "IF Hay Facturas para Enviar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Hay Facturas para Enviar": {
      "main": [
        [
          {
            "node": "Marcar Token Enviado",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respuesta Sin Facturas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta Sin Facturas": {
      "main": [
        [
          {
            "node": "Responder Sin Facturas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Marcar Token Enviado": {
      "main": [
        [
          {
            "node": "Prep Payload Email Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prep Payload Email Finanzas": {
      "main": [
        [
          {
            "node": "HMAC Token Email Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HMAC Token Email Finanzas": {
      "main": [
        [
          {
            "node": "Build Token Email Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Token Email Finanzas": {
      "main": [
        [
          {
            "node": "Email a Gerencia Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email a Gerencia Finanzas": {
      "main": [
        [
          {
            "node": "Respuesta Enviado Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta Enviado Finanzas": {
      "main": [
        [
          {
            "node": "Responder Enviado Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "timeSavedMode": "fixed",
    "timeSavedPerExecution": 1
  },
  "staticData": null,
  "meta": null,
  "pinData": {},
  "versionId": "c16e686c-a32e-48b8-8c2d-cb0093af0e8f",
  "activeVersionId": "c16e686c-a32e-48b8-8c2d-cb0093af0e8f",
  "versionCounter": 35,
  "triggerCount": 2,
  "tags": [],
  "shared": [
    {
      "updatedAt": "2026-04-09T15:54:00.902Z",
      "createdAt": "2026-04-09T15:54:00.902Z",
      "role": "workflow:owner",
      "workflowId": "OZXFFP7DW3Ba9gqT",
      "projectId": "W2XrXtMVi6WNLEGS",
      "project": {
        "updatedAt": "2026-04-09T15:46:35.950Z",
        "createdAt": "2026-04-09T15:37:33.410Z",
        "id": "W2XrXtMVi6WNLEGS",
        "name": "Alvaro  Mella <alvaro.mellaflores@gmail.com>",
        "type": "personal",
        "icon": null,
        "description": null,
        "creatorId": "e2235e6e-1014-4559-880b-d5293b8a90d8"
      }
    }
  ],
  "versionMetadata": {
    "name": null,
    "description": null
  }
}