Upload files to "Gheeraert"
This commit is contained in:
@@ -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": []
|
||||
}
|
||||
@@ -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": []
|
||||
}
|
||||
@@ -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 .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 '<?xml version=\"1.0\" encoding=\"utf-8\"?>',\n '<xmlStat>',\n ` <dateTime type=\"AT\">${xmlEsc(atDateTime)}</dateTime>`,\n ' <codeList>TLN</codeList>',\n ' <consignmentStat>',\n ` <id type=\"NOC\" datatype=\"varchar(50)\">${xmlEsc(consignmentId)}</id>`,\n ` <status>${xmlEsc(mapped.transpasStatus)}</status>`,\n ` <note>${xmlEsc(note)}</note>`,\n ' </consignmentStat>',\n '</xmlStat>',\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": []
|
||||
}
|
||||
@@ -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 .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 '<?xml version=\"1.0\" encoding=\"utf-8\"?>',\n '<xmlStat>',\n ` <dateTime type=\"AT\">${xmlEsc(atDateTime)}</dateTime>`,\n ' <codeList>TLN</codeList>',\n ' <consignmentStat>',\n ` <id type=\"NOC\" datatype=\"varchar(50)\">${xmlEsc(j.purchase_order_number)}</id>`,\n ' <status>35</status>',\n ` <note>${xmlEsc(note)}</note>`,\n ` <signature type=\"CMR\" filetype=\"${xmlEsc(fileType)}\">${base64Data}</signature>`,\n ` <name>${xmlEsc(originalName)}</name>`,\n ' </consignmentStat>',\n '</xmlStat>'\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": []
|
||||
}
|
||||
Reference in New Issue
Block a user