{
  "updatedAt": "2026-04-13T20:30:50.445Z",
  "createdAt": "2026-04-09T15:53:48.934Z",
  "id": "DJatA0c5L7e4De5p",
  "name": "Aprobacion Nominas Webhook",
  "description": null,
  "active": true,
  "isArchived": false,
  "nodes": [
    {
      "id": "e93d993d-611b-422e-8ea8-02be5d52200c",
      "webhookId": "169caff7-9b3a-4f02-9ef8-173b6ae4776f",
      "name": "Webhook Aprobar",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -2176,
        240
      ],
      "parameters": {
        "path": "nominas-approve",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "4d0db25c-7336-4fa0-8f28-9ad17a15e687",
      "webhookId": "5023dccd-5469-4dea-a73c-cd24b7b04177",
      "name": "Webhook Rechazar",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -2176,
        896
      ],
      "parameters": {
        "path": "nominas-reject",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "5bbe2ce8-f8cf-4ef2-82cc-a5a1a0bcc407",
      "webhookId": "5ef76069-bae2-4903-a07e-f447e41d11ec",
      "name": "Webhook Rechazo Submit",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -2176,
        1168
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "nominas-reject-submit",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "f752e463-8deb-411b-b456-4c07938f37e5",
      "webhookId": "6f740fc4-ebd6-41f4-9fcf-620ea823ebc9",
      "name": "Webhook Aprobar Submit",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        -2176,
        464
      ],
      "parameters": {
        "httpMethod": "POST",
        "path": "nominas-approve-submit",
        "responseMode": "responseNode",
        "options": {}
      }
    },
    {
      "id": "56e1a3fa-03a8-4b88-8247-8c5a532ca4e0",
      "name": "Parse Token",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2016,
        112
      ],
      "parameters": {
        "jsCode": "function b64urlDecode(s){\n  s = s.replace(/-/g,'+').replace(/_/g,'/');\n  while (s.length % 4) s += '=';\n  return Buffer.from(s, 'base64').toString('utf8');\n}\nfunction 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 inválido');const parts = token.split('.');const payloadStr = b64urlDecode(parts[0]);const payload = JSON.parse(payloadStr);if (payload.exp) {\n  const expMs = payload.exp < 1e12 ? payload.exp * 1000 : payload.exp;\n  if (Date.now() > expMs) throw new Error('Token expirado');\n}\nreturn [{ json: { ...payload, payloadStr, sigPart: parts[1], secret: 'MyE_Fujo_2026..', token } }];\n"
      }
    },
    {
      "id": "a7b2ef05-ddfb-4c73-aa7d-75e5dcdec783",
      "name": "HMAC Token",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        -1856,
        240
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "hex"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "20a722d1-a02d-432c-8617-109ba2feedcc",
      "name": "Verificar Token Aprobacion",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1696,
        112
      ],
      "parameters": {
        "jsCode": "function b64urlFromHexDouble(hex){\n  const base64str = Buffer.from(hex, 'hex').toString('base64');\n  return Buffer.from(base64str, 'utf8')\n    .toString('base64')\n    .replace(/=+$/,'')\n    .replace(/\\+/g,'-')\n    .replace(/\\//g,'_');\n}\n\nconst expected = b64urlFromHexDouble($json.data);\nif (expected !== $json.sigPart) throw new Error('Firma inválida');\n\nconst sd = $getWorkflowStaticData('global');\nif (!sd.nominaDecisionByToken || typeof sd.nominaDecisionByToken !== 'object') {\n  sd.nominaDecisionByToken = {};\n}\n\nconst now = Date.now();\nconst TTL_MS = 45 * 24 * 60 * 60 * 1000;\nfor (const [key, value] of Object.entries(sd.nominaDecisionByToken)) {\n  const atMs = Number(value?.atMs || 0);\n  if (!atMs || (now - atMs) > TTL_MS) delete sd.nominaDecisionByToken[key];\n}\n\nconst tokenKey = String($json.sigPart || '');\nif (!tokenKey) throw new Error('Token inválido');\n\nconst existing = sd.nominaDecisionByToken[tokenKey];\nif (existing) {\n  return [{\n    json: {\n      ...$json,\n      alreadyProcessed: true,\n      existingAction: existing.action || 'processed',\n      existingAtIso: existing.atIso || '',\n      tokenKey,\n    }\n  }];\n}\n\nreturn [{\n  json: {\n    ...$json,\n    alreadyProcessed: false,\n    tokenKey,\n  }\n}];"
      }
    },
    {
      "id": "31a947d2-ab58-43d5-bf63-3d5019337281",
      "name": "Compare Token",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1712,
        624
      ],
      "parameters": {
        "jsCode": "function b64urlFromHexDouble(hex){\n  const base64str = Buffer.from(hex, 'hex').toString('base64');\n  return Buffer.from(base64str, 'utf8')\n    .toString('base64')\n    .replace(/=+$/,'')\n    .replace(/\\+/g,'-')\n    .replace(/\\//g,'_');\n}\n\nconst expected = b64urlFromHexDouble($json.data);\nif (expected !== $json.sigPart) throw new Error('Firma inválida');\n\nconst sd = $getWorkflowStaticData('global');\nif (!sd.nominaDecisionByToken || typeof sd.nominaDecisionByToken !== 'object') {\n  sd.nominaDecisionByToken = {};\n}\n\nconst now = Date.now();\nconst TTL_MS = 45 * 24 * 60 * 60 * 1000;\nfor (const [key, value] of Object.entries(sd.nominaDecisionByToken)) {\n  const atMs = Number(value?.atMs || 0);\n  if (!atMs || (now - atMs) > TTL_MS) delete sd.nominaDecisionByToken[key];\n}\n\nconst tokenKey = String($json.sigPart || '');\nif (!tokenKey) throw new Error('Token inválido');\n\nconst existing = sd.nominaDecisionByToken[tokenKey];\nif (existing) {\n  return [{\n    json: {\n      ...$json,\n      alreadyProcessed: true,\n      existingAction: existing.action || 'processed',\n      existingAtIso: existing.atIso || '',\n      tokenKey,\n    }\n  }];\n}\n\nsd.nominaDecisionByToken[tokenKey] = {\n  action: 'approve',\n  atMs: now,\n  atIso: new Date(now).toISOString(),\n  folderName: $json.folderName || ''\n};\n\nreturn [{\n  json: {\n    ...$json,\n    alreadyProcessed: false,\n    decisionAction: 'approve',\n    tokenKey,\n  }\n}];"
      }
    },
    {
      "id": "ffc85bbb-8d0b-4456-b0d5-78e08d688c71",
      "webhookId": "299fd670-0fea-42f1-a62d-0736947b1bb5",
      "name": "Email a Gerencia General",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        -128,
        752
      ],
      "parameters": {
        "toRecipients": "gmaritano@mye.cl",
        "subject": "=Comprobante Aprobacion 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 bank = v.bankType || 'No especificado'; const total = v.facturasTotalTexto || '$0'; const folderUrl = v.webUrl || '#'; const excelUrl = v.excelWebUrl || '#'; 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;'>Nómina aprobada por Finanzas</td></tr><tr><td style='padding:20px; color:#333333; font-size:14px; line-height:1.6;'><p>Estimado Gian Carlo Maritano:</p><p>Junto con saludar, se informa que la nómina <b>${esc(v.folderName || '')}</b> ha sido aprobada en la etapa de Finanzas y queda disponible para su conocimiento.</p><ul><li><b>Tipo de banco:</b> ${esc(bank)}</li><li><b>Monto consolidado:</b> ${esc(total)}</li><li><b>Carpeta de respaldo:</b> <a href='${folderUrl}'>Abrir carpeta</a></li><li><b>Planilla de facturas:</b> <a href='${excelUrl}'>Abrir facturas_semana.xlsx</a></li></ul><p>Este correo corresponde a una notificación informativa de cierre de aprobación.</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": "3d80cc50-e548-4f11-8728-57ccf49d47a0",
      "webhookId": "44ed933f-4363-44e7-bc0c-7ed983bcedf7",
      "name": "Notificar Contador Aprobacion Final",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        320,
        752
      ],
      "parameters": {
        "toRecipients": "={{$(\"IF Stage Verificador Aprobado\").item.json.emailContador || $json.emailContador || \"pagosproveedores@mye.cl\"}}",
        "subject": "=Notificación enviada a Gerencia General: Nómina {{$('IF Stage Verificador Aprobado').item.json.bankType || $json.bankType || 'No especificado'}} por {{$('IF Stage Verificador Aprobado').item.json.facturasTotalTexto || $json.facturasTotalTexto || '$0'}}",
        "bodyContent": "={{ (() => { const source = $('IF Stage Verificador Aprobado').item.json || {}; const v = { ...source, ...($json || {}) }; const esc = (x) => String(x ?? '').replace(/[&<>]/g, (m) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' }[m])); const bank = source.bankType || v.bankType || 'No especificado'; const total = source.facturasTotalTexto || v.facturasTotalTexto || '$0'; const folderUrl = source.webUrl || v.webUrl || '#'; const excelUrl = source.excelWebUrl || v.excelWebUrl || '#'; 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;'>Gerencia General notificada</td></tr><tr><td style='padding:20px; color:#333333; font-size:14px; line-height:1.6;'><p>Estimado equipo contable:</p><p>Se informa que la nómina <b>${esc(source.folderName || v.folderName || '')}</b> ya fue aprobada en Finanzas y el correo de notificación a <b>Gian Carlo Maritano</b> fue enviado correctamente.</p><ul><li><b>Tipo de banco:</b> ${esc(bank)}</li><li><b>Monto consolidado:</b> ${esc(total)}</li><li><b>Carpeta de respaldo:</b> <a href='${folderUrl}'>Abrir carpeta</a></li><li><b>Planilla de facturas:</b> <a href='${excelUrl}'>Abrir facturas_semana.xlsx</a></li></ul><p>Este correo es solo informativo para dejar constancia del envío a Gerencia General.</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": "0656e6a0-4d66-4f5a-b58f-3d55801e8566",
      "name": "Respuesta Enviado GG",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        800,
        752
      ],
      "parameters": {
        "jsCode": "return [{ json: { body: '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Aprobación registrada</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:640px;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:26px;text-align:center;} .msg{font-size:14px;color:#333;line-height:1.6;} .firma{max-width:420px;width:100%;height:auto;margin-top:16px;}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Aprobación registrada</div><div class=\"content\"><div class=\"msg\">La aprobación fue enviada correctamente. Se notificó a Gian Carlo Maritano, Gerente General, y también se envió aviso al contador.</div><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>' } }];\n"
      }
    },
    {
      "id": "9a837ca3-6601-4178-ac6d-5d04f6ffeab6",
      "name": "Responder GG",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        1456,
        352
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "bf723c44-f80e-4aa4-890d-75ce11894034",
      "name": "Mostrar Formulario Rechazo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1968,
        896
      ],
      "parameters": {
        "jsCode": "function b64urlDecode(s){\n  s = String(s || '').replace(/-/g,'+').replace(/_/g,'/');\n  while (s.length % 4) s += '=';\n  return Buffer.from(s, 'base64').toString('utf8');\n}\nfunction inferStageFromToken(rawToken){\n  try {\n    const token = String(rawToken || '').trim();\n    if (!token || !token.includes('.')) return '';\n    const payloadStr = b64urlDecode(token.split('.')[0]);\n    const payload = JSON.parse(payloadStr);\n    return String(payload?.stage || '').trim().toLowerCase();\n  } catch {\n    return '';\n  }\n}\nconst token = ($json.token || $json.query?.token || '').toString();\nconst stage = (($json.stage || inferStageFromToken(token) || '')).toString().toLowerCase();\nconst approverName = stage === 'finanzas' ? 'Rodrigo Pulgar' : 'Ximena Inostroza';\nconst approverRole = stage === 'finanzas' ? 'Gerente de Administración y Finanzas' : 'Verificadora de Monto';\nconst headers = $json.headers || {};\nconst host = (headers['x-forwarded-host'] || headers.host || '').toString().trim();\nconst proto = (headers['x-forwarded-proto'] || headers['x-forwarded-protocol'] || 'http').toString().trim() || 'http';\nconst normalizeBaseWebhookUrl = (value) => { const raw = String(value ?? '').trim(); if (!raw) return ''; const withProtocol = /^[a-z]+:\\/\\//i.test(raw) || raw.startsWith('/') ? raw : 'https://' + raw; return withProtocol.replace(/\\/+$/,'').replace(/\\/webhook$/,''); };\nconst baseWebhookUrl = (() => {\n  if (host) return normalizeBaseWebhookUrl(proto + '://' + host);\n  for (const candidate of [$json.baseWebhookUrl, $vars?.baseWebhookUrl, $vars?.BASE_WEBHOOK_URL, $vars?.WEBHOOK_URL]) {\n    const normalized = normalizeBaseWebhookUrl(candidate);\n    if (normalized) return normalized;\n  }\n  return 'https://nonsuspended-worried-alyssa.ngrok-free.dev';\n})();\nconst actionUrl = baseWebhookUrl + '/webhook/nominas-reject-submit?token=' + encodeURIComponent(token);\n\nconst formLockScript = `<script>\n(() => {\n  const form = document.getElementById('reject-form');\n  const button = document.getElementById('reject-submit');\n  const note = document.getElementById('reject-note');\n  if (!form || !button) return;\n  const storageKey = 'nomina:reject:' + encodeURIComponent('${token}');\n  const ttlMs = 2 * 60 * 1000;\n  let submitting = false;\n  try {\n    const storedRaw = sessionStorage.getItem(storageKey);\n    if (storedRaw) {\n      const stored = JSON.parse(storedRaw);\n      if (stored && typeof stored.ts === 'number' && (Date.now() - stored.ts) < ttlMs) {\n        button.disabled = true;\n        button.textContent = 'Rechazo enviado';\n        if (note) note.textContent = 'Esta solicitud ya fue enviada. Espere la confirmación en pantalla.';\n      } else {\n        sessionStorage.removeItem(storageKey);\n      }\n    }\n  } catch {}\n  form.addEventListener('submit', (event) => {\n    if (submitting || button.disabled) {\n      event.preventDefault();\n      return;\n    }\n    submitting = true;\n    try {\n      sessionStorage.setItem(storageKey, JSON.stringify({ ts: Date.now() }));\n    } catch {}\n    button.disabled = true;\n    button.textContent = 'Enviando rechazo...';\n    if (note) note.textContent = 'Estamos registrando la observación. No cierre esta ventana.';\n  });\n})();\n</script>`;\n\nconst html = `<!doctype html>\n<html lang=\"es\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>Registrar rechazo de nómina</title>\n  <style>\n    :root{--mye-red:#ff171a;--mye-dark:#b61012;--bg:#f4f6f8;}\n    *{box-sizing:border-box;}\n    body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222;}\n    .wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;}\n    .card{width:100%;max-width:720px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12);}\n    .header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;}\n    .header h1{margin:0;font-size:20px;font-weight:700;}\n    .content{padding:26px;}\n    .intro{font-size:14px;line-height:1.6;color:#333;margin:0 0 18px;}\n    .label{display:block;font-weight:700;margin-bottom:8px;font-size:15px;}\n    textarea{width:100%;min-height:160px;border:1px solid #ddd;border-radius:10px;padding:12px 14px;font-size:14px;resize:vertical;}\n    .actions{margin-top:18px;display:flex;justify-content:center;}\n    button{background:var(--mye-dark);color:#fff;border:none;border-radius:10px;padding:12px 24px;font-size:14px;font-weight:700;cursor:pointer;}\n    button:hover{background:#990d10;}\n    .note{margin-top:12px;font-size:12px;color:#666;text-align:center;line-height:1.5;}\n    .footer{padding:18px 24px;border-top:1px solid #eee;text-align:center;}\n    .firma{max-width:420px;width:100%;height:auto;}\n  </style>\n</head>\n<body>\n  <div class=\"wrap\">\n    <div class=\"card\">\n      <div class=\"header\">\n        <h1>Registrar rechazo de nómina</h1>\n      </div>\n      <div class=\"content\">\n        <p class=\"intro\">${approverName}, ${approverRole}, por favor indique el motivo del rechazo para registrar la observación y notificar al contador responsable.</p>\n        <form id=\"reject-form\" method=\"POST\" action=\"${actionUrl}\">\n          <input type=\"hidden\" name=\"token\" value=\"${token}\" />\n          <label class=\"label\">Motivo del rechazo</label>\n          <textarea name=\"motivo\" placeholder=\"Ingrese aquí el detalle de la observación\" required></textarea>\n          <div class=\"actions\">\n            <button id=\"reject-submit\" type=\"submit\">Registrar rechazo</button>\n          </div>\n          <div id=\"reject-note\" class=\"note\">La observación será comunicada formalmente al contador para su revisión y corrección.</div>\n        </form>\n      </div>\n      <div class=\"footer\">\n        <img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\">\n      </div>\n    </div>\n  </div>\n  ${formLockScript}\n</body>\n</html>`;\nreturn [{ json: { body: html } }];\n"
      }
    },
    {
      "id": "b6c7c559-c0f5-4b7e-b622-52722af1b531",
      "name": "Responder Formulario",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        -1760,
        896
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "545c4c88-de9a-4587-9ac6-882f22923e04",
      "name": "Parse Token Rechazo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1968,
        1168
      ],
      "parameters": {
        "jsCode": "function b64urlDecode(s){\n  s = s.replace(/-/g,'+').replace(/_/g,'/');\n  while (s.length % 4) s += '=';\n  return Buffer.from(s, 'base64').toString('utf8');\n}\nfunction 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 inválido');const parts = token.split('.');const payloadStr = b64urlDecode(parts[0]);const payload = JSON.parse(payloadStr);if (payload.exp) {\n  const expMs = payload.exp < 1e12 ? payload.exp * 1000 : payload.exp;\n  if (Date.now() > expMs) throw new Error('Token expirado');\n}\nconst motivo = ($json.motivo || $json.body?.motivo || '').toString();\nreturn [{ json: { ...payload, payloadStr, sigPart: parts[1], motivo, secret: 'MyE_Fujo_2026..', token } }];\n"
      }
    },
    {
      "id": "8515bad6-efd5-4662-b077-048901a7a2c3",
      "name": "HMAC Rechazo",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        -1776,
        1168
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "hex"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "c3d59038-516e-4156-9163-1f52dbf56f29",
      "name": "Compare Token Rechazo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1584,
        1168
      ],
      "parameters": {
        "jsCode": "function b64urlFromHexDouble(hex){\n  const base64str = Buffer.from(hex, 'hex').toString('base64');\n  return Buffer.from(base64str, 'utf8')\n    .toString('base64')\n    .replace(/=+$/,'')\n    .replace(/\\+/g,'-')\n    .replace(/\\//g,'_');\n}\n\nconst expected = b64urlFromHexDouble($json.data);\nif (expected !== $json.sigPart) throw new Error('Firma inválida');\n\nconst sd = $getWorkflowStaticData('global');\nif (!sd.nominaDecisionByToken || typeof sd.nominaDecisionByToken !== 'object') {\n  sd.nominaDecisionByToken = {};\n}\n\nconst now = Date.now();\nconst TTL_MS = 45 * 24 * 60 * 60 * 1000;\nfor (const [key, value] of Object.entries(sd.nominaDecisionByToken)) {\n  const atMs = Number(value?.atMs || 0);\n  if (!atMs || (now - atMs) > TTL_MS) delete sd.nominaDecisionByToken[key];\n}\n\nconst tokenKey = String($json.sigPart || '');\nif (!tokenKey) throw new Error('Token inválido');\n\nconst existing = sd.nominaDecisionByToken[tokenKey];\nif (existing) {\n  return [{\n    json: {\n      ...$json,\n      alreadyProcessed: true,\n      existingAction: existing.action || 'processed',\n      existingAtIso: existing.atIso || '',\n      tokenKey,\n    }\n  }];\n}\n\nsd.nominaDecisionByToken[tokenKey] = {\n  action: 'reject',\n  atMs: now,\n  atIso: new Date(now).toISOString(),\n  folderName: $json.folderName || ''\n};\n\nreturn [{\n  json: {\n    ...$json,\n    alreadyProcessed: false,\n    decisionAction: 'reject',\n    tokenKey,\n  }\n}];"
      }
    },
    {
      "id": "8fd2073b-a9ae-4771-9a1d-32082d4a715c",
      "name": "IF Token Ya Usado (Vista Aprobar)",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1520,
        240
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "if-token-used-approve-preview",
              "leftValue": "={{$json.alreadyProcessed}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "b03dafe2-5f5b-4e19-bbe5-eb06af318a36",
      "name": "Mostrar Confirmacion Aprobar",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        0,
        0
      ],
      "parameters": {
        "jsCode": "const token = ($json.token || $json.query?.token || (($items('Normalizar Token Confirmacion Aprobar')[0] || {}).json || {}).token || (($items('Parse Token')[0] || {}).json || {}).token || '').toString();\nconst stage = ($json.stage || '').toString().toLowerCase();\nconst approverName = stage === 'finanzas' ? 'Rodrigo Pulgar' : 'Ximena Inostroza';\nconst approverRole = stage === 'finanzas' ? 'Gerente de Administración y Finanzas' : 'Verificadora de Monto';\nconst actionUrl = '/webhook/nominas-approve-submit?token=' + encodeURIComponent(token);\nconst bankType = ($json.bankType || 'No especificado').toString();\nconst monto = ($json.facturasTotalTexto || 'No disponible').toString();\nconst fecha = ($json.fechaSolicitudTexto || 'No disponible').toString();\n\nconst formLockScript = `<script>\n(() => {\n  const form = document.getElementById('approve-form');\n  const button = document.getElementById('approve-submit');\n  const note = document.getElementById('approve-note');\n  if (!form || !button) return;\n  const storageKey = 'nomina:approve:' + encodeURIComponent('${token}');\n  const ttlMs = 2 * 60 * 1000;\n  let submitting = false;\n  try {\n    const storedRaw = sessionStorage.getItem(storageKey);\n    if (storedRaw) {\n      const stored = JSON.parse(storedRaw);\n      if (stored && typeof stored.ts === 'number' && (Date.now() - stored.ts) < ttlMs) {\n        button.disabled = true;\n        button.textContent = 'Aprobación enviada';\n        if (note) note.textContent = 'Esta solicitud ya fue enviada. Espere la confirmación en pantalla.';\n      } else {\n        sessionStorage.removeItem(storageKey);\n      }\n    }\n  } catch {}\n  form.addEventListener('submit', (event) => {\n    if (submitting || button.disabled) {\n      event.preventDefault();\n      return;\n    }\n    submitting = true;\n    try {\n      sessionStorage.setItem(storageKey, JSON.stringify({ ts: Date.now() }));\n    } catch {}\n    button.disabled = true;\n    button.textContent = 'Enviando aprobación...';\n    if (note) note.textContent = 'Estamos registrando la aprobación. No cierre esta ventana.';\n  });\n})();\n</script>`;\n\nconst html = `<!doctype html>\n<html lang=\"es\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n  <title>Confirmación de aprobación</title>\n  <style>\n    :root{--mye-red:#ff171a;--mye-dark:#b61012;--bg:#f4f6f8;}\n    *{box-sizing:border-box;}\n    body{margin:0;font-family:Arial,Helvetica,sans-serif;background:var(--bg);color:#222;}\n    .wrap{min-height:100vh;display:flex;align-items:center;justify-content:center;padding:24px;}\n    .card{width:100%;max-width:720px;background:#fff;border-radius:14px;overflow:hidden;box-shadow:0 12px 40px rgba(0,0,0,.12);}\n    .header{background:var(--mye-red);color:#fff;padding:18px 24px;text-align:center;}\n    .header h1{margin:0;font-size:20px;font-weight:700;}\n    .content{padding:28px;text-align:center;}\n    .msg{font-size:15px;color:#333;line-height:1.7;margin-bottom:16px;}\n    .meta{font-size:14px;color:#555;margin-bottom:20px;line-height:1.8;}\n    .actions{display:flex;gap:12px;justify-content:center;flex-wrap:wrap;}\n    button{background:var(--mye-red);color:#fff;border:none;border-radius:10px;padding:12px 24px;font-size:14px;font-weight:700;cursor:pointer;}\n    button:hover{background:#d81216;}\n    button:disabled{background:#d48d8e;cursor:not-allowed;}\n    a{background:#efefef;color:#333;text-decoration:none;border-radius:10px;padding:12px 24px;font-size:14px;font-weight:700;display:inline-block;}\n    .note{margin-top:14px;font-size:12px;color:#666;line-height:1.5;}\n    .footer{padding:18px 24px;border-top:1px solid #eee;text-align:center;}\n    .firma{max-width:420px;width:100%;height:auto;}\n  </style>\n</head>\n<body>\n  <div class=\"wrap\">\n    <div class=\"card\">\n      <div class=\"header\">\n        <h1>Confirmación de aprobación</h1>\n      </div>\n      <div class=\"content\">\n        <div class=\"msg\">${stage === 'finanzas' ? '¿Está seguro que desea aprobar esta Nomina?' : approverName + ', por favor confirme si desea aprobar esta nómina para continuar con la siguiente etapa del proceso.'}</div>\n        <div class=\"meta\"><b>Tipo de banco:</b> ${bankType}<br><b>Monto consolidado:</b> ${monto}<br><b>Fecha:</b> ${fecha}</div>\n        <form id=\"approve-form\" method=\"POST\" action=\"${actionUrl}\">\n          <input type=\"hidden\" name=\"token\" value=\"${token}\" />\n          <div class=\"actions\">\n            <button id=\"approve-submit\" type=\"submit\">Confirmar aprobación</button>\n            <a href=\"javascript:window.close()\">Cancelar</a>\n          </div>\n          <div id=\"approve-note\" class=\"note\">Al confirmar, la aprobación quedará registrada una sola vez para este enlace.</div>\n        </form>\n      </div>\n      <div class=\"footer\">\n        <img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\">\n      </div>\n    </div>\n  </div>\n  ${formLockScript}\n</body>\n</html>`;\n\nreturn [{ json: { body: html } }];"
      }
    },
    {
      "id": "4f88b3ed-cde0-4636-bd6c-88fd018cf9f2",
      "name": "Responder Confirmacion Aprobar",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        208,
        0
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "fbd375e5-4f8c-49e5-b10c-cf134014e079",
      "name": "Parse Token Aprobar Submit",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -2016,
        624
      ],
      "parameters": {
        "jsCode": "function b64urlDecode(s){\n  s = s.replace(/-/g,'+').replace(/_/g,'/');\n  while (s.length % 4) s += '=';\n  return Buffer.from(s, 'base64').toString('utf8');\n}\nfunction 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 inválido');const parts = token.split('.');const payloadStr = b64urlDecode(parts[0]);const payload = JSON.parse(payloadStr);if (payload.exp) {\n  const expMs = payload.exp < 1e12 ? payload.exp * 1000 : payload.exp;\n  if (Date.now() > expMs) throw new Error('Token expirado');\n}\nreturn [{ json: { ...payload, payloadStr, sigPart: parts[1], secret: 'MyE_Fujo_2026..', token } }];\n"
      }
    },
    {
      "id": "c6145d8c-918d-473c-8346-85cb753df210",
      "name": "HMAC Token Aprobar Submit",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        -1856,
        464
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "hex"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "b20cc37d-02df-42e0-a6a0-37ab58bc8e70",
      "webhookId": "bbd528d2-a755-46c0-ab3b-d719eaa2b1ca",
      "name": "Notificar Administracion Rechazo",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        -368,
        1312
      ],
      "parameters": {
        "toRecipients": "pagosproveedores@mye.cl",
        "subject": "=Nómina rechazada en {{$node[\"Parse Token Rechazo\"].json.stage === 'finanzas' ? 'Finanzas' : 'Verificación de monto'}}: {{$node[\"Parse Token Rechazo\"].json.folderName}}",
        "bodyContent": "=<table role=\"presentation\" width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" bgcolor=\"#f4f6f8\" style=\"font-family: Arial, Helvetica, sans-serif;\">\n  <tr>\n    <td align=\"center\" style=\"padding:20px;\">\n      <table role=\"presentation\" width=\"600\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" bgcolor=\"#ffffff\" style=\"border-radius:6px; overflow:hidden;\">\n        <tr>\n          <td bgcolor=\"#ff171a\" style=\"color:#ffffff; padding:16px; font-size:18px;\">\n            Nómina rechazada en {{$node[\"Parse Token Rechazo\"].json.stage === 'finanzas' ? 'Finanzas' : 'Verificación de monto'}}\n          </td>\n        </tr>\n        <tr>\n          <td style=\"padding:20px; color:#333333; font-size:14px; line-height:1.6;\">\n            <p>Estimado Marco Aguilar:</p>\n            <p>Junto con saludar, se informa que la nómina <b>{{$node[\"Parse Token Rechazo\"].json.folderName}}</b> ha sido rechazada en la etapa de {{$node[\"Parse Token Rechazo\"].json.stage === 'finanzas' ? 'Finanzas' : 'Verificación de monto'}}.</p>\n            <p><b>Motivo informado:</b> {{$node[\"Parse Token Rechazo\"].json.motivo}}</p>\n            <ul>\n              <li><b>Responsable de la revisión:</b> {{$node[\"Parse Token Rechazo\"].json.stage === 'finanzas' ? 'Rodrigo Pulgar, Gerente de Administración y Finanzas' : 'Ximena Inostroza, Verificadora de Monto'}}</li>\n              <li><b>Tipo de banco:</b> {{$node[\"Parse Token Rechazo\"].json.bankType || \"No especificado\"}}</li>\n              <li><b>Monto consolidado:</b> {{$json.facturasTotalTexto || \"No disponible\"}}</li>\n              <li><b>Carpeta de respaldo:</b> <a href=\"{{$node[\"Parse Token Rechazo\"].json.webUrl}}\">Abrir carpeta</a></li>\n              <li><b>Planilla de facturas:</b> <a href=\"{{$node[\"Buscar facturas_semana (Rechazo)\"].json.webUrl}}\">Abrir facturas_semana.xlsx</a></li>\n            </ul>\n            <p>Se solicita revisar la observación y realizar las correcciones que correspondan.</p>\n            <hr style=\"border:none; border-top:1px solid #e0e0e0; margin:20px 0;\">\n            <div style=\"font-size:12px; color:#666;\">\n              <img src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\" style=\"max-width:420px; width:100%; height:auto;\">\n            </div>\n          </td>\n        </tr>\n      </table>\n    </td>\n  </tr>\n</table>\n",
        "additionalFields": {
          "bodyContentType": "html"
        }
      },
      "credentials": {
        "microsoftOutlookOAuth2Api": {
          "id": "p4O6wj9qoVBj9C9X",
          "name": "Microsoft Outlook account"
        }
      }
    },
    {
      "id": "cd64dd11-bfa4-4041-8155-dc5af093ab3a",
      "name": "Respuesta HTML Rechazo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -192,
        1312
      ],
      "parameters": {
        "jsCode": "return [{ json: { body: '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Rechazo registrado</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:640px;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:26px;text-align:center;} .msg{font-size:14px;color:#333;line-height:1.6;} .firma{max-width:420px;width:100%;height:auto;margin-top:16px;}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Rechazo registrado</div><div class=\"content\"><div class=\"msg\">El rechazo ha sido registrado correctamente y la notificación fue enviada al contador responsable para su gestión.</div><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>' } }];\n"
      }
    },
    {
      "id": "b3bb35cd-a637-46d3-beb5-1c70f18e1ba0",
      "name": "Responder Rechazo",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        64,
        1024
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    },
    {
      "id": "8f80d633-79a2-4f61-b2e3-186f930142b7",
      "name": "Buscar facturas_semana (Aprobado)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -1248,
        608
      ],
      "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"
        }
      }
    },
    {
      "id": "d23431ca-99ce-45c5-93a1-12d1b09a6633",
      "name": "Leer filas facturas (Aprobado)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -1056,
        608
      ],
      "parameters": {
        "url": "=https://graph.microsoft.com/v1.0/me/drive/items/{{$json.id}}/content",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftOAuth2Api",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          },
          "timeout": 180000
        }
      },
      "credentials": {
        "microsoftOAuth2Api": {
          "id": "7pDFU0vOqasMJYBC",
          "name": "Microsoft account"
        }
      }
    },
    {
      "id": "9cd991c5-73ef-4a21-a72c-edb079aae08d",
      "name": "Parsear Excel Facturas (Aprobado)",
      "type": "n8n-nodes-base.spreadsheetFile",
      "typeVersion": 2,
      "position": [
        -832,
        608
      ],
      "parameters": {
        "options": {}
      }
    },
    {
      "id": "10d813a0-bc26-409c-b9af-c9ac319083ae",
      "name": "Calcular total facturas (Aprobado)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -624,
        608
      ],
      "parameters": {
        "jsCode": "function parseMonto(value) {\n  if (value === null || value === undefined || value === '') return 0;\n\n  if (typeof value === 'number' && Number.isFinite(value)) {\n    return Math.max(0, Math.round(value));\n  }\n\n  const raw = String(value).replace(/\\$/g, '').replace(/\\s/g, '').trim();\n  if (!raw || raw === '-') return 0;\n\n  if (/^\\d{1,3}(\\.\\d{3})+(,\\d+)?$/.test(raw)) {\n    const n = Number(raw.replace(/\\./g, '').replace(',', '.'));\n    return Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;\n  }\n\n  if (/^\\d{1,3}(,\\d{3})+(\\.\\d+)?$/.test(raw)) {\n    const n = Number(raw.replace(/,/g, ''));\n    return Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;\n  }\n\n  const fallback = Number(raw.replace(/\\./g, '').replace(',', '.'));\n  if (Number.isFinite(fallback)) return Math.max(0, Math.round(fallback));\n\n  const digits = raw.replace(/[^\\d]/g, '');\n  return digits ? parseInt(digits, 10) : 0;\n}\n\nconst tokenData = ($items('Parse Token Aprobar Submit')[0] || {}).json || {};\n\nlet facturasCount = 0;\nlet facturasTotal = 0;\n\nfor (const item of items) {\n  const row = item.json || {};\n  const numeroFactura = String(row.numero_factura || '').trim();\n  const numeroOc = String(row.numero_oc || '').trim();\n  if (!numeroFactura && !numeroOc) continue;\n  const monto = parseMonto(row.monto_total);\n  if (!Number.isFinite(monto) || monto <= 0) continue;\n\n  facturasCount += 1;\n  facturasTotal += monto;\n}\n\nreturn [{\n  json: {\n    ...tokenData,\n    facturasCount,\n    facturasTotal,\n    facturasTotalTexto: facturasTotal > 0\n      ? '$' + Number(facturasTotal).toLocaleString('es-CL')\n      : (tokenData.facturasTotalTexto || 'No disponible')\n  }\n}];"
      }
    },
    {
      "id": "c9a61188-fd02-465a-bfe0-15ae3d1fd4fa",
      "name": "Buscar facturas_semana (Rechazo)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -1168,
        1312
      ],
      "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"
        }
      }
    },
    {
      "id": "a8e10ecc-76a7-4727-ba8c-785d9c289b78",
      "name": "Leer filas facturas (Rechazo)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -944,
        1312
      ],
      "parameters": {
        "url": "=https://graph.microsoft.com/v1.0/me/drive/items/{{$json.id}}/content",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftOAuth2Api",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          },
          "timeout": 180000
        }
      },
      "credentials": {
        "microsoftOAuth2Api": {
          "id": "7pDFU0vOqasMJYBC",
          "name": "Microsoft account"
        }
      }
    },
    {
      "id": "f6f80d1d-c644-45d0-9eed-52318db8b91a",
      "name": "Parsear Excel Facturas (Rechazo)",
      "type": "n8n-nodes-base.spreadsheetFile",
      "typeVersion": 2,
      "position": [
        -752,
        1312
      ],
      "parameters": {
        "options": {}
      }
    },
    {
      "id": "68f79698-3a32-455c-9433-9ef2da3dbe6e",
      "name": "Calcular total facturas (Rechazo)",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -560,
        1312
      ],
      "parameters": {
        "jsCode": "function parseMonto(value) {\n  if (value === null || value === undefined || value === '') return 0;\n\n  if (typeof value === 'number' && Number.isFinite(value)) {\n    return Math.max(0, Math.round(value));\n  }\n\n  const raw = String(value).replace(/\\$/g, '').replace(/\\s/g, '').trim();\n  if (!raw || raw === '-') return 0;\n\n  if (/^\\d{1,3}(\\.\\d{3})+(,\\d+)?$/.test(raw)) {\n    const n = Number(raw.replace(/\\./g, '').replace(',', '.'));\n    return Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;\n  }\n\n  if (/^\\d{1,3}(,\\d{3})+(\\.\\d+)?$/.test(raw)) {\n    const n = Number(raw.replace(/,/g, ''));\n    return Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;\n  }\n\n  const fallback = Number(raw.replace(/\\./g, '').replace(',', '.'));\n  if (Number.isFinite(fallback)) return Math.max(0, Math.round(fallback));\n\n  const digits = raw.replace(/[^\\d]/g, '');\n  return digits ? parseInt(digits, 10) : 0;\n}\n\nlet facturasCount = 0;\nlet facturasTotal = 0;\n\nfor (const item of items) {\n  const row = item.json || {};\n  const numeroFactura = String(row.numero_factura || '').trim();\n  const numeroOc = String(row.numero_oc || '').trim();\n  if (!numeroFactura && !numeroOc) continue;\n  const monto = parseMonto(row.monto_total);\n  if (!Number.isFinite(monto) || monto <= 0) continue;\n\n  facturasCount += 1;\n  facturasTotal += monto;\n}\n\nreturn [{\n  json: {\n    facturasCount,\n    facturasTotal,\n    facturasTotalTexto: '$' + Number(facturasTotal).toLocaleString('es-CL')\n  }\n}];"
      }
    },
    {
      "id": "7005373f-4630-4fc0-9ea0-de385fc7ea48",
      "name": "IF Token Ya Usado (Aprobar)",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1520,
        480
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "if-token-used-approve",
              "leftValue": "={{$json.alreadyProcessed}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "c4a8983e-107b-4248-a791-c590655ab614",
      "name": "Respuesta Ya Procesada GG",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1264,
        352
      ],
      "parameters": {
        "jsCode": "const action = String($json.existingAction || '').toLowerCase();\nconst when = ($json.existingAtIso || '').toString();\n\nlet actionTxt = 'procesado';\nif (action === 'approve') actionTxt = 'aprobado';\nif (action === 'reject') actionTxt = 'rechazado';\n\nconst whenLine = when ? '<div class=\"msg\">Fecha del registro: ' + when + '</div>' : '';\n\nconst html = '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Enlace ya utilizado</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:26px;text-align:center;} .msg{font-size:14px;color:#333;line-height:1.5;} .firma{max-width:420px;width:100%;height:auto;margin-top:16px;}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Enlace ya utilizado</div><div class=\"content\"><div class=\"msg\">Este correo ya fue ' + actionTxt + ' y no admite una nueva respuesta.</div>' + whenLine + '<img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>';\n\nreturn [{ json: { body: html } }];"
      }
    },
    {
      "id": "6ebd92e2-881b-46cf-bfa4-e4414bfdd274",
      "name": "IF Token Ya Usado (Rechazo)",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1392,
        1168
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "if-token-used-reject",
              "leftValue": "={{$json.alreadyProcessed}}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "8f7ab76d-513c-4c94-9bd6-737f19b1f03f",
      "name": "Respuesta Ya Procesada Rechazo",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1168,
        1024
      ],
      "parameters": {
        "jsCode": "const action = String($json.existingAction || '').toLowerCase();\nconst when = ($json.existingAtIso || '').toString();\n\nlet actionTxt = 'procesado';\nif (action === 'approve') actionTxt = 'aprobado';\nif (action === 'reject') actionTxt = 'rechazado';\n\nconst whenLine = when ? '<div class=\"msg\">Fecha del registro: ' + when + '</div>' : '';\n\nconst html = '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Enlace ya utilizado</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:26px;text-align:center;} .msg{font-size:14px;color:#333;line-height:1.5;} .firma{max-width:420px;width:100%;height:auto;margin-top:16px;}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Enlace ya utilizado</div><div class=\"content\"><div class=\"msg\">Este correo ya fue ' + actionTxt + ' y no admite una nueva respuesta.</div>' + whenLine + '<img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>';\n\nreturn [{ json: { body: html } }];"
      }
    },
    {
      "id": "4aaf6d98-601d-49a7-94f9-cc7eab304b62",
      "name": "Normalizar Token Confirmacion Aprobar",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -1264,
        16
      ],
      "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());\n\nconst facturasTotal = Number($json.facturasTotal ?? 0);\nconst facturasTotalTexto = ($json.facturasTotalTexto || (Number.isFinite(facturasTotal) && facturasTotal > 0\n  ? '$' + facturasTotal.toLocaleString('es-CL')\n  : '')).toString();\n\nreturn [{\n  json: {\n    ...$json,\n    facturasTotal: Number.isFinite(facturasTotal) ? facturasTotal : 0,\n    facturasTotalTexto,\n    fechaSolicitudTexto: ($json.fechaSolicitudTexto || nowText).toString(),\n  }\n}];"
      }
    },
    {
      "id": "98331350-6e57-4c04-9276-7fa76bd45bb1",
      "name": "IF Confirmacion Tiene Monto",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -1040,
        16
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "758d0c60-f06a-452d-b14f-0d1f3d7ee3c6",
              "leftValue": "={{($json.facturasTotalTexto || \"\").toString().trim()}}",
              "rightValue": "",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "286f3fb0-8aef-464d-b563-dc6cf0def87c",
      "name": "Buscar facturas_semana (Vista Aprobar)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -800,
        112
      ],
      "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"
        }
      }
    },
    {
      "id": "c814df29-63ce-439f-9b47-a28ccc3072d0",
      "name": "Leer filas facturas (Vista Aprobar)",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -592,
        112
      ],
      "parameters": {
        "url": "=https://graph.microsoft.com/v1.0/me/drive/items/{{$json.id}}/content",
        "authentication": "predefinedCredentialType",
        "nodeCredentialType": "microsoftOAuth2Api",
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          },
          "timeout": 180000
        }
      },
      "credentials": {
        "microsoftOAuth2Api": {
          "id": "7pDFU0vOqasMJYBC",
          "name": "Microsoft account"
        }
      }
    },
    {
      "id": "b986ad53-c3e6-4fe1-b9e5-da99abe79e9e",
      "name": "Parsear Excel Facturas (Vista Aprobar)",
      "type": "n8n-nodes-base.spreadsheetFile",
      "typeVersion": 2,
      "position": [
        -384,
        112
      ],
      "parameters": {
        "options": {}
      }
    },
    {
      "id": "11150e13-97e3-4795-868e-885955838e31",
      "name": "Preparar Confirmacion Aprobar",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -192,
        112
      ],
      "parameters": {
        "jsCode": "function parseMonto(value) {\n  if (value === null || value === undefined || value === '') return 0;\n  if (typeof value === 'number' && Number.isFinite(value)) return Math.max(0, Math.round(value));\n  const raw = String(value).replace(/\\$/g, '').replace(/\\s/g, '').trim();\n  if (!raw || raw === '-') return 0;\n  if (/^\\d{1,3}(\\.\\d{3})+(,\\d+)?$/.test(raw)) {\n    const n = Number(raw.replace(/\\./g, '').replace(',', '.'));\n    return Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;\n  }\n  if (/^\\d{1,3}(,\\d{3})+(\\.\\d+)?$/.test(raw)) {\n    const n = Number(raw.replace(/,/g, ''));\n    return Number.isFinite(n) ? Math.max(0, Math.round(n)) : 0;\n  }\n  const fallback = Number(raw.replace(/\\./g, '').replace(',', '.'));\n  if (Number.isFinite(fallback)) return Math.max(0, Math.round(fallback));\n  const digits = raw.replace(/[^\\d]/g, '');\n  return digits ? parseInt(digits, 10) : 0;\n}\n\nconst tokenData = ($items('Normalizar Token Confirmacion Aprobar')[0] || {}).json || {};\nlet facturasCount = 0;\nlet facturasTotal = 0;\nfor (const item of items) {\n  const row = item.json || {};\n  const numeroFactura = String(row.numero_factura || '').trim();\n  const numeroOc = String(row.numero_oc || '').trim();\n  if (!numeroFactura && !numeroOc) continue;\n  const monto = parseMonto(row.monto_total);\n  if (!Number.isFinite(monto) || monto <= 0) continue;\n  facturasCount += 1;\n  facturasTotal += monto;\n}\nconst 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());\nreturn [{\n  json: {\n    ...tokenData,\n    facturasCount,\n    facturasTotal,\n    facturasTotalTexto: facturasTotal > 0 ? '$' + Number(facturasTotal).toLocaleString('es-CL') : (tokenData.facturasTotalTexto || 'No disponible'),\n    fechaSolicitudTexto: (tokenData.fechaSolicitudTexto || nowText).toString(),\n  }\n}];"
      }
    },
    {
      "id": "907d9e35-c3a2-4a89-b40e-72426a3fb467",
      "name": "IF Stage Verificador Aprobado",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -384,
        480
      ],
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "if-stage-verificador-aprobado",
              "leftValue": "={{($json.stage || '').toString().toLowerCase()}}",
              "rightValue": "verificador",
              "operator": {
                "type": "string",
                "operation": "equals"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      }
    },
    {
      "id": "768884f6-6198-4010-a53e-20d2f25b50b2",
      "name": "Prep Payload Email Finanzas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -160,
        464
      ],
      "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());\n\nconst excelWebUrl = (((($items('Buscar facturas_semana (Aprobado)')[0] || {}).json || {}).webUrl) || ($json.excelWebUrl || '')).toString();\nconst facturasTotal = Number($json.facturasTotal || 0);\nconst facturasTotalTexto = ($json.facturasTotalTexto || ('$' + Number(facturasTotal).toLocaleString('es-CL'))).toString();\nconst linkedFacturasFolderName = ($json.linkedFacturasFolderName || $json.folderName || '').toString();\nconst linkedFacturasFolderPath = ($json.linkedFacturasFolderPath || '').toString();\nconst linkedFacturasFolderPathEncoded = ($json.linkedFacturasFolderPathEncoded || '').toString();\n\nconst payload = {\n  driveId: $json.driveId,\n  folderId: $json.folderId,\n  folderName: $json.folderName,\n  linkedFacturasFolderName,\n  linkedFacturasFolderPath,\n  linkedFacturasFolderPathEncoded,\n  linkedFacturasRootMode: Boolean($json.linkedFacturasRootMode),\n  linkedFolderSource: ($json.linkedFolderSource || '').toString(),\n  webUrl: $json.webUrl,\n  excelWebUrl,\n  weekFolder: $json.weekFolder,\n  bankType: $json.bankType,\n  fechaSolicitudTexto: ($json.fechaSolicitudTexto || nowText).toString(),\n  facturasTotal,\n  facturasTotalTexto,\n  facturasYearMonth: $json.facturasYearMonth || $json.yearMonth,\n  facturasDriveId: $json.facturasDriveId || $json.driveId,\n  yearMonth: $json.yearMonth,\n      emailContador: $json.emailContador || 'pagosproveedores@mye.cl',\n      emailVerificador: $json.emailVerificador || 'xinostroza@mye.cl',\n      emailFinanzas: $json.emailFinanzas || 'rpulgar@mye.cl',\n  stage: 'finanzas',\n};\n\nreturn [{\n  json: {\n    ...$json,\n    linkedFacturasFolderName,\n    linkedFacturasFolderPath,\n    linkedFacturasFolderPathEncoded,\n    excelWebUrl,\n    baseWebhookUrl: (() => {\n      const normalize = (value) => {\n        const raw = String(value ?? '').trim();\n        if (!raw) return '';\n        const withProtocol = /^[a-z]+:\\/\\//i.test(raw) || raw.startsWith('/') ? raw : 'https://' + raw;\n        return withProtocol.replace(/\\/+$/,'').replace(/\\/webhook$/,'');\n      };\n      for (const candidate of [$json.baseWebhookUrl, $vars?.baseWebhookUrl, $vars?.BASE_WEBHOOK_URL, $vars?.WEBHOOK_URL]) {\n        const normalized = normalize(candidate);\n        if (normalized) return normalized;\n      }\n      return 'https://nonsuspended-worried-alyssa.ngrok-free.dev';\n    })(),\n    secret: 'MyE_Fujo_2026..',\n    facturasTotal,\n    facturasTotalTexto,\n      emailContador: $json.emailContador || 'pagosproveedores@mye.cl',\n      emailVerificador: $json.emailVerificador || 'xinostroza@mye.cl',\n      emailFinanzas: $json.emailFinanzas || 'rpulgar@mye.cl',\n    payloadStr: JSON.stringify(payload),\n  }\n}];"
      }
    },
    {
      "id": "d39f6ad2-5589-4029-9108-dcc1eb0eb8a2",
      "name": "HMAC Token Email Finanzas",
      "type": "n8n-nodes-base.crypto",
      "typeVersion": 2,
      "position": [
        16,
        464
      ],
      "parameters": {
        "action": "hmac",
        "binaryData": false,
        "type": "SHA256",
        "value": "={{$json.payloadStr}}",
        "dataPropertyName": "data",
        "encoding": "base64"
      },
      "credentials": {
        "crypto": {
          "id": "hB0SZXy6Hqtzg9IQ",
          "name": "Crypto account"
        }
      }
    },
    {
      "id": "8eb17e07-49b5-42bb-acda-3a25d914713b",
      "name": "Build Token Email Finanzas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        240,
        464
      ],
      "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": "82ee390c-83ab-4742-9294-e9f5f6a212da",
      "webhookId": "d620b8ed-47ef-4d7e-b722-c79508b640db",
      "name": "Email a Gerencia Finanzas",
      "type": "n8n-nodes-base.microsoftOutlook",
      "typeVersion": 2,
      "position": [
        464,
        464
      ],
      "parameters": {
        "toRecipients": "={{$json.emailFinanzas || \"rpulgar@mye.cl\"}}",
        "subject": "=Confirmar Aprobació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 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 = 'Junto con saludar, la nomina fue validada correctamente, favor de dar por finalizada su revisión para Aprobar o Rechazar justificadamente la nomina adjunta'; 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;'>Solicitud de aprobación de nómina</td></tr><tr><td style='padding:20px; color:#333333; font-size:14px; line-height:1.6;'><p>Estimado Rodrigo Pulgar:</p><p>${esc(message)}</p><ul><li><b>Tipo de banco:</b> ${esc(bank)}</li><li><b>Monto consolidado:</b> ${esc(total)}</li><li><b>Carpeta de respaldo:</b> <a href='${folderUrl}'>Abrir carpeta</a></li><li><b>Planilla de facturas:</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 nómina</a><a href='${rejectUrl}' style='background:#808080; color:#ffffff; text-decoration:none; padding:12px 18px; border-radius:4px; display:inline-block;'>Rechazar nómina</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": "21805e06-787a-445f-a73e-b035890a63ca",
      "name": "Respuesta Enviado Finanzas",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        688,
        464
      ],
      "parameters": {
        "jsCode": "return [{ json: { body: '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Aprobación registrada</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:640px;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:26px;text-align:center;} .msg{font-size:14px;color:#333;line-height:1.6;} .firma{max-width:420px;width:100%;height:auto;margin-top:16px;}</style></head><body><div class=\"wrap\"><div class=\"card\"><div class=\"header\">Aprobación registrada</div><div class=\"content\"><div class=\"msg\">La aprobación ha sido registrada correctamente. Esta notificación será enviada a Rodrigo Pulgar, Gerente de Administración y Finanzas.</div><img class=\"firma\" src=\"https://mye.cl/nuevas-firmas/gifs/FIRMA-MARCAS-MYE.gif\" alt=\"Firma MYE\"></div></div></div></body></html>' } }];\n"
      }
    },
    {
      "id": "36db0d14-6bc9-4a4c-9cb5-97adbec9066a",
      "name": "Responder Finanzas",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        912,
        464
      ],
      "parameters": {
        "respondWith": "text",
        "responseBody": "={{$json.body}}",
        "options": {
          "responseHeaders": {
            "entries": [
              {
                "name": "Content-Type",
                "value": "text/html; charset=utf-8"
              }
            ]
          }
        }
      }
    }
  ],
  "connections": {
    "Webhook Aprobar": {
      "main": [
        [
          {
            "node": "Parse Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Token": {
      "main": [
        [
          {
            "node": "HMAC Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HMAC Token": {
      "main": [
        [
          {
            "node": "Verificar Token Aprobacion",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verificar Token Aprobacion": {
      "main": [
        [
          {
            "node": "IF Token Ya Usado (Vista Aprobar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Token": {
      "main": [
        [
          {
            "node": "IF Token Ya Usado (Aprobar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email a Gerencia General": {
      "main": [
        [
          {
            "node": "Notificar Contador Aprobacion Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notificar Contador Aprobacion Final": {
      "main": [
        [
          {
            "node": "Respuesta Enviado GG",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta Enviado GG": {
      "main": [
        [
          {
            "node": "Responder GG",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Rechazar": {
      "main": [
        [
          {
            "node": "Mostrar Formulario Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mostrar Formulario Rechazo": {
      "main": [
        [
          {
            "node": "Responder Formulario",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Rechazo Submit": {
      "main": [
        [
          {
            "node": "Parse Token Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Token Rechazo": {
      "main": [
        [
          {
            "node": "HMAC Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HMAC Rechazo": {
      "main": [
        [
          {
            "node": "Compare Token Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Compare Token Rechazo": {
      "main": [
        [
          {
            "node": "IF Token Ya Usado (Rechazo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notificar Administracion Rechazo": {
      "main": [
        [
          {
            "node": "Respuesta HTML Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta HTML Rechazo": {
      "main": [
        [
          {
            "node": "Responder Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar facturas_semana (Aprobado)": {
      "main": [
        [
          {
            "node": "Leer filas facturas (Aprobado)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Leer filas facturas (Aprobado)": {
      "main": [
        [
          {
            "node": "Parsear Excel Facturas (Aprobado)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsear Excel Facturas (Aprobado)": {
      "main": [
        [
          {
            "node": "Calcular total facturas (Aprobado)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calcular total facturas (Aprobado)": {
      "main": [
        [
          {
            "node": "IF Stage Verificador Aprobado",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar facturas_semana (Rechazo)": {
      "main": [
        [
          {
            "node": "Leer filas facturas (Rechazo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Leer filas facturas (Rechazo)": {
      "main": [
        [
          {
            "node": "Parsear Excel Facturas (Rechazo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsear Excel Facturas (Rechazo)": {
      "main": [
        [
          {
            "node": "Calcular total facturas (Rechazo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calcular total facturas (Rechazo)": {
      "main": [
        [
          {
            "node": "Notificar Administracion Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Token Ya Usado (Aprobar)": {
      "main": [
        [
          {
            "node": "Respuesta Ya Procesada GG",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar facturas_semana (Aprobado)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta Ya Procesada GG": {
      "main": [
        [
          {
            "node": "Responder GG",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Aprobar Submit": {
      "main": [
        [
          {
            "node": "Parse Token Aprobar Submit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Token Aprobar Submit": {
      "main": [
        [
          {
            "node": "HMAC Token Aprobar Submit",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HMAC Token Aprobar Submit": {
      "main": [
        [
          {
            "node": "Compare Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Token Ya Usado (Vista Aprobar)": {
      "main": [
        [
          {
            "node": "Respuesta Ya Procesada GG",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Normalizar Token Confirmacion Aprobar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Mostrar Confirmacion Aprobar": {
      "main": [
        [
          {
            "node": "Responder Confirmacion Aprobar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Token Ya Usado (Rechazo)": {
      "main": [
        [
          {
            "node": "Respuesta Ya Procesada Rechazo",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar facturas_semana (Rechazo)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Respuesta Ya Procesada Rechazo": {
      "main": [
        [
          {
            "node": "Responder Rechazo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalizar Token Confirmacion Aprobar": {
      "main": [
        [
          {
            "node": "IF Confirmacion Tiene Monto",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Confirmacion Tiene Monto": {
      "main": [
        [
          {
            "node": "Mostrar Confirmacion Aprobar",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Buscar facturas_semana (Vista Aprobar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Buscar facturas_semana (Vista Aprobar)": {
      "main": [
        [
          {
            "node": "Leer filas facturas (Vista Aprobar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Leer filas facturas (Vista Aprobar)": {
      "main": [
        [
          {
            "node": "Parsear Excel Facturas (Vista Aprobar)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parsear Excel Facturas (Vista Aprobar)": {
      "main": [
        [
          {
            "node": "Preparar Confirmacion Aprobar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Preparar Confirmacion Aprobar": {
      "main": [
        [
          {
            "node": "Mostrar Confirmacion Aprobar",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF Stage Verificador Aprobado": {
      "main": [
        [
          {
            "node": "Prep Payload Email Finanzas",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Email a Gerencia General",
            "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 Finanzas",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "callerPolicy": "workflowsFromSameOwner",
    "availableInMCP": false,
    "timeSavedMode": "fixed",
    "timeSavedPerExecution": 1
  },
  "staticData": {
    "global": {
      "nominaDecisionByToken": {
        "NXJ2bXcrT2RTa21idXFsNEdJMGRKKzdRandtNzIvZkFkZ3NsZS9XbncyVT0": {
          "action": "approve",
          "atMs": 1775853817680,
          "atIso": "2026-04-10T20:43:37.680Z",
          "folderName": "NOM-001"
        },
        "RU1QaVJTNENzWmxmVXh1M0lWZ0E3MUVkT3F4NllxY25PK3FPZHNBbkNjQT0": {
          "action": "approve",
          "atMs": 1775853848753,
          "atIso": "2026-04-10T20:44:08.753Z",
          "folderName": "NOM-001"
        },
        "Q1JUbG9OZWxEM1plQW9TU0JKRnNDVjJRRlFkWlhrK0t6SDU1YkdSWkl4RT0": {
          "action": "approve",
          "atMs": 1775855648661,
          "atIso": "2026-04-10T21:14:08.661Z",
          "folderName": "NOM-008"
        },
        "Y1Nkd1hYMURoSzRIRXczS1JCcEljUjI2VnhhRVlSWmg3cW9TcyswMHRkOD0": {
          "action": "approve",
          "atMs": 1775855662737,
          "atIso": "2026-04-10T21:14:22.737Z",
          "folderName": "NOM-008"
        },
        "aUlTRmtMc29NY2hDcUZYQUVFVjVMaFZnU0JGWGRzU3VVd0tXdEp4Kys2bz0": {
          "action": "approve",
          "atMs": 1775859270280,
          "atIso": "2026-04-10T22:14:30.280Z",
          "folderName": "NOM-OC-2026-04-10_18-04-40"
        },
        "WHpuWElGZE5MMlUwQjZyQ0dsbkN0SlZJb25mbHdLbHhSZ0Q1VUx0TWFHYz0": {
          "action": "approve",
          "atMs": 1775859283613,
          "atIso": "2026-04-10T22:14:43.613Z",
          "folderName": "NOM-OC-2026-04-10_18-04-40"
        },
        "SUYwSFdKbUw5YTlUQk9NNlp4ZkRrTitvVktVdEhGeWNMeHVqWWRWWFJzMD0": {
          "action": "reject",
          "atMs": 1776087959521,
          "atIso": "2026-04-13T13:45:59.521Z",
          "folderName": "NOM-FACT-2026-04-13_09-39-24"
        },
        "dGhieXZxTFpTQnFlNXVCaTVJc3dCbTM0UUZUdGlia0hVUWpkOUxmZ0tBcz0": {
          "action": "approve",
          "atMs": 1776133363028,
          "atIso": "2026-04-14T02:22:43.028Z",
          "folderName": "NOM-FACT-2026-04-13_15-21-50"
        },
        "azVhbzRXN01ndXREWUdNTlpSVjNGaURTYTZYa0FsWEJnUFFiak5NMDdVMD0": {
          "action": "approve",
          "atMs": 1776133464997,
          "atIso": "2026-04-14T02:24:24.997Z",
          "folderName": "NOM-FACT-2026-04-13_15-24-45"
        },
        "RWJ2QkpjenRlcmUzYlFFajNZWjRmR2dGZ1J6WTB5NW1zbWdrMnYxUllKVT0": {
          "action": "approve",
          "atMs": 1776133583074,
          "atIso": "2026-04-14T02:26:23.074Z",
          "folderName": "NOM-FACT-2026-04-13_15-27-45"
        },
        "aHZqak1Td2I1UTNrS2R1Q0tOMjk3N3pRM0xBR08rSVkwUm1ydFl3RnpYYz0": {
          "action": "approve",
          "atMs": 1776133788597,
          "atIso": "2026-04-14T02:29:48.597Z",
          "folderName": "NOM-FACT-2026-04-13_15-31-45"
        },
        "UFRkUWJJUTVkR29uREYwMkJmMTkvdXp2QS9BWG4xRWZvdG9tQXZhVFg5dz0": {
          "action": "approve",
          "atMs": 1776133857885,
          "atIso": "2026-04-14T02:30:57.885Z",
          "folderName": "NOM-FACT-2026-04-13_15-19-30"
        },
        "Wm5tUGxTVVJlczliTUo5Y1U3U2VxdjR1NnRXa3ZuNjlBTHMzT2o2dThMVT0": {
          "action": "approve",
          "atMs": 1776134055165,
          "atIso": "2026-04-14T02:34:15.165Z",
          "folderName": "NOM-FACT-2026-04-13_15-33-45"
        },
        "MVRTQ1pHOWRkbzNDZEV4UmJqbmJoMjVrdmJJYnNjVlh5Vkt4STdwbW1VRT0": {
          "action": "approve",
          "atMs": 1776134144916,
          "atIso": "2026-04-14T02:35:44.916Z",
          "folderName": "NOM-FACT-2026-04-13_15-35-45"
        },
        "SGNkNjFmd051aS9UNGxKYjVuaExjZHVSQ0pZbDVoSnpvTy8wQXB0eUV5OD0": {
          "action": "approve",
          "atMs": 1776174712852,
          "atIso": "2026-04-14T13:51:52.852Z",
          "folderName": "NOM-FACT-2026-04-13_15-21-50"
        },
        "SytSMDVBclpKM3JjV3hLRGo2eXBiei9KbDNkdXAxcmpCV2dGM0N3VitYbz0": {
          "action": "approve",
          "atMs": 1776174719219,
          "atIso": "2026-04-14T13:51:59.219Z",
          "folderName": "NOM-FACT-2026-04-13_15-24-45"
        },
        "YUsydVE1a0JqNlpZWGZBSHlLaVAyL0hIRk1mTE90a240MjI1amxlWnhxOD0": {
          "action": "approve",
          "atMs": 1776174722911,
          "atIso": "2026-04-14T13:52:02.911Z",
          "folderName": "NOM-FACT-2026-04-13_15-27-45"
        },
        "Ylo2RzJmNjVwSUI3cnFrbHVSaCtIQ2V2dERUQ3ROcVlrMnI4N2h6Nmx6dz0": {
          "action": "approve",
          "atMs": 1776174726806,
          "atIso": "2026-04-14T13:52:06.806Z",
          "folderName": "NOM-FACT-2026-04-13_15-31-45"
        },
        "K2pkN2dJbTdYcERDWWJTYlVRbGtOUFlyaFY3bmkxS1JBU0lQWFNZQStjdz0": {
          "action": "approve",
          "atMs": 1776174730547,
          "atIso": "2026-04-14T13:52:10.547Z",
          "folderName": "NOM-FACT-2026-04-13_15-19-30"
        },
        "OGVlSjNIOWNRNUVMWWVlUU9pam4yMzRLWUZjaWxSQlc5c0tWNytvcFEyRT0": {
          "action": "approve",
          "atMs": 1776174734248,
          "atIso": "2026-04-14T13:52:14.248Z",
          "folderName": "NOM-FACT-2026-04-13_15-33-45"
        },
        "WjZacUUvbkRCVVlIUmwrVFROSERiZ0JWU1VCbUFRTkFMVkkveXI4NTl4ST0": {
          "action": "approve",
          "atMs": 1776174738134,
          "atIso": "2026-04-14T13:52:18.134Z",
          "folderName": "NOM-FACT-2026-04-13_15-35-45"
        },
        "U0ZDL2RNamRDb0VuUXdVQTJlc2R3RFQ2cCtWTzkwcHVRVEhqYThmdy9PVT0": {
          "action": "approve",
          "atMs": 1776175510970,
          "atIso": "2026-04-14T14:05:10.970Z",
          "folderName": "NOM-FACT-2026-04-13_15-21-50"
        },
        "eG1pVGNyVWVrNit3YTVxc2FDOWhlbFFIb1V6NUY0cUs5TjVFNVpSL0NtRT0": {
          "action": "approve",
          "atMs": 1776175584100,
          "atIso": "2026-04-14T14:06:24.100Z",
          "folderName": "NOM-FACT-2026-04-13_15-24-45"
        },
        "dDJvSG9vSTRjd0RoWGtlSDZicnhZb1NvclhmVVFSOWwyakd1TkhRd0cwTT0": {
          "action": "approve",
          "atMs": 1776175628021,
          "atIso": "2026-04-14T14:07:08.021Z",
          "folderName": "NOM-FACT-2026-04-13_15-27-45"
        },
        "TlVqOTEwcjMrZnVSZy9SaVFyVHd2RVJOZWErN1F1REppRjhYN0duK2E5cz0": {
          "action": "approve",
          "atMs": 1776175663820,
          "atIso": "2026-04-14T14:07:43.820Z",
          "folderName": "NOM-FACT-2026-04-13_15-31-45"
        },
        "bkhydVlCTEdiTm1GYTVNY3FiaFhScjlqZ3NWUEpWRGorSWNYSHJTUHBxYz0": {
          "action": "approve",
          "atMs": 1776176062487,
          "atIso": "2026-04-14T14:14:22.487Z",
          "folderName": "NOM-FACT-2026-04-13_15-19-30"
        },
        "VFVKZFpjTGFGeC9pUlQ5QzUvd1Q2MTFuMkJkNjFaaitRVDhCTnVON21SMD0": {
          "action": "approve",
          "atMs": 1776176147211,
          "atIso": "2026-04-14T14:15:47.211Z",
          "folderName": "NOM-FACT-2026-04-13_15-33-45"
        },
        "N2pKWHdHenpWdmVkSmlGVVBCK2Q1aFJUQ2JJV25aVjh2U3ovcXU0S2FjST0": {
          "action": "approve",
          "atMs": 1776176300986,
          "atIso": "2026-04-14T14:18:20.986Z",
          "folderName": "NOM-FACT-2026-04-13_15-35-45"
        },
        "RVhheFZHZ25UWXQ5ZzBoMk01YVJVTDRBL25PbWxqVncrV1F0T2phWmxjVT0": {
          "action": "approve",
          "atMs": 1776187412832,
          "atIso": "2026-04-14T17:23:32.832Z",
          "folderName": "NOM-FACT-2026-04-14_11-12-19"
        },
        "SE1COEhPU1hwekMyanJ4SU4yQXlSdkVoSnk4YldWM2NOdkxLSHlpZ3dldz0": {
          "action": "approve",
          "atMs": 1776187461536,
          "atIso": "2026-04-14T17:24:21.536Z",
          "folderName": "NOM-FACT-2026-04-14_11-29-25"
        },
        "eU45NkphWjhUcE51ditSc1I3YXJ4VjVMVDUzVlVvVzFuZUdJamhZWTVNST0": {
          "action": "approve",
          "atMs": 1776187498808,
          "atIso": "2026-04-14T17:24:58.808Z",
          "folderName": "NOM-OC-2026-04-14_12-08-00"
        },
        "dS9lVTF6akRGZ0Vocmx4MHBUcmtxOW50MFI4OEdPMm9kUU5SMDh5VEhoST0": {
          "action": "reject",
          "atMs": 1776187681847,
          "atIso": "2026-04-14T17:28:01.847Z",
          "folderName": "NOM-FACT-2026-04-14_12-35-48"
        },
        "T1ZZT0paYmVCcysxK1JEQXA1LzBUdHJhaVd4N2Z1dllIVjJEeWcyNVA1bz0": {
          "action": "approve",
          "atMs": 1776187748257,
          "atIso": "2026-04-14T17:29:08.257Z",
          "folderName": "NOM-FACT-2026-04-14_12-35-48"
        },
        "MDA3N2hXSWZ0VmdhRFdONm00OVM1LzVEU2xLVkdyRC9hYmpaWkE2ODlhND0": {
          "action": "approve",
          "atMs": 1776187822193,
          "atIso": "2026-04-14T17:30:22.193Z",
          "folderName": "NOM-OC-2026-04-14_12-55-40"
        },
        "OXV3alNaK0ZsV0ZnK0ZBZjFUa0JpaHQyYXprWmdCRkV2WGdoMFRpaEdLRT0": {
          "action": "approve",
          "atMs": 1776187885016,
          "atIso": "2026-04-14T17:31:25.016Z",
          "folderName": "NOM-FACT-2026-04-14_13-09-17"
        },
        "aXNQMitRaXdFZW5QL0FSYURTUG4wdHRlK0l1VWxSbmFuaTBscndzbC9XZz0": {
          "action": "approve",
          "atMs": 1776187969963,
          "atIso": "2026-04-14T17:32:49.963Z",
          "folderName": "NOM-FACT-2026-04-14_11-12-19"
        },
        "RWxDSG44eUFubkFCd1RKUkE2cW14MThhTFYraUg0U3VUallzTDY1aWROUT0": {
          "action": "approve",
          "atMs": 1776187979292,
          "atIso": "2026-04-14T17:32:59.292Z",
          "folderName": "NOM-OC-2026-04-14_13-24-39"
        },
        "VFFCZlYxK1MrM1FKNWpZZHZrUC9JWFdXWitzMmJIb0RFWWNsQ1IwRjFhaz0": {
          "action": "approve",
          "atMs": 1776188066821,
          "atIso": "2026-04-14T17:34:26.821Z",
          "folderName": "NOM-FACT-2026-04-14_11-29-25"
        },
        "L1RZUUppbC9OdGxzOWZCWEFLSXBvTU9TNWp5UzJOMEZrcmZxYjhLUnV5Zz0": {
          "action": "approve",
          "atMs": 1776188079329,
          "atIso": "2026-04-14T17:34:39.329Z",
          "folderName": "NOM-OC-2026-04-14_12-08-00"
        },
        "V3IyeW51cVowWk9oTnUrTEh6ZUlJMmYxT1c3NVdSMGJ6Sk9zam5RRW50Zz0": {
          "action": "approve",
          "atMs": 1776188104921,
          "atIso": "2026-04-14T17:35:04.921Z",
          "folderName": "NOM-FACT-2026-04-14_12-35-48"
        },
        "T3U1S1MyWkx5cFVPWjVYdCtJZW9MRk9jQnhRWUpubVBDWFVTM1daNFh4MD0": {
          "action": "approve",
          "atMs": 1776188117733,
          "atIso": "2026-04-14T17:35:17.733Z",
          "folderName": "NOM-OC-2026-04-14_12-55-40"
        },
        "UXdYUWJYVjZDSk9UQWtDS3N6d25UYVpEdG9aTkMwdldFeGxUUWxsSCtKYz0": {
          "action": "approve",
          "atMs": 1776188129230,
          "atIso": "2026-04-14T17:35:29.230Z",
          "folderName": "NOM-FACT-2026-04-14_13-09-17"
        },
        "TnNjWUs0RHNob0phRG90TjBZSktodWlGVEd3OWJaQnFOZFJ5VG9oZG9OUT0": {
          "action": "approve",
          "atMs": 1776188168841,
          "atIso": "2026-04-14T17:36:08.841Z",
          "folderName": "NOM-OC-2026-04-14_13-24-39"
        },
        "UmRHTGRvYXlSaDlkVFBDYUg0SkRYNEwrZlNCTGRQNFJ2Zklza3RHdGRlMD0": {
          "action": "approve",
          "atMs": 1776188429334,
          "atIso": "2026-04-14T17:40:29.334Z",
          "folderName": "NOM-FACT-2026-04-14_13-38-17"
        },
        "S2g1TWg4MG5GQ3E1eXlNcXIzY1Z4NS9mdkl1Qkl0RHJmeFVFMmFDOHgzVT0": {
          "action": "approve",
          "atMs": 1776194260907,
          "atIso": "2026-04-14T19:17:40.907Z",
          "folderName": "NOM-OC-2026-04-14_14-12-40"
        },
        "eFk3Z3AwdExaR2MyNjh5UklraUIxNUJDUmdqNEpBK2RPYWdQa1BMWHBXcz0": {
          "action": "approve",
          "atMs": 1776194314592,
          "atIso": "2026-04-14T19:18:34.592Z",
          "folderName": "NOM-OC-2026-04-14_14-22-18"
        },
        "ZG1DVlZVaFFZSE56TVB1Z21xaU8xUzRVdlAwY2hxVkdvTnFXcWN2WjJFUT0": {
          "action": "approve",
          "atMs": 1776194928194,
          "atIso": "2026-04-14T19:28:48.194Z",
          "folderName": "NOM-FACT-2026-04-14_15-25-17"
        },
        "TENyeTE0KzBkT2NHTHp3N2dHeG5hMlBGQ2I5ekhYYkFXRkFVUWFubGptWT0": {
          "action": "approve",
          "atMs": 1776194956083,
          "atIso": "2026-04-14T19:29:16.083Z",
          "folderName": "NOM-FACT-2026-04-14_15-25-17"
        },
        "QzE1RUsvWEljVGllUWZ6dncyTnZTekdqbEFWZE8wNFhLVWtlZVpQVHVITT0": {
          "action": "approve",
          "atMs": 1776195239066,
          "atIso": "2026-04-14T19:33:59.066Z",
          "folderName": "NOM-OC-2026-04-14_14-12-40"
        },
        "MTJrSlZiWnppYVBVM1JaQnNxNVNzSnJ3bnlQR0MyTzFndnRJdGRoU1Z1OD0": {
          "action": "approve",
          "atMs": 1776195300229,
          "atIso": "2026-04-14T19:35:00.229Z",
          "folderName": "NOM-OC-2026-04-14_14-22-18"
        },
        "bHdrdFE1ZDB0TWZCSlk0L0hQeXNaS0c0SVFsR1VXbFZhM0h6cDhNb2VOND0": {
          "action": "approve",
          "atMs": 1776196071966,
          "atIso": "2026-04-14T19:47:51.966Z",
          "folderName": "NOM-FACT-2026-04-13_15-28-56"
        },
        "Z004Z1ZMNkI1SW9HMFJHTjEzWWwyRUt2eXFMWTd5YUdQc2x1YVNSQnZpWT0": {
          "action": "approve",
          "atMs": 1776197207210,
          "atIso": "2026-04-14T20:06:47.210Z",
          "folderName": "NOM-FACT-2026-04-13_15-28-56"
        },
        "eWxSYzlRRDhpVVpJUElIdTRIbnF3YTB2WHVnYjR0T2I5VzdjMU1sT2xZbz0": {
          "action": "approve",
          "atMs": 1776199402828,
          "atIso": "2026-04-14T20:43:22.828Z",
          "folderName": "NOM-FACT-2026-04-14_16-29-17"
        },
        "OWhpNmRJdkJTMjJVVFZIWEpXWVFoczZ2UWNzbVlRZVJSVWd0Vm4wcmtTVT0": {
          "action": "approve",
          "atMs": 1776201010160,
          "atIso": "2026-04-14T21:10:10.160Z",
          "folderName": "NOM-FACT-2026-04-14_16-29-17"
        },
        "SkFsSTEvQXo0K0NIZEgyb3p3K2t3ODEzRUUyeGxrcDA2S0wvb3o2OU9Sdz0": {
          "action": "approve",
          "atMs": 1776268016312,
          "atIso": "2026-04-15T15:46:56.312Z",
          "folderName": "NOM-FACT-2026-04-14_13-38-17"
        },
        "OERjenVOMzEyMlZqdGZnTlJ6blM3RnU2OSs2SzZjRmRYVFlzQUZ3MUNyaz0": {
          "action": "reject",
          "atMs": 1776269098247,
          "atIso": "2026-04-15T16:04:58.247Z",
          "folderName": "NOM-FACT-2026-04-15_11-55-17"
        },
        "dWMzOG9LZ3dUa21MU24zQnAxNURadXpUSkZ5bnVoWXNTeW5WTis3bUlXST0": {
          "action": "approve",
          "atMs": 1776269277448,
          "atIso": "2026-04-15T16:07:57.448Z",
          "folderName": "NOM-FACT-2026-04-15_11-58-17"
        },
        "QzBsU2d0Nnp4dkQyODRvcHUrdjc3VjlKR2NSU09vU0tmejZ2UkhvYUtoST0": {
          "action": "approve",
          "atMs": 1776274228658,
          "atIso": "2026-04-15T17:30:28.658Z",
          "folderName": "NOM-FACT-2026-04-15_11-58-17"
        },
        "b0dWYWwxdWpZeGc0SmFoRVhaNmpSQ0p0akExSlVQMEpWVUliQTFpNVN1az0": {
          "action": "approve",
          "atMs": 1776292499997,
          "atIso": "2026-04-15T22:34:59.997Z",
          "folderName": "NOM-FACT-2026-04-15_15-58-17"
        },
        "dzFoQkk1bXIwelZOVldSaTNyZnlQU0g1SnlLTG9MNVc0eTdjeVp4ZVhlZz0": {
          "action": "approve",
          "atMs": 1776292564238,
          "atIso": "2026-04-15T22:36:04.238Z",
          "folderName": "NOM-FACT-2026-04-15_16-00-23"
        },
        "UHR4dVI1djljTS93bkcvQWcvdDRtbzZnc1VYS01Ubk0rMVV0MitMU2FEdz0": {
          "action": "approve",
          "atMs": 1776292636328,
          "atIso": "2026-04-15T22:37:16.328Z",
          "folderName": "NOM-FACT-2026-04-15_16-02-17"
        },
        "bWFVSzZzZnNjQm1WaFc5eEdZQzVPNG1MVjArUlB0SXZsa2FMZ1BhaXJYbz0": {
          "action": "approve",
          "atMs": 1776292739026,
          "atIso": "2026-04-15T22:38:59.026Z",
          "folderName": "NOM-OC-2026-04-15_16-04-39"
        },
        "bm5hNWR1TGVWQWk2b2FNYytyT0Q4MXIrMzYwVHUzSG1LbG1KVU1ONExwWT0": {
          "action": "approve",
          "atMs": 1776292814673,
          "atIso": "2026-04-15T22:40:14.673Z",
          "folderName": "NOM-FACT-2026-04-15_16-40-18"
        },
        "SFBma1dHamx6QlZsQXN2UHhpTDlRUGttZUp2UzNOaFZ4QTNHL2RNWnBlOD0": {
          "action": "approve",
          "atMs": 1776292874303,
          "atIso": "2026-04-15T22:41:14.303Z",
          "folderName": "NOM-FACT-2026-04-15_17-54-18"
        },
        "SlpmNkZKdGFpdHR0QkZmZFdOR1g0SzFpT0RxZENKbHhzUVcwUnhvendWdz0": {
          "action": "approve",
          "atMs": 1776292944455,
          "atIso": "2026-04-15T22:42:24.455Z",
          "folderName": "NOM-FACT-2026-04-15_18-05-17"
        },
        "U0l1TlNhNDQ2QlROK0dsYVM4NnZmSjFiaTkra0h0dnlMSTRHUjNVTGFoWT0": {
          "action": "approve",
          "atMs": 1776293041395,
          "atIso": "2026-04-15T22:44:01.395Z",
          "folderName": "NOM-FACT-2026-04-15_18-39-23"
        },
        "OXFQMnhOUzlMV29nc1YwanhlSUtqaGxFTzJxYytXbFhFTlhXaTZ4dXJCYz0": {
          "action": "approve",
          "atMs": 1776343894437,
          "atIso": "2026-04-16T12:51:34.437Z",
          "folderName": "NOM-FACT-2026-04-15_15-58-17"
        },
        "eHRreXRzQTlCQng3YVZXRUcrZm9YaGsranRQTlVUSVo4ZXB4RkloQmd5UT0": {
          "action": "approve",
          "atMs": 1776343950490,
          "atIso": "2026-04-16T12:52:30.490Z",
          "folderName": "NOM-FACT-2026-04-15_16-00-23"
        },
        "TnVFcjJhRlVoZDJvZG9vWUV5M1lMUHFYNlVKMnFqbmJGZEtGT0VkK3U3QT0": {
          "action": "approve",
          "atMs": 1776344021661,
          "atIso": "2026-04-16T12:53:41.661Z",
          "folderName": "NOM-FACT-2026-04-15_16-02-17"
        },
        "UjBRa0txbENibnRJMm14bG8xWXBLckM3VGVQemt1Si9CRVoyYTFNR2Fqaz0": {
          "action": "approve",
          "atMs": 1776344078291,
          "atIso": "2026-04-16T12:54:38.291Z",
          "folderName": "NOM-OC-2026-04-15_16-04-39"
        },
        "UFluVnFsbk1sSjlyTDd1TDhIQTBnelJ4ZUxPNHdENHdHYnBHbUxPWUJkdz0": {
          "action": "approve",
          "atMs": 1776347540016,
          "atIso": "2026-04-16T13:52:20.016Z",
          "folderName": "NOM-FACT-2026-04-15_16-40-18"
        },
        "K3ltNVd4MUlJOVczdVF5enhrd2Q4RzBVZWhjVUFrUy9vYlRXR0lSeXdyZz0": {
          "action": "approve",
          "atMs": 1776349248579,
          "atIso": "2026-04-16T14:20:48.579Z",
          "folderName": "NOM-FACT-2026-04-15_18-53-18"
        },
        "REpzR1htTUxGSmRFNG0yTUhJeVYvWVV6UXlBRk5QN3c4L25iSGEvbklJWT0": {
          "action": "approve",
          "atMs": 1776354111016,
          "atIso": "2026-04-16T15:41:51.016Z",
          "folderName": "NOM-FACT-2026-04-16_11-17-17"
        },
        "TDRHNXl5a2VZeDJ3RFc4WFd5YlFDVnprWnByU2NVcnh1Y0pZZ1dUdmUydz0": {
          "action": "reject",
          "atMs": 1776354870197,
          "atIso": "2026-04-16T15:54:30.197Z",
          "folderName": "NOM-FACT-2026-04-16_11-37-17"
        },
        "ZjBUYys4bG5weW5aRkRHTDBScEtMTzN2M2kvd0lIdVZEb3R0QWk4eWRtWT0": {
          "action": "approve",
          "atMs": 1776356949775,
          "atIso": "2026-04-16T16:29:09.775Z",
          "folderName": "NOM-FACT-2026-04-16_11-58-18"
        },
        "NXRLSlczcGI3SHRQZ3JGZEZVSE83aWdPZ0w5VGd6WlRyTjBaaTJmM2V6UT0": {
          "action": "approve",
          "atMs": 1776358992066,
          "atIso": "2026-04-16T17:03:12.066Z",
          "folderName": "NOM-FACT-2026-04-15_17-54-18"
        },
        "d1lEWkpkRGhVM1NzaHlIZHcrZFZnMGQ2MUx0UEtDNWlucnJDVnNQUklPQT0": {
          "action": "approve",
          "atMs": 1776359048813,
          "atIso": "2026-04-16T17:04:08.813Z",
          "folderName": "NOM-FACT-2026-04-15_18-05-17"
        },
        "eWNmcVVsdjVCKzVscWRHVEh2NDYzNENNSE5uenhpUmtxcElQZEIrWGpCVT0": {
          "action": "approve",
          "atMs": 1776359113752,
          "atIso": "2026-04-16T17:05:13.752Z",
          "folderName": "NOM-FACT-2026-04-15_18-39-23"
        },
        "R01rMXFIR1FIV1B1ZTVyNk5TNWJUU3J0WmcwdUFCaXdiSHB5U0ZFK3JWRT0": {
          "action": "approve",
          "atMs": 1776359162498,
          "atIso": "2026-04-16T17:06:02.498Z",
          "folderName": "NOM-FACT-2026-04-15_18-53-18"
        },
        "R2dDUUZrbnNZb2hROEZ3SWV0d2c2N3lhQWtSaDNTZkR1b0VDUTJabHdXRT0": {
          "action": "approve",
          "atMs": 1776359222104,
          "atIso": "2026-04-16T17:07:02.104Z",
          "folderName": "NOM-FACT-2026-04-16_11-17-17"
        },
        "enp5RnpPZ0xJaTlTbU5rclpLVk5BYjZ0VGFSMnlPVndIbE83aUJyOEg5Zz0": {
          "action": "approve",
          "atMs": 1776359382590,
          "atIso": "2026-04-16T17:09:42.590Z",
          "folderName": "NOM-FACT-2026-04-16_11-58-18"
        },
        "N2s4U2RQcHFSclZUTitLOU14VjFDWHdzUG1kWjMzT1IxbnNmdkZTRlo5OD0": {
          "action": "approve",
          "atMs": 1776362266641,
          "atIso": "2026-04-16T17:57:46.641Z",
          "folderName": "NOM-OC-2026-04-16_13-53-00"
        },
        "MW56b3J5em13UXFJbHg0c0xZYTNlcklLdEJvazFaKzBwbDlBcE9Hb0c1Zz0": {
          "action": "approve",
          "atMs": 1776366721145,
          "atIso": "2026-04-16T19:12:01.145Z",
          "folderName": "NOM-OC-2026-04-16_13-53-00"
        },
        "VExlWEFpdXdlcXBwUitpUTJhK3Y5WVZMQnc1MU9xcnJ4NzRTU29vUUViRT0": {
          "action": "reject",
          "atMs": 1776367620826,
          "atIso": "2026-04-16T19:27:00.826Z",
          "folderName": "NOM-FACT-2026-04-16_15-23-18"
        },
        "Q0VjRmVUM1UyL05PNmU2TDNvbjBnNkRsQkdxYjlvOG5QM1g5RU80ZkJYQT0": {
          "action": "approve",
          "atMs": 1776368170653,
          "atIso": "2026-04-16T19:36:10.653Z",
          "folderName": "NOM-FACT-2026-04-16_15-30-17"
        },
        "YzZ1QldCYnJyc2ZBcnRRb2NWQ3F0Zys1Y1ZjeEo1cjNBcmQ3K2gvaTREUT0": {
          "action": "approve",
          "atMs": 1776369793331,
          "atIso": "2026-04-16T20:03:13.331Z",
          "folderName": "NOM-FACT-2026-04-16_15-30-17"
        },
        "bmtXeGJ1RmhxMjBMZDM0L1cyaEp3WExsbUQ0ZWJnRWJ5ZFVUZGs1cnQ5cz0": {
          "action": "approve",
          "atMs": 1776441386994,
          "atIso": "2026-04-17T15:56:26.994Z",
          "folderName": "NOM-OC-2026-04-17_11-31-40"
        },
        "dFNxKzlkZlhPRW53OHRXZU5OODdJR2FybmVXN2Z6eE1UWDI2a0JKT3UwQT0": {
          "action": "approve",
          "atMs": 1776441428515,
          "atIso": "2026-04-17T15:57:08.515Z",
          "folderName": "NOM-FACT-2026-04-17_11-38-17"
        },
        "eXZUZVpFNEhRTTFlSW1pUTA3SjNqVXFUYmRGMnJEWTNlZjRiQXJVUUh6VT0": {
          "action": "approve",
          "atMs": 1776442223239,
          "atIso": "2026-04-17T16:10:23.239Z",
          "folderName": "NOM-FACT-2026-04-17_12-01-24"
        },
        "NFJkWVBYcStpeHU5NzY5a1M4SVEzUnRkTTRVMWpaY21kMzZtK1ZIQmJnND0": {
          "action": "approve",
          "atMs": 1776450333856,
          "atIso": "2026-04-17T18:25:33.856Z",
          "folderName": "NOM-OC-2026-04-17_11-31-40"
        },
        "M1ZubGhwZ2VIb0ZwYnRhZEI1cDVXVlpqNEoxUlVpT1NwbGhKbHJUaFVDbz0": {
          "action": "reject",
          "atMs": 1776451037797,
          "atIso": "2026-04-17T18:37:17.797Z",
          "folderName": "NOM-FACT-2026-04-17_11-38-17"
        },
        "cXVnU29FS2VUMitEWldQbnpyOWxMU0pONHVKcStnSmhjbE5xem5JaDVoQT0": {
          "action": "approve",
          "atMs": 1776451059613,
          "atIso": "2026-04-17T18:37:39.613Z",
          "folderName": "NOM-FACT-2026-04-17_12-01-24"
        },
        "M0xxZ0diVEdlNmNwSjlHR0Vsa2JCeHZING5EazN5SmFVa3l4RW5UUlM3bz0": {
          "action": "approve",
          "atMs": 1776719977499,
          "atIso": "2026-04-20T21:19:37.499Z",
          "folderName": "NOM-FACT-2026-04-20_16-12-25"
        },
        "N1BUSXVpSE9Rem5LSlZnMlhTckZxb1RSSzBPSndTSHlmeDZHMzc2K1ZZTT0": {
          "action": "reject",
          "atMs": 1776720052006,
          "atIso": "2026-04-20T21:20:52.006Z",
          "folderName": "NOM-FACT-2026-04-20_16-24-34"
        },
        "aDR6Ulo1SFZneC9DUTRRV0tqcXBTaU1Rdk1QVWVpOTlMaUlMQTFLUDFHND0": {
          "action": "approve",
          "atMs": 1776720228706,
          "atIso": "2026-04-20T21:23:48.706Z",
          "folderName": "NOM-FACT-2026-04-20_16-24-34"
        },
        "clo1MlRGNFpVNkpieVc2TStDUUdSYnEwTi96VDUwK3Q2dWhvbjJkSjhJaz0": {
          "action": "approve",
          "atMs": 1776722917135,
          "atIso": "2026-04-20T22:08:37.135Z",
          "folderName": "NOM-FACT-2026-04-20_16-43-18"
        },
        "NGV2T2M0N2ZVSGlZbGk1Y1lMRm50NmMzd01EZ1EwTUhYTHRQY0xqbjNaUT0": {
          "action": "approve",
          "atMs": 1776722983891,
          "atIso": "2026-04-20T22:09:43.891Z",
          "folderName": "NOM-FACT-2026-04-20_16-53-18"
        },
        "VTB5SWtXWFliVEcvMFZkZWd2WW1LcERqemVvV3hkL0xpVGJXYXVSSmFZUT0": {
          "action": "approve",
          "atMs": 1776725908077,
          "atIso": "2026-04-20T22:58:28.077Z",
          "folderName": "NOM-FACT-2026-04-20_16-24-34"
        },
        "OCtBWS9BNVZYT1h1alJMZVVQT0s0UVZiVk1xUllaclhoMEgwSXhtVTFqRT0": {
          "action": "approve",
          "atMs": 1776726004761,
          "atIso": "2026-04-20T23:00:04.761Z",
          "folderName": "NOM-FACT-2026-04-20_16-43-18"
        },
        "cGs3V092M0xZUkYvaElZbWx0NUxhVGJSdS9LUGdUL3VZN3pmTU1LMy9BYz0": {
          "action": "approve",
          "atMs": 1776726197767,
          "atIso": "2026-04-20T23:03:17.767Z",
          "folderName": "NOM-FACT-2026-04-20_16-53-18"
        },
        "M0dINTFreENHdWdZRUNCZzZoWUZ2UTJ6VFdCbk9TYUMvMVAyR2VWbmZmST0": {
          "action": "approve",
          "atMs": 1776732979676,
          "atIso": "2026-04-21T00:56:19.676Z",
          "folderName": "NOM-FACT-2026-04-20_17-00-23"
        },
        "Z21kSFRMZm8reWl0ZUorMFhldGMwT3hydThUa25tYjdUc1dOc2c2MEhEND0": {
          "action": "approve",
          "atMs": 1776733059904,
          "atIso": "2026-04-21T00:57:39.904Z",
          "folderName": "NOM-FACT-2026-04-20_17-08-28"
        },
        "aTFqenNYZFY5cHFFMERPVVFyMnVxSE0veHE0SDUzczM0WlZ4K2ptZ1loUT0": {
          "action": "approve",
          "atMs": 1776774020321,
          "atIso": "2026-04-21T12:20:20.321Z",
          "folderName": "NOM-FACT-2026-04-20_17-00-23"
        },
        "aEdhOURLV0hXOEFVTHlPZ1NLUlo5bThBT1BMaVcvaEZWaWtYNFBqUU9JND0": {
          "action": "approve",
          "atMs": 1776774035699,
          "atIso": "2026-04-21T12:20:35.699Z",
          "folderName": "NOM-FACT-2026-04-20_16-12-25"
        },
        "dyt1TDdlR1h3T0EyZjJocWczQjJjRDlXSHNIRm9CbnZZNzdKUk5PNFF2OD0": {
          "action": "approve",
          "atMs": 1776774131282,
          "atIso": "2026-04-21T12:22:11.282Z",
          "folderName": "NOM-FACT-2026-04-20_17-08-28"
        },
        "dnUvcU9MSlkwQjZzakxyYy80UVdxeHVSUUlTN091d2Z5VXkvVmFqMzNFOD0": {
          "action": "approve",
          "atMs": 1776779336893,
          "atIso": "2026-04-21T13:48:56.893Z",
          "folderName": "NOM-FACT-2026-04-21_08-51-41"
        },
        "UDVUQjlEOUZSWmxzSm54a3ZKdXo4RTVQbjdQYU9PdzZLa2ZVWWJ3NWNUUT0": {
          "action": "approve",
          "atMs": 1776780566096,
          "atIso": "2026-04-21T14:09:26.096Z",
          "folderName": "NOM-FACT-2026-04-21_09-20-23"
        },
        "RG83OTNBdzVTRHhHdC9oRGF4bnVETDZaMTZodGRTZXc2V1JtNnpjT1Rsdz0": {
          "action": "approve",
          "atMs": 1776780727294,
          "atIso": "2026-04-21T14:12:07.294Z",
          "folderName": "NOM-FACT-2026-04-21_08-51-41"
        },
        "dkQwMDRsRlNrUHJzQkE1VEdOeFhiUTJRZlhEOXBuSG1RVkxQR3kxYkFCZz0": {
          "action": "approve",
          "atMs": 1776780834892,
          "atIso": "2026-04-21T14:13:54.892Z",
          "folderName": "NOM-FACT-2026-04-21_09-20-23"
        },
        "VlNhY2Q2dTMrZmZweGRXbmlEaHN5THl3ckppY2EvRnA0SGFrd3hsWFNhTT0": {
          "action": "approve",
          "atMs": 1776781138838,
          "atIso": "2026-04-21T14:18:58.838Z",
          "folderName": "NOM-FACT-2026-04-21_09-07-17"
        },
        "QmRZVHA4dmVIRlJGSGRyMnJFUEl3SDBXRHhhc2FyRmx6L21nbGU2TTU0QT0": {
          "action": "approve",
          "atMs": 1776783027786,
          "atIso": "2026-04-21T14:50:27.786Z",
          "folderName": "NOM-FACT-2026-04-21_10-45-17"
        },
        "VHpmTTlLajBVMnFSTWJIb0ZoaERkQ0dSZmFJL213MTNDeVVaRldUSU91ST0": {
          "action": "approve",
          "atMs": 1776783246381,
          "atIso": "2026-04-21T14:54:06.381Z",
          "folderName": "NOM-FACT-2026-04-21_09-07-17"
        },
        "K1hRcEFSdjJtZG5wNkJHcXlCOWUzSXpJMGkxRWtINTgwQldTeXh6cXJXcz0": {
          "action": "approve",
          "atMs": 1776783331676,
          "atIso": "2026-04-21T14:55:31.676Z",
          "folderName": "NOM-FACT-2026-04-21_10-45-17"
        }
      }
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "pinData": {},
  "versionId": "3954e92f-942a-4d31-b5ae-8564e71ef2bb",
  "activeVersionId": "3954e92f-942a-4d31-b5ae-8564e71ef2bb",
  "versionCounter": 151,
  "triggerCount": 4,
  "tags": [],
  "shared": [
    {
      "updatedAt": "2026-04-09T15:53:48.935Z",
      "createdAt": "2026-04-09T15:53:48.935Z",
      "role": "workflow:owner",
      "workflowId": "DJatA0c5L7e4De5p",
      "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
  }
}