{
  "elementsLearnedData": [],
  "elementsTestData": [
    {
      "data": [
        {
          "rowNumber": 2,
          "rowData": {
            "ID": "M001",
            "Data": "2026-09-20",
            "Tipo": "Venda",
            "Entidade": "Cliente Silva",
            "Nº Fatura": "FT 2026/101",
            "Descrição": "Remodelação cozinha",
            "Valor": "4500.00",
            "Estado": "Pago",
            "Data Pagamento": "2026-10-03",
            "Ref. Banco": "BNK-1001"
          }
        },
        {
          "rowNumber": 3,
          "rowData": {
            "ID": "M002",
            "Data": "2026-10-01",
            "Tipo": "Custo",
            "Entidade": "Leroy Merlin",
            "Nº Fatura": "FC LM-88231",
            "Descrição": "Materiais",
            "Valor": "-1234.56",
            "Estado": "Pago",
            "Data Pagamento": "2026-10-04",
            "Ref. Banco": "BNK-1002"
          }
        },
        {
          "rowNumber": 4,
          "rowData": {
            "ID": "M003",
            "Data": "2026-10-01",
            "Tipo": "Custo",
            "Entidade": "EDP Comercial",
            "Nº Fatura": "FC EDP-5521",
            "Descrição": "Eletricidade",
            "Valor": "-187.40",
            "Estado": "Pago",
            "Data Pagamento": "2026-10-05",
            "Ref. Banco": "BNK-1003"
          }
        },
        {
          "rowNumber": 5,
          "rowData": {
            "ID": "M004",
            "Data": "2026-10-02",
            "Tipo": "Custo",
            "Entidade": "Canalizações Lda",
            "Nº Fatura": "FC CL-0412",
            "Descrição": "Subempreitada canalização",
            "Valor": "-850.00",
            "Estado": "Pendente"
          }
        },
        {
          "rowNumber": 6,
          "rowData": {
            "ID": "M005",
            "Data": "2026-10-03",
            "Tipo": "Custo",
            "Entidade": "Pinturas Norte",
            "Nº Fatura": "FC PN-0077",
            "Descrição": "Subempreitada pintura",
            "Valor": "-850.00",
            "Estado": "Pendente"
          }
        },
        {
          "rowNumber": 7,
          "rowData": {
            "ID": "M006",
            "Data": "2026-10-05",
            "Tipo": "Venda",
            "Entidade": "Cliente Costa",
            "Nº Fatura": "FT 2026/102",
            "Descrição": "Casa de banho",
            "Valor": "2300.00",
            "Estado": "Pago",
            "Data Pagamento": "2026-10-08",
            "Ref. Banco": "BNK-1005"
          }
        },
        {
          "rowNumber": 8,
          "rowData": {
            "ID": "M007",
            "Data": "2026-09-10",
            "Tipo": "Custo",
            "Entidade": "Fidelidade Seguros",
            "Nº Fatura": "FC SF-2026-09",
            "Descrição": "Seguro obra",
            "Valor": "-95.00",
            "Estado": "Pago",
            "Data Pagamento": "2026-09-12",
            "Ref. Banco": "BNK-0931"
          }
        },
        {
          "rowNumber": 9,
          "rowData": {
            "ID": "M008",
            "Data": "2026-10-06",
            "Tipo": "Venda",
            "Entidade": "Cliente Ferreira",
            "Nº Fatura": "FT 2026/103",
            "Descrição": "Pintura exterior",
            "Valor": "1800.00",
            "Estado": "Pendente"
          }
        }
      ],
      "elementId": "0361B131-6AAA-4864-9281-06CF5D1CF75A"
    },
    {
      "data": [
        {
          "Key": "2026-10-03|4500.00|BNK-1001",
          "Date": "2026-10-03",
          "Description": "TRF RECEBIDA SILVA FT 2026/101",
          "Amount": "4500",
          "Bank Ref": "BNK-1001",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "matched (invoice number)",
          "Movimentos ID": "M001",
          "Imported At": "2026-10-16T16:55:08.866Z"
        },
        {
          "Key": "2026-10-04|-1234.56|BNK-1002",
          "Date": "2026-10-04",
          "Description": "PAG LEROY MERLIN",
          "Amount": "-1234.56",
          "Bank Ref": "BNK-1002",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "matched (amount and date)",
          "Movimentos ID": "M002",
          "Imported At": "2026-10-16T16:55:08.866Z"
        },
        {
          "Key": "2026-10-05|-187.40|BNK-1003",
          "Date": "2026-10-05",
          "Description": "DD EDP COMERCIAL",
          "Amount": "-187.4",
          "Bank Ref": "BNK-1003",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "matched (amount and date)",
          "Movimentos ID": "M003",
          "Imported At": "2026-10-16T16:55:08.866Z"
        },
        {
          "Key": "2026-10-06|-850.00|BNK-1004",
          "Date": "2026-10-06",
          "Description": "TRF SUBEMPREITADA",
          "Amount": "-850",
          "Bank Ref": "BNK-1004",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "sent to review",
          "Movimentos ID": "",
          "Imported At": "2026-10-16T16:55:08.866Z"
        },
        {
          "Key": "2026-10-08|2300.00|BNK-1005",
          "Date": "2026-10-08",
          "Description": "TRF RECEBIDA COSTA FT 2026/102",
          "Amount": "2300",
          "Bank Ref": "BNK-1005",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "matched (invoice number)",
          "Movimentos ID": "M006",
          "Imported At": "2026-10-16T16:55:08.866Z"
        },
        {
          "Key": "2026-10-09|-12.50|BNK-1006",
          "Date": "2026-10-09",
          "Description": "COMISSAO MANUTENCAO CONTA",
          "Amount": "-12.5",
          "Bank Ref": "BNK-1006",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "sent to review",
          "Movimentos ID": "",
          "Imported At": "2026-10-16T16:55:08.866Z"
        },
        {
          "Key": "2026-10-10|1000.00|BNK-1007",
          "Date": "2026-10-10",
          "Description": "TRF RECEBIDA FERREIRA FT 2026/103",
          "Amount": "1000",
          "Bank Ref": "BNK-1007",
          "File": "Extrato_2026-10_v3.xlsx",
          "Status": "sent to review",
          "Movimentos ID": "",
          "Imported At": "2026-10-16T16:55:08.866Z"
        }
      ],
      "elementId": "14ECFE2F-F714-4CEB-921D-C16FFA10AFE6"
    }
  ],
  "flow": {
    "id": "1826C726-F40A-44B1-8E5A-E52D51BAFD85",
    "name": "Bank Statement Reconciliation"
  },
  "flowVersion": {
    "clientMetadata": {
      "viewport": {
        "x": 223,
        "y": 209,
        "zoom": 1
      },
      "autoSave": true,
      "descriptions": {
        "flow": "",
        "initialData": "",
        "initialDataFields": {}
      }
    },
    "description": "",
    "elements": [
      {
        "clientMetadata": {
          "notes": "Retrieves data from Google Sheets for AI agents to analyze spreadsheet content, process existing data, or extract information for automated workflows. Perfect for reading user submissions, analyzing data trends, or importing data for further processing.",
          "elementId": "EXTENSION:::SHARED:::default:::google-sheets:::getRows",
          "isFirstElement": false,
          "dynamicOptionLabels": {},
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Get Bank Import Log Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::google-sheets:::getRows",
          "legacyElementId": "JS###v1###GoogleSheets###getRows",
          "methodName": "getRows",
          "position": {
            "x": 870,
            "y": 0
          }
        },
        "flowElementId": "AC25A7F8-4EBB-4D31-9C51-FFE73BECD5B0",
        "groupId": null,
        "id": "14ECFE2F-F714-4CEB-921D-C16FFA10AFE6",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "documentId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": null
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "sheetId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "NUMBER",
                    "label": null,
                    "type": "INPUT",
                    "value": 1590050248
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "offset",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "INT"
              }
            },
            {
              "name": "limit",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "INT"
              }
            },
            {
              "name": "withRowNumbers",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "K_FALSE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": false
                  }
                ],
                "mode": "BASIC",
                "parseJsonString": false,
                "resultType": "BOOLEAN"
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "getRows",
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "importLog",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "google-sheets",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Get Bank Import Log",
        "nextElementIds": [
          "0361B131-6AAA-4864-9281-06CF5D1CF75A"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "notes": "Downloads a file from Google Drive and saves it to the Files.",
          "elementId": "EXTENSION:::SHARED:::default:::google-drive-api:::downloadFile",
          "isFirstElement": false,
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Download Statement Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::google-drive-api:::downloadFile",
          "legacyElementId": "JS###v1###GoogleDrive###downloadFile",
          "methodName": "downloadFile",
          "position": {
            "x": 290,
            "y": 0
          }
        },
        "flowElementId": "476863E7-23A2-4C30-9EA5-28B4FFD6A6DF",
        "groupId": null,
        "id": "B0E937E1-B464-4A0B-8DB5-D0748F066CB5",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "fileId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "RESULT",
                    "label": "trigger",
                    "subPathSegments": [
                      {
                        "key": "id",
                        "optional": false
                      }
                    ],
                    "type": "TRIGGER_DATA",
                    "value": "CD4F15BF-2638-4C90-94EF-646B87D0553F"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "targetDirectory",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": "/bank-statements"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "downloadFile",
          "onFailElemId": "031ED7A1-CBF2-47E1-9D40-ED02DE0BD521",
          "packageId": "default",
          "resultAlias": "download",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "google-drive-api",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Download Statement",
        "nextElementIds": [
          "09801A48-CE0F-489C-8AD2-C200BC18F8E4"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "notes": "Retrieves data from Google Sheets for AI agents to analyze spreadsheet content, process existing data, or extract information for automated workflows. Perfect for reading user submissions, analyzing data trends, or importing data for further processing.",
          "elementId": "EXTENSION:::SHARED:::default:::google-sheets:::getRows",
          "isFirstElement": false,
          "dynamicOptionLabels": {},
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Get Movimentos Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::google-sheets:::getRows",
          "legacyElementId": "JS###v1###GoogleSheets###getRows",
          "methodName": "getRows",
          "position": {
            "x": 1160,
            "y": 0
          }
        },
        "flowElementId": "5539A14D-6F8E-41ED-96A8-F315C307E234",
        "groupId": null,
        "id": "0361B131-6AAA-4864-9281-06CF5D1CF75A",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "documentId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": null
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "sheetId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "NUMBER",
                    "label": null,
                    "type": "INPUT",
                    "value": 1652303199
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "offset",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "INT"
              }
            },
            {
              "name": "limit",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "INT"
              }
            },
            {
              "name": "withRowNumbers",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "K_TRUE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": true
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "getRows",
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "movimentos",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "google-sheets",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Get Movimentos",
        "nextElementIds": [
          "E9DCA508-145F-428A-BE67-8A0622E3A7C7"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "notes": "Monitors Google Drive for new files and triggers AI workflows when content is added, uploaded, or moved. Perfect for automated processing of incoming documents, immediate analysis of uploaded files, or triggering workflows when users add new content to specific folders. Supports recursive scanning of subfolders with separate trigger calls for each new file/folder. Polling interval can be customized (minimum 30 seconds).",
          "elementId": "EXTENSION:::SHARED:::default:::google-drive-api:::onNewFile",
          "isFirstElement": true,
          "blockDefinitionId": "EXTENSION:::SHARED:::default:::google-drive-api:::onNewFile",
          "newElementId": "EXTENSION:::SHARED:::default:::google-drive-api:::onNewFile",
          "legacyElementId": "JS###v1###GoogleDrive###onNewFile",
          "methodName": "onNewFile",
          "position": {
            "x": 0,
            "y": 0
          }
        },
        "flowElementId": "96FC5412-B118-47B6-AF39-628B028F825E",
        "groupId": null,
        "id": "CD4F15BF-2638-4C90-94EF-646B87D0553F",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "condition": null,
          "connectionId": null,
          "dynamicData": [],
          "eventName": "onNewFile",
          "frequency": {
            "repeat": {
              "every": 60
            },
            "schedule": "custom"
          },
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": null
          },
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "trigger",
          "serviceId": "google-drive-api",
          "slaConditions": [],
          "staticData": {
            "folderId": null,
            "processRecursively": false,
            "triggerConfiguration": "files_only"
          },
          "storeResult": true,
          "subtype": "POLLING",
          "type": "CUSTOM"
        },
        "name": "New Bank Statement File",
        "nextElementIds": [
          "B0E937E1-B464-4A0B-8DB5-D0748F066CB5"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "TRIGGER"
      },
      {
        "clientMetadata": {
          "notes": "Downloads an .xlsx workbook and returns one worksheet as structured rows, either as objects keyed by the header row or as arrays of raw values. Formula cells return their last calculated result, rich text is flattened to plain text, hyperlinks return their display text and dates are returned as ISO 8601 strings. Duplicate header names are made unique with a numeric suffix so no column is silently lost. Only the modern .xlsx format is supported; legacy .xls (Excel 97-2003), .xlsb and .ods files are rejected with a clear error.",
          "elementId": "EXTENSION:::SHARED:::default:::xls-tools:::parseXlsxFile",
          "isFirstElement": false,
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Read Transactions Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::xls-tools:::parseXlsxFile",
          "legacyElementId": "JS###v1###XLSToolsService###parseXlsxFile",
          "methodName": "parseXlsxFile",
          "position": {
            "x": 580,
            "y": 0
          }
        },
        "flowElementId": "1A768115-E8CB-4EC8-AC80-A4FBA72705AD",
        "groupId": null,
        "id": "09801A48-CE0F-489C-8AD2-C200BC18F8E4",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "fileUrl",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "download",
                    "subPathSegments": [
                      {
                        "key": "url",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "B0E937E1-B464-4A0B-8DB5-D0748F066CB5"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "sheet",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "STRING"
              }
            },
            {
              "name": "hasHeaderRow",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "K_TRUE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": true
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "rowShape",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "STRING"
              }
            },
            {
              "name": "maxRows",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "INT"
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "parseXlsxFile",
          "onFailElemId": "D97E84E8-ACD5-4CF5-97C6-C4E6DC6C0F0F",
          "packageId": "default",
          "resultAlias": "parse",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "xls-tools",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Read Transactions",
        "nextElementIds": [
          "14ECFE2F-F714-4CEB-921D-C16FFA10AFE6"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "elementId": "error-handler",
          "isFirstElement": false,
          "blockDefinitionId": "error-handler",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Rows Unreadable Result"
          },
          "position": {
            "x": 1710,
            "y": 280
          }
        },
        "flowElementId": "22DA22C9-5564-48BF-9180-48036092C34C",
        "groupId": null,
        "id": "0A1FA464-EF54-48DC-8861-8A98319D18D3",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "logging": null,
          "onFailElemId": null,
          "resultAlias": "errMatch",
          "saveToVariable": null,
          "storeResult": true
        },
        "name": "Rows Unreadable",
        "nextElementIds": [
          "A6EE87FB-163F-4FCE-9970-0345BBA9658C"
        ],
        "nextGroupIds": [],
        "type": "ERROR_HANDLER"
      },
      {
        "clientMetadata": {
          "elementId": "error-handler",
          "isFirstElement": false,
          "blockDefinitionId": "error-handler",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Read Failed Result"
          },
          "position": {
            "x": 1710,
            "y": 640
          }
        },
        "flowElementId": "85FC5081-A81F-46E5-9C46-3E731E1A92B2",
        "groupId": null,
        "id": "D97E84E8-ACD5-4CF5-97C6-C4E6DC6C0F0F",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "logging": null,
          "onFailElemId": null,
          "resultAlias": "errParse",
          "saveToVariable": null,
          "storeResult": true
        },
        "name": "Read Failed",
        "nextElementIds": [
          "A6EE87FB-163F-4FCE-9970-0345BBA9658C"
        ],
        "nextGroupIds": [],
        "type": "ERROR_HANDLER"
      },
      {
        "clientMetadata": {
          "elementId": "condition",
          "isFirstElement": false,
          "blockDefinitionId": "condition",
          "position": {
            "x": 2290,
            "y": 70
          }
        },
        "flowElementId": "C5B9482C-76C8-40B8-96FA-852E89AFD52C",
        "groupId": null,
        "id": "612C3709-A4EE-4B1D-BC6B-B2570A248807",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "condition": {
            "conditionParts": [
              {
                "id": "85baeaf1-350b-400a-8bfd-aaf9702b3e39",
                "nestedOperation": null,
                "operation": ">",
                "property": {
                  "expression": [
                    {
                      "id": "ELEMENT_RESULT",
                      "label": "reconcile",
                      "subPathSegments": [
                        {
                          "key": "reviewCount",
                          "optional": false
                        }
                      ],
                      "type": "ELEMENT_LINK",
                      "value": "E9DCA508-145F-428A-BE67-8A0622E3A7C7"
                    }
                  ],
                  "mode": "EXPRESSION",
                  "parseJsonString": false,
                  "resultType": null
                },
                "propertyType": "INT",
                "values": [
                  {
                    "expression": [
                      {
                        "id": "NUMBER",
                        "label": null,
                        "type": "INPUT",
                        "value": 0
                      }
                    ],
                    "mode": "EXPRESSION",
                    "parseJsonString": false,
                    "resultType": null
                  }
                ]
              }
            ],
            "grouping": [
              "85baeaf1-350b-400a-8bfd-aaf9702b3e39"
            ]
          },
          "elseComponent": {
            "componentId": "7EFD691D-7795-4FEB-AACC-969B15BF61F2",
            "componentType": "ELEMENT"
          },
          "logging": null,
          "onFailElemId": null,
          "resultAlias": "hasReview",
          "storeResult": false,
          "thenComponent": {
            "componentId": "BE24E877-ABF7-4C94-8CE7-BE31ACC63D64",
            "componentType": "ELEMENT"
          }
        },
        "name": "Anything to Review?",
        "nextElementIds": [
          "BE24E877-ABF7-4C94-8CE7-BE31ACC63D64",
          "7EFD691D-7795-4FEB-AACC-969B15BF61F2"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "preferredDateFormats": []
        },
        "type": "CONDITION"
      },
      {
        "clientMetadata": {
          "notes": "Adds multiple data rows to Google Sheets in bulk for AI agents to efficiently store large datasets, batch process results, or import data from external sources. Essential for high-volume data operations and bulk data migration workflows.",
          "elementId": "EXTENSION:::SHARED:::default:::google-sheets:::addRows",
          "isFirstElement": false,
          "dynamicOptionLabels": {},
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Record in Bank Import Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::google-sheets:::addRows",
          "legacyElementId": "JS###v1###GoogleSheets###addRows",
          "methodName": "addRows",
          "position": {
            "x": 2870,
            "y": 70
          }
        },
        "flowElementId": "E874EF1E-1656-49FC-A214-7AD6511FF19D",
        "groupId": null,
        "id": "7EFD691D-7795-4FEB-AACC-969B15BF61F2",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "documentId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": null
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "sheetId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "NUMBER",
                    "label": null,
                    "type": "INPUT",
                    "value": 1590050248
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "rows",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "reconcile",
                    "subPathSegments": [
                      {
                        "key": "logRows",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "E9DCA508-145F-428A-BE67-8A0622E3A7C7"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "addRows",
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "addLog",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "google-sheets",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Record in Bank Import",
        "nextElementIds": [],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "notes": "Sends emails through Gmail for AI agents to automate customer communication.",
          "elementId": "EXTENSION:::SHARED:::default:::gmail-service:::sendMessage",
          "isFirstElement": false,
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Email: File Could Not Be Read Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::gmail-service:::sendMessage",
          "legacyElementId": "JS###v1###GmailService###sendMessage",
          "methodName": "sendMessage",
          "position": {
            "x": 2000,
            "y": 460
          }
        },
        "flowElementId": "DB6889B6-6103-4F07-9F33-513E0A5F9A93",
        "groupId": null,
        "id": "A6EE87FB-163F-4FCE-9970-0345BBA9658C",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "to",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": ""
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "subject",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": "Bank statement could not be read: "
                  },
                  {
                    "id": "RESULT",
                    "label": "trigger",
                    "subPathSegments": [
                      {
                        "key": "name",
                        "optional": false
                      }
                    ],
                    "type": "TRIGGER_DATA",
                    "value": "CD4F15BF-2638-4C90-94EF-646B87D0553F"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "bodyType",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "STRING"
              }
            },
            {
              "name": "bodyContent",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": "The bank statement "
                  },
                  {
                    "id": "RESULT",
                    "label": "trigger",
                    "subPathSegments": [
                      {
                        "key": "name",
                        "optional": false
                      }
                    ],
                    "type": "TRIGGER_DATA",
                    "value": "CD4F15BF-2638-4C90-94EF-646B87D0553F"
                  },
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": " was not imported."
                  },
                  {
                    "id": "NEWLINE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": "\n"
                  },
                  {
                    "id": "NEWLINE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": "\n"
                  },
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": "Failed step: "
                  },
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "errDownload",
                    "subPathSegments": [
                      {
                        "key": "source",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "031ED7A1-CBF2-47E1-9D40-ED02DE0BD521"
                  },
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "errParse",
                    "subPathSegments": [
                      {
                        "key": "source",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "D97E84E8-ACD5-4CF5-97C6-C4E6DC6C0F0F"
                  },
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "errMatch",
                    "subPathSegments": [
                      {
                        "key": "source",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "0A1FA464-EF54-48DC-8861-8A98319D18D3"
                  },
                  {
                    "id": "NEWLINE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": "\n"
                  },
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": "Error: "
                  },
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "errDownload",
                    "subPathSegments": [
                      {
                        "key": "message",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "031ED7A1-CBF2-47E1-9D40-ED02DE0BD521"
                  },
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "errParse",
                    "subPathSegments": [
                      {
                        "key": "message",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "D97E84E8-ACD5-4CF5-97C6-C4E6DC6C0F0F"
                  },
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "errMatch",
                    "subPathSegments": [
                      {
                        "key": "message",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "0A1FA464-EF54-48DC-8861-8A98319D18D3"
                  },
                  {
                    "id": "NEWLINE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": "\n"
                  },
                  {
                    "id": "NEWLINE",
                    "label": null,
                    "type": "KEYWORD",
                    "value": "\n"
                  },
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": "Nothing was written to the Finance sheet. Fix the file and upload it again; transactions already recorded will be skipped."
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "from",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "STRING"
              }
            },
            {
              "name": "cc",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "ARRAY"
              }
            },
            {
              "name": "bcc",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "ARRAY"
              }
            },
            {
              "name": "threadId",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "STRING"
              }
            },
            {
              "name": "attachments",
              "type": "SIMPLE",
              "value": {
                "expression": [],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": "STRING"
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "sendMessage",
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "errEmail",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "gmail-service",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Email: File Could Not Be Read",
        "nextElementIds": [],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "notes": "Updates multiple rows in a specified sheet.",
          "elementId": "EXTENSION:::SHARED:::default:::google-sheets:::updateRows",
          "isFirstElement": false,
          "dynamicOptionLabels": {},
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Mark Movimentos as Paid Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::google-sheets:::updateRows",
          "legacyElementId": "JS###v1###GoogleSheets###updateRows",
          "methodName": "updateRows",
          "position": {
            "x": 2000,
            "y": 0
          }
        },
        "flowElementId": "FFC8E2B1-22E2-44B5-9121-1EA67980C93E",
        "groupId": null,
        "id": "87095CC3-22BD-4E33-BD31-7215AD4D0BAF",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "documentId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": null
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "sheetId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "NUMBER",
                    "label": null,
                    "type": "INPUT",
                    "value": 1652303199
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "rows",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "reconcile",
                    "subPathSegments": [
                      {
                        "key": "movUpdates",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "E9DCA508-145F-428A-BE67-8A0622E3A7C7"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "updateRows",
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "markPaid",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "google-sheets",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Mark Movimentos as Paid",
        "nextElementIds": [
          "612C3709-A4EE-4B1D-BC6B-B2570A248807"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "elementId": "custom-cloud-code",
          "isFirstElement": false,
          "blockDefinitionId": "custom-cloud-code",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Match Transactions Result"
          },
          "position": {
            "x": 1420,
            "y": 160
          }
        },
        "flowElementId": "8CDC4F33-A426-4C1D-91FF-9E64BCAC0A21",
        "groupId": null,
        "id": "E9DCA508-145F-428A-BE67-8A0622E3A7C7",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "codeArguments": [
            {
              "name": "statementRows",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "parse",
                    "subPathSegments": [
                      {
                        "key": "rows",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "09801A48-CE0F-489C-8AD2-C200BC18F8E4"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "importLog",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "importLog",
                    "subPathSegments": null,
                    "type": "ELEMENT_LINK",
                    "value": "14ECFE2F-F714-4CEB-921D-C16FFA10AFE6"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "movimentos",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "movimentos",
                    "subPathSegments": null,
                    "type": "ELEMENT_LINK",
                    "value": "0361B131-6AAA-4864-9281-06CF5D1CF75A"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "fileName",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "RESULT",
                    "label": "trigger",
                    "subPathSegments": [
                      {
                        "key": "name",
                        "optional": false
                      }
                    ],
                    "type": "TRIGGER_DATA",
                    "value": "CD4F15BF-2638-4C90-94EF-646B87D0553F"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            }
          ],
          "codeBody": {
            "expression": [
              {
                "id": "TEXT",
                "label": null,
                "type": "INPUT",
                "value": "// Inputs: statementRows (array of objects), importLog (array of objects), movimentos (array of {rowNumber,rowData}), fileName (string)\nconst DAY_WINDOW = 5;\n\nconst lc = s => String(s || '').trim().toLowerCase();\nfunction pick(row, aliases) {\n  for (const k of Object.keys(row)) if (aliases.includes(lc(k))) return row[k];\n  return undefined;\n}\nfunction toISODate(v) {\n  if (v === undefined || v === null || v === '') return null;\n  if (typeof v === 'number') { // Excel serial date\n    const d = new Date(Date.UTC(1899, 11, 30) + Math.round(v) * 86400000);\n    return d.toISOString().slice(0, 10);\n  }\n  const s = String(v).trim();\n  let m = s.match(/^(\\d{4})-(\\d{2})-(\\d{2})/);\n  if (m) return `${m[1]}-${m[2]}-${m[3]}`;\n  m = s.match(/^(\\d{1,2})[\\/.-](\\d{1,2})[\\/.-](\\d{4})/); // dd/mm/yyyy (Portuguese format)\n  if (m) return `${m[3]}-${m[2].padStart(2, '0')}-${m[1].padStart(2, '0')}`;\n  return null;\n}\nfunction toAmount(v) {\n  if (v === undefined || v === null || v === '') return null;\n  if (typeof v === 'number') return Math.round(v * 100) / 100;\n  let s = String(v).replace(/[^\\d,.\\-]/g, '');\n  const lastComma = s.lastIndexOf(','), lastDot = s.lastIndexOf('.');\n  if (lastComma > lastDot) s = s.replace(/\\./g, '').replace(',', '.');\n  else s = s.replace(/,/g, '');\n  const n = parseFloat(s);\n  return isNaN(n) ? null : Math.round(n * 100) / 100;\n}\nconst dayDiff = (a, b) => Math.abs((Date.parse(a) - Date.parse(b)) / 86400000);\nconst normRef = s => String(s || '').toUpperCase().replace(/[^A-Z0-9]/g, '');\nconst isPaid = r => ['pago', 'paid', 'liquidado'].includes(lc(r.rowData['Estado']));\n\nif (!Array.isArray(statementRows) || statementRows.length === 0)\n  throw new Error('No transaction rows found in the file.');\n\n// 1. Normalise statement rows\nconst txs = [];\nstatementRows.forEach((r, i) => {\n  const date = toISODate(pick(r, ['date', 'data', 'data mov.', 'data movimento', 'data valor', 'data lanc.', 'booking date']));\n  const description = String(pick(r, ['description', 'descrição', 'descricao', 'descritivo', 'movimento', 'details']) || '').trim();\n  let amount = toAmount(pick(r, ['amount', 'montante', 'valor', 'importância', 'importancia']));\n  if (amount === null) {\n    const debit = toAmount(pick(r, ['debit', 'débito', 'debito']));\n    const credit = toAmount(pick(r, ['credit', 'crédito', 'credito']));\n    if (debit !== null || credit !== null) amount = Math.round(((credit || 0) - Math.abs(debit || 0)) * 100) / 100;\n  }\n  const ref = String(pick(r, ['reference', 'referência', 'referencia', 'ref', 'ref.', 'bank reference']) || '').trim();\n  if (!date && amount === null && !description) return; // blank line\n  if (!date || amount === null)\n    throw new Error(`Row ${i + 2}: could not read the date or amount (columns found: ${Object.keys(r).join(', ')}).`);\n  txs.push({ date, description, amount, ref, key: `${date}|${amount.toFixed(2)}|${ref}` });\n});\nif (txs.length === 0) throw new Error('No transaction rows found in the file.');\n\n// 2. Known keys\nconst seen = new Set((importLog || []).map(r => String(r['Key'] || '').trim()).filter(Boolean));\n\n// 3. Match\nconst pool = (movimentos || []).filter(m => !isPaid(m));\nconst used = new Set();\nconst now = new Date().toISOString();\nconst movUpdates = [], reviewRows = [], logRows = [];\nconst counts = { matched: 0, review: 0, duplicate: 0 };\nconst describe = m => `${m.rowData['ID'] || 'row ' + m.rowNumber} (${m.rowData['Data'] || '?'}, ${m.rowData['Valor'] || '?'}, ${m.rowData['Nº Fatura'] || 'no invoice no.'})`;\n\nfor (const t of txs) {\n  const base = { Key: t.key, Date: t.date, Description: t.description, Amount: t.amount.toFixed(2), 'Bank Ref': t.ref, File: fileName };\n  if (seen.has(t.key)) {\n    counts.duplicate++;\n    logRows.push({ ...base, Status: 'skipped (duplicate)', 'Movimentos ID': '', 'Imported At': now });\n    continue;\n  }\n  seen.add(t.key);\n  const avail = pool.filter(m => !used.has(m.rowNumber));\n  const descN = normRef(t.description);\n  const sameAmount = m => { const v = toAmount(m.rowData['Valor']); return v !== null && Math.abs(v - t.amount) < 0.005; };\n  const invoiceHits = avail.filter(m => {\n    const inv = normRef(m.rowData['Nº Fatura']);\n    return inv.length >= 4 && descN.includes(inv);\n  });\n  // An invoice-number match counts only when the amount agrees too; otherwise (e.g. a partial payment) it goes to review\n  let candidates = invoiceHits.filter(sameAmount);\n  let rule = 'invoice number';\n  let amountMismatch = false;\n  if (invoiceHits.length > 0 && candidates.length === 0) {\n    candidates = invoiceHits;\n    amountMismatch = true;\n  } else if (invoiceHits.length === 0) {\n    rule = 'amount and date';\n    candidates = avail.filter(m => {\n      const v = toAmount(m.rowData['Valor']); const d = toISODate(m.rowData['Data']);\n      return v !== null && d && Math.abs(v - t.amount) < 0.005 && dayDiff(d, t.date) <= DAY_WINDOW;\n    });\n  }\n  if (candidates.length === 1 && !amountMismatch) {\n    const m = candidates[0];\n    used.add(m.rowNumber);\n    // Update Rows counts data rows (1 = first row under the header), so sheet row N is index N-1\n    movUpdates.push({ index: m.rowNumber - 1, values: { ...m.rowData, 'Estado': 'Pago', 'Data Pagamento': t.date, 'Ref. Banco': t.ref } });\n    counts.matched++;\n    logRows.push({ ...base, Status: `matched (${rule})`, 'Movimentos ID': m.rowData['ID'] || `row ${m.rowNumber}`, 'Imported At': now });\n  } else {\n    const reason = amountMismatch ? 'Invoice number matches but amount differs (partial or incorrect payment?)'\n      : candidates.length === 0 ? 'No match' : `${candidates.length} possible matches (${rule})`;\n    counts.review++;\n    reviewRows.push({ ...base, Reason: reason, Candidates: candidates.map(describe).join('; '), 'Added At': now, Resolved: '' });\n    logRows.push({ ...base, Status: 'sent to review', 'Movimentos ID': '', 'Imported At': now });\n  }\n}\n\nreturn {\n  movUpdates, reviewRows, logRows,\n  movUpdateCount: movUpdates.length, reviewCount: reviewRows.length,\n  summary: `${txs.length} transactions: ${counts.matched} matched, ${counts.review} sent to review, ${counts.duplicate} duplicates skipped`\n};\n"
              }
            ],
            "mode": "EXPRESSION",
            "parseJsonString": false,
            "resultType": null
          },
          "enabled": true,
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "onFailElemId": "0A1FA464-EF54-48DC-8861-8A98319D18D3",
          "resultAlias": "reconcile",
          "retryPolicy": null,
          "saveToVariable": null,
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "type": "CUSTOM_CLOUD_CODE"
        },
        "name": "Match Transactions",
        "nextElementIds": [
          "30CD258B-3E1A-4172-8556-2D27B89955BF"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "notes": "Adds multiple data rows to Google Sheets in bulk for AI agents to efficiently store large datasets, batch process results, or import data from external sources. Essential for high-volume data operations and bulk data migration workflows.",
          "elementId": "EXTENSION:::SHARED:::default:::google-sheets:::addRows",
          "isFirstElement": false,
          "dynamicOptionLabels": {},
          "blockDefinitionId": "api-service-method",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Add to To Review Result"
          },
          "newElementId": "EXTENSION:::SHARED:::default:::google-sheets:::addRows",
          "legacyElementId": "JS###v1###GoogleSheets###addRows",
          "methodName": "addRows",
          "position": {
            "x": 2580,
            "y": 0
          }
        },
        "flowElementId": "89215D04-2D7A-4C37-903C-55F622B86377",
        "groupId": null,
        "id": "BE24E877-ABF7-4C94-8CE7-BE31ACC63D64",
        "metaInfo": {
          "bodyParams": [
            {
              "name": "documentId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "TEXT",
                    "label": null,
                    "type": "INPUT",
                    "value": null
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "sheetId",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "NUMBER",
                    "label": null,
                    "type": "INPUT",
                    "value": 1996125149
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            },
            {
              "name": "rows",
              "type": "SIMPLE",
              "value": {
                "expression": [
                  {
                    "id": "ELEMENT_RESULT",
                    "label": "reconcile",
                    "subPathSegments": [
                      {
                        "key": "reviewRows",
                        "optional": false
                      }
                    ],
                    "type": "ELEMENT_LINK",
                    "value": "E9DCA508-145F-428A-BE67-8A0622E3A7C7"
                  }
                ],
                "mode": "EXPRESSION",
                "parseJsonString": false,
                "resultType": null
              }
            }
          ],
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "connectionId": null,
          "enabled": true,
          "hostType": "SHARED",
          "logging": {
            "input": {
              "logData": false,
              "message": null
            },
            "output": {
              "logData": false,
              "message": null
            }
          },
          "methodName": "addRows",
          "onFailElemId": null,
          "packageId": "default",
          "resultAlias": "addReview",
          "retryPolicy": null,
          "saveToVariable": null,
          "serviceId": "google-sheets",
          "simulationResult": null,
          "slaConditions": [],
          "storeResult": true,
          "subtype": "API_SERVICE",
          "type": "EXTENSION"
        },
        "name": "Add to To Review",
        "nextElementIds": [
          "7EFD691D-7795-4FEB-AACC-969B15BF61F2"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "learningStatus": "OFF"
        },
        "type": "ACTION"
      },
      {
        "clientMetadata": {
          "elementId": "condition",
          "isFirstElement": false,
          "blockDefinitionId": "condition",
          "position": {
            "x": 1710,
            "y": 70
          }
        },
        "flowElementId": "70737258-4965-4034-BE37-1A0632D07E2E",
        "groupId": null,
        "id": "30CD258B-3E1A-4172-8556-2D27B89955BF",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "condition": {
            "conditionParts": [
              {
                "id": "77cbae01-9998-4274-8f56-3808c1adeb9f",
                "nestedOperation": null,
                "operation": ">",
                "property": {
                  "expression": [
                    {
                      "id": "ELEMENT_RESULT",
                      "label": "reconcile",
                      "subPathSegments": [
                        {
                          "key": "movUpdateCount",
                          "optional": false
                        }
                      ],
                      "type": "ELEMENT_LINK",
                      "value": "E9DCA508-145F-428A-BE67-8A0622E3A7C7"
                    }
                  ],
                  "mode": "EXPRESSION",
                  "parseJsonString": false,
                  "resultType": null
                },
                "propertyType": "INT",
                "values": [
                  {
                    "expression": [
                      {
                        "id": "NUMBER",
                        "label": null,
                        "type": "INPUT",
                        "value": 0
                      }
                    ],
                    "mode": "EXPRESSION",
                    "parseJsonString": false,
                    "resultType": null
                  }
                ]
              }
            ],
            "grouping": [
              "77cbae01-9998-4274-8f56-3808c1adeb9f"
            ]
          },
          "elseComponent": {
            "componentId": "612C3709-A4EE-4B1D-BC6B-B2570A248807",
            "componentType": "ELEMENT"
          },
          "logging": null,
          "onFailElemId": null,
          "resultAlias": "hasMatches",
          "storeResult": false,
          "thenComponent": {
            "componentId": "87095CC3-22BD-4E33-BD31-7215AD4D0BAF",
            "componentType": "ELEMENT"
          }
        },
        "name": "Any Matches?",
        "nextElementIds": [
          "87095CC3-22BD-4E33-BD31-7215AD4D0BAF",
          "612C3709-A4EE-4B1D-BC6B-B2570A248807"
        ],
        "nextGroupIds": [],
        "serverFields": {
          "preferredDateFormats": []
        },
        "type": "CONDITION"
      },
      {
        "clientMetadata": {
          "elementId": "error-handler",
          "isFirstElement": false,
          "blockDefinitionId": "error-handler",
          "setResultToVariable": false,
          "saveToVariable": {
            "dataBucket": "Default",
            "variable": "Download Failed Result"
          },
          "position": {
            "x": 1710,
            "y": 460
          }
        },
        "flowElementId": "2CBBD82E-40B7-4B72-8DBE-F1A38FED7810",
        "groupId": null,
        "id": "031ED7A1-CBF2-47E1-9D40-ED02DE0BD521",
        "metaInfo": {
          "clientValidationState": {
            "errorMessage": null,
            "valid": true
          },
          "logging": null,
          "onFailElemId": null,
          "resultAlias": "errDownload",
          "saveToVariable": null,
          "storeResult": true
        },
        "name": "Download Failed",
        "nextElementIds": [
          "A6EE87FB-163F-4FCE-9970-0345BBA9658C"
        ],
        "nextGroupIds": [],
        "type": "ERROR_HANDLER"
      }
    ],
    "firstElementId": "CD4F15BF-2638-4C90-94EF-646B87D0553F",
    "groups": [],
    "id": "41C9D7DA-77FF-41CD-8A5E-7738C61518B4",
    "metaInfo": {
      "clientValidationState": {
        "errorMessage": null,
        "valid": true
      },
      "errorMessage": null,
      "executionStaticData": [],
      "initialData": null,
      "initialDataDefaultValues": {},
      "ownerFlowVersionId": null,
      "schedule": null,
      "sharedMemory": {
        "anchor": {
          "missingAnchorPolicy": null,
          "path": null,
          "type": "FLOW_MEMORY"
        },
        "expirationInSec": null
      },
      "wasLive": true
    }
  },
  "slaCalendars": [],
  "slaGoals": [],
  "subFlows": [],
  "exportDate": "2026-10-16T23:58:38.558Z"
}