{ "name": "Palletways - mail outbound manifest", "nodes": [ { "parameters": { "jsCode": "// Get today's date\nconst today = new Date();\n\n\nconst lastWorkday = new Date(today);\n\n// Format as YYYY-MM-DD\nconst yyyy = lastWorkday.getFullYear();\nconst mm = String(lastWorkday.getMonth() + 1).padStart(2, '0');\nconst dd = String(lastWorkday.getDate()).padStart(2, '0');\nconst formattedDate = `${yyyy}-${mm}-${dd}`;\n\nreturn [\n {\n json: {\n lastWorkday: formattedDate\n }\n }\n];" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 224, 96 ], "id": "87cb7b72-7c12-453d-b59a-b250461783b2", "name": "Last workday1" }, { "parameters": { "options": {} }, "type": "n8n-nodes-base.xml", "typeVersion": 1, "position": [ 896, 0 ], "id": "451e0c99-87ad-43db-9c4e-df5ae16a434b", "name": "XML1" }, { "parameters": { "rule": { "interval": [ { "field": "cronExpression", "expression": "0 21 * * 1-5" } ] } }, "type": "n8n-nodes-base.scheduleTrigger", "typeVersion": 1.2, "position": [ 0, 96 ], "id": "a20fc8f2-6abf-4394-b838-3fb3ed516bea", "name": "Schedule Trigger" }, { "parameters": { "url": "=https://portal.palletways.com/api/getObman/{{ $json[\"lastWorkday\"] }}?apikey=&output=xml", "sendQuery": true, "queryParameters": { "parameters": [ { "name": "apikey", "value": "SXJaM7PLjZDqfsnXSDP8Y9wDY6crxJySBg705MQEPus%3D" }, { "name": "date", "value": "={{ $json[\"lastWorkday\"] }}" }, { "name": "output", "value": "xml" } ] }, "options": {} }, "type": "n8n-nodes-base.httpRequest", "typeVersion": 4.2, "position": [ 448, 96 ], "id": "66d7ad62-59d6-4717-9ba3-9e077e5f9046", "name": "HTTP Request1" }, { "parameters": { "rules": { "values": [ { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "leftValue": "={{ $json.data }}", "rightValue": "No results found", "operator": { "type": "string", "operation": "notContains" }, "id": "de688612-45c4-4848-bc4e-a103c8698662" } ], "combinator": "and" } }, { "conditions": { "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict", "version": 3 }, "conditions": [ { "id": "4a99ac98-84cc-4ac7-a6ca-41b2c483b968", "leftValue": "={{ $json.data }}", "rightValue": "No results found", "operator": { "type": "string", "operation": "contains" } } ], "combinator": "and" } } ] }, "options": {} }, "type": "n8n-nodes-base.switch", "typeVersion": 3.4, "position": [ 672, 96 ], "id": "0289dc6a-3689-4a26-b5d4-c972ffbc94b3", "name": "Switch" }, { "parameters": { "authentication": "webhook", "content": "=Helaas vandaag geen zendingen", "options": {} }, "type": "n8n-nodes-base.discord", "typeVersion": 2, "position": [ 896, 192 ], "id": "2f225c34-5c28-4fb9-83bb-db7a5aa447da", "name": "Discord1", "webhookId": "a58fdc48-676c-4c66-83cc-08d51fe6162e", "credentials": { "discordWebhookApi": { "id": "VYa8b5qqxdFRsDTN", "name": "Discord Webhook account" } } }, { "parameters": { "jsCode": "const dataArray = $input.first().json.results.result || [];\nconst arr = Array.isArray(dataArray) ? dataArray : [dataArray];\nreturn arr.map(item => ({ json: item }));" }, "id": "7cb6c1fb-82ab-4697-a87b-1071ee749f82", "name": "Splits items", "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1120, 0 ] }, { "parameters": { "assignments": { "assignments": [ { "id": "04c98403-7693-44ad-b62a-f0f59263da38", "name": "TrackingID", "value": "={{ $json.TrackingID }}", "type": "string" }, { "id": "aa60dff2-1dbf-4b90-b3fe-075bf4f67e4c", "name": "Lifts", "value": "={{ $json.Lifts }}", "type": "string" }, { "id": "156a7b15-f318-46b2-a3ef-a52b323dddfd", "name": "del_company", "value": "={{ $json.del_company }}", "type": "string" }, { "id": "a581e643-2a9f-42d6-93e5-37550fd150e5", "name": "del_addr1", "value": "={{ $json.del_addr1 }}", "type": "string" }, { "id": "936c0d1e-5aff-4efb-9796-62b82cf926ef", "name": "del_town", "value": "={{ $json.del_town }}", "type": "string" }, { "id": "fb9d6c9f-fa6f-4fc7-8a6b-ddd77b71cd12", "name": "l_binrequest", "value": "={{ $json.l_binrequest }}", "type": "string" }, { "id": "d42734cc-5864-4155-b7e6-337a34d09f34", "name": "del_postcode", "value": "={{ $json.del_postcode }}", "type": "string" }, { "id": "f95601e7-de43-4b6f-9dc2-318b2ddcd510", "name": "", "value": "", "type": "string" } ] }, "options": {} }, "type": "n8n-nodes-base.set", "typeVersion": 3.4, "position": [ 1344, 0 ], "id": "b6a4ecba-a5ef-48fc-bfd2-ad67f4a626a5", "name": "Edit Fields" }, { "parameters": { "jsCode": "// n8n Code node (JavaScript)\n// Input: meerdere items met velden zoals TrackingID, Lifts, del_company, del_addr1, del_town, del_postcode, l_binrequest\n// Output: 1 item met { html, subject, totals... }\n\nfunction escapeHtml(value) {\n const s = String(value ?? '');\n return s\n .replace(/&/g, '&')\n .replace(//g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''');\n}\n\nfunction norm(val) {\n return String(val ?? '').trim();\n}\n\nfunction isYes(val) {\n const v = norm(val).toLowerCase();\n return v === 'yes' || v === 'true' || v === '1' || v === 'ja';\n}\n\n\nconst rows = $input.all().map(i => i.json);\n\n// sorteer op postcode (laag -> hoog), spaties eruit zodat \"3454 PT\" goed sorteert\nrows.sort((a, b) => {\n const pa = String(a?.del_postcode ?? '').toUpperCase().replace(/\\s+/g, '');\n const pb = String(b?.del_postcode ?? '').toUpperCase().replace(/\\s+/g, '');\n return pa.localeCompare(pb, 'nl-NL', { numeric: true, sensitivity: 'base' });\n});\n\n\n\n\n// totalen\nconst totalStops = rows.length;\nconst totalLifts = rows.reduce((sum, r) => sum + (parseInt(r.Lifts, 10) || 0), 0);\nconst bookInYes = rows.reduce((sum, r) => sum + (isYes(r.l_binrequest) ? 1 : 0), 0);\n\n// datum/tijd (Amsterdam)\nconst now = new Date();\nconst ts = new Intl.DateTimeFormat('nl-NL', {\n timeZone: 'Europe/Amsterdam',\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit'\n}).format(now);\n\nconst subject = `Overzicht zendingen (${totalStops} stops / ${totalLifts} lifts) - ${ts}`;\n\nconst headerHtml = `\n
\n
Overzicht zendingen
\n
\n Gemaakt: ${escapeHtml(ts)}
\n Stops: ${escapeHtml(totalStops)}  | \n Lifts: ${escapeHtml(totalLifts)}  | \n Book-in: ${escapeHtml(bookInYes)}\n
\n`;\n\n// tabel header\nconst tableHead = `\n \n \n \n \n \n \n \n \n \n \n \n \n \n`;\n\n// rijen\nconst tableRows = rows.map((r, idx) => {\n const tracking = escapeHtml(norm(r.TrackingID));\n const liftsNum = parseInt(r.Lifts, 10) || 0;\n\n const company = escapeHtml(norm(r.del_company));\n const addr1 = escapeHtml(norm(r.del_addr1));\n const postcode = escapeHtml(norm(r.del_postcode));\n const town = escapeHtml(norm(r.del_town));\n\n const bookIn = isYes(r.l_binrequest);\n const bookInLabel = bookIn ? 'YES' : 'NO';\n\n // zebra + highlight book-in\n const baseBg = (idx % 2 === 0) ? '#ffffff' : '#fafafa';\n const rowBg = bookIn ? '#fff3cd' : baseBg; // licht geel bij book-in\n const rowBorder = '1px solid #eee';\n\n return `\n \n \n \n \n \n \n \n \n \n `;\n}).join('');\n\n// tabel footer + afsluiting\nconst footerHtml = `\n \n
TrackingIDLiftsOntvangerAdresPostcodePlaatsBook-in
${tracking}${escapeHtml(liftsNum)}${company}${addr1}${postcode}${town}\n ${escapeHtml(bookInLabel)}\n
\n\n
\n Dit is een automatische mail.\n
\n
\n`;\n\nconst html = headerHtml + tableHead + tableRows + footerHtml;\n\n// Output als 1 item (handig voor Email node)\nreturn [\n {\n json: {\n subject,\n html,\n totalStops,\n totalLifts,\n bookInYes,\n generatedAt: ts\n }\n }\n];\n" }, "type": "n8n-nodes-base.code", "typeVersion": 2, "position": [ 1568, 0 ], "id": "7f7d3f6d-2f14-4577-b17c-e152b84c6673", "name": "Code in JavaScript" }, { "parameters": { "toRecipients": "jeroen@dmsmail.nl", "subject": "={{$json.subject}}", "bodyContent": "={{$json.html}}", "additionalFields": { "ccRecipients": "p.vanderzaag@dewittransport.nl", "bodyContentType": "html" } }, "type": "n8n-nodes-base.microsoftOutlook", "typeVersion": 2, "position": [ 1792, 0 ], "id": "564694a0-eb48-4719-8206-7d1af11102e3", "name": "Send a message1", "webhookId": "e5bafec1-3fc5-47e6-b233-ceb72cc129eb", "credentials": { "microsoftOutlookOAuth2Api": { "id": "PGANiL6y4sGEEvao", "name": "Microsoft Outlook Palletways" } } } ], "pinData": {}, "connections": { "Last workday1": { "main": [ [ { "node": "HTTP Request1", "type": "main", "index": 0 } ] ] }, "XML1": { "main": [ [ { "node": "Splits items", "type": "main", "index": 0 } ] ] }, "Schedule Trigger": { "main": [ [ { "node": "Last workday1", "type": "main", "index": 0 } ] ] }, "HTTP Request1": { "main": [ [ { "node": "Switch", "type": "main", "index": 0 } ] ] }, "Switch": { "main": [ [ { "node": "XML1", "type": "main", "index": 0 } ], [ { "node": "Discord1", "type": "main", "index": 0 } ] ] }, "Splits items": { "main": [ [ { "node": "Edit Fields", "type": "main", "index": 0 } ] ] }, "Edit Fields": { "main": [ [ { "node": "Code in JavaScript", "type": "main", "index": 0 } ] ] }, "Code in JavaScript": { "main": [ [ { "node": "Send a message1", "type": "main", "index": 0 } ] ] } }, "active": true, "settings": { "executionOrder": "v1", "binaryMode": "separate", "timezone": "Europe/Amsterdam", "callerPolicy": "workflowsFromSameOwner", "availableInMCP": false }, "versionId": "7f7d66d3-e2ef-4f24-b01b-457d58f9a32e", "meta": { "templateCredsSetupCompleted": true, "instanceId": "bef8d409866a58c0777dfe7cca1b9c2400fd051c056d361501393ab423006b5f" }, "nodeGroups": [], "id": "DlRwcKdGRgo0GfJ2", "tags": [ { "updatedAt": "2025-11-11T04:59:39.416Z", "createdAt": "2025-11-11T04:59:39.416Z", "id": "ClOZrAjJKoGLFvaO", "name": "Palletways" } ] }