Add comprehensive documentation and final improvements
Documentation Added: - AI_INSIGHTS_DEMO_SETUP_GUIDE.md: Complete setup guide for demo sessions - AI_INSIGHTS_DATA_FLOW.md: Architecture and data flow diagrams - AI_INSIGHTS_QUICK_START.md: Quick reference guide - DEMO_SESSION_ANALYSIS_REPORT.md: Detailed analysis of demo session d67eaae4 - ROOT_CAUSE_ANALYSIS_AND_FIXES.md: Complete analysis of 8 issues (6 fixed, 2 analyzed) - COMPLETE_FIX_SUMMARY.md: Executive summary of all fixes - FIX_MISSING_INSIGHTS.md: Forecasting and procurement fix guide - FINAL_STATUS_SUMMARY.md: Status overview - verify_fixes.sh: Automated verification script - enhance_procurement_data.py: Procurement data enhancement script Service Improvements: - Demo session cleanup worker: Use proper settings for Redis configuration with TLS/auth - Procurement service: Add Redis initialization with proper error handling and cleanup - Production fixture: Remove duplicate worker assignments (cleaned 56 duplicates) - Orchestrator fixture: Add purchase order metadata for better tracking Impact: - Complete documentation for troubleshooting and setup - Improved Redis connection handling across services - Clean production data without duplicates - Better error handling and logging 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -448,7 +448,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -510,7 +509,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -563,7 +561,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -625,7 +622,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -678,7 +674,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -732,7 +727,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -785,7 +779,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -838,7 +831,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -892,7 +884,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -945,7 +936,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -998,7 +988,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -1051,7 +1040,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -1105,7 +1093,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6",
|
||||
"c1a2b3c4-d5e6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -1158,7 +1145,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -1728,7 +1714,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -1789,7 +1774,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -1850,7 +1834,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -1911,7 +1894,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -1972,7 +1954,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -2033,7 +2014,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -2094,7 +2074,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -2155,7 +2134,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -2216,7 +2194,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -2277,7 +2254,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -2338,7 +2314,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -2399,7 +2374,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -2460,7 +2434,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -2764,7 +2737,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -2977,7 +2949,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -3099,7 +3070,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -3160,7 +3130,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -3221,7 +3190,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -3282,7 +3250,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -3343,7 +3310,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -3465,7 +3431,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -3526,7 +3491,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -3587,7 +3551,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -3648,7 +3611,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -3770,7 +3732,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -3892,7 +3853,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -3953,7 +3913,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -4136,7 +4095,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -4197,7 +4155,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -4258,7 +4215,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -4502,7 +4458,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -4563,7 +4518,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -4746,7 +4700,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
@@ -4807,7 +4760,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -4868,7 +4820,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -4929,7 +4880,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -5051,7 +5001,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000001",
|
||||
"50000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -5112,7 +5061,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -5173,7 +5121,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -5356,7 +5303,6 @@
|
||||
"30000000-0000-0000-0000-000000000001"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000006",
|
||||
"50000000-0000-0000-0000-000000000006"
|
||||
],
|
||||
"station_id": "STATION-01",
|
||||
@@ -5417,7 +5363,6 @@
|
||||
"30000000-0000-0000-0000-000000000002"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-02",
|
||||
@@ -5478,7 +5423,6 @@
|
||||
"30000000-0000-0000-0000-000000000003"
|
||||
],
|
||||
"staff_assigned": [
|
||||
"50000000-0000-0000-0000-000000000005",
|
||||
"50000000-0000-0000-0000-000000000005"
|
||||
],
|
||||
"station_id": "STATION-03",
|
||||
|
||||
@@ -31,6 +31,102 @@
|
||||
"errors_encountered": 0,
|
||||
"warnings_generated": 2
|
||||
},
|
||||
"run_metadata": {
|
||||
"purchase_orders": [
|
||||
{
|
||||
"id": "50000000-0000-0000-0000-000000000001",
|
||||
"status": "completed",
|
||||
"delivery_date": "BASE_TS - 2d",
|
||||
"items": [
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000001",
|
||||
"product_name": "Harina de Trigo T55",
|
||||
"quantity": 500.0,
|
||||
"unit": "kilograms"
|
||||
},
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000002",
|
||||
"product_name": "Harina de Trigo T65",
|
||||
"quantity": 200.0,
|
||||
"unit": "kilograms"
|
||||
},
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000005",
|
||||
"product_name": "Harina de Centeno",
|
||||
"quantity": 100.0,
|
||||
"unit": "kilograms"
|
||||
},
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000031",
|
||||
"product_name": "Sal Marina Fina",
|
||||
"quantity": 50.0,
|
||||
"unit": "kilograms"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "50000000-0000-0000-0000-000000000002",
|
||||
"status": "completed",
|
||||
"delivery_date": "BASE_TS - 1d",
|
||||
"items": [
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000011",
|
||||
"product_name": "Mantequilla sin Sal 82% MG",
|
||||
"quantity": 80.0,
|
||||
"unit": "kilograms"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "50000000-0000-0000-0000-000000000004",
|
||||
"status": "confirmed",
|
||||
"delivery_date": "BASE_TS + 1d",
|
||||
"items": [
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000001",
|
||||
"product_name": "Harina de Trigo T55",
|
||||
"quantity": 1000.0,
|
||||
"unit": "kilograms"
|
||||
},
|
||||
{
|
||||
"ingredient_id": "10000000-0000-0000-0000-000000000021",
|
||||
"product_name": "Levadura Fresca de Panadería",
|
||||
"quantity": 50.0,
|
||||
"unit": "kilograms"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"production_batches": [
|
||||
{
|
||||
"id": "40000000-0000-0000-0000-000000000001",
|
||||
"product_id": "20000000-0000-0000-0000-000000000001",
|
||||
"product_name": "Baguette Francesa Tradicional",
|
||||
"status": "COMPLETED",
|
||||
"scheduled_date": "BASE_TS - 1d 16h",
|
||||
"quantity": 98.0,
|
||||
"unit": "units"
|
||||
},
|
||||
{
|
||||
"id": "40000000-0000-0000-0000-000000000002",
|
||||
"product_id": "20000000-0000-0000-0000-000000000002",
|
||||
"product_name": "Croissant de Mantequilla Artesanal",
|
||||
"status": "COMPLETED",
|
||||
"scheduled_date": "BASE_TS - 1d 15h",
|
||||
"quantity": 115.0,
|
||||
"unit": "units"
|
||||
},
|
||||
{
|
||||
"id": "40000000-0000-0000-0000-000000000003",
|
||||
"product_id": "20000000-0000-0000-0000-000000000003",
|
||||
"product_name": "Pan de Pueblo con Masa Madre",
|
||||
"status": "COMPLETED",
|
||||
"scheduled_date": "BASE_TS - 1d 14h",
|
||||
"quantity": 80.0,
|
||||
"unit": "units"
|
||||
}
|
||||
]
|
||||
},
|
||||
"production_coordination": {
|
||||
"batches_synchronized": [
|
||||
{
|
||||
|
||||
209
shared/demo/fixtures/professional/enhance_procurement_data.py
Executable file
209
shared/demo/fixtures/professional/enhance_procurement_data.py
Executable file
@@ -0,0 +1,209 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Enhance Procurement Data for AI Insights
|
||||
Adds purchase order items with price trends to enable procurement insights
|
||||
"""
|
||||
|
||||
import json
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
# Set seed for reproducibility
|
||||
random.seed(42)
|
||||
|
||||
# Price trend data (realistic price movements over 90 days)
|
||||
INGREDIENTS_WITH_TRENDS = [
|
||||
{
|
||||
"id": "10000000-0000-0000-0000-000000000001",
|
||||
"name": "Harina de Trigo T55",
|
||||
"base_price": 0.85,
|
||||
"trend": 0.08, # 8% increase over 90 days
|
||||
"variability": 0.02,
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"id": "10000000-0000-0000-0000-000000000002",
|
||||
"name": "Harina de Trigo T65",
|
||||
"base_price": 0.95,
|
||||
"trend": 0.06, # 6% increase
|
||||
"variability": 0.02,
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"id": "10000000-0000-0000-0000-000000000011",
|
||||
"name": "Mantequilla sin Sal",
|
||||
"base_price": 6.50,
|
||||
"trend": 0.12, # 12% increase (highest)
|
||||
"variability": 0.05,
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"id": "10000000-0000-0000-0000-000000000012",
|
||||
"name": "Leche Entera Fresca",
|
||||
"base_price": 0.95,
|
||||
"trend": -0.03, # 3% decrease (seasonal surplus)
|
||||
"variability": 0.02,
|
||||
"unit": "L"
|
||||
},
|
||||
{
|
||||
"id": "10000000-0000-0000-0000-000000000021",
|
||||
"name": "Levadura Fresca",
|
||||
"base_price": 4.20,
|
||||
"trend": 0.04, # 4% increase
|
||||
"variability": 0.03,
|
||||
"unit": "kg"
|
||||
},
|
||||
{
|
||||
"id": "10000000-0000-0000-0000-000000000032",
|
||||
"name": "Azúcar Blanco",
|
||||
"base_price": 1.10,
|
||||
"trend": 0.02, # 2% increase (stable)
|
||||
"variability": 0.01,
|
||||
"unit": "kg"
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def calculate_price(ingredient, days_ago):
|
||||
"""
|
||||
Calculate price based on linear trend + random variability
|
||||
|
||||
Args:
|
||||
ingredient: Dict with base_price, trend, variability
|
||||
days_ago: Number of days in the past
|
||||
|
||||
Returns:
|
||||
Price at that point in time
|
||||
"""
|
||||
# Apply trend proportionally based on how far back in time
|
||||
# If trend is 8% over 90 days, price 45 days ago had 4% increase from base
|
||||
trend_factor = 1 + (ingredient["trend"] * (90 - days_ago) / 90)
|
||||
|
||||
# Add random variability
|
||||
variability = random.uniform(-ingredient["variability"], ingredient["variability"])
|
||||
|
||||
price = ingredient["base_price"] * trend_factor * (1 + variability)
|
||||
return round(price, 2)
|
||||
|
||||
|
||||
def parse_days_ago(order_date_str):
|
||||
"""Parse order_date to extract days ago"""
|
||||
if 'BASE_TS' in order_date_str:
|
||||
if '- ' in order_date_str:
|
||||
# Extract number from "BASE_TS - 1d" or "BASE_TS - 1h"
|
||||
parts = order_date_str.split('- ')[1]
|
||||
if 'd' in parts:
|
||||
try:
|
||||
return int(parts.split('d')[0])
|
||||
except:
|
||||
pass
|
||||
elif 'h' in parts:
|
||||
# Hours - treat as 0 days
|
||||
return 0
|
||||
elif '+ ' in order_date_str:
|
||||
# Future date - treat as 0 days ago (current price)
|
||||
return 0
|
||||
return 30 # Default fallback
|
||||
|
||||
|
||||
def add_items_to_pos():
|
||||
"""Add items arrays to purchase orders with realistic price trends"""
|
||||
|
||||
fixture_path = Path(__file__).parent / "07-procurement.json"
|
||||
|
||||
print("🔧 Enhancing Procurement Data for AI Insights...")
|
||||
print()
|
||||
|
||||
# Load existing data
|
||||
with open(fixture_path, 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
pos = data.get('purchase_orders', [])
|
||||
print(f"📦 Found {len(pos)} purchase orders")
|
||||
print()
|
||||
|
||||
items_added = 0
|
||||
|
||||
for i, po in enumerate(pos):
|
||||
# Parse order date to get days ago
|
||||
order_date_str = po.get('order_date', 'BASE_TS - 1d')
|
||||
days_ago = parse_days_ago(order_date_str)
|
||||
|
||||
# Select 2-4 random ingredients for this PO
|
||||
num_items = random.randint(2, 4)
|
||||
selected_ingredients = random.sample(INGREDIENTS_WITH_TRENDS, k=num_items)
|
||||
|
||||
items = []
|
||||
po_subtotal = 0.0
|
||||
|
||||
for ingredient in selected_ingredients:
|
||||
# Calculate price at this point in time
|
||||
unit_price = calculate_price(ingredient, days_ago)
|
||||
|
||||
# Order quantity (realistic for ingredient type)
|
||||
if ingredient["unit"] == "kg":
|
||||
quantity = random.randint(100, 500)
|
||||
else: # Liters
|
||||
quantity = random.randint(50, 200)
|
||||
|
||||
total_price = round(quantity * unit_price, 2)
|
||||
po_subtotal += total_price
|
||||
|
||||
items.append({
|
||||
"ingredient_id": ingredient["id"],
|
||||
"ingredient_name": ingredient["name"],
|
||||
"ordered_quantity": float(quantity),
|
||||
"unit": ingredient["unit"],
|
||||
"unit_price": unit_price,
|
||||
"total_price": total_price,
|
||||
"received_quantity": None,
|
||||
"status": "pending" if po.get('status') != 'delivered' else "received"
|
||||
})
|
||||
|
||||
# Add items to PO
|
||||
po['items'] = items
|
||||
|
||||
# Update PO totals to match items
|
||||
po['subtotal'] = round(po_subtotal, 2)
|
||||
tax_rate = 0.21 # 21% IVA in Spain
|
||||
po['tax_amount'] = round(po_subtotal * tax_rate, 2)
|
||||
po['shipping_cost'] = 15.0 if po_subtotal < 500 else 20.0
|
||||
po['total_amount'] = round(po['subtotal'] + po['tax_amount'] + po['shipping_cost'], 2)
|
||||
|
||||
items_added += len(items)
|
||||
|
||||
print(f" ✓ PO-{i+1} ({order_date_str}): {len(items)} items, €{po['total_amount']:.2f} total")
|
||||
|
||||
# Save back
|
||||
with open(fixture_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, indent=2, ensure_ascii=False)
|
||||
|
||||
print()
|
||||
print("=" * 60)
|
||||
print("✅ PROCUREMENT DATA ENHANCEMENT COMPLETE")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print(f"📊 SUMMARY:")
|
||||
print(f" • Purchase orders enhanced: {len(pos)}")
|
||||
print(f" • Total items added: {items_added}")
|
||||
print(f" • Average items per PO: {items_added / len(pos):.1f}")
|
||||
print()
|
||||
print("🎯 PRICE TRENDS ADDED:")
|
||||
for ing in INGREDIENTS_WITH_TRENDS:
|
||||
direction = "↑" if ing["trend"] > 0 else "↓"
|
||||
print(f" {direction} {ing['name']}: {ing['trend']*100:+.1f}% over 90 days")
|
||||
print()
|
||||
print("🚀 PROCUREMENT INSIGHTS READY:")
|
||||
print(" ✓ Price Forecaster: Can detect trends & recommend actions")
|
||||
print(" ✓ Supplier Performance: Can analyze delivery reliability")
|
||||
print(" ✓ Cost Optimizer: Can identify bulk buying opportunities")
|
||||
print()
|
||||
print("Next steps:")
|
||||
print(" 1. Create new demo session")
|
||||
print(" 2. Wait 60 seconds for AI models")
|
||||
print(" 3. Check for procurement insights (expect 1-2)")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
add_items_to_pos()
|
||||
Reference in New Issue
Block a user