#Stable version for Maruti Suzuki import streamlit as st import pandas as pd import numpy as np import plotly.express as px import plotly.graph_objects as go from datetime import datetime, timedelta import random # Page configuration st.set_page_config( page_title="Maruti Suzuki - Complete Supply Chain Hub", page_icon="🚗", layout="wide", initial_sidebar_state="expanded" ) # Custom CSS (same as before) st.markdown(""" """, unsafe_allow_html=True) # Initialize session state if 'executed_mitigations' not in st.session_state: st.session_state.executed_mitigations = [] if 'external_signals' not in st.session_state: st.session_state.external_signals = [] # UPDATED: Generate 8-week forward-looking demand data for Maruti components @st.cache_data def generate_8week_demand_data(): today = datetime(2025, 9, 24) # Current date dates = [today + timedelta(days=x) for x in range(56)] # 8 weeks = 56 days # Maruti-specific materials/components based on actual product lineup materials = [ 'ENG001-K15C Engine Assembly', 'TRX001-CVT Transmission', 'STR001-Electric Power Steering', 'BRK001-ABS Brake System', 'SUS001-MacPherson Strut' ] all_data = [] for material in materials: np.random.seed(hash(material) % 1000) # Generate base demand patterns (higher volumes for Maruti scale) base_demand = np.random.normal(180, 20, 56) # First 14 days: FIRM DEMAND from production schedule firm_demand = np.clip(base_demand[:14], 120, 250).astype(int) # Days 15-56: Customer shared demand (dealer network forecast) customer_shared = np.clip(base_demand[14:] * (1 + 0.08 * np.sin(np.linspace(0, 3.14, 42))), 100, 280).astype(int) # Days 15-56: AI-corrected demand (with market signals) external_factors = np.zeros(42) # Festive season impact (weeks 3-4) external_factors[0:14] += np.random.normal(0, 8, 14) # EV transition impact (weeks 5-8) - negative for ICE components if 'ENG001' in material or 'TRX001' in material: external_factors[14:] -= 5 # New model launch boost (weeks 6-7) external_factors[28:42] += 12 corrected_demand = np.clip(customer_shared + external_factors, 80, 320).astype(int) # Generate supply plan for 56 days supply_capacity = np.random.normal(185, 15, 56) supply_plan = np.clip(supply_capacity, 140, 280).astype(int) # Apply disruptions to supply (monsoon impact on days 15-18) supply_actual = supply_plan.copy() supply_actual[15:19] = (supply_actual[15:19] * 0.75).astype(int) for i, date in enumerate(dates): # Determine which demand to use if i < 14: demand_used = firm_demand[i] firm_val = firm_demand[i] customer_val = None corrected_val = None demand_type = "Production Schedule" else: demand_used = corrected_demand[i-14] firm_val = None customer_val = customer_shared[i-14] corrected_val = corrected_demand[i-14] demand_type = "AI-Corrected Forecast" # Calculate shortfall shortfall = max(0, demand_used - supply_actual[i]) all_data.append({ 'Date': date, 'Week': f"Week {(i//7)+1}", 'Day': i + 1, 'Material': material, 'Firm_Demand': firm_val, 'Customer_Demand': customer_val, 'Corrected_Demand': corrected_val, 'Demand_Used': demand_used, 'Supply_Plan': supply_plan[i], 'Supply_Projected': supply_actual[i], 'Shortfall': shortfall, 'Demand_Type': demand_type, 'Gap': supply_actual[i] - demand_used }) return pd.DataFrame(all_data) # UPDATED: Maruti Tier-1 suppliers data based on actual suppliers @st.cache_data def get_tier1_suppliers(): return { 'Motherson Automotive': { 'location': 'Noida', 'materials': ['STR001-Electric Power Steering', 'ENG001-K15C Engine Assembly'], 'capacity': 250, 'reliability': 96, 'lead_time': 2, 'risk_factors': ['Component shortage', 'Transportation delays', 'Quality issues'] }, 'Bosch India': { 'location': 'Bangalore', 'materials': ['BRK001-ABS Brake System', 'ENG001-K15C Engine Assembly'], 'capacity': 220, 'reliability': 98, 'lead_time': 3, 'risk_factors': ['Semiconductor shortage', 'Supplier strikes', 'Raw material costs'] }, 'Valeo India': { 'location': 'Chennai', 'materials': ['SUS001-MacPherson Strut', 'TRX001-CVT Transmission'], 'capacity': 200, 'reliability': 94, 'lead_time': 2, 'risk_factors': ['Monsoon flooding', 'Port congestion', 'Currency fluctuation'] }, 'AISIN India': { 'location': 'Haryana', 'materials': ['TRX001-CVT Transmission', 'STR001-Electric Power Steering'], 'capacity': 180, 'reliability': 95, 'lead_time': 4, 'risk_factors': ['Technology delays', 'Capacity bottlenecks', 'Logistics issues'] } } # UPDATED: Generate ecosystem data for Maruti suppliers @st.cache_data def generate_ecosystem_data(): today = datetime(2025, 9, 24) dates = [today + timedelta(days=x) for x in range(14)] suppliers = get_tier1_suppliers() all_data = [] for supplier_name, supplier_info in suppliers.items(): for material in supplier_info['materials']: np.random.seed(hash(supplier_name + material) % 1000) base_capacity = supplier_info['capacity'] normal_supply = np.full(14, base_capacity, dtype=int) disrupted_supply = normal_supply.copy() if supplier_name == 'Motherson Automotive': disrupted_supply[3:6] = (disrupted_supply[3:6] * 0.4).astype(int) disruption_cause = "Component shortage from Tier-2 suppliers" disruption_days = list(range(3, 6)) elif supplier_name == 'Bosch India': disrupted_supply[6:9] = (disrupted_supply[6:9] * 0.3).astype(int) disruption_cause = "Semiconductor chip shortage" disruption_days = list(range(6, 9)) elif supplier_name == 'Valeo India': disrupted_supply[4:8] = (disrupted_supply[4:8] * 0.5).astype(int) disruption_cause = "Monsoon flooding in Chennai" disruption_days = list(range(4, 8)) elif supplier_name == 'AISIN India': disrupted_supply[9:12] = (disrupted_supply[9:12] * 0.2).astype(int) disruption_cause = "Production line automation failure" disruption_days = list(range(9, 12)) else: disruption_cause = "Normal Operations" disruption_days = [] lead_time = supplier_info['lead_time'] maruti_supply = np.full(14, base_capacity, dtype=int) for disruption_day in disruption_days: arrival_day = disruption_day + lead_time if arrival_day < 14: reduction = normal_supply[disruption_day] - disrupted_supply[disruption_day] maruti_supply[arrival_day] = max(maruti_supply[arrival_day] - reduction, 0) for i, date in enumerate(dates): all_data.append({ 'Date': date, 'Supplier': supplier_name, 'Material': material, 'Tier1_Normal_Supply': int(normal_supply[i]), 'Tier1_Disrupted_Supply': int(disrupted_supply[i]), 'Tier1_Impact': int(normal_supply[i] - disrupted_supply[i]), 'Maruti_Normal_Supply': int(normal_supply[i]), 'Maruti_Impacted_Supply': int(maruti_supply[i]), 'Maruti_Impact': int(normal_supply[i] - maruti_supply[i]), 'Disruption_Cause': disruption_cause if i in disruption_days else "Normal Operations", 'Lead_Time_Days': lead_time, 'Is_Disrupted': i in disruption_days, 'Is_Maruti_Impacted': maruti_supply[i] < normal_supply[i] }) return pd.DataFrame(all_data) # UPDATED: External signals for Maruti market context @st.cache_data def get_external_signals(): return [ {'Source': 'Weather API', 'Signal': 'Heavy monsoon expected in Chennai for next 4 days', 'Impact': 'Supply Risk', 'Confidence': 96}, {'Source': 'Market Intelligence', 'Signal': 'Festive season demand surge - historically 20% increase', 'Impact': 'Demand Spike', 'Confidence': 94}, {'Source': 'Government Policy', 'Signal': 'New EV incentive scheme announced - ICE demand may soften', 'Impact': 'Demand Shift', 'Confidence': 89}, {'Source': 'Supplier Network', 'Signal': 'Semiconductor supply improving by 15% next quarter', 'Impact': 'Supply Recovery', 'Confidence': 92}, {'Source': 'Social Media Analytics', 'Signal': 'High anticipation for new Maruti hybrid models', 'Impact': 'Future Demand', 'Confidence': 78}, {'Source': 'Industry Reports', 'Signal': 'Rural market recovery driving small car demand', 'Impact': 'Volume Growth', 'Confidence': 87}, {'Source': 'Dealer Network', 'Signal': 'Inventory clearance promotions planned for month-end', 'Impact': 'Short-term Boost', 'Confidence': 98} ] # UPDATED: Generate alerts for 8-week data def generate_detailed_alerts(df): alerts = [] for material in df['Material'].unique(): material_data = df[df['Material'] == material] shortage_days = material_data[material_data['Shortfall'] > 5] if not shortage_days.empty: for _, row in shortage_days.iterrows(): root_causes = [] if row['Day'] > 14: if row['Corrected_Demand'] and row['Customer_Demand']: diff = row['Corrected_Demand'] - row['Customer_Demand'] if diff > 10: root_causes.append(f"AI detected {diff} units additional demand from market signals") if row['Day'] >= 15 and row['Day'] <= 18: root_causes.append("Monsoon disruption affecting supplier delivery") else: root_causes.append("Production schedule demand exceeding supplier capacity") if not root_causes: root_causes.append("Base demand exceeding current supply capacity") mitigation_options = [ {"option": "Activate backup production line at Haryana plant", "impact": "+40 units/day", "cost": "High", "timeline": "24 hours"}, {"option": "Expedite air freight from alternate suppliers", "impact": "+20 units/day", "cost": "Medium", "timeline": "12 hours"}, {"option": "Emergency sourcing from Suzuki Japan", "impact": "+60 units/day", "cost": "Very High", "timeline": "48 hours"}, {"option": "Reallocate inventory from Gurgaon warehouse", "impact": "+25 units/day", "cost": "Low", "timeline": "18 hours"} ] if row['Shortfall'] > 40: best_option = mitigation_options[2] elif row['Shortfall'] > 20: best_option = mitigation_options[0] else: best_option = mitigation_options[1] alerts.append({ 'material': material, 'date': row['Date'].strftime('%Y-%m-%d'), 'week': row['Week'], 'shortage': int(row['Shortfall']), 'demand_type': row['Demand_Type'], 'severity': 'Critical' if row['Shortfall'] > 40 else 'High' if row['Shortfall'] > 20 else 'Medium', 'root_causes': root_causes, 'mitigation_options': mitigation_options, 'best_option': best_option }) return alerts # Keep mitigation strategies for ecosystem (updated for Maruti context) def generate_mitigation_strategies(supplier, material, impact_amount, impact_days): base_strategies = [ { 'strategy': 'Activate Alternate Supplier Network', 'description': f'Engage backup Tier-1 supplier for {material}', 'timeline': '24-48 hours', 'cost': 'High (+12% unit cost)', 'effectiveness': '92%', 'capacity': f'+{impact_amount * 0.9:.0f} units/day', }, { 'strategy': 'Emergency Suzuki Japan Import', 'description': f'Air freight {material} from Suzuki Corporation', 'timeline': '48-72 hours', 'cost': 'Very High (+35% logistics cost)', 'effectiveness': '85%', 'capacity': f'+{impact_amount * 0.85:.0f} units/day', }, { 'strategy': 'Cross-Plant Inventory Transfer', 'description': f'Transfer {material} stock from other Maruti plants', 'timeline': '12-24 hours', 'cost': 'Medium (+6% handling cost)', 'effectiveness': '70%', 'capacity': f'+{impact_amount * 0.7:.0f} units/day', } ] if impact_amount > 150: recommended = [0, 1] elif impact_amount > 75: recommended = [0, 2] else: recommended = [2] return base_strategies, recommended # Load data df_demand = generate_8week_demand_data() df_ecosystem = generate_ecosystem_data() external_signals = get_external_signals() suppliers = get_tier1_suppliers() # Updated title for Maruti Suzuki st.title("🚗 Maruti Suzuki Supply Chain Command Center") # Tab Navigation (same as before) st.sidebar.title("🎯 Dashboard Navigation") dashboard_tab = st.sidebar.radio( "Select Dashboard:", ["📊 Demand & Supply Forecast", "🌐 Ecosystem Supplier Impact", "🛡️ Buffer Optimizer"], index=0 ) # TAB 1: 8-WEEK DEMAND & SUPPLY FORECAST (Updated for Maruti) if dashboard_tab == "📊 Demand & Supply Forecast": st.markdown("""
8-Week Production Planning | Production Schedule (Days 1-14) | AI-Enhanced Market Forecast (Days 15-56)
Date: {alert['date']} ({alert['week']}) | Shortage: {alert['shortage']} units | Type: {alert['demand_type']}
Tier-1 Supplier Disruption Analysis | Cascading Impact on Production | Automated Response Systems
AI-driven safety stock recommendations across Maruti's production network
🚗 Maruti Suzuki 8-Week Supply Chain Command Center | Production Schedule + AI-Enhanced Forecast | Tier-1 Supplier Intelligence + Buffer Optimization
Powered by Agentic AI | 8-Week Planning Horizon | Comprehensive Automotive Supply Chain Resilience