{
  "name": "LGM 07 — Customer Event Recipe (SIMULATED)",
  "nodes": [
    {
      "parameters": {},
      "id": "f07-start",
      "name": "Start",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        120,
        480
      ]
    },
    {
      "parameters": {
        "jsCode": "// Manual-run fixture. Edit branch_hint/event_type here to exercise\n// different downstream paths when you click Execute workflow.\nconst branchHint = 'enquiry.received';\nconst fixture = {\n  event_id: 'EVT-' + Math.floor(Math.random() * 90000 + 10000),\n  event_type: branchHint,\n  received_at: new Date().toISOString(),\n  contact: {\n    name: 'Maya Reeve',\n    phone: '+61400000111',\n    email: 'maya@example.invalid',\n    marketing_consent: true\n  },\n  payload: {\n    suburb: 'Cranbourne',\n    service_type: 'front yard earthworks',\n    budget_aud: 6500,\n    urgency: 'soon'\n  },\n  source: 'manual-test'\n};\nreturn [{ json: fixture }];"
      },
      "id": "f07-manual-fixture",
      "name": "Build Manual Fixture",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        340,
        480
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "lgm-customer-event",
        "responseMode": "lastNode",
        "options": {}
      },
      "id": "f07-webhook",
      "name": "Customer Event Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 1,
      "position": [
        120,
        320
      ],
      "webhookId": "lgm-customer-event"
    },
    {
      "parameters": {
        "jsCode": "// Normalise the inbound event into a stable shape that the rest of the\n// workflow can rely on. Replace per-event validation with stricter schemas\n// when wiring real sources.\nconst items = $input.all();\nconst $json = items[0].json || {};\n\nconst normalized = {\n  event_id: $json.event_id || 'EVT-' + Math.floor(Math.random() * 90000 + 10000),\n  event_type: $json.event_type || 'unknown',\n  received_at: new Date().toISOString(),\n  contact: {\n    name: $json.contact?.name || 'Unknown contact',\n    phone: $json.contact?.phone || '',\n    email: $json.contact?.email || '',\n    marketing_consent: $json.contact?.marketing_consent !== false\n  },\n  payload: $json.payload || {},\n  source: $json.source || 'generic-webhook'\n};\n\nreturn [{ json: normalized }];"
      },
      "id": "f07-normalize",
      "name": "Normalise Event",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        560,
        320
      ]
    },
    {
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "enquiry.received",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "enquiry",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "quote.sent",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "quote",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "job.completed",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "job",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "missed.call",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "missed",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "booking.confirmed",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "booking",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "order.cod",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "cod",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "delivery.failed",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "ndr",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "loyalty.enrol",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "loyalty",
              "renameOutput": true
            },
            {
              "conditions": {
                "options": {
                  "caseSensitive": true,
                  "leftValue": "",
                  "typeValidation": "loose"
                },
                "conditions": [
                  {
                    "leftValue": "={{ $json.event_type }}",
                    "rightValue": "winback.due",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    }
                  }
                ],
                "combinator": "and"
              },
              "outputKey": "winback",
              "renameOutput": true
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "id": "f07-switch",
      "name": "Route by event_type",
      "type": "n8n-nodes-base.switch",
      "typeVersion": 3.2,
      "position": [
        780,
        320
      ]
    },
    {
      "parameters": {
        "jsCode": "// Enquiry branch — handover to flagship pipeline (in production: HTTP POST\n// to the flagship webhook). Here we just emit a simulated handoff so the\n// recipe is runnable without the flagship workflow running.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: enquiry.received' },\n  { type: 'note', label: 'Pattern',\n    text: 'In production this branches to workflow LGM-01 via Execute Workflow (or a separate HTTP endpoint). The recipe keeps the routing key + payload intact.' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-01-flagship-enquiry',\n      trigger: 'enquiry.received',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'enquiry', simulatedOutputs } }];"
      },
      "id": "f07-enq",
      "name": "Handle Enquiry",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        100
      ]
    },
    {
      "parameters": {
        "jsCode": "// Quote branch — handover to LGM-03.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: quote.sent' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-03-quote-followup',\n      trigger: 'quote.sent',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'quote', simulatedOutputs } }];"
      },
      "id": "f07-quote",
      "name": "Handle Quote",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        220
      ]
    },
    {
      "parameters": {
        "jsCode": "// Job-completed branch — handover to LGM-04.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: job.completed' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-04-review-request',\n      trigger: 'job.completed',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'job', simulatedOutputs } }];"
      },
      "id": "f07-job",
      "name": "Handle Job",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        340
      ]
    },
    {
      "parameters": {
        "jsCode": "// Missed-call branch — handover to LGM-02.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: missed.call' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-02-missed-call-textback',\n      trigger: 'missed.call',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'missed', simulatedOutputs } }];"
      },
      "id": "f07-missed",
      "name": "Handle Missed Call",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        460
      ]
    },
    {
      "parameters": {
        "jsCode": "// Booking-confirmed branch — no downstream message by default; updates\n// CRM stage to 'Booked' and emits an internal ack. Customer-selected slot\n// is preserved verbatim in payload.slot.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: booking.confirmed' },\n  { type: 'note', label: 'Pattern',\n    text: 'Booking confirmation: update CRM stage to \"Booked\". Customer-selected slot is echoed from the payload — never auto-pick a slot in production.' },\n  { type: 'code', label: 'CRM update (SIMULATED)',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'crm-update',\n      trigger: 'booking.confirmed',\n      contact: $json.contact,\n      stage: 'Booked',\n      slot: $json.payload?.slot || 'NOT_PROVIDED',\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'booking', simulatedOutputs } }];"
      },
      "id": "f07-booking",
      "name": "Handle Booking",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        580
      ]
    },
    {
      "parameters": {
        "jsCode": "// COD order confirmation — handover to a COD-confirmation pattern.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: order.cod' },\n  { type: 'note', label: 'Pattern',\n    text: 'Cash-on-delivery confirmation: SMS to confirm amount + window, replies YES/NO; if no reply within window, escalate to dispatcher call.' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-cod-confirmation',\n      trigger: 'order.cod',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'cod', simulatedOutputs } }];"
      },
      "id": "f07-cod",
      "name": "Handle COD",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        700
      ]
    },
    {
      "parameters": {
        "jsCode": "// Delivery failed (NDR) — handover to reschedule pattern.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: delivery.failed' },\n  { type: 'note', label: 'Pattern',\n    text: 'Non-delivery report: SMS self-serve reschedule link on first attempt, agent call on second, deposit-required or release on third.' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-ndr-reschedule',\n      trigger: 'delivery.failed',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'ndr', simulatedOutputs } }];"
      },
      "id": "f07-ndr",
      "name": "Handle NDR",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        820
      ]
    },
    {
      "parameters": {
        "jsCode": "// Loyalty enrolment — handover to enrolment welcome.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: loyalty.enrol' },\n  { type: 'note', label: 'Pattern',\n    text: 'Loyalty enrolment: confirm membership, attach member number from CRM, send welcome email; do NOT auto-trigger a campaign — explicit campaign configuration required.' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-loyalty-enrolment',\n      trigger: 'loyalty.enrol',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'loyalty', simulatedOutputs } }];"
      },
      "id": "f07-loyalty",
      "name": "Handle Loyalty",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        940
      ]
    },
    {
      "parameters": {
        "jsCode": "// Winback / rebook — handover to dormancy pattern.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: winback.due' },\n  { type: 'note', label: 'Pattern',\n    text: 'Dormant customer: soft nudge first; opt-out (PAUSE / STOP) keywords must be honoured by the message provider before any further sequence fires.' },\n  { type: 'code', label: 'Handoff payload',\n    language: 'json',\n    body: JSON.stringify({\n      handoff_to: 'lgm-rebook-winback',\n      trigger: 'winback.due',\n      contact: $json.contact,\n      payload: $json.payload,\n      idempotency_key: $json.event_id\n    }, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'winback', simulatedOutputs } }];"
      },
      "id": "f07-winback",
      "name": "Handle Winback",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        1060
      ]
    },
    {
      "parameters": {
        "jsCode": "// Fallback for unknown event_type — log and ack so the source doesn't retry.\nconst items = $input.all();\nconst $json = items[0].json;\nconst simulatedOutputs = [\n  { type: 'heading', label: '1. Recipe: unknown event_type' },\n  { type: 'note', label: 'Ack', text: `Unknown event_type \"${$json.event_type}\"; logged for human review.` },\n  { type: 'code', label: 'Raw event',\n    language: 'json',\n    body: JSON.stringify($json, null, 2) }\n];\nreturn [{ json: { ...$json, branch: 'unknown', simulatedOutputs } }];"
      },
      "id": "f07-unknown",
      "name": "Handle Unknown",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1000,
        1180
      ]
    },
    {
      "parameters": {},
      "id": "f07-sink",
      "name": "Sink",
      "type": "n8n-nodes-base.noOp",
      "typeVersion": 1,
      "position": [
        1240,
        540
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "Build Manual Fixture",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build Manual Fixture": {
      "main": [
        [
          {
            "node": "Normalise Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Customer Event Webhook": {
      "main": [
        [
          {
            "node": "Normalise Event",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Normalise Event": {
      "main": [
        [
          {
            "node": "Route by event_type",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by event_type": {
      "main": [
        [
          {
            "node": "Handle Enquiry",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Quote",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Job",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Missed Call",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Booking",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle COD",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle NDR",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Loyalty",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Winback",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Handle Unknown",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Enquiry": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Quote": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Job": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Missed Call": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Booking": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle COD": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle NDR": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Loyalty": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Winback": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Handle Unknown": {
      "main": [
        [
          {
            "node": "Sink",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "lgm-07-customer-event-recipe",
  "id": "lgm-07-customer-event-recipe",
  "meta": {
    "templateCredsSetupCompleted": false,
    "description": "GENERIC recipe. Manual Trigger + Webhook entrypoints → Normalise → Switch by event_type → simulated handoff payloads. Replace each Handle node with an HTTP call / Execute Workflow / etc. to wire to a real downstream."
  },
  "tags": [
    {
      "name": "lgm-07-customer-event-recipe"
    }
  ]
}
