{
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodes": [
    {
      "id": "a353a1ba-6ba7-4422-9b10-fb3be59ea16b",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2480,
        -880
      ],
      "parameters": {
        "width": 476,
        "height": 680,
        "content": "## How it works\n\nThis workflow automates purchase order creation with AI-powered supplier selection. It receives purchase requests, validates data and calculates totals, then uses AI to analyze requirements and recommend the optimal supplier based on cost, delivery speed, and item specialization. High-value orders (>$5k) route through email approval. Once approved, the system generates a professional PO PDF with AI insights, archives it to Google Drive, emails it to the supplier, and notifies your procurement team via Slack.\n\n## Setup steps\n\n1. **Configure webhook** - Connect from your procurement system or request form\n2. **Add OpenAI API key** - For AI supplier recommendations (GPT-4 recommended)\n3. **Customize supplier database** - Edit supplier list in \"Enrich with Supplier Data\" node\n4. **Set approval threshold** - Adjust $5k limit in \"Validate Request\" node if needed\n5. **Add HTML to PDF API** - Get key at htmlcsstoimage.com\n6. **Connect Google Drive** - Authenticate for PO archival\n7. **Connect Gmail** - Authenticate for supplier emails and approvals\n8. **Add Slack webhook** - Get URL from Slack for team notifications\n9. **Test with sample order** before production use\n\n\ud83d\udca1 **Required data:** items array (productName, quantity), requestedBy, department"
      },
      "typeVersion": 1
    },
    {
      "id": "76c5983c-6e71-430e-afc2-0c37d4daacf0",
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "position": [
        -1584,
        -128
      ],
      "parameters": {
        "path": "purchase-order",
        "options": {},
        "httpMethod": "POST"
      },
      "typeVersion": 1
    },
    {
      "id": "5b88f32b-c376-4d39-af78-f755eb05b56d",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1552,
        -320
      ],
      "parameters": {
        "color": 7,
        "width": 984,
        "height": 524,
        "content": "## Data Processing & AI Analysis\n\nValidates purchase request, calculates totals, formats data for AI analysis. AI then recommends optimal supplier by balancing cost, delivery speed, and item specialization. Enriches with complete supplier details."
      },
      "typeVersion": 1
    },
    {
      "id": "34128432-54da-40ca-9a5c-fdb59949cde6",
      "name": "Validate Request",
      "type": "n8n-nodes-base.code",
      "position": [
        -1360,
        -128
      ],
      "parameters": {
        "jsCode": "// Validate purchase request data\nconst item = $input.first().json;\n\n// Required fields\nconst requiredFields = ['items', 'requestedBy', 'department'];\nconst missingFields = requiredFields.filter(field => !item[field]);\n\nif (missingFields.length > 0) {\n  throw new Error(`Missing: ${missingFields.join(', ')}`);\n}\n\nif (!Array.isArray(item.items) || item.items.length === 0) {\n  throw new Error('Items array required with at least one item');\n}\n\n// Process items\nitem.items.forEach((lineItem, i) => {\n  if (!lineItem.productName || !lineItem.quantity) {\n    throw new Error(`Item ${i + 1} missing productName or quantity`);\n  }\n  lineItem.quantity = parseFloat(lineItem.quantity);\n  lineItem.unitPrice = parseFloat(lineItem.unitPrice) || 0;\n  lineItem.totalPrice = lineItem.quantity * lineItem.unitPrice;\n});\n\n// Calculate totals\nitem.subtotal = item.items.reduce((sum, i) => sum + i.totalPrice, 0);\nitem.tax = parseFloat(item.tax) || (item.subtotal * 0.1);\nitem.shipping = parseFloat(item.shipping) || 0;\nitem.total = item.subtotal + item.tax + item.shipping;\n\n// Generate PO number\nif (!item.poNumber) {\n  const date = new Date();\n  const year = date.getFullYear();\n  const month = String(date.getMonth() + 1).padStart(2, '0');\n  const random = Math.floor(Math.random() * 10000).toString().padStart(4, '0');\n  item.poNumber = `PO-${year}${month}-${random}`;\n}\n\n// Set defaults\nitem.currency = item.currency || 'USD';\nitem.currencySymbol = item.currencySymbol || '$';\nitem.urgency = item.urgency || 'normal';\nitem.poDate = new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\nitem.deliveryDate = item.deliveryDate || new Date(Date.now() + 14*24*60*60*1000).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' });\n\n// Determine if approval needed (e.g., over $5000)\nitem.requiresApproval = item.total > 5000;\nitem.approvalThreshold = 5000;\n\nreturn { json: item };"
      },
      "typeVersion": 2
    },
    {
      "id": "1f998ade-f0e6-44c8-adc0-16030fc33b5a",
      "name": "Prepare AI Context",
      "type": "n8n-nodes-base.set",
      "position": [
        -1152,
        -128
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "ai_context",
              "name": "aiContext",
              "type": "string",
              "value": "=Purchase Order Request:\n\nItems Needed:\n{{ $json.items.map(i => `- ${i.productName} (Qty: ${i.quantity}, Category: ${i.category || 'General'})`).join('\\n') }}\n\nTotal Value: {{ $json.currencySymbol }}{{ $json.total }}\nUrgency: {{ $json.urgency }}\nDepartment: {{ $json.department }}\nPreferred Supplier: {{ $json.preferredSupplier || 'None specified' }}\nBudget Constraint: {{ $json.budgetLimit || 'No limit' }}\n\nAvailable Suppliers:\n1. Acme Supplies - Reliable, 3-day delivery, competitive pricing, good for general items\n2. FastShip Industrial - Premium pricing, same-day delivery, best for urgent orders\n3. BulkSaver Wholesale - Lowest prices, 7-14 day delivery, minimum order $1000\n4. TechSource Pro - Specializes in IT equipment, 5-day delivery, excellent support\n5. BuildMart Direct - Construction materials, 2-day delivery, volume discounts"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "a9b4dd5a-2de0-4888-8a18-9a981cba10ef",
      "name": "AI Supplier Selector",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        -960,
        -128
      ],
      "parameters": {
        "text": "=You are a procurement AI assistant. Based on the purchase order request, analyze the requirements and recommend the optimal supplier.\n\nConsider:\n1. Urgency level (urgent = fast delivery priority)\n2. Total order value (budget optimization)\n3. Item categories (supplier specialization)\n4. Delivery requirements\n5. Cost vs speed trade-offs\n\n{{ $json.aiContext }}\n\nProvide your recommendation in this exact JSON format:\n{\n  \"recommendedSupplier\": \"Supplier Name\",\n  \"reasoning\": \"Brief explanation\",\n  \"estimatedDelivery\": \"X days\",\n  \"costOptimization\": \"savings/premium percentage\",\n  \"alternativeSupplier\": \"Backup option\",\n  \"specialNotes\": \"Any important considerations\"\n}\n\nRespond ONLY with valid JSON, no other text.",
        "agent": "conversationalAgent",
        "options": {
          "systemMessage": "You are a procurement optimization expert. Analyze purchase orders and recommend optimal suppliers based on cost, delivery time, and requirements. Always respond with valid JSON only."
        },
        "promptType": "define"
      },
      "typeVersion": 1.7
    },
    {
      "id": "d8df922b-7aa9-45c8-a300-2b3c441a98b6",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -176,
        -176
      ],
      "parameters": {
        "color": 7,
        "width": 344,
        "height": 352,
        "content": "## PO Generation\n\nCreates professional purchase order HTML with itemized pricing, supplier details, and AI recommendation insights box. Converts to print-ready PDF."
      },
      "typeVersion": 1
    },
    {
      "id": "e4641062-3229-4b46-b6b7-b2d9adb7752a",
      "name": "Enrich with Supplier Data",
      "type": "n8n-nodes-base.code",
      "position": [
        -640,
        -128
      ],
      "parameters": {
        "jsCode": "// Parse AI recommendation and enrich data\nconst item = $input.first().json;\nconst aiResponse = item.output || item.text || '{}';\n\n// Try to parse AI JSON response\nlet aiRecommendation;\ntry {\n  // Remove markdown code blocks if present\n  const cleanResponse = aiResponse.replace(/```json\\n?/g, '').replace(/```\\n?/g, '').trim();\n  aiRecommendation = JSON.parse(cleanResponse);\n} catch (e) {\n  // Fallback to default supplier\n  aiRecommendation = {\n    recommendedSupplier: 'Acme Supplies',\n    reasoning: 'Default supplier - AI parsing failed',\n    estimatedDelivery: '5 days',\n    costOptimization: 'standard',\n    alternativeSupplier: 'FastShip Industrial'\n  };\n}\n\n// Get original request data\nconst requestData = $('Validate Request').first().json;\n\n// Supplier database (in production, fetch from database)\nconst suppliers = {\n  'Acme Supplies': {\n    name: 'Acme Supplies',\n    email: 'user@example.com',\n    phone: '+1234567890',\n    address: '123 Industrial Pkwy, City, ST 12345',\n    paymentTerms: 'Net 30',\n    deliveryDays: 3\n  },\n  'FastShip Industrial': {\n    name: 'FastShip Industrial',\n    email: 'user@example.com',\n    phone: '+1234567890',\n    address: '456 Express Lane, City, ST 12345',\n    paymentTerms: 'Net 15',\n    deliveryDays: 1\n  },\n  'BulkSaver Wholesale': {\n    name: 'BulkSaver Wholesale',\n    email: 'user@example.com',\n    phone: '+1234567890',\n    address: '789 Warehouse Dr, City, ST 12345',\n    paymentTerms: 'Net 45',\n    deliveryDays: 10\n  },\n  'TechSource Pro': {\n    name: 'TechSource Pro',\n    email: 'user@example.com',\n    phone: '+1234567890',\n    address: '321 Tech Blvd, City, ST 12345',\n    paymentTerms: 'Net 30',\n    deliveryDays: 5\n  },\n  'BuildMart Direct': {\n    name: 'BuildMart Direct',\n    email: 'user@example.com',\n    phone: '+1234567890',\n    address: '654 Construction Ave, City, ST 12345',\n    paymentTerms: 'Net 30',\n    deliveryDays: 2\n  }\n};\n\n// Get selected supplier info\nconst selectedSupplier = suppliers[aiRecommendation.recommendedSupplier] || suppliers['Acme Supplies'];\n\n// Add company info\nconst enrichedData = {\n  ...requestData,\n  \n  // AI recommendation\n  aiRecommendation: aiRecommendation,\n  \n  // Supplier details\n  supplier: selectedSupplier,\n  \n  // Company info\n  companyName: requestData.companyName || 'Media Jade',\n  companyAddress: requestData.companyAddress || '456 Company Street',\n  companyCity: requestData.companyCity || 'San Francisco, CA 94105',\n  companyEmail: requestData.companyEmail || 'user@example.com',\n  companyPhone: requestData.companyPhone || '+1234567890',\n  \n  // Shipping details\n  shipToAddress: requestData.shipToAddress || '456 Company Street',\n  shipToCity: requestData.shipToCity || 'San Francisco, CA 94105',\n  shipToContact: requestData.shipToContact || requestData.requestedBy,\n  shipToPhone: requestData.shipToPhone || '+1234567890',\n  \n  // Additional info\n  specialInstructions: requestData.specialInstructions || '',\n  notes: requestData.notes || 'Please confirm receipt and estimated delivery date.'\n};\n\nreturn { json: enrichedData };"
      },
      "typeVersion": 2
    },
    {
      "id": "ec882f38-544e-4514-ac8f-5c38384e0142",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -544,
        -432
      ],
      "parameters": {
        "color": 7,
        "width": 344,
        "height": 476,
        "content": "## Approval Routing\n\nRoutes orders >$5k through email approval workflow. Orders \u2264$5k auto-proceed to PO generation. Enforces spending controls without slowing routine purchases."
      },
      "typeVersion": 1
    },
    {
      "id": "2dab2d00-191e-40cf-b736-c2c500402da0",
      "name": "Needs Approval?",
      "type": "n8n-nodes-base.if",
      "position": [
        -480,
        -176
      ],
      "parameters": {
        "conditions": {
          "boolean": [
            {
              "value1": "={{ $json.requiresApproval }}",
              "value2": true
            }
          ]
        }
      },
      "typeVersion": 1
    },
    {
      "id": "8372fea8-02b6-4ac3-8408-09b560beeb6f",
      "name": "Request Approval",
      "type": "n8n-nodes-base.gmail",
      "position": [
        -304,
        -240
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "7f75092b-2435-464f-847d-efb6a5f81258",
      "name": "Generate PO Document",
      "type": "n8n-nodes-base.code",
      "position": [
        -144,
        16
      ],
      "parameters": {
        "jsCode": "// Generate purchase order HTML\nconst item = $input.first().json;\n\nconst formatCurrency = (amount) => {\n  return `${item.currencySymbol}${amount.toFixed(2)}`;\n};\n\nconst html = `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>Purchase Order - ${item.poNumber}</title>\n    <style>\n        @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');\n        * { margin: 0; padding: 0; box-sizing: border-box; }\n        body { font-family: 'Inter', sans-serif; line-height: 1.6; color: #1f2937; }\n        .container { max-width: 900px; margin: 0 auto; padding: 40px; }\n        .header { display: flex; justify-content: space-between; margin-bottom: 40px; padding-bottom: 20px; border-bottom: 3px solid #10b981; }\n        .company-name { color: #10b981; font-size: 28px; font-weight: 700; }\n        .company-details { font-size: 13px; color: #6b7280; margin-top: 8px; }\n        .po-badge { text-align: right; }\n        .po-title { background: linear-gradient(135deg, #10b981 0%, #059669 100%); color: white; padding: 12px 25px; border-radius: 8px; font-size: 20px; font-weight: 700; letter-spacing: 1.5px; }\n        .po-number { font-size: 14px; color: #1f2937; font-weight: 600; margin-top: 8px; }\n        .urgency-badge { display: inline-block; padding: 4px 12px; border-radius: 12px; font-size: 11px; font-weight: 700; margin-top: 8px; }\n        .urgency-urgent { background: #fee2e2; color: #991b1b; }\n        .urgency-normal { background: #dbeafe; color: #1e40af; }\n        \n        .info-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 25px; margin-bottom: 35px; }\n        .info-box { background: #f0fdf4; padding: 20px; border-radius: 10px; border: 1px solid #bbf7d0; }\n        .info-box h3 { color: #15803d; font-size: 13px; font-weight: 700; text-transform: uppercase; margin-bottom: 12px; }\n        .info-box p { font-size: 13px; color: #166534; margin: 5px 0; }\n        \n        .ai-insight { background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); padding: 20px; border-radius: 10px; border-left: 5px solid #f59e0b; margin-bottom: 30px; }\n        .ai-insight h3 { color: #92400e; font-size: 15px; font-weight: 700; margin-bottom: 10px; }\n        .ai-insight p { color: #78350f; font-size: 13px; margin: 5px 0; }\n        \n        .items-table { width: 100%; border-collapse: separate; border-spacing: 0; margin-bottom: 25px; box-shadow: 0 2px 4px rgba(0,0,0,0.06); border-radius: 10px; overflow: hidden; }\n        .items-table thead { background: linear-gradient(135deg, #10b981 0%, #059669 100%); }\n        .items-table th { padding: 14px; text-align: left; font-weight: 600; font-size: 12px; color: white; text-transform: uppercase; }\n        .items-table tbody tr { background: white; }\n        .items-table tbody tr:nth-child(even) { background: #f9fafb; }\n        .items-table td { padding: 12px 14px; border-bottom: 1px solid #e5e7eb; font-size: 13px; }\n        .text-right { text-align: right; }\n        \n        .totals { margin-left: auto; width: 350px; }\n        .total-row { display: flex; justify-content: space-between; padding: 10px 0; font-size: 14px; }\n        .total-row.final { background: #ecfdf5; padding: 15px; border-radius: 8px; font-weight: 700; font-size: 18px; color: #065f46; margin-top: 10px; }\n        \n        .footer { margin-top: 40px; padding-top: 20px; border-top: 2px solid #e5e7eb; font-size: 12px; color: #6b7280; }\n        @media print { body { print-color-adjust: exact; -webkit-print-color-adjust: exact; } }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n        <div class=\"header\">\n            <div>\n                <div class=\"company-name\">${item.companyName}</div>\n                <div class=\"company-details\">\n                    ${item.companyAddress}<br>\n                    ${item.companyCity}<br>\n                    ${item.companyEmail} | ${item.companyPhone}\n                </div>\n            </div>\n            <div class=\"po-badge\">\n                <div class=\"po-title\">PURCHASE ORDER</div>\n                <div class=\"po-number\">${item.poNumber}</div>\n                <div class=\"po-number\">${item.poDate}</div>\n                <span class=\"urgency-badge urgency-${item.urgency}\">${item.urgency.toUpperCase()}</span>\n            </div>\n        </div>\n\n        <div class=\"info-grid\">\n            <div class=\"info-box\">\n                <h3>Vendor</h3>\n                <p><strong>${item.supplier.name}</strong></p>\n                <p>${item.supplier.address}</p>\n                <p>${item.supplier.email}</p>\n                <p>${item.supplier.phone}</p>\n                <p><strong>Payment Terms:</strong> ${item.supplier.paymentTerms}</p>\n            </div>\n            <div class=\"info-box\">\n                <h3>Ship To</h3>\n                <p><strong>${item.shipToContact}</strong></p>\n                <p>${item.shipToAddress}</p>\n                <p>${item.shipToCity}</p>\n                <p>${item.shipToPhone}</p>\n                <p><strong>Delivery:</strong> ${item.deliveryDate}</p>\n            </div>\n        </div>\n\n        <div class=\"info-grid\">\n            <div class=\"info-box\">\n                <h3>Requested By</h3>\n                <p><strong>${item.requestedBy}</strong></p>\n                <p>Department: ${item.department}</p>\n                <p>Date: ${item.poDate}</p>\n            </div>\n            <div class=\"info-box\">\n                <h3>Order Details</h3>\n                <p><strong>PO Number:</strong> ${item.poNumber}</p>\n                <p><strong>Urgency:</strong> ${item.urgency}</p>\n                <p><strong>Estimated Delivery:</strong> ${item.aiRecommendation.estimatedDelivery}</p>\n            </div>\n        </div>\n\n        ${item.aiRecommendation ? `\n        <div class=\"ai-insight\">\n            <h3>\ud83e\udd16 AI Procurement Insight</h3>\n            <p><strong>Supplier Selection:</strong> ${item.aiRecommendation.reasoning}</p>\n            <p><strong>Cost Optimization:</strong> ${item.aiRecommendation.costOptimization}</p>\n            <p><strong>Alternative Supplier:</strong> ${item.aiRecommendation.alternativeSupplier}</p>\n            ${item.aiRecommendation.specialNotes ? `<p><strong>Notes:</strong> ${item.aiRecommendation.specialNotes}</p>` : ''}\n        </div>\n        ` : ''}\n\n        <table class=\"items-table\">\n            <thead>\n                <tr>\n                    <th style=\"width: 10%;\">Item #</th>\n                    <th style=\"width: 40%;\">Product Description</th>\n                    <th class=\"text-right\" style=\"width: 12%;\">Quantity</th>\n                    <th class=\"text-right\" style=\"width: 15%;\">Unit Price</th>\n                    <th class=\"text-right\" style=\"width: 15%;\">Total</th>\n                </tr>\n            </thead>\n            <tbody>\n                ${item.items.map((lineItem, index) => `\n                <tr>\n                    <td>${index + 1}</td>\n                    <td>${lineItem.productName}${lineItem.productCode ? ` (${lineItem.productCode})` : ''}</td>\n                    <td class=\"text-right\">${lineItem.quantity}</td>\n                    <td class=\"text-right\">${formatCurrency(lineItem.unitPrice)}</td>\n                    <td class=\"text-right\"><strong>${formatCurrency(lineItem.totalPrice)}</strong></td>\n                </tr>\n                `).join('')}\n            </tbody>\n        </table>\n\n        <div class=\"totals\">\n            <div class=\"total-row\">\n                <span>Subtotal:</span>\n                <span>${formatCurrency(item.subtotal)}</span>\n            </div>\n            <div class=\"total-row\">\n                <span>Tax:</span>\n                <span>${formatCurrency(item.tax)}</span>\n            </div>\n            <div class=\"total-row\">\n                <span>Shipping:</span>\n                <span>${formatCurrency(item.shipping)}</span>\n            </div>\n            <div class=\"total-row final\">\n                <span>Total:</span>\n                <span>${formatCurrency(item.total)}</span>\n            </div>\n        </div>\n\n        ${item.specialInstructions ? `\n        <div style=\"background: #f8fafc; padding: 20px; border-radius: 8px; margin-top: 25px;\">\n            <h3 style=\"color: #475569; font-size: 14px; font-weight: 700; margin-bottom: 10px;\">Special Instructions:</h3>\n            <p style=\"color: #64748b; font-size: 13px;\">${item.specialInstructions}</p>\n        </div>\n        ` : ''}\n\n        <div class=\"footer\">\n            <p><strong>Notes:</strong> ${item.notes}</p>\n            <p style=\"margin-top: 10px;\">This purchase order is subject to our standard terms and conditions. Please confirm receipt and provide tracking information.</p>\n            <p style=\"margin-top: 10px;\"><strong>Authorized by:</strong> ${item.requestedBy} | <strong>Department:</strong> ${item.department}</p>\n        </div>\n    </div>\n</body>\n</html>\n`;\n\nreturn {\n  json: {\n    html: html,\n    poNumber: item.poNumber,\n    supplierEmail: item.supplier.email,\n    supplierName: item.supplier.name,\n    total: item.total,\n    fileName: `PO_${item.poNumber}_${item.supplier.name.replace(/[^a-zA-Z0-9]/g, '_')}.pdf`,\n    ...item\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "817d0d2a-54b1-41c9-9e3a-944c2cf834ad",
      "name": "HTML to PDF",
      "type": "n8n-nodes-htmlcsstopdf.htmlcsstopdf",
      "position": [
        48,
        16
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "f63b61f7-855c-4a78-b418-1edccec085e4",
      "name": "Archive in Drive",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        288,
        -112
      ],
      "parameters": {
        "name": "={{ $('Generate PO Document').item.json.fileName }}",
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "options": {},
        "folderId": {
          "__rl": true,
          "mode": "list",
          "value": "root"
        }
      },
      "typeVersion": 3
    },
    {
      "id": "8ae567c0-551e-4496-babb-df74a6992eb2",
      "name": "Email to Supplier",
      "type": "n8n-nodes-base.gmail",
      "position": [
        320,
        144
      ],
      "parameters": {
        "options": {}
      },
      "credentials": {
        "gmailOAuth2": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2.1
    },
    {
      "id": "8b9508f2-0982-4959-8f67-2275ee48e34a",
      "name": "Log in Procurement System",
      "type": "n8n-nodes-base.code",
      "position": [
        496,
        16
      ],
      "parameters": {
        "jsCode": "// Log PO in procurement system\nconst item = $input.first().json;\n\nconst procurementLog = {\n  poNumber: item.poNumber,\n  poDate: new Date().toISOString(),\n  supplier: item.supplier.name,\n  supplierEmail: item.supplier.email,\n  total: item.total,\n  currency: item.currency,\n  status: 'Sent to Supplier',\n  requestedBy: item.requestedBy,\n  department: item.department,\n  urgency: item.urgency,\n  expectedDelivery: item.deliveryDate,\n  items: item.items.map(i => ({\n    productName: i.productName,\n    quantity: i.quantity,\n    unitPrice: i.unitPrice\n  })),\n  aiRecommendation: item.aiRecommendation,\n  approvalRequired: item.requiresApproval,\n  approvalStatus: item.requiresApproval ? 'Pending' : 'Not Required',\n  pdfUrl: item.pdfUrl || 'pending',\n  trackingNumber: null,\n  deliveryStatus: 'Awaiting Confirmation',\n  \n  // For API integration\n  apiEndpoint: 'https://api.yourprocurementsystem.com/purchase-orders',\n  apiMethod: 'POST',\n  \n  // Activity log\n  activityLog: [\n    {\n      timestamp: new Date().toISOString(),\n      action: 'PO Created',\n      user: item.requestedBy,\n      details: `PO ${item.poNumber} created and sent to ${item.supplier.name}`\n    }\n  ]\n};\n\nreturn {\n  json: {\n    ...item,\n    procurementLog: procurementLog,\n    loggedAt: new Date().toISOString()\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "6e332a6f-2d25-46f1-a938-89124d5b075d",
      "name": "Sticky Note10",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        224,
        -272
      ],
      "parameters": {
        "color": 7,
        "width": 664,
        "height": 576,
        "content": "## Distribution & Tracking\n\nArchives PDF to Drive for compliance, emails supplier with PO attachment, logs complete order details in procurement system for tracking, then sends Slack notification with AI recommendation summary and Drive link."
      },
      "typeVersion": 1
    },
    {
      "id": "c2c27e06-f07e-48f1-b94c-b4561b6af615",
      "name": "Notify Procurement Team",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        720,
        16
      ],
      "parameters": {
        "url": "https://hooks.slack.com/services/YOUR/SLACK/WEBHOOK",
        "options": {},
        "jsonBody": "={\n  \"text\": \"\ud83d\uded2 Purchase Order Created\",\n  \"blocks\": [\n    {\n      \"type\": \"section\",\n      \"text\": {\n        \"type\": \"mrkdwn\",\n        \"text\": \"*\ud83d\uded2 Purchase Order Sent*\\n\\n*PO #:* {{ $('Generate PO Document').item.json.poNumber }}\\n*Supplier:* {{ $('Generate PO Document').item.json.supplierName }}\\n*Total:* {{ $('Generate PO Document').item.json.currency }} {{ $('Generate PO Document').item.json.total }}\\n*Urgency:* {{ $('Generate PO Document').item.json.urgency }}\\n*Requested By:* {{ $('Generate PO Document').item.json.requestedBy }}\\n\\n*\ud83e\udd16 AI Recommendation:*\\n{{ $('Generate PO Document').item.json.aiRecommendation.reasoning }}\\n\\n<{{ $('Archive in Drive').item.json.webViewLink }}|View PO in Drive>\"\n      }\n    }\n  ]\n}",
        "sendBody": true,
        "specifyBody": "json"
      },
      "typeVersion": 4.1
    },
    {
      "id": "0e7e26b7-0885-48af-8be8-e08a8e094b16",
      "name": "OpenAI Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "position": [
        -960,
        64
      ],
      "parameters": {
        "model": {
          "__rl": true,
          "mode": "list",
          "value": "gpt-4.1-mini"
        },
        "options": {}
      },
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1.2
    }
  ],
  "connections": {
    "HTML to PDF": {
      "main": [
        [
          {
            "node": "Archive in Drive",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Needs Approval?": {
      "main": [
        [
          {
            "node": "Request Approval",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Generate PO Document",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Webhook Trigger": {
      "main": [
        [
          {
            "node": "Validate Request",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Archive in Drive": {
      "main": [
        [
          {
            "node": "Email to Supplier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Request": {
      "main": [
        [
          {
            "node": "Prepare AI Context",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Email to Supplier": {
      "main": [
        [
          {
            "node": "Log in Procurement System",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Supplier Selector",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Prepare AI Context": {
      "main": [
        [
          {
            "node": "AI Supplier Selector",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Supplier Selector": {
      "main": [
        [
          {
            "node": "Enrich with Supplier Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Generate PO Document": {
      "main": [
        [
          {
            "node": "HTML to PDF",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Enrich with Supplier Data": {
      "main": [
        [
          {
            "node": "Needs Approval?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Log in Procurement System": {
      "main": [
        [
          {
            "node": "Notify Procurement Team",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}