PD03 commited on
Commit
e448628
Β·
verified Β·
1 Parent(s): 99c9b10

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +507 -1
src/streamlit_app.py CHANGED
@@ -101,4 +101,510 @@ st.markdown("""
101
  border: none;
102
  border-radius: 8px;
103
  padding: 0.5rem 1rem;
104
- font
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  border: none;
102
  border-radius: 8px;
103
  padding: 0.5rem 1rem;
104
+ font-weight: 600;
105
+ transition: all 0.3s ease;
106
+ }
107
+
108
+ .stButton > button:hover {
109
+ transform: translateY(-2px);
110
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
111
+ }
112
+ </style>
113
+ """, unsafe_allow_html=True)
114
+
115
+ # Data generation function (embedded in main file)
116
+ @st.cache_data
117
+ def generate_synthetic_procurement_data():
118
+ """Generate synthetic SAP S/4HANA procurement data"""
119
+ fake = Faker()
120
+
121
+ # Vendors data
122
+ vendors = [
123
+ "Siemens AG", "BASF SE", "BMW Group", "Mercedes-Benz", "Bosch GmbH",
124
+ "ThyssenKrupp", "Bayer AG", "Continental AG", "Henkel AG", "SAP SE"
125
+ ]
126
+
127
+ # Material categories
128
+ material_categories = [
129
+ "Raw Materials", "Components", "Packaging", "Services",
130
+ "IT Equipment", "Office Supplies", "Machinery", "Chemicals"
131
+ ]
132
+
133
+ # Generate purchase orders
134
+ purchase_orders = []
135
+ for i in range(500):
136
+ order_date = fake.date_between(start_date='-2y', end_date='today')
137
+ delivery_date = order_date + timedelta(days=random.randint(1, 30))
138
+
139
+ po = {
140
+ 'po_number': f"PO{str(i+1).zfill(6)}",
141
+ 'vendor': random.choice(vendors),
142
+ 'material_category': random.choice(material_categories),
143
+ 'order_date': order_date,
144
+ 'delivery_date': delivery_date,
145
+ 'order_value': round(random.uniform(1000, 100000), 2),
146
+ 'quantity': random.randint(1, 1000),
147
+ 'unit_price': round(random.uniform(10, 500), 2),
148
+ 'status': random.choice(['Open', 'Delivered', 'Invoiced', 'Paid']),
149
+ 'plant': random.choice(['Plant_001', 'Plant_002', 'Plant_003']),
150
+ 'buyer': fake.name(),
151
+ 'currency': 'EUR',
152
+ 'payment_terms': random.choice(['30 Days', '60 Days', '90 Days']),
153
+ 'on_time_delivery': random.choice([True, False]),
154
+ 'quality_score': round(random.uniform(7, 10), 1)
155
+ }
156
+ purchase_orders.append(po)
157
+
158
+ # Generate spend analytics data
159
+ spend_data = []
160
+ for vendor in vendors:
161
+ for category in material_categories:
162
+ spend = {
163
+ 'vendor': vendor,
164
+ 'category': category,
165
+ 'total_spend': round(random.uniform(10000, 500000), 2),
166
+ 'contract_compliance': round(random.uniform(80, 100), 1),
167
+ 'risk_score': round(random.uniform(1, 10), 1),
168
+ 'savings_potential': round(random.uniform(5, 25), 1)
169
+ }
170
+ spend_data.append(spend)
171
+
172
+ return pd.DataFrame(purchase_orders), pd.DataFrame(spend_data)
173
+
174
+ # AI Agent Classes (embedded in main file)
175
+ class LLMPoweredProcurementAgent:
176
+ """AI Agent powered by OpenAI GPT for intelligent procurement analysis"""
177
+
178
+ def __init__(self, po_data: pd.DataFrame, spend_data: pd.DataFrame):
179
+ self.po_data = po_data
180
+ self.spend_data = spend_data
181
+ # Check if OpenAI API key is available
182
+ if 'OPENAI_API_KEY' in st.secrets:
183
+ self.client = openai.OpenAI(api_key=st.secrets["OPENAI_API_KEY"])
184
+ self.llm_available = True
185
+ else:
186
+ self.client = None
187
+ self.llm_available = False
188
+
189
+ def generate_executive_summary(self) -> str:
190
+ """Generate an executive summary using GPT"""
191
+
192
+ if not self.llm_available:
193
+ # Fallback to rule-based summary if no API key
194
+ total_spend = self.po_data['order_value'].sum()
195
+ total_orders = len(self.po_data)
196
+ on_time_rate = self.po_data['on_time_delivery'].mean() * 100
197
+
198
+ return f"""
199
+ **Executive Summary - Procurement Performance**
200
+
201
+ πŸ“Š **Key Metrics**: Processed {total_orders:,} orders worth €{total_spend:,.0f} across {len(self.po_data['vendor'].unique())} vendors.
202
+
203
+ 🎯 **Performance Highlights**:
204
+ β€’ On-time delivery rate: {on_time_rate:.1f}%
205
+ β€’ Average quality score: {self.po_data['quality_score'].mean():.1f}/10
206
+ β€’ Top spending category: {self.po_data.groupby('material_category')['order_value'].sum().idxmax()}
207
+
208
+ πŸ’‘ **Strategic Recommendations**:
209
+ β€’ Focus on vendor consolidation opportunities
210
+ β€’ Improve contract compliance monitoring
211
+ β€’ Implement performance-based partnerships
212
+
213
+ *Note: Connect OpenAI API for enhanced AI insights*
214
+ """
215
+
216
+ # Prepare data summary for LLM
217
+ data_summary = {
218
+ "total_spend": float(self.po_data['order_value'].sum()),
219
+ "total_orders": len(self.po_data),
220
+ "unique_vendors": len(self.po_data['vendor'].unique()),
221
+ "avg_order_value": float(self.po_data['order_value'].mean()),
222
+ "on_time_delivery_rate": float(self.po_data['on_time_delivery'].mean()),
223
+ "top_vendors": self.po_data.groupby('vendor')['order_value'].sum().nlargest(3).to_dict(),
224
+ "top_categories": self.po_data.groupby('material_category')['order_value'].sum().nlargest(3).to_dict(),
225
+ "quality_score_avg": float(self.po_data['quality_score'].mean())
226
+ }
227
+
228
+ prompt = f"""
229
+ As a senior procurement analyst, provide an executive summary of the procurement performance based on this data:
230
+
231
+ {json.dumps(data_summary, indent=2)}
232
+
233
+ Please provide:
234
+ 1. A concise executive overview (2-3 sentences)
235
+ 2. Key performance highlights
236
+ 3. Areas of concern (if any)
237
+ 4. Strategic recommendations (2-3 bullet points)
238
+
239
+ Keep the tone professional and actionable. Focus on business impact.
240
+ """
241
+
242
+ try:
243
+ response = self.client.chat.completions.create(
244
+ model="gpt-4",
245
+ messages=[
246
+ {"role": "system", "content": "You are an expert procurement analyst with 15+ years of experience in SAP S/4HANA systems."},
247
+ {"role": "user", "content": prompt}
248
+ ],
249
+ max_tokens=500,
250
+ temperature=0.7
251
+ )
252
+ return response.choices[0].message.content
253
+ except Exception as e:
254
+ return f"AI Analysis temporarily unavailable: {str(e)}"
255
+
256
+ def chat_with_data(self, user_question: str) -> str:
257
+ """Natural language interface to query procurement data"""
258
+
259
+ if not self.llm_available:
260
+ # Simple rule-based responses
261
+ question_lower = user_question.lower()
262
+
263
+ if "spend" in question_lower or "cost" in question_lower:
264
+ total_spend = self.po_data['order_value'].sum()
265
+ return f"Your total procurement spend is €{total_spend:,.0f}. The top spending category is {self.po_data.groupby('material_category')['order_value'].sum().idxmax()}. Connect OpenAI API for detailed analysis."
266
+
267
+ elif "vendor" in question_lower or "supplier" in question_lower:
268
+ top_vendor = self.po_data.groupby('vendor')['order_value'].sum().idxmax()
269
+ return f"Your top vendor by spend is {top_vendor}. You work with {len(self.po_data['vendor'].unique())} vendors total. Connect OpenAI API for detailed vendor analysis."
270
+
271
+ elif "risk" in question_lower:
272
+ return "Risk analysis shows mixed performance across vendors. Connect OpenAI API for comprehensive risk assessment."
273
+
274
+ else:
275
+ return "I can help with procurement analysis! Try asking about spending, vendors, or risks. Connect OpenAI API for advanced AI conversation."
276
+
277
+ # Create a data context for the LLM
278
+ data_context = {
279
+ "procurement_summary": {
280
+ "total_spend": float(self.po_data['order_value'].sum()),
281
+ "order_count": len(self.po_data),
282
+ "vendor_count": len(self.po_data['vendor'].unique()),
283
+ "date_range": f"{self.po_data['order_date'].min()} to {self.po_data['order_date'].max()}",
284
+ "categories": self.po_data['material_category'].unique().tolist(),
285
+ "vendors": self.po_data['vendor'].unique().tolist()
286
+ },
287
+ "performance_metrics": {
288
+ "avg_quality_score": float(self.po_data['quality_score'].mean()),
289
+ "on_time_delivery_rate": float(self.po_data['on_time_delivery'].mean()),
290
+ "avg_order_value": float(self.po_data['order_value'].mean())
291
+ }
292
+ }
293
+
294
+ prompt = f"""
295
+ User Question: {user_question}
296
+
297
+ Procurement Data Context:
298
+ {json.dumps(data_context, indent=2)}
299
+
300
+ Please answer the user's question based on the procurement data provided. If you need specific calculations or data analysis that isn't available in the context, explain what additional analysis would be needed.
301
+
302
+ Keep your response conversational but professional, and always relate back to business impact where possible.
303
+ """
304
+
305
+ try:
306
+ response = self.client.chat.completions.create(
307
+ model="gpt-4",
308
+ messages=[
309
+ {"role": "system", "content": "You are an AI procurement analyst assistant. Answer questions about procurement data in a helpful, conversational way while maintaining professional expertise."},
310
+ {"role": "user", "content": prompt}
311
+ ],
312
+ max_tokens=400,
313
+ temperature=0.7
314
+ )
315
+ return response.choices[0].message.content
316
+ except Exception as e:
317
+ return f"I'm having trouble accessing the AI right now. Please try again later. Error: {str(e)}"
318
+
319
+ def analyze_spend_patterns(self) -> Dict[str, Any]:
320
+ """Analyze spending patterns and generate insights"""
321
+ total_spend = self.po_data['order_value'].sum()
322
+ avg_order_value = self.po_data['order_value'].mean()
323
+
324
+ # Top spending categories
325
+ category_spend = self.po_data.groupby('material_category')['order_value'].sum().sort_values(ascending=False)
326
+
327
+ # Vendor performance analysis
328
+ vendor_performance = self.po_data.groupby('vendor').agg({
329
+ 'order_value': 'sum',
330
+ 'on_time_delivery': 'mean',
331
+ 'quality_score': 'mean'
332
+ }).round(2)
333
+
334
+ return {
335
+ 'total_spend': total_spend,
336
+ 'avg_order_value': avg_order_value,
337
+ 'top_categories': category_spend.to_dict(),
338
+ 'vendor_performance': vendor_performance.to_dict('index')
339
+ }
340
+
341
+ # Initialize session state and data
342
+ if 'data_loaded' not in st.session_state:
343
+ with st.spinner('πŸ”„ Generating synthetic SAP S/4HANA data...'):
344
+ st.session_state.po_df, st.session_state.spend_df = generate_synthetic_procurement_data()
345
+ st.session_state.data_loaded = True
346
+
347
+ # Initialize AI agents
348
+ @st.cache_resource
349
+ def initialize_agents():
350
+ analytics_agent = LLMPoweredProcurementAgent(st.session_state.po_df, st.session_state.spend_df)
351
+ return analytics_agent
352
+
353
+ analytics_agent = initialize_agents()
354
+
355
+ # API Key status check
356
+ api_key_status = "🟒 Connected" if 'OPENAI_API_KEY' in st.secrets else "πŸ”΄ Not Connected"
357
+
358
+ # Main header
359
+ st.markdown(f"""
360
+ <div class="main-header">
361
+ <h1>πŸ€– SAP S/4HANA Agentic AI Procurement Analytics</h1>
362
+ <p>Autonomous Intelligence for Procurement Excellence</p>
363
+ <small>OpenAI Status: {api_key_status}</small>
364
+ </div>
365
+ """, unsafe_allow_html=True)
366
+
367
+ # Sidebar navigation
368
+ with st.sidebar:
369
+ st.markdown("### πŸ€– AI-Powered Analytics")
370
+ st.markdown(f"**OpenAI Status:** {api_key_status}")
371
+
372
+ if 'OPENAI_API_KEY' not in st.secrets:
373
+ st.warning("⚠️ Add OpenAI API key in Spaces settings for full AI features")
374
+
375
+ selected = option_menu(
376
+ "Navigation",
377
+ ["🏠 Dashboard", "πŸ’¬ AI Chat", "πŸ“Š Analytics", "🎯 Recommendations"],
378
+ icons=['house', 'chat', 'graph-up', 'target'],
379
+ menu_icon="cast",
380
+ default_index=0,
381
+ styles={
382
+ "container": {"padding": "0!important", "background-color": "#fafafa"},
383
+ "icon": {"color": "#0066cc", "font-size": "18px"},
384
+ "nav-link": {"font-size": "16px", "text-align": "left", "margin": "0px", "--hover-color": "#eee"},
385
+ "nav-link-selected": {"background-color": "#0066cc"},
386
+ }
387
+ )
388
+
389
+ if selected == "🏠 Dashboard":
390
+ # AI-generated insights at the top
391
+ st.markdown("### 🧠 AI Executive Summary")
392
+
393
+ with st.spinner('πŸ€– AI is analyzing your procurement data...'):
394
+ executive_summary = analytics_agent.generate_executive_summary()
395
+
396
+ st.markdown(f"""
397
+ <div class="ai-insight">
398
+ <h4>πŸ“Š Intelligent Analysis</h4>
399
+ <div style="white-space: pre-line;">{executive_summary}</div>
400
+ </div>
401
+ """, unsafe_allow_html=True)
402
+
403
+ # Key metrics
404
+ insights = analytics_agent.analyze_spend_patterns()
405
+
406
+ col1, col2, col3, col4 = st.columns(4)
407
+
408
+ with col1:
409
+ st.markdown("""
410
+ <div class="metric-card">
411
+ <h3 style="color: var(--primary-color); margin: 0;">Total Spend</h3>
412
+ <h2 style="margin: 0.5rem 0;">€{:,.0f}</h2>
413
+ <p style="color: #28a745; margin: 0;">πŸ“ˆ +12% vs last period</p>
414
+ </div>
415
+ """.format(insights['total_spend']), unsafe_allow_html=True)
416
+
417
+ with col2:
418
+ st.markdown("""
419
+ <div class="metric-card">
420
+ <h3 style="color: var(--primary-color); margin: 0;">Avg Order Value</h3>
421
+ <h2 style="margin: 0.5rem 0;">€{:,.0f}</h2>
422
+ <p style="color: #ffc107; margin: 0;">πŸ“Š Stable trend</p>
423
+ </div>
424
+ """.format(insights['avg_order_value']), unsafe_allow_html=True)
425
+
426
+ with col3:
427
+ active_vendors = len(st.session_state.po_df['vendor'].unique())
428
+ st.markdown("""
429
+ <div class="metric-card">
430
+ <h3 style="color: var(--primary-color); margin: 0;">Active Vendors</h3>
431
+ <h2 style="margin: 0.5rem 0;">{}</h2>
432
+ <p style="color: #17a2b8; margin: 0;">🀝 Partnership focus</p>
433
+ </div>
434
+ """.format(active_vendors), unsafe_allow_html=True)
435
+
436
+ with col4:
437
+ on_time_delivery = st.session_state.po_df['on_time_delivery'].mean() * 100
438
+ st.markdown("""
439
+ <div class="metric-card">
440
+ <h3 style="color: var(--primary-color); margin: 0;">On-Time Delivery</h3>
441
+ <h2 style="margin: 0.5rem 0;">{:.1f}%</h2>
442
+ <p style="color: #28a745; margin: 0;">⏰ Excellent performance</p>
443
+ </div>
444
+ """.format(on_time_delivery), unsafe_allow_html=True)
445
+
446
+ # Charts
447
+ st.markdown("### πŸ“Š Executive Dashboard")
448
+
449
+ col1, col2 = st.columns(2)
450
+
451
+ with col1:
452
+ # Spend by category
453
+ category_spend = st.session_state.po_df.groupby('material_category')['order_value'].sum().reset_index()
454
+ fig_pie = px.pie(
455
+ category_spend,
456
+ values='order_value',
457
+ names='material_category',
458
+ title='Spend Distribution by Category',
459
+ color_discrete_sequence=px.colors.qualitative.Set3
460
+ )
461
+ fig_pie.update_layout(
462
+ title_font_size=16,
463
+ title_x=0.5,
464
+ showlegend=True,
465
+ height=400
466
+ )
467
+ st.plotly_chart(fig_pie, use_container_width=True)
468
+
469
+ with col2:
470
+ # Top vendors
471
+ vendor_spend = st.session_state.po_df.groupby('vendor')['order_value'].sum().reset_index()
472
+ vendor_spend = vendor_spend.nlargest(8, 'order_value')
473
+
474
+ fig_bar = px.bar(
475
+ vendor_spend,
476
+ x='vendor',
477
+ y='order_value',
478
+ title='Top Vendors by Spend',
479
+ color='order_value',
480
+ color_continuous_scale='Blues'
481
+ )
482
+ fig_bar.update_layout(
483
+ title_font_size=16,
484
+ title_x=0.5,
485
+ xaxis_tickangle=45,
486
+ height=400
487
+ )
488
+ st.plotly_chart(fig_bar, use_container_width=True)
489
+
490
+ elif selected == "πŸ’¬ AI Chat":
491
+ st.markdown("### πŸ’¬ Chat with Your Procurement Data")
492
+
493
+ st.markdown(f"""
494
+ <div class="ai-insight">
495
+ <h4>πŸ€– Intelligent Procurement Assistant</h4>
496
+ <p>Ask me anything about your procurement data! I can help you understand trends, analyze vendor performance, identify opportunities, and more.</p>
497
+ <p><small>Status: {api_key_status}</small></p>
498
+ </div>
499
+ """, unsafe_allow_html=True)
500
+
501
+ # Chat interface
502
+ if "messages" not in st.session_state:
503
+ st.session_state.messages = [
504
+ {"role": "assistant", "content": "Hello! I'm your AI procurement analyst. What would you like to know about your procurement data?"}
505
+ ]
506
+
507
+ # Display chat messages
508
+ for message in st.session_state.messages:
509
+ with st.chat_message(message["role"]):
510
+ st.markdown(message["content"])
511
+
512
+ # Chat input
513
+ if prompt := st.chat_input("Ask about your procurement data..."):
514
+ # Add user message to chat history
515
+ st.session_state.messages.append({"role": "user", "content": prompt})
516
+ with st.chat_message("user"):
517
+ st.markdown(prompt)
518
+
519
+ # Generate AI response
520
+ with st.chat_message("assistant"):
521
+ with st.spinner("πŸ€– Analyzing your question..."):
522
+ response = analytics_agent.chat_with_data(prompt)
523
+ st.markdown(response)
524
+
525
+ # Add assistant response to chat history
526
+ st.session_state.messages.append({"role": "assistant", "content": response})
527
+
528
+ # Suggested questions
529
+ st.markdown("#### πŸ’‘ Try asking:")
530
+
531
+ col1, col2, col3 = st.columns(3)
532
+
533
+ sample_questions = [
534
+ "πŸ“Š What are my spending trends?",
535
+ "πŸ† Who are my best vendors?",
536
+ "⚠️ What risks should I worry about?"
537
+ ]
538
+
539
+ for i, (col, question) in enumerate(zip([col1, col2, col3], sample_questions)):
540
+ with col:
541
+ if st.button(question, key=f"q_{i}"):
542
+ # Add the question to chat
543
+ st.session_state.messages.append({"role": "user", "content": question})
544
+ with st.spinner("πŸ€– Analyzing..."):
545
+ response = analytics_agent.chat_with_data(question)
546
+ st.session_state.messages.append({"role": "assistant", "content": response})
547
+ st.rerun()
548
+
549
+ elif selected == "πŸ“Š Analytics":
550
+ st.markdown("### πŸ“ˆ Advanced Analytics Dashboard")
551
+
552
+ # Vendor performance analysis
553
+ vendor_performance = st.session_state.po_df.groupby('vendor').agg({
554
+ 'order_value': 'sum',
555
+ 'on_time_delivery': 'mean',
556
+ 'quality_score': 'mean',
557
+ 'po_number': 'count'
558
+ }).round(2)
559
+ vendor_performance.columns = ['Total Spend', 'On-Time Delivery', 'Quality Score', 'Order Count']
560
+
561
+ st.markdown("#### πŸ† Vendor Performance Analysis")
562
+ st.dataframe(vendor_performance.sort_values('Total Spend', ascending=False), use_container_width=True)
563
+
564
+ # Performance scatter plot
565
+ fig_scatter = px.scatter(
566
+ st.session_state.po_df,
567
+ x='on_time_delivery',
568
+ y='quality_score',
569
+ size='order_value',
570
+ color='vendor',
571
+ title='Vendor Performance: Quality vs Delivery',
572
+ labels={'on_time_delivery': 'On-Time Delivery Rate', 'quality_score': 'Quality Score'}
573
+ )
574
+ fig_scatter.update_layout(height=500)
575
+ st.plotly_chart(fig_scatter, use_container_width=True)
576
+
577
+ elif selected == "🎯 Recommendations":
578
+ st.markdown("### πŸš€ AI-Generated Strategic Recommendations")
579
+
580
+ st.markdown("""
581
+ <div class="ai-insight">
582
+ <h3>🎯 Strategic Procurement Optimization</h3>
583
+ <p>Based on data analysis, here are actionable recommendations to optimize your procurement strategy.</p>
584
+ </div>
585
+ """, unsafe_allow_html=True)
586
+
587
+ recommendations = [
588
+ "🎯 **Vendor Consolidation**: Consider consolidating to top 5-7 vendors to reduce costs by 10-15%",
589
+ "πŸ“ˆ **Contract Optimization**: Renegotiate contracts with top 3 spending vendors for volume discounts",
590
+ "⚑ **Process Automation**: Implement automated PO approval for orders under €5,000",
591
+ "πŸ“Š **Performance Monitoring**: Set up real-time dashboards for vendor performance tracking",
592
+ "🀝 **Strategic Partnerships**: Develop long-term partnerships with high-performing vendors"
593
+ ]
594
+
595
+ for i, rec in enumerate(recommendations, 1):
596
+ st.markdown(f"""
597
+ <div class="alert alert-success">
598
+ <h4>Recommendation #{i}</h4>
599
+ <p>{rec}</p>
600
+ </div>
601
+ """, unsafe_allow_html=True)
602
+
603
+ # Footer
604
+ st.markdown("---")
605
+ st.markdown("""
606
+ <div style="text-align: center; padding: 1rem; color: #666;">
607
+ <p>πŸ€– Powered by Agentic AI | Built with Streamlit | SAP S/4HANA Integration Demo</p>
608
+ <p><em>This is a demonstration application with synthetic data for learning purposes</em></p>
609
+ </div>
610
+ """, unsafe_allow_html=True)