This workflow corresponds to n8n.io template #14927 — we link there as the canonical source.
This workflow follows the Agent → HTTP Request recipe pattern — see all workflows that pair these two integrations.
The workflow JSON
Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →
{
"nodes": [
{
"id": "sticky-main-overview",
"name": "Sticky Note - Overview",
"type": "n8n-nodes-base.stickyNote",
"position": [
-440,
130
],
"parameters": {
"color": 6,
"width": 380,
"height": 650,
"content": "## QA AUDITOR & SCHEDULER\n\n### Operational Objective\nAudits draft sales orders for data completeness and semantically schedules Odoo activities based on Arabic notes.\n\n### Execution Strategy\n1. **Ingestion:** Merges Sales Orders, Customer Info, and POS Notes into one payload.\n2. **AI Semantic Engine:** Extracts missing fields, maps UTMs, and calculates exact dates from Arabic slang.\n3. **Routing Matrix:** Dynamically updates Odoo records, schedules `mail.activity` tasks, or dispatches automated WhatsApp alerts to the assigned employee."
},
"typeVersion": 1
},
{
"id": "sticky-phase-1",
"name": "Sticky Note - Stage 1",
"type": "n8n-nodes-base.stickyNote",
"position": [
-20,
50
],
"parameters": {
"color": 7,
"width": 1150,
"height": 340,
"content": "## 1. Ingestion & Payload Consolidation\nIteratively queries Odoo for unaudited draft orders. It cross-references associated partner IDs and POS names, merging everything by position into a master JSON."
},
"typeVersion": 1
},
{
"id": "sticky-phase-2",
"name": "Sticky Note - Stage 2",
"type": "n8n-nodes-base.stickyNote",
"position": [
1180,
50
],
"parameters": {
"color": 7,
"width": 550,
"height": 550,
"content": "## 2. LLM Semantic Parsing Engine\nApplies business logic to validate fields and parses Egyptian Arabic slang to identify delivery schedules."
},
"typeVersion": 1
},
{
"id": "sticky-phase-3",
"name": "Sticky Note - Stage 3",
"type": "n8n-nodes-base.stickyNote",
"position": [
1780,
-150
],
"parameters": {
"color": 7,
"width": 1500,
"height": 800,
"content": "## 3. Dynamic Execution & Routing Matrix\nEvaluates the action flag from the AI. Executes parallel updates, creates Odoo activities, or sends targeted staff alerts without intersecting pathways."
},
"typeVersion": 1
},
{
"id": "ec27238c-a2c5-48ec-8da9-2959dd838ee9",
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"position": [
20,
250
],
"parameters": {
"rule": {
"interval": [
{
"field": "minutes",
"minutesInterval": 30
}
]
}
},
"typeVersion": 1.3
},
{
"id": "42a40d75-3d9c-4daf-9a96-3e438ee2e17f",
"name": "Get Sales Orders",
"type": "n8n-nodes-base.odoo",
"position": [
220,
250
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "getAll",
"returnAll": true,
"filterRequest": {
"filter": [
{
"value": "draft",
"fieldName": "state"
},
{
"value": "={{ $now.minus({ hours: 48 }).toFormat('yyyy-MM-dd HH:mm:ss') }}",
"operator": "greaterOrEqual",
"fieldName": "date_order"
},
{
"value": "={{ false }}",
"fieldName": "x_alert_sent"
}
]
},
"customResource": "sale.order"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "fd54222a-1080-45ba-b2d6-24e768eff6a7",
"name": "Get Customer Data",
"type": "n8n-nodes-base.odoo",
"position": [
420,
250
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "get",
"customResource": "res.partner",
"customResourceId": "={{ $json.partner_id[0] }}"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "160ae58d-29ce-4508-a133-92dd48a56b44",
"name": "Get POS Order",
"type": "n8n-nodes-base.odoo",
"position": [
620,
150
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "getAll",
"returnAll": true,
"filterRequest": {
"filter": [
{
"value": "={{ $('Get Sales Orders').item.json.origin }}",
"fieldName": "name"
}
]
},
"customResource": "pos.order"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"retryOnFail": false,
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "0c39ed00-db17-4fba-8a93-c95747c76ae4",
"name": "Get many items",
"type": "n8n-nodes-base.odoo",
"position": [
820,
150
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "getAll",
"returnAll": true,
"filterRequest": {
"filter": [
{
"value": "={{ $('Get POS Order').item.json.id }}",
"fieldName": "order_id"
}
]
},
"customResource": "pos.order.line"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1,
"alwaysOutputData": true
},
{
"id": "c3fdb2be-718a-4490-8cc6-5029c48796a4",
"name": "Merge",
"type": "n8n-nodes-base.merge",
"position": [
1000,
250
],
"parameters": {
"mode": "combine",
"options": {},
"combineBy": "combineByPosition"
},
"typeVersion": 3.2
},
{
"id": "24bd423d-11ad-4cec-932f-452b9d0015c0",
"name": "Edit Fields",
"type": "n8n-nodes-base.set",
"position": [
1220,
250
],
"parameters": {
"options": {},
"assignments": {
"assignments": [
{
"id": "e8453312-ee53-4283-8cc3-29392887addf",
"name": "id",
"type": "string",
"value": "={{ $json.id }}"
},
{
"id": "1ad1b188-07dd-465c-9126-c3c985a850ce",
"name": "name",
"type": "string",
"value": "={{ $json.name }}"
},
{
"id": "88f09236-6ad8-4b10-b393-0538616de515",
"name": "partner_id",
"type": "string",
"value": "={{ $json.partner_id }}"
},
{
"id": "9ad2f57a-a361-4282-9028-8e3fe856fb55",
"name": "phone",
"type": "string",
"value": "={{ $json.phone }}"
},
{
"id": "86f9bb21-aaa4-40e1-a60e-4fd37c5e3bca",
"name": "mobile",
"type": "string",
"value": "={{ $json.mobile }}"
},
{
"id": "20eb273a-0f18-45ab-9ab1-f0676a7eb1f7",
"name": "street",
"type": "string",
"value": "={{ $json.street }}"
},
{
"id": "22b26f53-ea76-4e9a-ba9f-d95773490e20",
"name": "city",
"type": "string",
"value": "={{ $json.city }}"
},
{
"id": "cba994e3-93a7-42f7-ab69-f0e0e6969b31",
"name": "state_id",
"type": "string",
"value": "={{ $json.state_id }}"
},
{
"id": "a0fde605-43ba-46c5-b3c9-a818214529dc",
"name": "source_id",
"type": "string",
"value": "={{ $('Get Sales Orders').item.json.source_id[1] }}"
},
{
"id": "415a016e-5e81-47d9-acf5-75806fcb22a1",
"name": "note",
"type": "string",
"value": "={{ $('Get POS Order').item.json.general_note }}"
},
{
"id": "53571f5b-e4c8-4fef-bb56-f1c94ff57c84",
"name": "pricelist_id",
"type": "string",
"value": "={{ $json.pricelist_id }}"
},
{
"id": "ae7431be-5b38-4d78-a103-3c5219afa110",
"name": "user_id",
"type": "string",
"value": "={{ $json.user_id }}"
},
{
"id": "9e5624e3-e4fb-41b0-b42b-90310a876c4a",
"name": "customer_note",
"type": "string",
"value": "={{ $('Get many items').item.json.customer_note }}"
}
]
}
},
"typeVersion": 3.4
},
{
"id": "2d2db425-f478-4057-b228-7b85f052995c",
"name": "AI Agent",
"type": "@n8n/n8n-nodes-langchain.agent",
"position": [
1440,
250
],
"parameters": {
"text": "=Today's Date: {{ $now.toFormat('yyyy-MM-dd') }}\nToday's Day: {{ $now.toFormat('EEEE') }}\n\nAnalyze the following Odoo order data and provide the JSON response according to the system instructions:\n\n{{ JSON.stringify($json) }}",
"options": {
"systemMessage": "You are an Odoo Data Analyst. Your task is to analyze the provided JSON order data and determine the required action based on these logic rules:\n\n1. **Website Orders Fast-Track (PRIORITY OVERRIDE)**:\n - Inspect the \"source_id\" field. If it is NOT \"false\", null, or empty (meaning the order came from the website):\n - STOP ALL further analysis.\n - Immediately set \"action\" to \"nothing\".\n - Set \"extracted_source\" to \"Already Exists\".\n - Keep \"missing_fields\" empty, \"customer_reference\" null, and \"schedule_activity.needs_scheduling\" to false.\n\n2. **Source Mapping (For POS/Manual Orders ONLY - If source_id is false/empty)**:\n - Inspect the \"note\" field to determine the source.\n - If it contains \"Meta\", set \"extracted_source\" to \"Social Media (Meta)\".\n - If it contains \"TikTok\", set \"extracted_source\" to \"Social Media (TikTok)\".\n - If it contains \"Other\", set \"extracted_source\" to \"Social Media (Other)\".\n - Otherwise, set \"extracted_source\" to \"None\".\n\n3. **Check Completeness (For POS/Manual Orders ONLY)**:\n - Inspect these fields: [street, city, state_id]. If any is \"false\", null, or an empty string, add it to the \"missing_fields\" array.\n - **Phone Rule**: Check \"phone\" and \"mobile\". If BOTH are \"false\" or empty, add \"phone\" to missing_fields. If AT LEAST ONE is valid, do NOT add them.\n - **Source Rule (CRITICAL)**: If \"extracted_source\" is \"None\", you MUST add \"note\" to the \"missing_fields\" array.\n\n4. **Customer Note & Scheduling Analysis (For POS/Manual Orders ONLY)**:\n - Look for the customer note field in the provided data.\n - If a note exists, extract its exact Arabic text and set it as \"customer_reference\". If no note exists, set it to null.\n - Analyze the note's context using semantic understanding (Customers may use Egyptian slang, misspellings, or various formats for dates):\n - If the note implies ANY future delivery date, postponement, or specific timeframe (e.g., \"\u0628\u0643\u0631\u0629\", \"\u0643\u0645\u0627\u0646 \u064a\u0648\u0645\u064a\u0646\", \"\u064a\u0648\u0645 \u0627\u0644\u062a\u0644\u0627\u062a\", \"\u0627\u0648\u0644 \u0627\u0644\u0634\u0647\u0631\", \"\u0628\u0639\u062f \u0627\u0633\u0628\u0648\u0639\", \"\u062a\u0623\u062c\u064a\u0644 \u0644\u064a\u0648\u0645 25\"), set \"schedule_activity.needs_scheduling\" to true.\n - Calculate the exact \"due_date\" in \"YYYY-MM-DD\" format strictly based on Today's Date (provided in the user text). Smartly handle relative dates.\n - Write a short, clear \"summary\" (e.g., \"\u0645\u064a\u0639\u0627\u062f \u0627\u0633\u062a\u0644\u0627\u0645: \u063a\u062f\u0627\u064b\", \"\u062a\u0623\u062c\u064a\u0644 \u0625\u0644\u0649 \u064a\u0648\u0645 \u0627\u0644\u062b\u0644\u0627\u062b\u0627\u0621\").\n - If the note contains only general instructions with NO timing attached (e.g., \"\u062a\u063a\u0644\u064a\u0641 \u062c\u064a\u062f\", \"\u0628\u062f\u0648\u0646 \u0641\u0627\u062a\u0648\u0631\u0629\", \"\u0631\u0646 \u0639\u0644\u064a\u0627 \u0642\u0628\u0644\u0647\u0627\") or if there is no note, set \"needs_scheduling\" to false and \"due_date\" to null.\n\n5. **Determine Action (For POS/Manual Orders)**:\n - \"nothing\": \"extracted_source\" is NOT \"None\", \"missing_fields\" is empty, AND \"customer_reference\" is null. (Note: Website orders automatically get this action via Rule 1).\n - \"update_only\": \"missing_fields\" is empty, AND (\"extracted_source\" is newly found OR \"customer_reference\" has text that needs to be saved).\n - \"update_and_alert\": \"missing_fields\" is NOT empty, BUT a valid source exists.\n - \"alert_only\": \"extracted_source\" is \"None\".\n\n**Output Requirement**: You must respond ONLY with a valid JSON object in this format:\n{\n \"action\": \"string\",\n \"extracted_source\": \"string\",\n \"missing_fields\": [\"field1\", \"field2\"],\n \"customer_reference\": \"string or null\",\n \"schedule_activity\": {\n \"needs_scheduling\": true or false,\n \"due_date\": \"YYYY-MM-DD or null\",\n \"summary\": \"string or null\"\n },\n \"reason\": \"Brief explanation in Arabic\"\n}"
},
"promptType": "define",
"hasOutputParser": true
},
"typeVersion": 3.1
},
{
"id": "b8f5fd01-1013-4027-9ab9-be1dac56aa7f",
"name": "OpenAI Chat Model",
"type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
"position": [
1340,
450
],
"parameters": {
"model": {
"__rl": true,
"mode": "list",
"value": "gpt-4o-mini"
},
"options": {},
"builtInTools": {}
},
"credentials": {
"openAiApi": {
"name": "<your credential>"
}
},
"typeVersion": 1.3
},
{
"id": "c56c6e53-e13c-4bd5-bc87-8e35bfc1607e",
"name": "Simple Memory",
"type": "@n8n/n8n-nodes-langchain.memoryBufferWindow",
"position": [
1520,
450
],
"parameters": {
"sessionKey": "chat_history",
"sessionIdType": "customKey",
"contextWindowLength": 60
},
"typeVersion": 1.3
},
{
"id": "37762191-acdc-4302-845c-2709d14a9b68",
"name": "Switch",
"type": "n8n-nodes-base.switch",
"position": [
1800,
250
],
"parameters": {
"rules": {
"values": [
{
"outputKey": "Update and Alert",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5dad5653-9b51-41eb-aab8-0112cd029007",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ JSON.parse($json.output).action }}",
"rightValue": "update_and_alert"
}
]
},
"renameOutput": true
},
{
"outputKey": "Update Only",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5b6649c6-5096-43c7-9dbf-1ea634dd4683",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ JSON.parse($json.output).action }}",
"rightValue": "update_only"
}
]
},
"renameOutput": true
},
{
"outputKey": "Alert Only",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "c843a7b3-92b9-44c9-97c3-99c678441fde",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ JSON.parse($json.output).action }}",
"rightValue": "alert_only"
}
]
},
"renameOutput": true
},
{
"outputKey": "Nothing",
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "9c3bb943-2f23-41b9-b7ff-c44a8acebf1a",
"operator": {
"name": "filter.operator.equals",
"type": "string",
"operation": "equals"
},
"leftValue": "={{ JSON.parse($json.output).action }}",
"rightValue": "nothing"
}
]
},
"renameOutput": true
}
]
},
"options": {}
},
"typeVersion": 3.4
},
{
"id": "bfd19eae-a585-4645-a400-02716f4beb78",
"name": "Get Source ID",
"type": "n8n-nodes-base.odoo",
"position": [
2050,
-50
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "getAll",
"filterRequest": {
"filter": [
{
"value": "={{ JSON.parse($json.output).extracted_source }}",
"fieldName": "name"
}
]
},
"customResource": "utm.source"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "426ada44-0969-4576-88fc-273a67ba0877",
"name": "Update Sales Order",
"type": "n8n-nodes-base.odoo",
"position": [
2250,
-50
],
"parameters": {
"resource": "custom",
"operation": "update",
"customResource": "sale.order",
"customResourceId": "={{ $('Get Sales Orders').first().json.id }}",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "source_id",
"fieldValue": "={{ $json.id }}"
},
{
"fieldName": "pricelist_id",
"fieldValue": "={{ $('Get POS Order').item.json.pricelist_id[0] }}"
},
{
"fieldName": "client_order_ref",
"fieldValue": "={{ JSON.parse($('AI Agent').item.json.output).customer_reference }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "c9b41d7e-b6bd-49b1-9b16-b22346e87207",
"name": "Get User Partner",
"type": "n8n-nodes-base.odoo",
"position": [
2480,
50
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "get",
"customResource": "res.users",
"customResourceId": "={{ $('Get Sales Orders').first().json.user_id[0] }}"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "d92097ed-858a-4ace-a107-189ef8d83c72",
"name": "Loop Over Items",
"type": "n8n-nodes-base.splitInBatches",
"position": [
2680,
50
],
"parameters": {
"options": {}
},
"typeVersion": 3
},
{
"id": "c8260a35-3284-430b-a8e0-0d0e35d08041",
"name": "WhatsApp Alert",
"type": "n8n-nodes-base.httpRequest",
"onError": "continueRegularOutput",
"position": [
2880,
50
],
"parameters": {
"url": "=https://YOUR_EVOLUTION_API_URL/message/sendText/{{ Math.random() < 0.5 ? 'instance1' : 'instance2' }}",
"method": "POST",
"options": {},
"sendBody": true,
"sendHeaders": true,
"bodyParameters": {
"parameters": [
{
"name": "number",
"value": "=={{ $json.phone_sanitized ? $json.phone_sanitized.replace(/\\D/g, '') : '' }}"
},
{
"name": "text",
"value": "=={{ \n (() => {\n const employeeName = $('Get Sales Orders').item.json.user_id ? $('Get Sales Orders').item.json.user_id[1] : \"\u0632\u0645\u064a\u0644\u0646\u0627 \u0627\u0644\u0639\u0632\u064a\u0632\";\n const customerName = $('Get Sales Orders').item.json.partner_id ? $('Get Sales Orders').item.json.partner_id[1] : \"\u063a\u064a\u0631 \u0645\u062d\u062f\u062f\";\n const orderName = $('Get Sales Orders').item.json.name;\n const orderId = $('Get Sales Orders').item.json.id;\n \n const aiOutput = JSON.parse($('Switch').item.json.output);\n const missing = aiOutput.missing_fields || [];\n \n const fieldNames = {\n \"phone\": \"\u0631\u0642\u0645 \u0627\u0644\u0647\u0627\u062a\u0641\",\n \"mobile\": \"\u0631\u0642\u0645 \u0627\u0644\u0645\u0648\u0628\u0627\u064a\u0644\",\n \"state_id\": \"\u0627\u0644\u0645\u062d\u0627\u0641\u0638\u0629\",\n \"city\": \"\u0627\u0644\u0645\u062f\u064a\u0646\u0629\",\n \"street\": \"\u0627\u0644\u0639\u0646\u0648\u0627\u0646 \u0628\u0627\u0644\u062a\u0641\u0635\u064a\u0644\",\n \"note\": \"\u0645\u0635\u062f\u0631 \u0627\u0644\u0637\u0644\u0628 (\u0627\u0644\u0633\u0648\u0631\u0633)\"\n };\n \n const missingText = missing.map(f => \"\ud83d\udccd \" + (fieldNames[f] || f)).join('\\n');\n const orderLink = `https://YOUR_ODOO_DOMAIN.com/odoo/sales/${orderId}`;\n \n return `\ud83d\udce2 *\u062a\u0646\u0628\u064a\u0647 \u0645\u0646 \u0625\u062f\u0627\u0631\u0629 XQ Pharma*\\n\\n\u064a\u0627 \u0623\u0633\u062a\u0627\u0630 ${employeeName}\u060c\\n\\n\u064a\u0631\u062c\u0649 \u0627\u0644\u0639\u0644\u0645 \u0623\u0646 \u0627\u0644\u0637\u0644\u0628 \u0631\u0642\u0645 *(${orderName})* \u0627\u0644\u062e\u0627\u0635 \u0628\u0627\u0644\u0639\u0645\u064a\u0644 *(${customerName})* \u062a\u0645 \u0625\u0646\u0634\u0627\u0624\u0647 \u0628\u0628\u064a\u0627\u0646\u0627\u062a \u0646\u0627\u0642\u0635\u0629\u060c \u0645\u0645\u0627 \u0642\u062f \u064a\u0639\u0637\u0644 \u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u0634\u062d\u0646.\\n\\n*\u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0645\u0637\u0644\u0648\u0628\u0629:*\\n${missingText}\\n\\n\u064a\u0631\u062c\u0649 \u0627\u0633\u062a\u0643\u0645\u0627\u0644 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0641\u0648\u0631\u0627\u064b \u0645\u0646 \u062e\u0644\u0627\u0644 \u0627\u0644\u0631\u0627\u0628\u0637 \u0627\u0644\u062a\u0627\u0644\u064a:\\n\ud83d\udd17 ${orderLink}\\n\\n\u0634\u0643\u0631\u0627\u064b \u0644\u062a\u0639\u0627\u0648\u0646\u0643.`;\n })() \n}}"
}
]
},
"headerParameters": {
"parameters": [
{
"name": "apikey",
"value": "YOUR_API_KEY_HERE"
}
]
}
},
"typeVersion": 4.3
},
{
"id": "44957777-4c44-4228-8534-b83c1e77b11a",
"name": "Mark Alert Sent",
"type": "n8n-nodes-base.odoo",
"position": [
3080,
50
],
"parameters": {
"resource": "custom",
"operation": "update",
"customResource": "sale.order",
"customResourceId": "={{ $('Get Sales Orders').first().json.id }}",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "x_alert_sent",
"fieldValue": "={{ true }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "7f4973c8-f9c4-4faa-baf2-2988080786e7",
"name": "Get Source ID2",
"type": "n8n-nodes-base.odoo",
"position": [
2050,
250
],
"parameters": {
"options": {},
"resource": "custom",
"operation": "getAll",
"filterRequest": {
"filter": [
{
"value": "={{ JSON.parse($json.output).extracted_source }}",
"fieldName": "name"
}
]
},
"customResource": "utm.source"
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "808b2b60-c3c5-43d2-9108-7f2aef3fb03a",
"name": "Update Sales Order2",
"type": "n8n-nodes-base.odoo",
"position": [
2250,
250
],
"parameters": {
"resource": "custom",
"operation": "update",
"customResource": "sale.order",
"customResourceId": "={{ $('Get Sales Orders').all()[$itemIndex].json.id }}",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "source_id",
"fieldValue": "={{ $json.id }}"
},
{
"fieldName": "pricelist_id",
"fieldValue": "={{ $('Get POS Order').item.json.pricelist_id[0] }}"
},
{
"fieldName": "client_order_ref",
"fieldValue": "={{ JSON.parse($('AI Agent').item.json.output).customer_reference }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
},
"alwaysOutputData": "<your credential>"
},
"typeVersion": 1
},
{
"id": "6928f7a2-493e-4d57-a2f7-b3753dacbabd",
"name": "If Needs Scheduling",
"type": "n8n-nodes-base.if",
"position": [
2480,
250
],
"parameters": {
"options": {},
"conditions": {
"options": {
"version": 3,
"leftValue": "",
"caseSensitive": true,
"typeValidation": "strict"
},
"combinator": "and",
"conditions": [
{
"id": "5c905e69-717b-42b4-910e-e8e0a4dcaacc",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
},
"leftValue": "={{ JSON.parse($('AI Agent').item.json.output).schedule_activity.needs_scheduling }}",
"rightValue": ""
}
]
}
},
"typeVersion": 2.3
},
{
"id": "1690dc40-208f-4408-9815-32baa4bdcaaa",
"name": "Create Activity",
"type": "n8n-nodes-base.odoo",
"position": [
2720,
180
],
"parameters": {
"resource": "custom",
"customResource": "mail.activity",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "date_deadline",
"fieldValue": "={{ JSON.parse($('AI Agent').item.json.output).schedule_activity.due_date }}"
},
{
"fieldName": "summary",
"fieldValue": "={{ JSON.parse($('AI Agent').item.json.output).schedule_activity.summary }}"
},
{
"fieldName": "user_id",
"fieldValue": "={{ $('Get Sales Orders').item.json.user_id ? $('Get Sales Orders').item.json.user_id[0] : undefined }}"
},
{
"fieldName": "activity_type_id",
"fieldValue": "={{ 4 }}"
},
{
"fieldName": "res_model_id",
"fieldValue": "={{ 586 }}"
},
{
"fieldName": "res_id",
"fieldValue": "={{ $json.id }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "4c34022a-583e-4d32-aa22-974388953304",
"name": "Mark Alert Sent1",
"type": "n8n-nodes-base.odoo",
"position": [
2920,
180
],
"parameters": {
"resource": "custom",
"operation": "update",
"customResource": "sale.order",
"customResourceId": "={{ $('Get Sales Orders').all()[$itemIndex].json.id }}",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "x_alert_sent",
"fieldValue": "={{ true }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "b86e0fd8-397e-4afa-9053-605a260a7a67",
"name": "Mark Alert Sent3",
"type": "n8n-nodes-base.odoo",
"position": [
2720,
340
],
"parameters": {
"resource": "custom",
"operation": "update",
"customResource": "sale.order",
"customResourceId": "={{ $('Get Sales Orders').all()[$itemIndex].json.id }}",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "x_alert_sent",
"fieldValue": "={{ true }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
},
{
"id": "88ade31a-d77e-4377-b9bb-2b4cdcf419d2",
"name": "Mark Alert Sent2",
"type": "n8n-nodes-base.odoo",
"position": [
2050,
480
],
"parameters": {
"resource": "custom",
"operation": "update",
"customResource": "sale.order",
"customResourceId": "={{ $('Get Sales Orders').item.json.id }}",
"fieldsToCreateOrUpdate": {
"fields": [
{
"fieldName": "x_alert_sent",
"fieldValue": "={{ true }}"
}
]
}
},
"credentials": {
"odooApi": {
"name": "<your credential>"
}
},
"typeVersion": 1
}
],
"connections": {
"Merge": {
"main": [
[
{
"node": "Edit Fields",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "Get Source ID",
"type": "main",
"index": 0
}
],
[
{
"node": "Get Source ID2",
"type": "main",
"index": 0
}
],
[
{
"node": "Get User Partner",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Alert Sent2",
"type": "main",
"index": 0
}
]
]
},
"AI Agent": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Edit Fields": {
"main": [
[
{
"node": "AI Agent",
"type": "main",
"index": 0
}
]
]
},
"Get POS Order": {
"main": [
[
{
"node": "Get many items",
"type": "main",
"index": 0
}
]
]
},
"Get Source ID": {
"main": [
[
{
"node": "Update Sales Order",
"type": "main",
"index": 0
}
]
]
},
"Simple Memory": {
"ai_memory": [
[
{
"node": "AI Agent",
"type": "ai_memory",
"index": 0
}
]
]
},
"Get Source ID2": {
"main": [
[
{
"node": "Update Sales Order2",
"type": "main",
"index": 0
}
]
]
},
"Get many items": {
"main": [
[
{
"node": "Merge",
"type": "main",
"index": 1
}
]
]
},
"WhatsApp Alert": {
"main": [
[
{
"node": "Mark Alert Sent",
"type": "main",
"index": 0
}
]
]
},
"Create Activity": {
"main": [
[
{
"node": "Mark Alert Sent1",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "WhatsApp Alert",
"type": "main",
"index": 0
}
]
]
},
"Mark Alert Sent": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Get Sales Orders": {
"main": [
[
{
"node": "Get Customer Data",
"type": "main",
"index": 0
}
]
]
},
"Get User Partner": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"Schedule Trigger": {
"main": [
[
{
"node": "Get Sales Orders",
"type": "main",
"index": 0
}
]
]
},
"Get Customer Data": {
"main": [
[
{
"node": "Get POS Order",
"type": "main",
"index": 0
},
{
"node": "Merge",
"type": "main",
"index": 0
}
]
]
},
"OpenAI Chat Model": {
"ai_languageModel": [
[
{
"node": "AI Agent",
"type": "ai_languageModel",
"index": 0
}
]
]
},
"Update Sales Order": {
"main": [
[
{
"node": "Get User Partner",
"type": "main",
"index": 0
}
]
]
},
"If Needs Scheduling": {
"main": [
[
{
"node": "Create Activity",
"type": "main",
"index": 0
}
],
[
{
"node": "Mark Alert Sent3",
"type": "main",
"index": 0
}
]
]
},
"Update Sales Order2": {
"main": [
[
{
"node": "If Needs Scheduling",
"type": "main",
"index": 0
}
]
]
}
}
}
Credentials you'll need
Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.
alwaysOutputDataodooApiopenAiApi
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
Manual order entry in retail and e-commerce often results in fragmented data. Sales representatives might skip mandatory address fields or write critical delivery instructions in unstructured, regional slang inside the POS notes.
Source: https://n8n.io/workflows/14927/ — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
What this workflow does
This workflow is for beauty salons who want consistent, high‑quality social media content without writing every post manually. It also suits agencies and automation builders who manage multiple beauty
This workflow was born out of a very real problem.
Content marketers and SEO specialists who need to generate multiple SEO-optimized articles targeting keyword variations. Ideal for affiliate sites, niche blogs, or service-based businesses creating lo
This workflow automates end-to-end sustainability lifecycle management for corporate sustainability teams, ESG governance officers, and circular economy programme leads. It addresses the challenge of