{
  "nodes": [
    {
      "id": "c7138ff9-2c46-4e55-bef7-19f466c5fd7d",
      "name": "Phone Validator",
      "type": "n8n-nodes-base.code",
      "position": [
        2064,
        1152
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// \u0642\u0627\u0626\u0645\u0629 \u0623\u0643\u0648\u0627\u062f \u0627\u0644\u062f\u0648\u0644\nconst countryCodes = {\n  'OM': '968', 'JO': '962', 'AE': '971', 'SA': '966', 'KW': '965',\n  'QA': '974', 'BH': '973', 'EG': '20', 'IQ': '964', 'LB': '961',\n  'SY': '963', 'PS': '970', 'YE': '967', 'US': '1', 'GB': '44',\n  'DE': '49', 'FR': '33', 'IT': '39', 'ES': '34', 'TR': '90',\n  'IN': '91', 'PK': '92'\n};\n\n// \u062c\u0644\u0628 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0646 fulfilment trigger\nconst fulfillmentData = $('fulfilment').item.json;\n\nconst phone = fulfillmentData.destination?.phone ||\n              fulfillmentData.shipping_address?.phone ||\n              fulfillmentData.phone || \n              '';\n\nconst countryCode = fulfillmentData.destination?.country_code ||\n                    fulfillmentData.shipping_address?.country_code ||\n                    'OM';\n\n// \u062a\u0646\u0636\u064a\u0641 \u0627\u0644\u0631\u0642\u0645\nlet formattedPhone = phone.trim().replace(/\\s+/g, '').replace(/[^0-9+]/g, '');\n\n// \u0644\u0648 \u0627\u0644\u0631\u0642\u0645 \u0641\u0627\u0636\u064a\nif (!formattedPhone || formattedPhone.length < 5) {\n  return {\n    phone: phone,\n    original_phone: phone,\n    country_code: countryCode,\n    validation_status: 'empty_or_invalid'\n  };\n}\n\n// \u0646\u0634\u064a\u0643 \u0625\u0630\u0627 \u0627\u0644\u0631\u0642\u0645 \u0628\u064a\u0628\u062f\u0623 \u0628\u0643\u0648\u062f \u062f\u0648\u0644\u0629\nconst startsWithCode = Object.values(countryCodes).some(code => {\n  const cleanPhone = formattedPhone.replace('+', '');\n  return cleanPhone.startsWith(code);\n});\n\nif (!startsWithCode) {\n  // \u0627\u0644\u0631\u0642\u0645 \u0645\u0627 \u0628\u064a\u0628\u062f\u0623 \u0628\u0643\u0648\u062f - \u0646\u0636\u064a\u0641 \u0627\u0644\u0643\u0648\u062f \u062d\u0633\u0628 \u0627\u0644\u0628\u0644\u062f\n  const defaultCode = countryCodes[countryCode] || '968';\n  const cleanPhone = formattedPhone.replace('+', '');\n  formattedPhone = '+' + defaultCode + cleanPhone;\n} else if (!formattedPhone.startsWith('+')) {\n  // \u0627\u0644\u0643\u0648\u062f \u0645\u0648\u062c\u0648\u062f \u0628\u0633 \u0645\u0627 \u0641\u064a \u0639\u0644\u0627\u0645\u0629 +\n  formattedPhone = '+' + formattedPhone;\n}\n\nreturn {\n  phone: formattedPhone,\n  original_phone: phone,\n  country_code: countryCode,\n  validation_status: 'success'\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "a65aa462-8570-4162-b5a0-63f533f69fa6",
      "name": "Update Order Shipped1",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1632,
        1152
      ],
      "parameters": {
        "query": "UPDATE orders SET status = 'shipped', shipping_company = '{{ ($('fulfilment').item.json.tracking_company || '').replace(/'/g, \"''\") }}', tracking_number = '{{ $('fulfilment').item.json.tracking_number || '' }}' WHERE order_id = {{ $('fulfilment').item.json.order_id }} RETURNING customer_id",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "2b0bb6ff-c294-46f8-b8cd-db64aaa22248",
      "name": "Select rows from a table6",
      "type": "n8n-nodes-base.postgres",
      "position": [
        1872,
        1152
      ],
      "parameters": {
        "limit": 1,
        "table": {
          "__rl": true,
          "mode": "list",
          "value": "customers",
          "cachedResultName": "customers"
        },
        "where": {
          "values": [
            {
              "value": "={{ $('fulfilment').item.json.destination.phone }}",
              "column": "phone"
            }
          ]
        },
        "schema": {
          "__rl": true,
          "mode": "list",
          "value": "public"
        },
        "options": {},
        "operation": "select"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.6
    },
    {
      "id": "fa7ad08f-3440-4c37-ae50-dcf3bf525aa2",
      "name": "Get Customer1",
      "type": "n8n-nodes-base.postgres",
      "position": [
        2256,
        1152
      ],
      "parameters": {
        "query": "SELECT phone, language, first_name FROM customers WHERE website_id = {{ $('Select rows from a table6').item.json.website_id }}",
        "options": {},
        "operation": "executeQuery"
      },
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "5f221872-1c2e-4f0e-90f0-d1fd83b4b142",
      "name": "Check Language",
      "type": "n8n-nodes-base.if",
      "position": [
        2464,
        1152
      ],
      "parameters": {
        "conditions": {
          "string": [
            {
              "value1": "={{ ($('Get Customer1').item.json.language || 'en').trim().substring(0, 2) }}",
              "value2": "ar"
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "a95ed7ff-3755-4f60-bc45-757436a953b5",
      "name": "If10",
      "type": "n8n-nodes-base.if",
      "position": [
        2672,
        960
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "4e62f9c7-e498-4f22-8b94-2d9d2f72a806",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "=+96897666604"
            },
            {
              "id": "fe42ee4c-90fa-4daa-a7fb-be978382acb7",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "+1234567890"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "b63cc981-23db-413b-82ce-368981374730",
      "name": "If11",
      "type": "n8n-nodes-base.if",
      "position": [
        2672,
        1344
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "4e62f9c7-e498-4f22-8b94-2d9d2f72a806",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "=+96897666604"
            },
            {
              "id": "fe42ee4c-90fa-4daa-a7fb-be978382acb7",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $('Phone Validator').item.json.phone }}",
              "rightValue": "+1234567890"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "431ba0fb-59f1-43c9-80f4-239525e516d2",
      "name": "WhatsApp Shipped AR",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2912,
        944
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v18.0/819420977915834/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{ $('Phone Validator').item.json.phone.replace('+', '') }}\",\n  \"type\": \"text\",\n  \"text\": {\n    \"body\": \"\u0645\u0631\u062d\u0628\u064b\u0627 {{ $('Get Customer1').item.json.first_name }}\u060c\\n\\n\u064a\u0633\u0631\u0651\u0646\u0627 \u0625\u0639\u0644\u0627\u0645\u0643\u0645 \u0628\u0623\u0646\u0647 \u062a\u0645 \u0634\u062d\u0646 \u0637\u0644\u0628\u0643\u0645 \u0628\u0646\u062c\u0627\u062d.\\n\u0631\u0642\u0645 \u0627\u0644\u0637\u0644\u0628: {{ $('fulfilment').item.json.order_id }}\\n\u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639: {{ $('fulfilment').item.json.tracking_number }}\\n\u0634\u0631\u0643\u0629 \u0627\u0644\u0634\u062d\u0646: {{ $('fulfilment').item.json.tracking_company }}\\n\u0631\u0627\u0628\u0637 \u0627\u0644\u062a\u062a\u0628\u0639 : {{ $('fulfilment').item.json.tracking_url }}\\n\u0627\u0644\u0645\u062f\u0629 \u0627\u0644\u0645\u062a\u0648\u0642\u0639\u0629 \u0644\u0644\u062a\u0648\u0635\u064a\u0644: \u0645\u0646 7 \u0625\u0644\u0649 12 \u064a\u0648\u0645 \u0639\u0645\u0644.\\n\\n\u064a\u0645\u0643\u0646\u0643\u0645 \u0645\u062a\u0627\u0628\u0639\u0629 \u062d\u0627\u0644\u0629 \u0627\u0644\u0634\u062d\u0646\u0629 \u0639\u0628\u0631 \u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639\u060c \u0648\u0633\u0646\u062d\u0631\u0635 \u0639\u0644\u0649 \u0625\u0628\u0642\u0627\u0626\u0643\u0645 \u0639\u0644\u0649 \u0627\u0637\u0644\u0627\u0639 \u062d\u062a\u0649 \u0627\u0633\u062a\u0644\u0627\u0645 \u0627\u0644\u0637\u0644\u0628.\\n\u0646\u0634\u0643\u0631\u0643\u0645 \u0639\u0644\u0649 \u062b\u0642\u062a\u0643\u0645 \u0628\u0639\u064f\u0645\u0627\u0646 \u0644\u0627\u0643\u062c\u0631\u064a.\\n\\n\u0645\u0639 \u0623\u0637\u064a\u0628 \u0627\u0644\u062a\u062d\u064a\u0627\u062a\u060c\\n\u0639\u064f\u0645\u0627\u0646 \u0644\u0627\u0643\u062c\u0631\u064a\"\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "6d6fac70-72c3-4c35-9291-11e0b63bd4dd",
      "name": "WhatsApp Shipped EN1",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        2912,
        1328
      ],
      "parameters": {
        "url": "https://graph.facebook.com/v18.0/819420977915834/messages",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"messaging_product\": \"whatsapp\",\n  \"to\": \"{{ $('Phone Validator').item.json.phone.replace('+', '') }}\",\n  \"type\": \"text\",\n  \"text\": {\n    \"body\": \"Hello {{ $('Get Customer1').item.json.first_name }},\\n\\nWe are pleased to inform you that your order has been shipped successfully.\\n\\nOrder No: {{ $('fulfilment').item.json.order_id }}\\nTracking No: {{ $('fulfilment').item.json.tracking_number }}\\nCourier Company: {{ $('fulfilment').item.json.tracking_company }}\\nTracking Url: {{ $('fulfilment').item.json.tracking_url }}\\nEstimated delivery time: 7\u201312 business days.\\n\\nYou may track your shipment using the tracking number provided. We will continue to keep you informed until your order is delivered.\\nT  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth"
      },
      "credentials": {
        "httpBearerAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "8ba4a7f3-90d8-4a9f-81d5-6c0aba6b5cc2",
      "name": "fulfilment",
      "type": "n8n-nodes-base.shopifyTrigger",
      "position": [
        1472,
        1152
      ],
      "parameters": {
        "topic": "fulfillments/create",
        "authentication": "accessToken"
      },
      "credentials": {
        "shopifyAccessTokenApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "474ccf63-f94e-40e6-bc63-b41448e7c222",
      "name": "Sticky Note15",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        736,
        320
      ],
      "parameters": {
        "width": 560,
        "height": 1744,
        "content": "---\n\n## \ud83c\udfaf Key Features\n- \u2705 **Real-time Fulfillment Sync:** Instant database update when order ships\n- \u2705 **Complete Tracking Info:** Includes tracking number, company, and URL\n- \u2705 **Bilingual Support:** Auto-detects customer language preference from database\n- \u2705 **Phone Validation:** Handles 23+ country codes with auto-formatting\n- \u2705 **Test Protection:** Prevents notifications to development numbers\n- \u2705 **Personalization:** Uses customer first name in greeting\n- \u2705 **Delivery Expectations:** Sets clear 7-12 day timeline\n- \u2705 **Professional Branding:** Luxury brand tone in both languages\n- \u2705 **Trackable Links:** Includes clickable tracking URL\n\n---\n\n## \ud83d\udcca Database Operations\n\n### **Orders Table Update**\n- **Status Change:** 'open/paid' \u2192 'shipped'\n- **New Fields Added:**\n  - shipping_company: Courier service name\n  - tracking_number: Package tracking ID\n- **Lookup Key:** order_id (from Shopify)\n- **Returns:** customer_id for subsequent queries\n\n### **Customers Table Query**\n- **Lookup:** By website_id (Shopify customer ID)\n- **Retrieved:** phone, language, first_name\n- **Purpose:** Get communication preferences\n\n---\n\n## \ud83d\udcde Technical Details\n- **WhatsApp API Version:** v18.0\n- **API Endpoint:** graph.facebook.com/v18.0/819420977915834/messages\n- **Authentication:** Bearer YOUR_TOKEN_HERE (credential: \"whatsapp mira\")\n- **Phone Format:** International format with country code (+CountryCode + Number)\n- **API Phone Format:** Removes '+' before sending to WhatsApp API\n- **Database:** PostgreSQL\n- **Credential Name:** \"Postgres account\"\n- **Default Country:** Oman (+968) if country_code not detected\n- **Test Numbers Blocked:** \n  - +96897666604 (Oman)\n  - +962798087441 (Jordan)\n\n---\n\n## \ud83d\udd04 Data Flow Summary\n1. **Fulfillment created** \u2192 Shopify webhook fires\n2. **Update order status** \u2192 Mark as 'shipped' with tracking details\n3. **Lookup customer** \u2192 Find by phone from fulfillment data\n4. **Validate phone** \u2192 Format with country code\n5. **Get preferences** \u2192 Retrieve language and name from database\n6. **Detect language** \u2192 Route to AR or EN path\n7. **Filter tests** \u2192 Skip internal phone numbers\n8. **Send notification** \u2192 WhatsApp message with tracking info\n\n---\n\n## \ud83d\udcbc Business Logic\n- **Delivery Window:** Consistently communicates 7-12 business days\n- **Brand Voice:** Professional luxury brand tone\n- **Customer Service:** Proactive communication at shipping milestone\n- **Tracking Empowerment:** Provides all tools for self-service tracking\n- **Multi-channel Sync:** Database, Shopify, and WhatsApp aligned\n\n---\n\n## \ud83c\udf10 Multi-language Support\n| Element | Arabic | English |\n|---------|--------|---------|\n| Greeting | \u0645\u0631\u062d\u0628\u064b\u0627 | Hello |\n| Status | \u062a\u0645 \u0634\u062d\u0646 \u0637\u0644\u0628\u0643\u0645 \u0628\u0646\u062c\u0627\u062d | Successfully shipped |\n| Order No | \u0631\u0642\u0645 \u0627\u0644\u0637\u0644\u0628 | Order No |\n| Tracking No | \u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639 | Tracking No |\n| Courier | \u0634\u0631\u0643\u0629 \u0627\u0644\u0634\u062d\u0646 | Courier Company |\n| Delivery | \u0645\u0646 7 \u0625\u0644\u0649 12 \u064a\u0648\u0645 \u0639\u0645\u0644 | 7\u201312 business days |\n"
      },
      "typeVersion": 1
    },
    {
      "id": "a2592b35-7df6-48c8-b193-48483233cc50",
      "name": "Sticky Note18",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3168,
        832
      ],
      "parameters": {
        "color": 6,
        "width": 672,
        "height": 864,
        "content": "\n### **8A. Arabic Shipping Notification - \"WhatsApp Shipped AR\"**\n- **Type:** HTTP Request (POST)\n- **Endpoint:** Facebook Graph API v18.0 (WhatsApp Business)\n- **Phone Format:** Removes '+' prefix before API call\n- **Message Content (Arabic):**\n  - **Greeting:** \"\u0645\u0631\u062d\u0628\u064b\u0627 [first_name]\" (Hello)\n  - **Status:** \"\u062a\u0645 \u0634\u062d\u0646 \u0637\u0644\u0628\u0643\u0645 \u0628\u0646\u062c\u0627\u062d\" (Your order has been shipped successfully)\n  - **Order Details:**\n    - \u0631\u0642\u0645 \u0627\u0644\u0637\u0644\u0628 (Order No): order_id\n    - \u0631\u0642\u0645 \u0627\u0644\u062a\u062a\u0628\u0639 (Tracking No): tracking_number\n    - \u0634\u0631\u0643\u0629 \u0627\u0644\u0634\u062d\u0646 (Courier): tracking_company\n    - \u0631\u0627\u0628\u0637 \u0627\u0644\u062a\u062a\u0628\u0639 (Tracking URL): tracking_url\n  - **Delivery Time:** 7-12 business days (in Arabic)\n  - **Instructions:** Can track via tracking number\n- **Tone:** Formal, professional Arabic suitable for luxury brand\n- **Purpose:** Send comprehensive shipping notification to Arabic-speaking customers\n\n---\n\n### **8B. English Shipping Notification - \"WhatsApp Shipped EN1\"**\n- **Type:** HTTP Request (POST)\n- **Endpoint:** Same WhatsApp Business API\n- **Phone Format:** Removes '+' prefix\n- **Message Content (English):**\n  - **Greeting:** \"Hello [first_name]\"\n  - **Status:** \"Your order has been shipped successfully\"\n  - **Order Details:**\n    - Order No: order_id\n    - Tracking No: tracking_number\n    - Courier Company: tracking_company\n    - Tracking URL: tracking_url\n  - **Delivery Time:** 7-12 business days\n  - **Instructions:** Track shipment using tracking number\n  \"\n- **Tone:** Professional, informative English\n- **Purpose:** Send comprehensive shipping notification to English-speaking customers\n\n"
      },
      "typeVersion": 1
    }
  ],
  "connections": {
    "If10": {
      "main": [
        [
          {
            "node": "WhatsApp Shipped AR",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If11": {
      "main": [
        [
          {
            "node": "WhatsApp Shipped EN1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "fulfilment": {
      "main": [
        [
          {
            "node": "Update Order Shipped1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Customer1": {
      "main": [
        [
          {
            "node": "Check Language",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Language": {
      "main": [
        [
          {
            "node": "If10",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "If11",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Phone Validator": {
      "main": [
        [
          {
            "node": "Get Customer1",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Order Shipped1": {
      "main": [
        [
          {
            "node": "Select rows from a table6",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Select rows from a table6": {
      "main": [
        [
          {
            "node": "Phone Validator",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}