diff --git a/Gheeraert/Gheeraert Workflow 2 - OrderID ophalen.json b/Gheeraert/Gheeraert Workflow 2 - OrderID ophalen.json new file mode 100644 index 0000000..da76f84 --- /dev/null +++ b/Gheeraert/Gheeraert Workflow 2 - OrderID ophalen.json @@ -0,0 +1,357 @@ +{ + "name": "Gheeraert Workflow 2 - OrderID ophalen", + "nodes": [ + { + "parameters": { + "method": "POST", + "url": "https://my-uat.gheeraert.be/token", + "sendBody": true, + "contentType": "form-urlencoded", + "bodyParameters": { + "parameters": [ + { + "name": "grant_type", + "value": "password" + }, + { + "name": "username", + "value": "api@dewittransport.nl" + }, + { + "name": "password", + "value": "my.gheeraert" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + -368, + -96 + ], + "id": "f5b22505-d130-43e6-9600-85e55051d7cb", + "name": "Get Gheeraert Token" + }, + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT\n id,\n purchase_order_number,\n transpas_legnr,\n transpas_reference,\n file_name\nFROM public.ghe_order_log\nWHERE file_upload_status = 'sent'\n AND gheeraert_order_id IS NULL\n AND is_closed = false\n AND (\n next_status_poll_at IS NULL\n OR next_status_poll_at <= CURRENT_TIMESTAMP\n )\nORDER BY\n COALESCE(last_order_lookup_at, created_at),\n id\nLIMIT 25;", + "options": {} + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -144, + -96 + ], + "id": "1c71fb93-6d01-4187-aa56-b5816f37ab6b", + "name": "Get Orders Without Gheeraert ID", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "jsCode": "return $input.all().map(item => {\n const purchaseOrderNumber = String(item.json.purchase_order_number || '').trim();\n\n return {\n json: {\n ...item.json,\n encodedPurchaseOrderNumber: encodeURIComponent(purchaseOrderNumber),\n },\n };\n});" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 80, + -96 + ], + "id": "5fb9dc99-37cb-4a46-bde7-e43bc94bbf34", + "name": "Prepare PurchaseOrder Lookup" + }, + { + "parameters": { + "jsCode": "return $input.all().map(item => {\n const j = item.json;\n\n let response = j.gheeraertOrder;\n\n // In jouw output is gheeraertOrder een JSON-string.\n if (typeof response === 'string') {\n try {\n response = JSON.parse(response);\n } catch (e) {\n response = null;\n }\n }\n\n // Fallback als response direct op json staat.\n if (!response && (j.OrderID || j.ID || j.orderID)) {\n response = j;\n }\n\n // Soms komt API als array terug.\n const order = Array.isArray(response) ? response[0] : response;\n\n const rawOrderId =\n order?.OrderID ??\n order?.orderID ??\n order?.ID ??\n order?.id ??\n null;\n\n const gheeraertOrderId = rawOrderId !== null ? Number(rawOrderId) : null;\n const found = Number.isFinite(gheeraertOrderId) && gheeraertOrderId > 0;\n\n let errorMessage = '';\n\n if (j.error?.message) {\n errorMessage = j.error.message;\n }\n\n let apiMessage = '';\n\n if (errorMessage.includes('Order not found')) {\n apiMessage = 'Gheeraert OrderID nog niet gevonden';\n } else if (errorMessage) {\n apiMessage = errorMessage.slice(0, 500);\n }\n\n return {\n json: {\n ...j,\n\n found,\n gheeraertOrderId: found ? Math.trunc(gheeraertOrderId) : null,\n\n gheeraertTrackingId: order?.TrackingID ?? null,\n gheeraertPurchaseOrderNumber: order?.PurchaseOrderNumber ?? null,\n gheeraertExtOrderNumber: order?.ExtOrderNumber ?? null,\n gheeraertExtDelNoteNumber: order?.ExtDelNoteNumber ?? null,\n\n lookupMessage: found\n ? `Gheeraert OrderID gevonden: ${Math.trunc(gheeraertOrderId)}`\n : (apiMessage || 'Gheeraert OrderID nog niet gevonden'),\n },\n };\n});" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 752, + -96 + ], + "id": "5011b72f-6521-49a6-8d6b-30447bd9e2b5", + "name": "Normalize Gheeraert Lookup" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 3 + }, + "conditions": [ + { + "id": "7da7e84c-8efd-459f-987a-7b3676b19c06", + "leftValue": "={{ $json.found }}", + "rightValue": "true", + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.3, + "position": [ + 976, + -96 + ], + "id": "168fc7f2-8447-4b76-a8cf-24c5be91604e", + "name": "OrderID Found?" + }, + { + "parameters": { + "operation": "executeQuery", + "query": "UPDATE public.ghe_order_log\nSET\n gheeraert_order_id = $1::integer,\n last_order_lookup_at = CURRENT_TIMESTAMP,\n next_status_poll_at = CURRENT_TIMESTAMP,\n file_upload_error = NULL\nWHERE id = $2::bigint;", + "options": { + "queryReplacement": "=$1 = {{ $json.gheeraertOrderId }}\n$2 = {{ $json.id }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1200, + -192 + ], + "id": "3503f64e-1483-4401-825e-22cac20fab82", + "name": "Update Gheeraert OrderID", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "UPDATE public.ghe_order_log\nSET\n last_order_lookup_at = CURRENT_TIMESTAMP,\n next_status_poll_at = CURRENT_TIMESTAMP + INTERVAL '10 minutes',\n file_upload_error = $1::text\nWHERE id = $2::bigint\n AND gheeraert_order_id IS NULL;", + "options": { + "queryReplacement": "=$1 = {{ $json.lookupMessage }}\n$2 = {{ $json.id }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1200, + 0 + ], + "id": "994d3fcc-4926-40de-a8fa-fe64f5aabbee", + "name": "OrderID Not Found Retry Later", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "url": "=https://my-uat.gheeraert.be/api/Order/ByPurchaseOrderNumber/{{$json.encodedPurchaseOrderNumber}}", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Authorization", + "value": "=Bearer {{ $('Get Gheeraert Token').first().json.access_token }}" + }, + { + "name": "Accept", + "value": "application/json" + } + ] + }, + "options": { + "response": { + "response": { + "responseFormat": "text", + "outputPropertyName": "gheeraertOrder" + } + } + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 304, + -32 + ], + "id": "f8874799-dbed-4a32-86ee-ae56fcafebf3", + "name": "Lookup Gheeraert OrderID", + "notesInFlow": false, + "onError": "continueRegularOutput" + }, + { + "parameters": { + "mode": "combine", + "combineBy": "combineByPosition", + "options": {} + }, + "type": "n8n-nodes-base.merge", + "typeVersion": 3.2, + "position": [ + 528, + -96 + ], + "id": "a4c3324a-8ad3-40dd-8267-33c91af7740a", + "name": "Merge" + }, + { + "parameters": { + "rule": { + "interval": [ + { + "field": "cronExpression", + "expression": "*/20 6-22 * * 1-5" + } + ] + } + }, + "type": "n8n-nodes-base.scheduleTrigger", + "typeVersion": 1.3, + "position": [ + -592, + -96 + ], + "id": "61885d7b-a67f-477a-a772-5063858bc108", + "name": "Schedule Trigger" + } + ], + "pinData": {}, + "connections": { + "Get Gheeraert Token": { + "main": [ + [ + { + "node": "Get Orders Without Gheeraert ID", + "type": "main", + "index": 0 + } + ] + ] + }, + "Get Orders Without Gheeraert ID": { + "main": [ + [ + { + "node": "Prepare PurchaseOrder Lookup", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare PurchaseOrder Lookup": { + "main": [ + [ + { + "node": "Merge", + "type": "main", + "index": 0 + }, + { + "node": "Lookup Gheeraert OrderID", + "type": "main", + "index": 0 + } + ] + ] + }, + "Normalize Gheeraert Lookup": { + "main": [ + [ + { + "node": "OrderID Found?", + "type": "main", + "index": 0 + } + ] + ] + }, + "OrderID Found?": { + "main": [ + [ + { + "node": "Update Gheeraert OrderID", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "OrderID Not Found Retry Later", + "type": "main", + "index": 0 + } + ] + ] + }, + "Update Gheeraert OrderID": { + "main": [ + [] + ] + }, + "Lookup Gheeraert OrderID": { + "main": [ + [ + { + "node": "Merge", + "type": "main", + "index": 1 + } + ] + ] + }, + "Merge": { + "main": [ + [ + { + "node": "Normalize Gheeraert Lookup", + "type": "main", + "index": 0 + } + ] + ] + }, + "Schedule Trigger": { + "main": [ + [ + { + "node": "Get Gheeraert Token", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1", + "binaryMode": "separate" + }, + "versionId": "1d9a70a4-7abe-4927-a8ca-ababafe107e6", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "bef8d409866a58c0777dfe7cca1b9c2400fd051c056d361501393ab423006b5f" + }, + "nodeGroups": [], + "id": "BHfu3wTZCa8C9Gwr", + "tags": [] +} \ No newline at end of file diff --git a/Gheeraert/Gheeraert workflow 3 — statussen ophalen.json b/Gheeraert/Gheeraert workflow 3 — statussen ophalen.json new file mode 100644 index 0000000..663ba69 --- /dev/null +++ b/Gheeraert/Gheeraert workflow 3 — statussen ophalen.json @@ -0,0 +1,337 @@ +{ + "name": "Gheeraert workflow 3 — statussen ophalen", + "nodes": [ + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT\n id,\n purchase_order_number,\n transpas_legnr,\n transpas_reference,\n gheeraert_order_id,\n last_status_poll_at,\n next_status_poll_at,\n delivered_at,\n pod_online_at,\n pod_downloaded_at\nFROM public.ghe_order_log\nWHERE file_upload_status = 'sent'\n AND gheeraert_order_id IS NOT NULL\n AND is_closed = false\n AND (\n next_status_poll_at IS NULL\n OR next_status_poll_at <= CURRENT_TIMESTAMP\n )\nORDER BY\n COALESCE(last_status_poll_at, created_at),\n id\nLIMIT 25;", + "options": {} + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 224, + -272 + ], + "id": "efb74e39-f147-40e3-af5b-c8022ad51944", + "name": "Get Orders With Gheeraert ID", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "method": "POST", + "url": "https://my-uat.gheeraert.be/token", + "sendBody": true, + "contentType": "form-urlencoded", + "bodyParameters": { + "parameters": [ + { + "name": "grant_type", + "value": "password" + }, + { + "name": "username", + "value": "api@dewittransport.nl" + }, + { + "name": "password", + "value": "my.gheeraert" + } + ] + }, + "options": {} + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 448, + -272 + ], + "id": "b049495e-5e3d-4c86-8ad7-5283fdf82efe", + "name": "Get Gheeraert Token" + }, + { + "parameters": { + "url": "={{ 'https://my-uat.gheeraert.be/api/OrderTracking/' + $('Get Orders With Gheeraert ID').item.json.gheeraert_order_id }}", + "sendHeaders": true, + "headerParameters": { + "parameters": [ + { + "name": "Authorization", + "value": "={{ 'Bearer ' + $('Get Gheeraert Token').first().json.access_token }}" + }, + { + "name": "Accept", + "value": "application/json" + } + ] + }, + "options": { + "response": { + "response": { + "responseFormat": "json" + } + } + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + 672, + -272 + ], + "id": "1407cf2f-34b0-4a58-bdc3-86ac1ea72777", + "name": "Lookup Gheeraert OrderTracking", + "onError": "continueRegularOutput" + }, + { + "parameters": { + "jsCode": "function simpleHash(input) {\n const str = String(input ?? '');\n let h1 = 0xdeadbeef ^ str.length;\n let h2 = 0x41c6ce57 ^ str.length;\n\n for (let i = 0; i < str.length; i++) {\n const ch = str.charCodeAt(i);\n h1 = Math.imul(h1 ^ ch, 2654435761);\n h2 = Math.imul(h2 ^ ch, 1597334677);\n }\n\n h1 =\n Math.imul(h1 ^ (h1 >>> 16), 2246822507) ^\n Math.imul(h2 ^ (h2 >>> 13), 3266489909);\n\n h2 =\n Math.imul(h2 ^ (h2 >>> 16), 2246822507) ^\n Math.imul(h1 ^ (h1 >>> 13), 3266489909);\n\n return (\n (h2 >>> 0).toString(16).padStart(8, '0') +\n (h1 >>> 0).toString(16).padStart(8, '0')\n );\n}\n\nreturn $input.all().map(item => {\n const j = item.json;\n\n const base = [\n j.gheeraert_order_id ?? '',\n j.status_id ?? '',\n j.tracking_date ?? '',\n j.tracking_comments ?? '',\n j.barcode ?? '',\n j.tracking_url ?? '',\n ].join('|');\n\n return {\n json: {\n ...j,\n status_hash: simpleHash(base),\n },\n };\n});" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 1120, + -272 + ], + "id": "c517653a-9b40-4c9a-a1a8-c7e0f0cf3636", + "name": "Make Status Hash" + }, + { + "parameters": { + "operation": "executeQuery", + "query": "WITH input AS (\n SELECT $1::jsonb AS j\n),\ntyped AS (\n SELECT\n (j->>'order_log_id')::bigint AS order_log_id,\n (j->>'gheeraert_order_id')::integer AS gheeraert_order_id,\n (j->>'purchase_order_number')::varchar AS purchase_order_number,\n (j->>'status_id')::integer AS status_id,\n (j->>'tracking_date')::timestamp AS tracking_date,\n (j->>'tracking_comments')::text AS tracking_comments,\n (j->>'tracking_url')::text AS tracking_url,\n NULLIF(j->>'barcode', '')::varchar AS barcode,\n NULLIF(j->>'user_name', '')::varchar AS user_name,\n (j->>'status_hash')::varchar AS status_hash\n FROM input\n),\nins AS (\n INSERT INTO public.ghe_status_log (\n order_log_id,\n gheeraert_order_id,\n purchase_order_number,\n status_id,\n tracking_date,\n tracking_comments,\n tracking_url,\n barcode,\n user_name,\n status_hash\n )\n SELECT\n order_log_id,\n gheeraert_order_id,\n purchase_order_number,\n status_id,\n tracking_date,\n tracking_comments,\n tracking_url,\n barcode,\n user_name,\n status_hash\n FROM typed\n ON CONFLICT (status_hash)\n DO NOTHING\n RETURNING id\n)\nSELECT\n ins.id AS inserted_id,\n typed.order_log_id,\n typed.gheeraert_order_id,\n typed.purchase_order_number,\n typed.status_id,\n typed.tracking_date,\n typed.tracking_comments,\n typed.tracking_url,\n typed.barcode,\n typed.user_name,\n typed.status_hash\nFROM typed\nLEFT JOIN ins ON TRUE;", + "options": { + "queryReplacement": "={{ [JSON.stringify($json)] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1440, + -272 + ], + "id": "0612800b-26e7-415d-8bf3-225edbbb93e4", + "name": "Insert ghe_status_log", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 3 + }, + "conditions": [ + { + "id": "5d26cbeb-2ed9-45a4-914b-754a130fc915", + "leftValue": "={{ $json.inserted_id }}", + "rightValue": "", + "operator": { + "type": "string", + "operation": "notEmpty", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.3, + "position": [ + 1664, + -272 + ], + "id": "7ef41b79-2a94-4ab3-9e0d-aecf274dcd7e", + "name": "If" + }, + { + "parameters": { + "operation": "executeQuery", + "query": "\nWITH input AS (\n SELECT $1::jsonb AS j\n)\nUPDATE public.ghe_order_log\nSET\n last_status_poll_at = CURRENT_TIMESTAMP,\n last_status_id = (j->>'status_id')::integer,\n last_status_text = (j->>'tracking_comments')::varchar,\n last_tracking_date = (j->>'tracking_date')::timestamp,\n\n delivered_at = CASE\n WHEN (j->>'status_id')::integer = 30 AND delivered_at IS NULL\n THEN (j->>'tracking_date')::timestamp\n ELSE delivered_at\n END,\n\n pod_online_at = CASE\n WHEN (j->>'status_id')::integer = 35 AND pod_online_at IS NULL\n THEN (j->>'tracking_date')::timestamp\n ELSE pod_online_at\n END,\n\n next_status_poll_at = CASE\n WHEN (j->>'status_id')::integer = 35 THEN CURRENT_TIMESTAMP + INTERVAL '1 day'\n WHEN (j->>'status_id')::integer = 30 THEN CURRENT_TIMESTAMP + INTERVAL '2 hours'\n ELSE CURRENT_TIMESTAMP + INTERVAL '15 minutes'\n END\nFROM input\nWHERE public.ghe_order_log.id = (j->>'order_log_id')::bigint;", + "options": { + "queryReplacement": "=={{ [JSON.stringify($json)] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + 1920, + -336 + ], + "id": "bb2fd5f0-0958-41aa-b739-a93689508021", + "name": "Update ghe_order_log", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "content": "## workflow 1: orders versturen + loggen\n## workflow 2: Gheeraert OrderID ophalen\n## workflow 3: tracking ophalen + statuslog vullen\n", + "width": 720 + }, + "type": "n8n-nodes-base.stickyNote", + "typeVersion": 1, + "position": [ + 48, + -464 + ], + "id": "3d0643a3-a9ab-481f-b8e3-cd00c9d54628", + "name": "Sticky Note" + }, + { + "parameters": { + "rule": { + "interval": [ + { + "field": "cronExpression", + "expression": "*/20 6-22 * * 1-5" + } + ] + } + }, + "type": "n8n-nodes-base.scheduleTrigger", + "typeVersion": 1.3, + "position": [ + 0, + -272 + ], + "id": "201f3623-82ac-43a6-aade-8d4d967a43bf", + "name": "Schedule Trigger" + }, + { + "parameters": { + "jsCode": "const orders = $('Get Orders With Gheeraert ID').all().map(i => i.json);\n\nconst orderByGheeraertId = new Map(\n orders.map(order => [String(order.gheeraert_order_id), order])\n);\n\nconst out = [];\n\nfor (const item of $input.all()) {\n const t = item.json;\n\n const gheOrderId = String(t.OrderID ?? '');\n const order = orderByGheeraertId.get(gheOrderId);\n\n if (!order) {\n out.push({\n json: {\n error: true,\n error_text: `Geen matching order gevonden voor Gheeraert OrderID ${gheOrderId}`,\n gheeraert_order_id: t.OrderID ?? null,\n purchase_order_number: t.PurchaseOrderNumber ?? null,\n raw: t,\n },\n });\n continue;\n }\n\n out.push({\n json: {\n order_log_id: order.id ?? null,\n gheeraert_order_id: t.OrderID ?? order.gheeraert_order_id ?? null,\n purchase_order_number: t.PurchaseOrderNumber ?? order.purchase_order_number ?? null,\n transpas_legnr: order.transpas_legnr ?? t.ExtOrderNumber ?? null,\n transpas_reference: order.transpas_reference ?? null,\n\n status_id: t.StatusID ?? null,\n tracking_date: t.TrackingDate ?? null,\n tracking_comments: t.PublicTrackingComments ?? null,\n tracking_url: t.TrackingURL ?? null,\n barcode: t.Barcode ?? null,\n user_name: t.UserName ?? null,\n\n gheeraert_track_id: t.TrackID ?? null,\n location: t.Location ?? null,\n eta: t.ETA ?? null,\n raw: t,\n },\n });\n}\n\nreturn out;" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + 896, + -272 + ], + "id": "0e004fcc-f058-4f5c-aa75-f4ee40768295", + "name": "Attach Order Context" + } + ], + "pinData": {}, + "connections": { + "Get Orders With Gheeraert ID": { + "main": [ + [ + { + "node": "Get Gheeraert Token", + "type": "main", + "index": 0 + } + ] + ] + }, + "Get Gheeraert Token": { + "main": [ + [ + { + "node": "Lookup Gheeraert OrderTracking", + "type": "main", + "index": 0 + } + ] + ] + }, + "Lookup Gheeraert OrderTracking": { + "main": [ + [ + { + "node": "Attach Order Context", + "type": "main", + "index": 0 + } + ] + ] + }, + "Make Status Hash": { + "main": [ + [ + { + "node": "Insert ghe_status_log", + "type": "main", + "index": 0 + } + ] + ] + }, + "Insert ghe_status_log": { + "main": [ + [ + { + "node": "If", + "type": "main", + "index": 0 + } + ] + ] + }, + "If": { + "main": [ + [ + { + "node": "Update ghe_order_log", + "type": "main", + "index": 0 + } + ] + ] + }, + "Schedule Trigger": { + "main": [ + [ + { + "node": "Get Orders With Gheeraert ID", + "type": "main", + "index": 0 + } + ] + ] + }, + "Attach Order Context": { + "main": [ + [ + { + "node": "Make Status Hash", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1", + "binaryMode": "separate" + }, + "versionId": "0c994af9-2e64-48c1-80ca-cb00d8ae00e5", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "bef8d409866a58c0777dfe7cca1b9c2400fd051c056d361501393ab423006b5f" + }, + "nodeGroups": [], + "id": "csPbDxZ03HyBjtwh", + "tags": [] +} \ No newline at end of file diff --git a/Gheeraert/Gheeraert workflow 4 — Transpas status XML export.json b/Gheeraert/Gheeraert workflow 4 — Transpas status XML export.json new file mode 100644 index 0000000..e92af84 --- /dev/null +++ b/Gheeraert/Gheeraert workflow 4 — Transpas status XML export.json @@ -0,0 +1,262 @@ +{ + "name": "Gheeraert workflow 4 — Transpas status XML export", + "nodes": [ + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT\n id,\n order_log_id,\n gheeraert_order_id,\n purchase_order_number,\n status_id,\n tracking_date,\n tracking_comments,\n tracking_url,\n barcode,\n user_name,\n transpas_export_status\nFROM public.ghe_status_log\nWHERE COALESCE(transpas_export_status, 'pending') = 'pending'\nORDER BY tracking_date, id\nLIMIT 100;", + "options": {} + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -1552, + -192 + ], + "id": "a00a8bbb-bf11-4292-9520-86aea2ae2dc1", + "name": "Get pending ghe_status_log", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "jsCode": "// n8n Code node: Gheeraert status -> Transpas status XML\n// Mode: Run once for each item\n\nconst AMP_FIX_RE = /&(?!amp;|lt;|gt;|quot;|apos;|#\\d+;|#x[0-9A-Fa-f]+;)/g;\n\nfunction xmlEsc(value) {\n return String(value ?? '')\n .replace(AMP_FIX_RE, '&')\n .replace(//g, '>')\n .replace(/\\\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction formatATDateTime(input) {\n if (!input) return '';\n const d = new Date(input);\n if (isNaN(d.getTime())) return '';\n const pad = (n) => String(n).padStart(2, '0');\n return (\n d.getFullYear() +\n pad(d.getMonth() + 1) +\n pad(d.getDate()) +\n pad(d.getHours()) +\n pad(d.getMinutes()) +\n pad(d.getSeconds())\n );\n}\n\nfunction safeFilePart(value) {\n return String(value || '')\n .replace(/[^a-zA-Z0-9._-]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 80) || 'status';\n}\n\nfunction nowStamp() {\n const d = new Date();\n const p = (n) => String(n).padStart(2, '0');\n return `${d.getFullYear()}${p(d.getMonth() + 1)}${p(d.getDate())}_${p(d.getHours())}${p(d.getMinutes())}${p(d.getSeconds())}_${String(d.getMilliseconds()).padStart(3, '0')}`;\n}\n\nfunction mapStatus(statusId) {\n const sid = Number(statusId);\n switch (sid) {\n case 0: return { export: true, transpasStatus: '0', label: 'Cancelled' };\n case 5: return { export: false, transpasStatus: null, label: 'New' };\n case 10: return { export: true, transpasStatus: null, label: 'Confirmed' };\n case 20: return { export: false, transpasStatus: null, label: 'Accepted' };\n case 21: return { export: false, transpasStatus: null, label: 'Depot_Assigned' };\n case 22: return { export: false, transpasStatus: null, label: 'Planned' };\n case 23: return { export: true, transpasStatus: '23', label: 'Collected' };\n case 24: return { export: true, transpasStatus: '24', label: 'Arrived_At_Depot' };\n case 25: return { export: false, transpasStatus: null, label: 'Storage_At_Depot' };\n case 26: return { export: true, transpasStatus: '26', label: 'Shipped_From_Depot' };\n case 27: return { export: true, transpasStatus: '27', label: 'Incomplete' };\n case 28: return { export: true, transpasStatus: '28', label: 'Manco' };\n case 30: return { export: true, transpasStatus: '30', label: 'Delivered' };\n case 35: return { export: true, transpasStatus: '35', label: 'POD_Online' };\n case 40: return { export: false, transpasStatus: null, label: 'Invoiced' };\n case 50: return { export: false, transpasStatus: null, label: 'Closed' };\n case 100: return { export: false, transpasStatus: null, label: 'Custom_100' };\n default: return { export: false, transpasStatus: null, label: `Unknown_${sid}` };\n }\n}\n\nconst j = $json;\nconst mapped = mapStatus(j.status_id);\nconst atDateTime = formatATDateTime(j.tracking_date);\nconst consignmentId = String(j.purchase_order_number || '').trim();\n\nlet noteParts = [mapped.label, j.tracking_comments || ''];\nif (j.tracking_url) noteParts.push(`POD/URL: ${j.tracking_url}`);\nif (j.barcode) noteParts.push(`Barcode: ${j.barcode}`);\nconst note = noteParts.filter(Boolean).join(' - ');\n\nlet xml = '';\nlet fileName = null;\n\nif (mapped.export && consignmentId && atDateTime) {\n xml = [\n '',\n '',\n ` ${xmlEsc(atDateTime)}`,\n ' TLN',\n ' ',\n ` ${xmlEsc(consignmentId)}`,\n ` ${xmlEsc(mapped.transpasStatus)}`,\n ` ${xmlEsc(note)}`,\n ' ',\n '',\n ].join('\\n');\n\n fileName = `GHE_TLN_${safeFilePart(consignmentId)}_${safeFilePart(mapped.transpasStatus)}_${nowStamp()}.xml`;\n}\n\nreturn {\n json: {\n ...j,\n mapped_label: mapped.label,\n mapped_transpas_status: mapped.transpasStatus,\n should_export_to_transpas: mapped.export,\n transpas_xml: xml || null,\n transpas_xml_file: fileName,\n },\n};" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -1328, + -192 + ], + "id": "ec13ec89-6e87-4ea2-9ac1-a55bae2daef8", + "name": "Build Transpas XML" + }, + { + "parameters": { + "conditions": { + "options": { + "caseSensitive": true, + "leftValue": "", + "typeValidation": "strict", + "version": 3 + }, + "conditions": [ + { + "id": "2aa00fa4-f1bc-490f-ac20-45359523ea8f", + "leftValue": "={{ $json.should_export_to_transpas }}", + "rightValue": "", + "operator": { + "type": "boolean", + "operation": "true", + "singleValue": true + } + } + ], + "combinator": "and" + }, + "options": {} + }, + "type": "n8n-nodes-base.if", + "typeVersion": 2.3, + "position": [ + -1104, + -192 + ], + "id": "1c38efca-a152-4568-a73d-5e4b0710dea9", + "name": "Should export to Transpas?" + }, + { + "parameters": { + "jsCode": "const xml = $json.transpas_xml;\nconst fileName = $json.transpas_xml_file || 'status.xml';\n\nconst binaryData = await this.helpers.prepareBinaryData(\n Buffer.from(xml, 'utf8'),\n fileName,\n 'application/xml'\n);\n\nreturn {\n json: {\n ...$json,\n },\n binary: {\n data: binaryData,\n },\n};" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -880, + -288 + ], + "id": "a384cc7c-6eed-4fdc-b1d2-0a3e0d0bbaa3", + "name": "Create XML Binary" + }, + { + "parameters": { + "protocol": "sftp", + "operation": "upload", + "path": "=/prod/to_tp/tln/{{ $json.transpas_xml_file }}", + "options": {} + }, + "type": "n8n-nodes-base.ftp", + "typeVersion": 1, + "position": [ + -656, + -288 + ], + "id": "b997c3af-a1ff-426a-b1c2-b442aa013a61", + "name": "SFTP Upload", + "credentials": { + "sftp": { + "id": "uKyzg5cSXQqXOuHI", + "name": "SFTP n8n" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "UPDATE public.ghe_status_log\nSET\n transpas_xml_file = $1::varchar,\n transpas_xml_created_at = CURRENT_TIMESTAMP,\n transpas_export_status = 'exported',\n transpas_export_error = NULL\nWHERE id = $2::bigint;", + "options": { + "queryReplacement": "={{ [$json.transpas_xml_file, $json.id] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -432, + -288 + ], + "id": "f0980ea4-86e1-40fe-b616-f6a294606aa1", + "name": "Mark exported", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "WITH input AS (\n SELECT $1::jsonb AS j\n)\nUPDATE public.ghe_status_log\nSET\n transpas_export_status = 'ignored',\n transpas_export_error = (j->>'error_text')::text\nFROM input\nWHERE public.ghe_status_log.id = (j->>'id')::bigint;", + "options": { + "queryReplacement": "={{ [JSON.stringify({ id: $json.id, error_text: 'Status niet geëxporteerd volgens mapping: ' + ($json.mapped_label || 'onbekend') })] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -896, + -96 + ], + "id": "051233d8-8852-4cde-b5ec-4c01d5c7fc80", + "name": "Mark ignored", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "rule": { + "interval": [ + { + "field": "cronExpression", + "expression": "*/20 6-22 * * 1-5" + } + ] + } + }, + "type": "n8n-nodes-base.scheduleTrigger", + "typeVersion": 1.3, + "position": [ + -1760, + -192 + ], + "id": "705a4240-1aa6-44f8-834d-03dc81cc0ca6", + "name": "Schedule Trigger" + } + ], + "pinData": {}, + "connections": { + "Get pending ghe_status_log": { + "main": [ + [ + { + "node": "Build Transpas XML", + "type": "main", + "index": 0 + } + ] + ] + }, + "Build Transpas XML": { + "main": [ + [ + { + "node": "Should export to Transpas?", + "type": "main", + "index": 0 + } + ] + ] + }, + "Should export to Transpas?": { + "main": [ + [ + { + "node": "Create XML Binary", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Mark ignored", + "type": "main", + "index": 0 + } + ] + ] + }, + "Create XML Binary": { + "main": [ + [ + { + "node": "SFTP Upload", + "type": "main", + "index": 0 + } + ] + ] + }, + "SFTP Upload": { + "main": [ + [ + { + "node": "Mark exported", + "type": "main", + "index": 0 + } + ] + ] + }, + "Schedule Trigger": { + "main": [ + [ + { + "node": "Get pending ghe_status_log", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1", + "binaryMode": "separate" + }, + "versionId": "7006b721-596e-4654-96dd-c6d71a1e10e3", + "meta": { + "instanceId": "bef8d409866a58c0777dfe7cca1b9c2400fd051c056d361501393ab423006b5f" + }, + "nodeGroups": [], + "id": "tgpdWats31Z0Idf6", + "tags": [] +} \ No newline at end of file diff --git a/Gheeraert/Gheeraert workflow 5 — POD naar Transpas XML.json b/Gheeraert/Gheeraert workflow 5 — POD naar Transpas XML.json new file mode 100644 index 0000000..45eadd8 --- /dev/null +++ b/Gheeraert/Gheeraert workflow 5 — POD naar Transpas XML.json @@ -0,0 +1,366 @@ +{ + "name": "Gheeraert workflow 5 — POD naar Transpas XML", + "nodes": [ + { + "parameters": { + "operation": "executeQuery", + "query": "SELECT\n id,\n order_log_id,\n gheeraert_order_id,\n purchase_order_number,\n status_id,\n tracking_date,\n tracking_comments,\n tracking_url,\n barcode,\n user_name,\n pod_downloaded,\n pod_file_name,\n pod_downloaded_at,\n transpas_export_status,\n transpas_export_error\nFROM public.ghe_status_log\nWHERE status_id = 35\n AND tracking_url IS NOT NULL\n AND COALESCE(pod_downloaded, false) = false\nORDER BY tracking_date, id\nLIMIT 50;", + "options": {} + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -2432, + -80 + ], + "id": "dde4054e-d2d2-4d79-be5d-ab1f772e23e7", + "name": "Get pending PODs", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "url": "={{ $json.tracking_url }}", + "options": { + "response": { + "response": { + "responseFormat": "file" + } + } + } + }, + "type": "n8n-nodes-base.httpRequest", + "typeVersion": 4.4, + "position": [ + -2192, + -80 + ], + "id": "a94882b8-2b42-4a17-ae8a-0f3df1196a0c", + "name": "Download POD", + "onError": "continueErrorOutput" + }, + { + "parameters": { + "jsCode": "function safeFilePart(value) {\n return String(value || '')\n .replace(/[^a-zA-Z0-9._-]+/g, '_')\n .replace(/^_+|_+$/g, '')\n .slice(0, 80) || 'pod';\n}\n\nfunction nowStampFromInput(input) {\n const d = input ? new Date(input) : new Date();\n const dt = isNaN(d.getTime()) ? new Date() : d;\n const p = (n) => String(n).padStart(2, '0');\n return `${dt.getFullYear()}${p(dt.getMonth() + 1)}${p(dt.getDate())}_${p(dt.getHours())}${p(dt.getMinutes())}${p(dt.getSeconds())}`;\n}\n\nfunction xmlEsc(value) {\n return String(value ?? '')\n .replace(/&(?!amp;|lt;|gt;|quot;|apos;|#\\d+;|#x[0-9A-Fa-f]+;)/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction formatATDateTime(input) {\n if (!input) return '';\n const d = new Date(input);\n if (isNaN(d.getTime())) return '';\n const pad = (n) => String(n).padStart(2, '0');\n return (\n d.getFullYear() +\n pad(d.getMonth() + 1) +\n pad(d.getDate()) +\n pad(d.getHours()) +\n pad(d.getMinutes()) +\n pad(d.getSeconds())\n );\n}\n\nconst j = $json;\nif (!j.tracking_url) {\n throw new Error('tracking_url ontbreekt');\n}\nif (!$binary?.data) {\n throw new Error('Geen binary data gevonden in HTTP download');\n}\n\nlet ext = 'bin';\nlet baseName = '';\ntry {\n const u = new URL(j.tracking_url);\n const pathname = u.pathname || '';\n const parts = pathname.split('/').filter(Boolean);\n baseName = parts.length ? parts[parts.length - 1] : '';\n const m = pathname.match(/\\.([A-Za-z0-9]+)$/);\n if (m) ext = m[1].toLowerCase();\n} catch (e) {}\n\nconst podFileName = `GHE_POD_${safeFilePart(j.purchase_order_number)}_${nowStampFromInput(j.tracking_date)}.${ext}`;\nconst transpasXmlFile = `GHE_POD_XML_${safeFilePart(j.purchase_order_number)}_${nowStampFromInput(j.tracking_date)}.xml`;\nconst atDateTime = formatATDateTime(j.tracking_date) || formatATDateTime(new Date().toISOString());\n\nconst binary = $binary.data;\nbinary.fileName = podFileName;\nbinary.mimeType = binary.mimeType || 'application/octet-stream';\nconst base64Data = binary.data;\n\nconst originalName = baseName || podFileName;\nconst fileType = ext || 'bin';\nconst note = [\n 'POD Online',\n j.tracking_comments || '',\n j.tracking_url ? `URL: ${j.tracking_url}` : '',\n].filter(Boolean).join(' - ');\n\nconst transpasXml = [\n '',\n '',\n ` ${xmlEsc(atDateTime)}`,\n ' TLN',\n ' ',\n ` ${xmlEsc(j.purchase_order_number)}`,\n ' 35',\n ` ${xmlEsc(note)}`,\n ` ${base64Data}`,\n ` ${xmlEsc(originalName)}`,\n ' ',\n ''\n].join('\\n');\n\nreturn {\n json: {\n ...j,\n pod_file_name: podFileName,\n transpas_xml: transpasXml,\n transpas_xml_file: transpasXmlFile,\n },\n binary: {\n data: binary,\n },\n};" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -1952, + -80 + ], + "id": "bc443c37-8620-4c4a-a37d-7c2632a30827", + "name": "Build POD Transpas XML" + }, + { + "parameters": { + "jsCode": "const xml = $json.transpas_xml;\nconst fileName = $json.transpas_xml_file || 'pod_status.xml';\n\nconst binaryData = await this.helpers.prepareBinaryData(\n Buffer.from(xml, 'utf8'),\n fileName,\n 'application/xml'\n);\n\nreturn {\n json: {\n ...$json,\n },\n binary: {\n data: binaryData,\n },\n};" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -1712, + -80 + ], + "id": "6c04eb86-5476-473a-a911-ced8dac43c69", + "name": "Create POD XML Binary" + }, + { + "parameters": { + "protocol": "sftp", + "operation": "upload", + "path": "=/dewit/pod_xml/{{ $json.transpas_xml_file }}", + "options": {} + }, + "type": "n8n-nodes-base.ftp", + "typeVersion": 1, + "position": [ + -1472, + -80 + ], + "id": "c5300449-3418-4f22-99e0-f017dc3e167d", + "name": "SFTP Upload POD XML", + "credentials": { + "sftp": { + "id": "uKyzg5cSXQqXOuHI", + "name": "SFTP n8n" + } + }, + "onError": "continueErrorOutput" + }, + { + "parameters": { + "operation": "executeQuery", + "query": "UPDATE public.ghe_status_log\nSET\n pod_downloaded = true,\n pod_file_name = $1::varchar,\n pod_downloaded_at = CURRENT_TIMESTAMP,\n transpas_xml_file = $2::varchar,\n transpas_xml_created_at = CURRENT_TIMESTAMP,\n transpas_export_status = 'exported',\n transpas_export_error = NULL\nWHERE id = $3::bigint;", + "options": { + "queryReplacement": "={{ [$json.pod_file_name, $json.transpas_xml_file, $json.id] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -1232, + -144 + ], + "id": "117c6ad2-aa7c-41aa-ae45-bf840867fd3b", + "name": "Mark POD Exported", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "UPDATE public.ghe_order_log\nSET\n pod_downloaded_at = CURRENT_TIMESTAMP,\n next_status_poll_at = CURRENT_TIMESTAMP + INTERVAL '1 day'\nWHERE id = $1::bigint;", + "options": { + "queryReplacement": "={{ [$json.order_log_id] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -992, + -144 + ], + "id": "1e1a3c7e-189d-4cb0-89c3-a200409c936d", + "name": "Update ghe_order_log POD", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "operation": "executeQuery", + "query": "WITH input AS (\n SELECT $1::jsonb AS j\n)\nUPDATE public.ghe_status_log\nSET\n transpas_export_status = 'error',\n transpas_export_error = COALESCE(NULLIF(transpas_export_error, ''), '') || CASE WHEN COALESCE(NULLIF(transpas_export_error, ''), '') = '' THEN '' ELSE ' | ' END || (j->>'error_text')::text\nFROM input\nWHERE public.ghe_status_log.id = (j->>'id')::bigint;", + "options": { + "queryReplacement": "={{ [JSON.stringify({ id: $json.id, error_text: $json.error_text || 'POD download/upload/XML verwerking mislukt' })] }}" + } + }, + "type": "n8n-nodes-base.postgres", + "typeVersion": 2.6, + "position": [ + -1472, + 80 + ], + "id": "0a50219a-8844-49fc-89d1-a60cb38d07c3", + "name": "Log POD Error", + "credentials": { + "postgres": { + "id": "pxziuCOuNpsUFKrm", + "name": "transpas_n8n_gheeraert" + } + } + }, + { + "parameters": { + "jsCode": "const err = $json.error || {};\nconst message = err.message || $json.message || 'POD download/upload/XML verwerking mislukt';\nreturn { json: { ...$json, error_text: message } };" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -1952, + 80 + ], + "id": "6aad54d4-797f-4713-83f2-1f61d1600a7b", + "name": "Prepare POD Error" + }, + { + "parameters": { + "jsCode": "const err = $json.error || {};\nconst message = err.message || $json.message || 'SFTP upload POD XML mislukt';\nreturn { json: { ...$json, error_text: message } };" + }, + "type": "n8n-nodes-base.code", + "typeVersion": 2, + "position": [ + -1232, + 80 + ], + "id": "895e1542-95c2-40a6-9101-295480730af2", + "name": "Prepare SFTP Error" + }, + { + "parameters": { + "rule": { + "interval": [ + { + "field": "cronExpression", + "expression": "*/20 6-22 * * 1-5" + } + ] + } + }, + "type": "n8n-nodes-base.scheduleTrigger", + "typeVersion": 1.3, + "position": [ + -2640, + -80 + ], + "id": "1917c911-de8d-4c6b-8d71-cd0884573a08", + "name": "Schedule Trigger" + }, + { + "parameters": { + "protocol": "sftp", + "operation": "list", + "options": {} + }, + "type": "n8n-nodes-base.ftp", + "typeVersion": 1, + "position": [ + -992, + 64 + ], + "id": "8f75c195-722e-4e8c-83ad-19d329cda22e", + "name": "FTP", + "credentials": { + "sftp": { + "id": "uKyzg5cSXQqXOuHI", + "name": "SFTP n8n" + } + } + } + ], + "pinData": {}, + "connections": { + "Get pending PODs": { + "main": [ + [ + { + "node": "Download POD", + "type": "main", + "index": 0 + } + ] + ] + }, + "Download POD": { + "main": [ + [ + { + "node": "Build POD Transpas XML", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Prepare POD Error", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare POD Error": { + "main": [ + [ + { + "node": "Log POD Error", + "type": "main", + "index": 0 + } + ] + ] + }, + "Build POD Transpas XML": { + "main": [ + [ + { + "node": "Create POD XML Binary", + "type": "main", + "index": 0 + } + ] + ] + }, + "Create POD XML Binary": { + "main": [ + [ + { + "node": "SFTP Upload POD XML", + "type": "main", + "index": 0 + } + ] + ] + }, + "SFTP Upload POD XML": { + "main": [ + [ + { + "node": "Mark POD Exported", + "type": "main", + "index": 0 + }, + { + "node": "FTP", + "type": "main", + "index": 0 + } + ], + [ + { + "node": "Prepare SFTP Error", + "type": "main", + "index": 0 + } + ] + ] + }, + "Prepare SFTP Error": { + "main": [ + [ + { + "node": "Log POD Error", + "type": "main", + "index": 0 + } + ] + ] + }, + "Mark POD Exported": { + "main": [ + [ + { + "node": "Update ghe_order_log POD", + "type": "main", + "index": 0 + } + ] + ] + }, + "Schedule Trigger": { + "main": [ + [ + { + "node": "Get pending PODs", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1", + "binaryMode": "separate" + }, + "versionId": "1761ac71-29de-4791-880a-4d790f991107", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "bef8d409866a58c0777dfe7cca1b9c2400fd051c056d361501393ab423006b5f" + }, + "nodeGroups": [], + "id": "CsLGuXIeZQszqTPz", + "tags": [] +} \ No newline at end of file