{
  "id": "S7oD6M9jeI4crXTE",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Mechanical Design Change Approval Workflow",
  "tags": [],
  "nodes": [
    {
      "id": "df5d467f-a92d-4bb7-82c3-50fe15665dd5",
      "name": "Webhook - Receive Drawing Change Request",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -208,
        0
      ],
      "parameters": {
        "path": "drawing-change-request",
        "options": {},
        "httpMethod": "POST",
        "responseMode": "responseNode"
      },
      "typeVersion": 2.1
    },
    {
      "id": "7d142bd4-d69d-43ef-9384-b1630b8faecb",
      "name": "IF - Validate Required Fields",
      "type": "n8n-nodes-base.if",
      "position": [
        48,
        0
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "551f4c78-14de-489c-a042-ba581b3c3675",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{$json.body[\"drawing_no\"]}}",
              "rightValue": ""
            },
            {
              "id": "49c27d9e-2d59-4f90-aef5-d67c8b8cf4ef",
              "operator": {
                "type": "string",
                "operation": "empty",
                "singleValue": true
              },
              "leftValue": "={{$json.body[\"change_reason\"]}}",
              "rightValue": ""
            },
            {
              "id": "6c07ec3b-30ad-4dcf-8be4-5ce9d4396937",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{$json.body[\"change_reason\"].length}}",
              "rightValue": "0"
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "61fa5e4c-35d1-4593-bfbc-14267c572564",
      "name": "Switch - Determine Approver by Impact",
      "type": "n8n-nodes-base.switch",
      "position": [
        896,
        64
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "4cfc044f-bbf0-4eb7-8880-5b315e09c182",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "leftValue": "={{$json.body[\"change_reason\"]}}",
                    "rightValue": "Text"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "ede4491e-c27a-413d-9882-936c9e8bbdb2",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "leftValue": "={{$json.body[\"change_reason\"]}}",
                    "rightValue": "Dimension"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "b2ad2872-6403-43e8-89e6-dba13cc91d02",
                    "operator": {
                      "type": "string",
                      "operation": "contains"
                    },
                    "leftValue": "={{$json.body[\"change_reason\"]}}",
                    "rightValue": "Material"
                  }
                ]
              }
            }
          ]
        },
        "options": {
          "fallbackOutput": "extra"
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "dd868a0c-325c-48b4-89e5-d7e5f9c94407",
      "name": "Set Low",
      "type": "n8n-nodes-base.set",
      "position": [
        1152,
        -224
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d22a6366-6f87-4051-b0a5-d4362f5a8b15",
              "name": "impact_level",
              "type": "string",
              "value": "Low"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "ed7001d2-e187-4ffd-b1ac-544ce52a9131",
      "name": "Set High",
      "type": "n8n-nodes-base.set",
      "position": [
        1152,
        128
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "7f881411-2d27-4fc2-8336-2121f24a2a15",
              "name": "impact_level",
              "type": "string",
              "value": "High"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "3e15a561-ef6f-40b1-83ff-a61a6e176cc2",
      "name": "Set Medium",
      "type": "n8n-nodes-base.set",
      "position": [
        1152,
        -32
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "c0c06460-8771-4f9e-90c2-38bbba6954bc",
              "name": "impact_level",
              "type": "string",
              "value": "Medium"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "0384c030-560b-4f1c-a2a8-881145d88245",
      "name": "Set Medium (Fallback)",
      "type": "n8n-nodes-base.set",
      "position": [
        1152,
        320
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "d85a6aa7-ecaa-49ad-a7c5-352f03ad62a4",
              "name": "impact_level",
              "type": "string",
              "value": "Medium"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "9413b3e4-1858-4fc3-836d-880ac1de6dae",
      "name": "Notify Slack (Approval Request)",
      "type": "n8n-nodes-base.slack",
      "position": [
        1680,
        80
      ],
      "parameters": {
        "text": "=\ud83d\ude80 *New ECR Approval Request*\n\n*ID:* {{ $json.ecr_id }}\n*Reason:* {{ $json.body.change_reason }}\n*Impact:* {{ $json.impact_level }}\n\n\ud83d\udc47 *Action Required:*\n{{ $execution.resumeFormUrl }}",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "=Enter your channel ID"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "3aaa7b82-9ae8-4f5b-bdeb-4b77ad2ac439",
      "name": "Wait (Form)",
      "type": "n8n-nodes-base.wait",
      "position": [
        1872,
        80
      ],
      "parameters": {
        "resume": "form",
        "options": {},
        "formTitle": "Engineering Change Request (ECR) Approval",
        "formFields": {
          "values": [
            {
              "fieldType": "dropdown",
              "fieldLabel": "decision",
              "fieldOptions": {
                "values": [
                  {
                    "option": "approve"
                  },
                  {
                    "option": "reject"
                  }
                ]
              }
            },
            {
              "fieldType": "textarea",
              "fieldLabel": "comment"
            }
          ]
        },
        "formDescription": "Please review the details and provide your decision."
      },
      "typeVersion": 1.1
    },
    {
      "id": "aca62028-ec94-4a5b-b196-66c5ed95842f",
      "name": "Notify Approval (Slack)",
      "type": "n8n-nodes-base.slack",
      "position": [
        2288,
        -16
      ],
      "parameters": {
        "text": "\u2705 ECR Approved. Proceeding to ECO issuance.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "=Enter your channel ID"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "c48e5ef0-4ba5-49f5-a7d0-863903844a36",
      "name": "Notify Rejection (Slack)",
      "type": "n8n-nodes-base.slack",
      "position": [
        2288,
        176
      ],
      "parameters": {
        "text": "=\u274c ECR Rejected. Please review and resubmit.",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "mode": "id",
          "value": "=Enter your channel ID"
        },
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.4
    },
    {
      "id": "77b995f1-0376-4e8f-8924-f4c929ad11f1",
      "name": "Return Response (Error)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        336,
        -128
      ],
      "parameters": {
        "options": {
          "responseCode": 400
        },
        "respondWith": "json",
        "responseBody": "{\"error\": \"drawing_no and change_reason are required fields.\"}"
      },
      "typeVersion": 1.5
    },
    {
      "id": "0c61661d-570e-4cf6-96e3-dc212865eaaf",
      "name": "Generate ECR Metadata (Set Node)",
      "type": "n8n-nodes-base.set",
      "position": [
        704,
        96
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "1160a04b-76b7-4d7c-8cc0-745c3dcda5b3",
              "name": "ecr_id",
              "type": "string",
              "value": "=ECR-{{ $now.format('yyyyMMdd-HHmm') }}"
            },
            {
              "id": "dadf308e-a811-41c5-a066-16067e9d9c0d",
              "name": "token",
              "type": "string",
              "value": "={{ $json.data }}"
            },
            {
              "id": "fcc9fc2f-8a56-49a2-b3f7-ca36f720aeb3",
              "name": "status",
              "type": "string",
              "value": "Pending"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "c1a765da-51c5-4068-b406-a1f90aae42a1",
      "name": "Return Success (Respond to Webhook)",
      "type": "n8n-nodes-base.respondToWebhook",
      "position": [
        1472,
        80
      ],
      "parameters": {
        "options": {},
        "respondWith": "json",
        "responseBody": "={\n  \"message\": \"Request received. Approval process started.\",\n  \"id\": \"{{ $json.ecr_id }}\",\n  \"token\": \"{{ $json.token }}\",\n  \"change_reason\": \"{{ $json.body.change_reason }}\",\n  \"drawing_no\": \"{{ $json.body.drawing_no }}\",\n  \"impact_level\": \"{{ $json.impact_level }}\"\n}\n"
      },
      "typeVersion": 1.5
    },
    {
      "id": "0dc81c06-623d-4123-ac0c-ee4bde72ca62",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1200,
        -704
      ],
      "parameters": {
        "width": 3760,
        "height": 1344,
        "content": "## \u2699\ufe0f Manage Engineering Change Requests (ECR) via Slack\n\n## \ud83d\udccb Overview\nStreamline your engineering change management process by integrating generic webhooks with Slack interactive approvals. This workflow receives a generic design change request, categorizes its impact level, and routes it to a Slack channel for approval.\n\nThis template is ideal for **Mechanical Engineering teams**, **Manufacturing**, and **Project Managers** who need to track drawing changes (ECR/ECO) without complex PLM software.\n\n## \ud83d\ude80 How it works\n1. **Receive Request:** Catches a POST webhook containing `drawing_no` and `change_reason`.\n2. **Validation & Logic:** Ensures data integrity and determines the \"Impact Level\" (High, Medium, Low) based on keywords in the reason (e.g., \"Dimension\" triggers specific logic).\n3. **Notification:** Sends a formatted message to a designated Slack channel with a link to an approval form.\n4. **Human in the Loop:** The workflow waits (pauses) until a reviewer approves or rejects the request via the n8n form.\n5. **Final Notification:** Posts the final decision back to Slack.\n\n## \ud83d\udee0\ufe0f Setup Steps\n1. **Configure Webhook:** Use the production URL of the Webhook node in your upstream application (e.g., Google Forms, internal tools, or Typeform).\n2. **Connect Slack:** Select your Slack credential and choose the channel where approval requests should be sent in the **Notify Slack** nodes.\n3. **Customize Logic:** Open the **Switch** node to adjust the keywords (e.g., \"Material\", \"Dimension\") that determine the impact level according to your company's policy.\n\n## \ud83d\udca1 Requirements\n- n8n (Self-hosted or Cloud)\n- Slack account and a channel for notifications"
      },
      "typeVersion": 1
    },
    {
      "id": "6c2fb377-08f3-4ff9-8cfb-6fd66a138fc5",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -256,
        -144
      ],
      "parameters": {
        "color": 7,
        "width": 752,
        "height": 336,
        "content": "Validate Incoming Request"
      },
      "typeVersion": 1
    },
    {
      "id": "e491d0d3-7b26-476b-8d95-1eb8ba2456de",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        832,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 576,
        "height": 768,
        "content": "Determine Impact Level & Assign Metadata"
      },
      "typeVersion": 1
    },
    {
      "id": "a4398b0b-950b-4f75-99d3-b1d6ee744587",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        1632,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 368,
        "content": " Notify & Wait for Human Approval"
      },
      "typeVersion": 1
    },
    {
      "id": "f6be5eb3-b3f6-4a49-b67a-1f658b069406",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        2048,
        -32
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 368,
        "content": " Process Decision"
      },
      "typeVersion": 1
    },
    {
      "id": "0a650e48-3500-4541-9378-47e66a37b38d",
      "name": "Check Decision",
      "type": "n8n-nodes-base.switch",
      "position": [
        2080,
        80
      ],
      "parameters": {
        "rules": {
          "values": [
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "2e61dd0e-b34a-4f02-991e-6a7dec82599e",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.decision }}",
                    "rightValue": "approve"
                  }
                ]
              }
            },
            {
              "conditions": {
                "options": {
                  "version": 3,
                  "leftValue": "",
                  "caseSensitive": true,
                  "typeValidation": "strict"
                },
                "combinator": "and",
                "conditions": [
                  {
                    "id": "3c40e6af-6b31-4b1d-980f-56ae9d2ea5a1",
                    "operator": {
                      "type": "string",
                      "operation": "equals"
                    },
                    "leftValue": "={{ $json.decision }}",
                    "rightValue": "reject"
                  }
                ]
              }
            }
          ]
        },
        "options": {}
      },
      "typeVersion": 3.4
    },
    {
      "id": "cd65a39e-d449-4f2c-ba21-88b5901521db",
      "name": "Generate Secure Token",
      "type": "n8n-nodes-base.crypto",
      "position": [
        512,
        96
      ],
      "parameters": {
        "action": "generate",
        "encodingType": "hex"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "9ed4ac16-c745-48fb-8a58-d7234c9f671c",
  "connections": {
    "Set Low": {
      "main": [
        [
          {
            "node": "Return Success (Respond to Webhook)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set High": {
      "main": [
        [
          {
            "node": "Return Success (Respond to Webhook)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Medium": {
      "main": [
        [
          {
            "node": "Return Success (Respond to Webhook)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait (Form)": {
      "main": [
        [
          {
            "node": "Check Decision",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Decision": {
      "main": [
        [
          {
            "node": "Notify Approval (Slack)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Notify Rejection (Slack)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate Secure Token": {
      "main": [
        [
          {
            "node": "Generate ECR Metadata (Set Node)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Set Medium (Fallback)": {
      "main": [
        [
          {
            "node": "Return Success (Respond to Webhook)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "IF - Validate Required Fields": {
      "main": [
        [
          {
            "node": "Return Response (Error)",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate Secure Token",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Notify Slack (Approval Request)": {
      "main": [
        [
          {
            "node": "Wait (Form)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate ECR Metadata (Set Node)": {
      "main": [
        [
          {
            "node": "Switch - Determine Approver by Impact",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Return Success (Respond to Webhook)": {
      "main": [
        [
          {
            "node": "Notify Slack (Approval Request)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Switch - Determine Approver by Impact": {
      "main": [
        [
          {
            "node": "Set Low",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Medium",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set High",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Set Medium (Fallback)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook - Receive Drawing Change Request": {
      "main": [
        [
          {
            "node": "IF - Validate Required Fields",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}