import streamlit as st
import pandas as pd
import plotly.express as px
from streamlit_option_menu import option_menu
import numpy as np
from datetime import datetime, timedelta
# Import our modules
from data.synthetic_data import SAPDataGenerator
from agents.procurement_agent import ProcurementAgent
from utils.charts import ProcurementCharts
# Page configuration
st.set_page_config(
page_title="🚀 SAP S/4HANA Procurement AI",
page_icon="🚀",
layout="wide",
initial_sidebar_state="expanded"
)
# Custom CSS for beautiful UI
st.markdown("""
""", unsafe_allow_html=True)
# Initialize session state
if 'data_loaded' not in st.session_state:
st.session_state.data_loaded = False
st.session_state.po_data = None
st.session_state.supplier_data = None
st.session_state.spend_data = None
@st.cache_data
def load_synthetic_data():
"""Load and cache synthetic data"""
generator = SAPDataGenerator()
po_data = generator.generate_purchase_orders(1000)
supplier_data = generator.generate_supplier_performance()
spend_data = generator.generate_spend_analysis()
return po_data, supplier_data, spend_data
def main():
# Main header
st.markdown('
🚀 SAP S/4HANA Procurement AI Assistant
', unsafe_allow_html=True)
st.markdown('Intelligent Procurement Analytics with AI-Powered Insights
', unsafe_allow_html=True)
# Load data
if not st.session_state.data_loaded:
with st.spinner("🔄 Loading SAP S/4HANA Data..."):
po_data, supplier_data, spend_data = load_synthetic_data()
st.session_state.po_data = po_data
st.session_state.supplier_data = supplier_data
st.session_state.spend_data = spend_data
st.session_state.data_loaded = True
# Sidebar navigation
with st.sidebar:
st.image("https://via.placeholder.com/200x80/667eea/white?text=SAP+S/4HANA", width=200)
selected = option_menu(
menu_title="Navigation",
options=["🏠 Dashboard", "📊 Analytics", "🤖 AI Insights", "🔍 Deep Dive", "⚙️ Settings"],
icons=["house", "graph-up", "robot", "search", "gear"],
menu_icon="cast",
default_index=0,
styles={
"container": {"padding": "0!important", "background-color": "#fafafa"},
"icon": {"color": "#667eea", "font-size": "18px"},
"nav-link": {"font-size": "16px", "text-align": "left", "margin": "0px", "--hover-color": "#eee"},
"nav-link-selected": {"background-color": "#667eea"},
}
)
# Initialize AI agent
agent = ProcurementAgent()
charts = ProcurementCharts()
# Main content based on selection
if selected == "🏠 Dashboard":
show_dashboard(st.session_state.po_data, st.session_state.supplier_data, charts)
elif selected == "📊 Analytics":
show_analytics(st.session_state.po_data, st.session_state.spend_data, charts)
elif selected == "🤖 AI Insights":
show_ai_insights(st.session_state.po_data, st.session_state.supplier_data, agent)
elif selected == "🔍 Deep Dive":
show_deep_dive(st.session_state.po_data, st.session_state.supplier_data)
elif selected == "⚙️ Settings":
show_settings()
def show_dashboard(po_data, supplier_data, charts):
st.subheader("📈 Executive Dashboard")
# KPI Metrics
col1, col2, col3, col4 = st.columns(4)
total_spend = po_data['Total_Value'].sum()
total_pos = len(po_data)
avg_delivery = po_data['Delivery_Performance'].mean()
top_supplier = po_data.groupby('Supplier')['Total_Value'].sum().idxmax()
with col1:
st.markdown(f"""
💰 Total Spend
${total_spend:,.0f}
""", unsafe_allow_html=True)
with col2:
st.markdown(f"""
📋 Purchase Orders
{total_pos:,}
""", unsafe_allow_html=True)
with col3:
st.markdown(f"""
🎯 Avg Delivery
{avg_delivery:.1f}%
""", unsafe_allow_html=True)
with col4:
st.markdown(f"""
🏆 Top Supplier
{top_supplier}
""", unsafe_allow_html=True)
st.markdown("---")
# Charts
col1, col2 = st.columns(2)
with col1:
fig_trend = charts.create_spend_trend_chart(po_data)
st.plotly_chart(fig_trend, use_container_width=True)
with col2:
fig_category = charts.create_category_pie_chart(po_data)
st.plotly_chart(fig_category, use_container_width=True)
# Status and Performance
col1, col2 = st.columns(2)
with col1:
fig_status = charts.create_status_donut_chart(po_data)
st.plotly_chart(fig_status, use_container_width=True)
with col2:
fig_supplier = charts.create_supplier_performance_chart(po_data)
st.plotly_chart(fig_supplier, use_container_width=True)
def show_analytics(po_data, spend_data, charts):
st.subheader("📊 Advanced Analytics")
# Filter controls
col1, col2, col3 = st.columns(3)
with col1:
selected_suppliers = st.multiselect(
"Select Suppliers:",
options=po_data['Supplier'].unique(),
default=po_data['Supplier'].unique()[:5]
)
with col2:
selected_categories = st.multiselect(
"Select Categories:",
options=po_data['Category'].unique(),
default=po_data['Category'].unique()[:5]
)
with col3:
date_range = st.date_input(
"Date Range:",
value=(po_data['PO_Date'].min(), po_data['PO_Date'].max()),
min_value=po_data['PO_Date'].min(),
max_value=po_data['PO_Date'].max()
)
# Filter data
filtered_data = po_data[
(po_data['Supplier'].isin(selected_suppliers)) &
(po_data['Category'].isin(selected_categories))
]
st.markdown("---")
# Advanced Charts
tab1, tab2, tab3 = st.tabs(["📈 Trends", "🏢 Suppliers", "📦 Categories"])
with tab1:
col1, col2 = st.columns(2)
with col1:
# Monthly trend
fig_trend = charts.create_spend_trend_chart(filtered_data)
st.plotly_chart(fig_trend, use_container_width=True)
with col2:
# Delivery performance over time
monthly_delivery = filtered_data.groupby(filtered_data['PO_Date'].dt.to_period('M'))['Delivery_Performance'].mean().reset_index()
monthly_delivery['PO_Date'] = monthly_delivery['PO_Date'].astype(str)
fig = px.bar(monthly_delivery, x='PO_Date', y='Delivery_Performance',
title='🚚 Monthly Delivery Performance',
color='Delivery_Performance',
color_continuous_scale='RdYlGn')
fig.update_layout(height=400, plot_bgcolor='rgba(0,0,0,0)')
st.plotly_chart(fig, use_container_width=True)
with tab2:
# Supplier analysis
supplier_summary = filtered_data.groupby('Supplier').agg({
'Total_Value': ['sum', 'mean', 'count'],
'Delivery_Performance': 'mean'
}).round(2)
supplier_summary.columns = ['Total Spend', 'Avg PO Value', 'PO Count', 'Delivery %']
supplier_summary = supplier_summary.reset_index()
st.dataframe(
supplier_summary.style.highlight_max(axis=0),
use_container_width=True,
height=400
)
with tab3:
# Category deep dive
category_analysis = filtered_data.groupby('Category').agg({
'Total_Value': 'sum',
'Quantity': 'sum',
'Unit_Price': 'mean',
'Delivery_Performance': 'mean'
}).round(2)
st.dataframe(
category_analysis.style.highlight_max(axis=0),
use_container_width=True,
height=400
)
def show_ai_insights(po_data, supplier_data, agent):
st.subheader("🤖 AI-Powered Procurement Insights")
# Generate insights
with st.spinner("🧠 AI Agent is analyzing your procurement data..."):
insights = agent.generate_insights(po_data, supplier_data)
# Executive Summary
st.markdown(f"""
📋 Executive Summary
{insights['summary']}
""", unsafe_allow_html=True)
# Tabs for different insights
tab1, tab2, tab3 = st.tabs(["💰 Spend Analysis", "🏢 Supplier Intelligence", "⚠️ Risk Alerts"])
with tab1:
spend_insights = insights['spend_analysis']
col1, col2 = st.columns(2)
with col1:
st.metric("Total Spend", f"${spend_insights.get('total_spend', 0):,.2f}")
st.metric("Avg PO Value", f"${spend_insights.get('avg_po_value', 0):,.2f}")
with col2:
st.metric("Spending Trend", spend_insights.get('monthly_trend', 'N/A').title())
st.metric("Top Category", spend_insights.get('top_category', 'N/A'))
st.subheader("🎯 AI Recommendations")
for recommendation in spend_insights.get('recommendations', []):
st.markdown(f"""
{recommendation}
""", unsafe_allow_html=True)
with tab2:
supplier_insights = insights['supplier_analysis']
col1, col2 = st.columns(2)
with col1:
best = supplier_insights.get('best_performer', {})
st.success(f"🏆 Best Performer: {best.get('name', 'N/A')} ({best.get('performance', 0):.1f}%)")
with col2:
worst = supplier_insights.get('worst_performer', {})
st.error(f"⚠️ Needs Improvement: {worst.get('name', 'N/A')} ({worst.get('performance', 0):.1f}%)")
st.subheader("📈 Supplier Recommendations")
for recommendation in supplier_insights.get('recommendations', []):
st.markdown(f"""
{recommendation}
""", unsafe_allow_html=True)
with tab3:
anomalies = insights['anomalies']
if anomalies:
st.subheader(f"🚨 {len(anomalies)} Critical Issues Detected")
for anomaly in anomalies:
risk_color = {"High": "🔴", "Medium": "🟡", "Low": "🟢"}
st.markdown(f"""
{risk_color.get(anomaly.get('risk_level', 'Medium'), '🟡')} {anomaly['type']}
PO: {anomaly.get('po_number', 'N/A')} | Supplier: {anomaly.get('supplier', 'N/A')}
Risk Level: {anomaly.get('risk_level', 'Unknown')}
""", unsafe_allow_html=True)
else:
st.success("🎉 No critical issues detected in your procurement data!")
def show_deep_dive(po_data, supplier_data):
st.subheader("🔍 Deep Dive Analysis")
# Data explorer
st.subheader("📊 Purchase Orders Data Explorer")
# Search and filter
col1, col2, col3 = st.columns(3)
with col1:
search_po = st.text_input("🔍 Search PO Number:")
with col2:
filter_status = st.selectbox("Filter by Status:", ['All'] + list(po_data['Status'].unique()))
with col3:
min_value = st.number_input("Min PO Value:", min_value=0, value=0)
# Apply filters
filtered_po = po_data.copy()
if search_po:
filtered_po = filtered_po[filtered_po['PO_Number'].str.contains(search_po, case=False)]
if filter_status != 'All':
filtered_po = filtered_po[filtered_po['Status'] == filter_status]
if min_value > 0:
filtered_po = filtered_po[filtered_po['Total_Value'] >= min_value]
# Display filtered data
st.dataframe(
filtered_po.style.highlight_max(axis=0),
use_container_width=True,
height=400
)
# Download data
csv = filtered_po.to_csv(index=False)
st.download_button(
label="📥 Download Filtered Data",
data=csv,
file_name=f"procurement_data_{datetime.now().strftime('%Y%m%d_%H%M%S')}.csv",
mime="text/csv"
)
def show_settings():
st.subheader("⚙️ Application Settings")
st.info("🚀 **Demo Configuration**")
col1, col2 = st.columns(2)
with col1:
st.markdown("### 📊 Data Settings")
data_refresh = st.button("🔄 Refresh Synthetic Data")
if data_refresh:
st.session_state.data_loaded = False
st.rerun()
st.markdown("### 🎨 Theme Settings")
theme = st.selectbox("Choose Theme:", ["Default", "Dark", "Light"])
with col2:
st.markdown("### 🤖 AI Settings")
ai_model = st.selectbox("AI Model:", ["GPT-4", "Claude", "Local Model"])
confidence = st.slider("Confidence Threshold:", 0.0, 1.0, 0.8)
st.markdown("### 📈 Chart Settings")
chart_style = st.selectbox("Chart Style:", ["Modern", "Classic", "Minimal"])
st.markdown("---")
st.markdown("### 📋 Application Info")
st.json({
"version": "1.0.0",
"framework": "Streamlit",
"data_source": "Synthetic SAP S/4HANA",
"ai_agent": "Custom Procurement Agent",
"last_updated": datetime.now().strftime("%Y-%m-%d %H:%M:%S")
})
if __name__ == "__main__":
main()