Upload files to "Gheeraert"

This commit is contained in:
2026-07-03 07:29:55 +02:00
parent b140307141
commit 560b30b2b9
4 changed files with 1322 additions and 0 deletions
@@ -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, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\\\"/g, '&quot;')\n .replace(/'/g, '&apos;');\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": []
}