{
  "id": "JvFJ2REOLcJvdEj4",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Market Price Benchmarking Workflow",
  "tags": [],
  "nodes": [
    {
      "id": "aa2c90cd-9d20-4af1-b33a-c768a143e309",
      "name": "Groq Chat Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGroq",
      "position": [
        144,
        1200
      ],
      "parameters": {
        "model": "llama-3.3-70b-versatile",
        "options": {
          "temperature": 0.2
        }
      },
      "typeVersion": 1
    },
    {
      "id": "dd4d010f-a734-42b9-9358-0d61ac19f38a",
      "name": "Schedule Benchmark Run",
      "type": "n8n-nodes-base.scheduleTrigger",
      "position": [
        -1424,
        1248
      ],
      "parameters": {
        "rule": {
          "interval": [
            {
              "triggerAtHour": 9
            }
          ]
        }
      },
      "typeVersion": 1.3
    },
    {
      "id": "fd7d207b-7a2f-4c44-b753-2e0a1c33611e",
      "name": "Fetch Procurement Data",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -1200,
        1248
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1H5x2h3NuJ47I3VAAXO0WpiMgPfG-xgIH9ezXY1jl4uE/edit#gid=0",
          "cachedResultName": "Procurement_Data"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1H5x2h3NuJ47I3VAAXO0WpiMgPfG-xgIH9ezXY1jl4uE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1H5x2h3NuJ47I3VAAXO0WpiMgPfG-xgIH9ezXY1jl4uE/edit?usp=drivesdk",
          "cachedResultName": "Procurement"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "89d6cc17-74f1-46a4-9713-6d8d5a6a4927",
      "name": "Group Latest & Historical Prices",
      "type": "n8n-nodes-base.code",
      "position": [
        -976,
        1248
      ],
      "parameters": {
        "jsCode": "const grouped = {};\n\n// Step 1: Group by item\nfor (const item of items) {\n  const key = item.json.item;\n\n  if (!grouped[key]) {\n    grouped[key] = [];\n  }\n\n  grouped[key].push(item.json);\n}\n\n// Step 2: Process each group\nconst result = [];\n\nfor (const key in grouped) {\n  const records = grouped[key];\n\n  // Sort by date (latest first)\n  records.sort((a, b) => new Date(b.last_purchase_date) - new Date(a.last_purchase_date));\n\n  const latest = records[0];\n  const historical = records.slice(1);\n\n  result.push({\n    json: {\n      item: key,\n      latest,\n      historical\n    }\n  });\n}\n\nreturn result;"
      },
      "typeVersion": 2
    },
    {
      "id": "a43c9a98-3770-4149-a859-524c45f195fc",
      "name": "Calculate Market Benchmark Metrics",
      "type": "n8n-nodes-base.code",
      "position": [
        -752,
        1248
      ],
      "parameters": {
        "jsCode": "return items.map(item => {\n  const latest = item.json.latest;\n  const historical = item.json.historical;\n\n  let totalValue = 0;\n  let totalQty = 0;\n\n  // Calculate weighted average\n  for (const record of historical) {\n    totalValue += record.price_internal * record.quantity;\n    totalQty += record.quantity;\n  }\n\n  const avg_market_price = totalQty > 0 ? totalValue / totalQty : latest.price_internal;\n\n  // Variance\n  const variance = latest.price_internal - avg_market_price;\n  const variance_pct = (variance / avg_market_price) * 100;\n\n  // Basic trend (simple logic for now)\n  let trend = \"stable\";\n  if (historical.length > 0) {\n    const lastHistorical = historical[0].price_internal;\n    if (latest.price_internal > lastHistorical) trend = \"rising\";\n    else if (latest.price_internal < lastHistorical) trend = \"falling\";\n  }\n\n  return {\n    json: {\n      item: item.json.item,\n      category: latest.category,\n      supplier: latest.supplier,\n      price_internal: latest.price_internal,\n      quantity: latest.quantity,\n      avg_market_price: parseFloat(avg_market_price.toFixed(2)),\n      variance: parseFloat(variance.toFixed(2)),\n      variance_pct: parseFloat(variance_pct.toFixed(2)),\n      trend,\n      contract_type: latest.contract_type,\n      region: latest.region,\n      target_price_last: latest.target_price_last,\n      price_vs_target_pct : ((latest.price_internal - latest.target_price_last) / latest.target_price_last) * 100\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "73635f81-3d4a-4b19-ac44-3320dba1bfce",
      "name": "Process Items for Market News",
      "type": "n8n-nodes-base.splitInBatches",
      "position": [
        -384,
        1440
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 3
    },
    {
      "id": "5bdceffe-7178-4f28-b820-922bfa00370f",
      "name": "Rate Limit Control",
      "type": "n8n-nodes-base.wait",
      "position": [
        352,
        1440
      ],
      "parameters": {
        "amount": 2
      },
      "typeVersion": 1.1
    },
    {
      "id": "156585be-a6bc-48d2-8baf-b7b57d731f8d",
      "name": "Fetch Market News (Google RSS)",
      "type": "n8n-nodes-base.rssFeedRead",
      "position": [
        -160,
        1440
      ],
      "parameters": {
        "url": "=https://news.google.com/rss/search?q={{$json[\"item\"]}}+price+{{$json[\"region\"]}}",
        "options": {}
      },
      "typeVersion": 1.2
    },
    {
      "id": "e6b38238-e157-45c0-be21-c73fbca9a1f1",
      "name": "Extract Market Trend Signals",
      "type": "n8n-nodes-base.code",
      "position": [
        128,
        1440
      ],
      "parameters": {
        "jsCode": "const itemName = $('Process Items for Market News').first().json.item;\n\n// Take only top 5 news for THIS item\nconst topArticles = items.slice(0, 5);\n\nconst headlines = topArticles.map(a => \n  (a.json.title || \"\").toLowerCase()\n);\n\nconst combined = headlines.join(\" \");\n\nlet market_trend = \"stable\";\n\nif (/rise|rising|increase|surge|jump|higher/.test(combined)) {\n  market_trend = \"rising\";\n} else if (/fall|falling|drop|decline|lower|decrease/.test(combined)) {\n  market_trend = \"falling\";\n} else if (/volatile|uncertain|fluctuat/.test(combined)) {\n  market_trend = \"volatile\";\n}\n\nreturn [{\n  json: {\n    item: itemName,\n    market_trend,\n    headlines,\n    news_summary: headlines.join(\" | \")\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "eff67bca-1a8f-4e85-b3e7-6b0588269a17",
      "name": "Merge Pricing Data with Market Signals",
      "type": "n8n-nodes-base.merge",
      "position": [
        -192,
        1104
      ],
      "parameters": {
        "mode": "combine",
        "options": {},
        "fieldsToMatchString": "item"
      },
      "typeVersion": 3.2
    },
    {
      "id": "f4bb1a76-cc72-48a1-a2d6-8e792ba56d2f",
      "name": "AI Procurement Risk Analysis",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        64,
        976
      ],
      "parameters": {
        "text": "=Analyze the following procurement scenario:\n\nItem: {{$json.item}}\nCategory: {{$json.category}}\nSupplier: {{$json.supplier}}\n\nInternal Price: {{$json.price_internal}}\nBenchmark Price: {{$json.avg_market_price}}\nVariance %: {{$json.variance_pct}}\n\nPrevious Target Price: {{$json.target_price_last}}\nPrice vs Target %: {{$json.price_vs_target_pct}}\n\nInternal Trend: {{$json.trend}}\nMarket Trend: {{$json.market_trend}}\n\nMarket News:\n{{$json.news_summary}}\n\nInstructions:\n1. Determine risk level based on variance and trends\n2. Suggest realistic target price range (min & max)\n3. Provide a practical negotiation strategy\n4. Suggest best timing (negotiate now, wait, or lock contract)\n5. Summarize insights clearly\n6. Target price max should not exceed current internal price unless strongly justified by rising market trend.\n\nAlways return output in STRICT JSON format",
        "options": {
          "systemMessage": "You are a senior procurement analyst with expertise in strategic sourcing, cost optimization, and supplier negotiation.\n\nYour role is to analyze internal procurement pricing against benchmark data and market signals, and provide actionable insights.\n\nRules:\n- Be precise and data-driven\n- Do NOT hallucinate market prices\n- Use given data as primary source\n- Use market trends and news only as supporting signals\n- Always return output in STRICT JSON format\n- No explanations outside JSON\n\nRisk Guidelines:\n- Variance < 5% \u2192 Low Risk\n- Variance 5%\u201315% \u2192 Medium Risk\n- Variance > 15% \u2192 High Risk\n\nAdjust risk:\n- If market trend is rising \u2192 increase risk by one level\n- If market trend is falling \u2192 decrease risk by one level\n\n\n=> Always return output in STRICT JSON format\n\nOutput must include:\n- risk_level (Low / Medium / High)\n- target_price_min\n- target_price_max\n- negotiation_strategy\n- timing_advice\n- ai_summary"
        },
        "promptType": "define"
      },
      "typeVersion": 3.1
    },
    {
      "id": "964ce629-1755-4265-8d32-33ad020e4139",
      "name": "Parse AI Response to Structured JSON",
      "type": "n8n-nodes-base.code",
      "position": [
        416,
        1088
      ],
      "parameters": {
        "jsCode": "return items.map((item, index) => {\n  let content = item.json.output || \"\";\n\n  // Clean markdown\n  content = content.replace(/```json|```/g, '').trim();\n\n  let parsed = {};\n\n  try {\n    parsed = JSON.parse(content);\n  } catch (e) {\n    parsed = {\n      risk_level: \"unknown\",\n      ai_summary: content\n    };\n  }\n\n  \n  const original = $items(\"Merge Pricing Data with Market Signals\")[index].json;\n\n  return {\n    json: {\n            item: original.item,\n      category: original.category,\n      supplier: original.supplier,\n      price_internal: original.price_internal,\n      avg_market_price: original.avg_market_price,\n      variance_pct: original.variance_pct,\n      market_trend: original.market_trend,\n\n      \n      ...parsed\n    }\n  };\n});"
      },
      "typeVersion": 2
    },
    {
      "id": "0a72a6f4-2ea0-470f-9502-76bbcefaf995",
      "name": "Evaluate Overpricing Risk",
      "type": "n8n-nodes-base.if",
      "position": [
        720,
        1088
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "or",
          "conditions": [
            {
              "id": "432eac0d-a43a-4f2f-9cb1-69a9f1f0eb76",
              "operator": {
                "type": "number",
                "operation": "gt"
              },
              "leftValue": "={{ $json.variance_pct }}",
              "rightValue": 5
            },
            {
              "id": "7f85f4c3-ad8e-455e-9205-2883036ce891",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.risk_level }}",
              "rightValue": "High"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "08b5b52b-6330-4ccd-99f7-4c7c2813dfd8",
      "name": "Prepare Alert Notification Message",
      "type": "n8n-nodes-base.set",
      "position": [
        944,
        992
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "a2ef001a-64aa-4b9a-8456-e46286176374",
              "name": "alert_message",
              "type": "string",
              "value": "=Overpricing Risk Detected\n\nItem: {{$json.item}}\nSupplier: {{$json.supplier}}\n\nInternal Price: \u20b9{{$json.price_internal}}\nMarket Avg: \u20b9{{$json.avg_market_price}}\n\nVariance: {{$json.variance_pct}}%\nRisk: {{$json.risk_level}}\n\nAI Insight:\n{{$json.ai_summary}}\n\nSuggested Range:\n\u20b9{{$json.target_price_min}} - \u20b9{{$json.target_price_max}}"
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "bceef9fa-b89d-45fe-b7cd-fe2d5cd763f3",
      "name": "Send Overpricing Alert",
      "type": "n8n-nodes-base.slack",
      "position": [
        1168,
        992
      ],
      "parameters": {
        "text": "={{ $json.alert_message }}",
        "user": {
          "__rl": true,
          "mode": "list",
          "value": "U0ANV4YLNTV",
          "cachedResultName": ""
        },
        "select": "user",
        "otherOptions": {},
        "authentication": "oAuth2"
      },
      "typeVersion": 2.4
    },
    {
      "id": "2821f985-402b-40bb-a701-80356ff77d8d",
      "name": "Store Benchmark Report",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        1056,
        1248
      ],
      "parameters": {
        "columns": {
          "value": {
            "item": "={{ $json.item }}",
            "trend": "={{ $('Calculate Market Benchmark Metrics').item.json.trend }}",
            "region": "={{ $('Calculate Market Benchmark Metrics').item.json.region }}",
            "category": "={{ $json.category }}",
            "supplier": "={{ $json.supplier }}",
            "variance": "={{ $('Calculate Market Benchmark Metrics').item.json.variance }}",
            "timestamp": "={{ new Date().toISOString() }}",
            "ai_summary": "={{ $json.ai_summary }}",
            "risk_level": "={{ $json.risk_level }}",
            "variance_pct": "={{ $json.variance_pct }}",
            "contract_type": "={{ $('Calculate Market Benchmark Metrics').item.json.contract_type }}",
            "timing_advice": "={{ $json.timing_advice }}",
            "price_internal": "={{ $json.price_internal }}",
            "avg_market_price": "={{ $json.avg_market_price }}",
            "target_price_max": "={{ $json.target_price_max }}",
            "target_price_min": "={{ $json.target_price_min }}",
            "negotiation_strategy": "={{ $json.negotiation_strategy }}"
          },
          "schema": [
            {
              "id": "timestamp",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timestamp",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "item",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "item",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "category",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "category",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "supplier",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "supplier",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "price_internal",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "price_internal",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "avg_market_price",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "avg_market_price",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "variance",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "variance",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "variance_pct",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "variance_pct",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "trend",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "trend",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "risk_level",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "risk_level",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "target_price_min",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "target_price_min",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "target_price_max",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "target_price_max",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "negotiation_strategy",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "negotiation_strategy",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "timing_advice",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "timing_advice",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "contract_type",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "contract_type",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "region",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "region",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "ai_summary",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "ai_summary",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "append",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": 521362572,
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1H5x2h3NuJ47I3VAAXO0WpiMgPfG-xgIH9ezXY1jl4uE/edit#gid=521362572",
          "cachedResultName": "Benchmark_Reports"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1H5x2h3NuJ47I3VAAXO0WpiMgPfG-xgIH9ezXY1jl4uE",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1H5x2h3NuJ47I3VAAXO0WpiMgPfG-xgIH9ezXY1jl4uE/edit?usp=drivesdk",
          "cachedResultName": "Procurement"
        }
      },
      "typeVersion": 4.7
    },
    {
      "id": "d7b8cc18-f70f-4cb9-b880-7c4493ca2103",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -2304,
        800
      ],
      "parameters": {
        "width": 752,
        "height": 752,
        "content": "## Market Price Benchmarking & Procurement Risk Intelligence Workflow\n\nThis workflow automates procurement price benchmarking by comparing internal purchase data with market signals and AI-driven insights. It helps identify overpricing risks, optimize negotiation strategies, and maintain a structured audit trail.\n\n\n### How it works:\nThe workflow runs on a schedule and fetches internal procurement data from Google Sheets. It processes the data to identify the latest purchase per item and calculates benchmark metrics such as average price, variance, and trend. It then enriches this data with real-time market signals using Google News RSS feeds, extracting trends from recent headlines.\n\nNext, an AI model (Groq) analyzes both internal and market data to generate risk levels, target price ranges, and negotiation recommendations. A rule-based decision engine evaluates whether the item poses an overpricing risk.\n\nIf a risk is detected, an alert is sent via Slack or Email. All results\u2014both normal and alert cases\u2014are stored in Google Sheets for reporting and auditing.\n\n\n### Setup steps:\n1. Connect Google Sheets (input + report sheet)\n2. Configure Groq API credentials\n3. Connect Slack or Email for alerts\n4. Adjust schedule and thresholds if needed"
      },
      "typeVersion": 1
    },
    {
      "id": "4d10a167-159d-41a8-bd7b-60eb3906570a",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -1488,
        960
      ],
      "parameters": {
        "color": 7,
        "width": 928,
        "height": 576,
        "content": "## Data Ingestion & Preparation\n\nThis section retrieves procurement data from Google Sheets and prepares it for analysis. It identifies the latest purchase records for each item and calculates key benchmarking metrics such as average price, variance, and price trends. This structured dataset forms the foundation for comparing internal procurement performance against market conditions."
      },
      "typeVersion": 1
    },
    {
      "id": "90c01d9f-e116-4ff9-b921-202be4545e8f",
      "name": "Sticky Note2",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        1408
      ],
      "parameters": {
        "color": 7,
        "width": 1024,
        "height": 432,
        "content": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n## Market Intelligence Enrichment\n\nThis section enriches internal procurement data with external market intelligence. It dynamically fetches news for each item using Google RSS feeds and processes headlines to determine market trends such as rising, falling, or stable. Rate limiting ensures reliable API usage while maintaining workflow stability."
      },
      "typeVersion": 1
    },
    {
      "id": "cb982082-b3de-4a26-8aca-c018a166fa51",
      "name": "Sticky Note3",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -464,
        768
      ],
      "parameters": {
        "color": 7,
        "width": 448,
        "height": 544,
        "content": "## Data Consolidation\n\nThis step combines internal pricing metrics with external market signals into a unified dataset. By merging structured data and market insights, it ensures each item has complete contextual information before entering the AI analysis stage."
      },
      "typeVersion": 1
    },
    {
      "id": "01078426-8023-43e8-8608-727b53fce222",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        656,
        768
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 656,
        "content": "## Decision, Alerting & Reporting\n\nThis section evaluates whether a procurement case poses an overpricing risk using rule-based conditions. If a risk is detected, a formatted alert is sent via Slack or Email with key insights and recommendations. Regardless of risk level, all results are stored in Google Sheets, creating a centralized reporting system and audit trail for monitoring procurement performance."
      },
      "typeVersion": 1
    },
    {
      "id": "e79297d2-3262-40ea-bd44-6e059c0bc54e",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        32,
        768
      ],
      "parameters": {
        "color": 7,
        "width": 560,
        "height": 560,
        "content": "## AI Analysis & Structuring\n\nThis section uses an AI model to analyze procurement data alongside market trends. It generates insights such as risk level, target price ranges, negotiation strategies, and timing advice. The response is then parsed into a structured JSON format to ensure compatibility with downstream decision-making and reporting steps."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "857883e8-6264-4948-9664-881c2d169ba7",
  "connections": {
    "Groq Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "AI Procurement Risk Analysis",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Rate Limit Control": {
      "main": [
        [
          {
            "node": "Process Items for Market News",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Procurement Data": {
      "main": [
        [
          {
            "node": "Group Latest & Historical Prices",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Schedule Benchmark Run": {
      "main": [
        [
          {
            "node": "Fetch Procurement Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Evaluate Overpricing Risk": {
      "main": [
        [
          {
            "node": "Prepare Alert Notification Message",
            "type": "main",
            "index": 0
          },
          {
            "node": "Store Benchmark Report",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Store Benchmark Report",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "AI Procurement Risk Analysis": {
      "main": [
        [
          {
            "node": "Parse AI Response to Structured JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract Market Trend Signals": {
      "main": [
        [
          {
            "node": "Rate Limit Control",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process Items for Market News": {
      "main": [
        [
          {
            "node": "Merge Pricing Data with Market Signals",
            "type": "main",
            "index": 1
          }
        ],
        [
          {
            "node": "Fetch Market News (Google RSS)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Market News (Google RSS)": {
      "main": [
        [
          {
            "node": "Extract Market Trend Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Group Latest & Historical Prices": {
      "main": [
        [
          {
            "node": "Calculate Market Benchmark Metrics",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Calculate Market Benchmark Metrics": {
      "main": [
        [
          {
            "node": "Process Items for Market News",
            "type": "main",
            "index": 0
          },
          {
            "node": "Merge Pricing Data with Market Signals",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Alert Notification Message": {
      "main": [
        [
          {
            "node": "Send Overpricing Alert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse AI Response to Structured JSON": {
      "main": [
        [
          {
            "node": "Evaluate Overpricing Risk",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Merge Pricing Data with Market Signals": {
      "main": [
        [
          {
            "node": "AI Procurement Risk Analysis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}