{
  "nodes": [
    {
      "parameters": {
        "url": "https://cluster.dentalautomation.ai/v2/iv/transactions/getByPatient",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "clientId",
              "value": "60198b19bb70666ce6a6a37c"
            },
            {
              "name": "practiceld",
              "value": "6019946277c6020112360b92"
            },
            {
              "name": "appointmentDateStart",
              "value": "2025-01-01"
            },
            {
              "name": "appointmentDateEnd",
              "value": "2025-01-02"
            }
          ]
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "apiKey",
              "value": "dcy1cbUi4lbbmUT9JQ7PFtRju4xY3w4g"
            }
          ]
        },
        "options": {}
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.3,
      "position": [
        -32,
        32
      ],
      "id": "13e351cc-6499-4fcd-80b1-94c9b4cdeca7",
      "name": "HTTP Request1",
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "fieldToSplitOut": "data",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        176,
        32
      ],
      "id": "38923b27-88db-4658-870f-4bb5ea477600",
      "name": "Split Out"
    },
    {
      "parameters": {
        "jsCode": "const crypto = require('crypto');\n\n// 1. Configuraci\u00f3n (Usa tu variable de entorno)\n// Aseg\u00farate de que $env.ENCRYPTION_KEY tenga 32 caracteres para AES-256\nconst algorithm = 'aes-256-cbc';\nconst key = $env.ENCRYPTION_KEY; \nconst ivLength = 16; // AES standard\n\n// Iteramos sobre cada paciente (item)\nreturn items.map(item => {\n  const data = item.json;\n  \n  // A. Generar HASH (Huella digital para b\u00fasquedas)\n  // Usamos SHA-256 nativo\n  const hash = crypto.createHash('sha256').update(JSON.stringify(data)).digest('hex');\n\n  // B. ENCRIPTAR (La B\u00f3veda)\n  const iv = crypto.randomBytes(ivLength);\n  // Agregamos 'hex' como segundo par\u00e1metro\nconst cipher = crypto.createCipheriv(algorithm, Buffer.from(key, 'hex'), iv);\n  \n  let encrypted = cipher.update(JSON.stringify(data), 'utf8', 'hex');\n  encrypted += cipher.final('hex');\n  \n  // Guardamos el IV junto con la data (necesario para desencriptar)\n  // Formato: IV:DATA\n  const encryptedPayload = iv.toString('hex') + ':' + encrypted;\n\n  // C. Retornar el objeto listo para MySQL\n  return {\n    json: {\n      payload_hash: hash,\n      encrypted_payload: encryptedPayload,\n      original_data_preview: data._id // Opcional, solo para que veas cu\u00e1l es\n    }\n  };\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        384,
        32
      ],
      "id": "43e90f1d-f14b-4869-ab7f-ff999f6632ee",
      "name": "Code in JavaScript"
    },
    {
      "parameters": {
        "table": {
          "__rl": true,
          "value": "raw_api_ingest",
          "mode": "list",
          "cachedResultName": "raw_api_ingest"
        },
        "dataMode": "defineBelow",
        "valuesToSend": {
          "values": [
            {
              "column": "payload_hash",
              "value": "={{ $json.payload_hash }}"
            },
            {
              "column": "raw_payload",
              "value": "={{ $json.encrypted_payload }}"
            },
            {
              "column": "is_processed",
              "value": "0"
            },
            {
              "column": "endpoint_source",
              "value": "API_DENTAL"
            }
          ]
        },
        "options": {
          "skipOnConflict": true
        }
      },
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.5,
      "position": [
        592,
        32
      ],
      "id": "0c9a2d16-fb1f-4a6c-801d-eecf740e8eed",
      "name": "Insert rows in a table",
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const crypto = require('crypto');\nconst algorithm = 'aes-256-cbc';\nconst key = $env.ENCRYPTION_KEY;\n\nreturn items.map(item => {\n  // 1. Intentamos tomar la data encriptada. \n  // OJO: Como venimos del nodo MySQL, a veces la data original viaja en 'json.raw_payload' \n  // o 'json.encrypted_payload' dependiendo de si el nodo anterior pas\u00f3 la entrada.\n  const encryptedText = item.json.raw_payload || item.json.encrypted_payload; \n\n  if (!encryptedText || !encryptedText.includes(':')) {\n    return { \n      json: { \n        ERROR: \"No se recibi\u00f3 la data encriptada del nodo anterior.\",\n        HINT: \"Aseg\u00farate de que el nodo MySQL tenga activada la opci\u00f3n 'Pass Through' o conecta este nodo directo al de encriptaci\u00f3n.\"\n      } \n    };\n  }\n\n  try {\n    // 2. Proceso de Desencriptado (El mismo de siempre)\n    const textParts = encryptedText.split(':');\n    const iv = Buffer.from(textParts.shift(), 'hex');\n    const encryptedData = textParts.join(':');\n\n    const decipher = crypto.createDecipheriv(algorithm, Buffer.from(key), iv);\n    let decrypted = decipher.update(encryptedData, 'hex', 'utf8');\n    decrypted += decipher.final('utf8');\n\n    // 3. RESULTADO PARA EL JEFE\n    return {\n      json: {\n        \"TEST_RESULT\": \"\u2705 PRUEBA EXITOSA\",\n        \"1_LO_QUE_HAY_EN_DB\": encryptedText.substring(0, 30) + \"...\", // Mostramos solo un pedacito de la basura\n        \"2_LO_QUE_VE_EL_BOT\": JSON.parse(decrypted) // El paciente recuperado\n      }\n    };\n  } catch (error) {\n    return { json: { STATUS: \"FALL\u00d3\", error: error.message } };\n  }\n});"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1104,
        96
      ],
      "id": "c6e83f0a-f663-4590-80e3-1b679259f353",
      "name": "Code in JavaScript1"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT raw_payload FROM raw_api_ingest ORDER BY ingest_id DESC LIMIT 1;",
        "options": {}
      },
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.5,
      "position": [
        800,
        32
      ],
      "id": "eeb4c3d8-6d65-4462-b48c-48fe3d580b91",
      "name": "Execute a SQL query",
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "rule": {
          "interval": [
            {
              "field": "hours",
              "triggerAtMinute": 1
            }
          ]
        }
      },
      "type": "n8n-nodes-base.scheduleTrigger",
      "typeVersion": 1.3,
      "position": [
        -352,
        320
      ],
      "id": "1e77ecb8-213e-4391-a083-347df124d1b2",
      "name": "Schedule Trigger"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "START TRANSACTION;\n\n-- 1. COPIAR (Con protecci\u00f3n anti-duplicados)\n-- Usamos INSERT IGNORE: Si el hash ya existe en el archivo, \n-- simplemente no lo copia y sigue adelante sin dar error.\nINSERT IGNORE INTO raw_api_ingest_archive (\n    endpoint_source, \n    raw_payload, \n    payload_hash, \n    ingested_at, \n    is_processed\n)\nSELECT \n    endpoint_source, \n    raw_payload, \n    payload_hash, \n    ingested_at, \n    is_processed\nFROM raw_api_ingest\nWHERE ingested_at < NOW() - INTERVAL 5 MINUTE; \n-- (Recuerda cambiar '0 MINUTE' por '7 DAY' cuando pases a producci\u00f3n)\n\n-- 2. BORRAR (Limpiar la mesa)\n-- Borramos de la ingesta todo lo que ya cumpli\u00f3 el tiempo.\n-- No importa si se copi\u00f3 o si se ignor\u00f3 (porque ya exist\u00eda),\n-- el objetivo es que salga de la tabla principal.\nDELETE FROM raw_api_ingest\nWHERE ingested_at < NOW() - INTERVAL 5 MINUTE;\n\nCOMMIT;",
        "options": {}
      },
      "type": "n8n-nodes-base.mySql",
      "typeVersion": 2.5,
      "position": [
        32,
        448
      ],
      "id": "ebbaadab-6870-4520-b6ea-11e231729aaf",
      "name": "Vault Archiving",
      "credentials": {
        "mySql": {
          "name": "<your credential>"
        }
      }
    }
  ],
  "connections": {
    "HTTP Request1": {
      "main": [
        [
          {
            "node": "Split Out",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Split Out": {
      "main": [
        [
          {
            "node": "Code in JavaScript",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code in JavaScript": {
      "main": [
        [
          {
            "node": "Insert rows in a table",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Insert rows in a table": {
      "main": [
        [
          {
            "node": "Execute a SQL query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute a SQL query": {
      "main": [
        [
          {
            "node": "Code in JavaScript1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Trigger": {
      "main": [
        [
          {
            "node": "Vault Archiving",
            "type": "main",
            "index": 0
          },
          {
            "node": "HTTP Request1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "meta": {
    "templateCredsSetupCompleted": true
  }
}