from typing import Dict, List from config import RECOMMENDATIONS_RULES def generate_recommendations(analysis_results: Dict) -> List[Dict]: """ Generate actionable recommendations based on analysis results Args: analysis_results: Dictionary with analysis results from AI Returns: List of recommendation dictionaries """ recommendations = [] if not analysis_results: return recommendations # Product not found recommendations if not analysis_results.get('product_found', False): recommendations.append({ 'type': 'critical', 'priority': 1, 'title': '🚨 Produkt nie znaleziony', 'description': 'Produkt nie jest widoczny na półce lub jest niedostępny.', 'action': 'Uzupełnij asortyment lub sprawdź lokalizację produktu', 'estimated_impact': '+100% dostępności', 'time_to_fix': '5-15 minut', 'difficulty': 'Łatwe' }) return recommendations # Position recommendations shelf_position = analysis_results.get('shelf_position', '').lower() if shelf_position in ['bottom', 'dół', 'dolna']: recommendations.append({ 'type': 'position', 'priority': 2, 'title': '📈 Przenieś na poziom oczu', 'description': 'Produkt znajduje się na dolnej półce, co znacznie zmniejsza widoczność.', 'action': 'Przenieś produkty na poziom oczu (120-160cm)', 'estimated_impact': '+30% sprzedaży', 'time_to_fix': '2-3 minuty', 'difficulty': 'Łatwe' }) elif shelf_position in ['top', 'góra', 'górna']: recommendations.append({ 'type': 'position', 'priority': 3, 'title': '👁️ Popraw widoczność', 'description': 'Produkt na górnej półce - rozważ przeniesienie lub dodatkowe oznakowanie.', 'action': 'Przenieś na środkową półkę lub dodaj shelf talker', 'estimated_impact': '+20% widoczności', 'time_to_fix': '2-3 minuty', 'difficulty': 'Łatwe' }) # Facing count recommendations facing_count = analysis_results.get('facing_count', 0) if facing_count == 1: recommendations.append({ 'type': 'quantity', 'priority': 3, 'title': '➕ Zwiększ liczbę facings', 'description': 'Tylko jeden facing - zwiększenie do 2-3 poprawia widoczność.', 'action': 'Dodaj 1-2 dodatkowe facings', 'estimated_impact': '+15% widoczności', 'time_to_fix': '1-2 minuty', 'difficulty': 'Bardzo łatwe' }) elif facing_count == 0: recommendations.append({ 'type': 'quantity', 'priority': 1, 'title': '🔄 Uzupełnij produkty', 'description': 'Brak produktów na półce.', 'action': 'Uzupełnij asortyment z magazynu', 'estimated_impact': '+100% dostępności', 'time_to_fix': '5-10 minut', 'difficulty': 'Łatwe' }) # Price visibility recommendations if not analysis_results.get('price_visible', False): recommendations.append({ 'type': 'pricing', 'priority': 2, 'title': '💰 Dodaj widoczną cenę', 'description': 'Brak widocznej ceny może zniechęcać klientów.', 'action': 'Dodaj lub popraw czytelność cenówki', 'estimated_impact': '+10% konwersji', 'time_to_fix': '1-2 minuty', 'difficulty': 'Bardzo łatwe' }) # Product condition recommendations condition = analysis_results.get('product_condition', '').lower() if condition in ['dusty', 'zakurzony']: recommendations.append({ 'type': 'condition', 'priority': 4, 'title': '🧹 Wyczyść produkty', 'description': 'Produkty wyglądają na zakurzone, co wpływa na postrzeganie jakości.', 'action': 'Wyczyść produkty i opakowania', 'estimated_impact': '+5% percepcji jakości', 'time_to_fix': '2-3 minuty', 'difficulty': 'Bardzo łatwe' }) elif condition in ['damaged', 'uszkodzony']: recommendations.append({ 'type': 'condition', 'priority': 1, 'title': '⚠️ Wymień uszkodzone produkty', 'description': 'Uszkodzone produkty negatywnie wpływają na wizerunek marki.', 'action': 'Usuń uszkodzone produkty i zastąp nowymi', 'estimated_impact': '+15% percepcji marki', 'time_to_fix': '3-5 minut', 'difficulty': 'Łatwe' }) # Competition recommendations competitors = analysis_results.get('competitors_nearby', []) if len(competitors) > 3: recommendations.append({ 'type': 'competition', 'priority': 3, 'title': '🎯 Zwiększ wyróżnienie', 'description': f'Silna konkurencja w pobliżu ({len(competitors)} produktów konkurencyjnych).', 'action': 'Dodaj materiały POS lub zwiększ liczbę facings', 'estimated_impact': '+20% uwagi klientów', 'time_to_fix': '5-10 minut', 'difficulty': 'Średnie' }) # Shelf share recommendations shelf_share = analysis_results.get('shelf_share', 0) if shelf_share < 10: recommendations.append({ 'type': 'share', 'priority': 2, 'title': '📊 Zwiększ udział w półce', 'description': f'Niski udział w półce ({shelf_share}%). Rozważ negocjacje z menedżerem kategorii.', 'action': 'Zwiększ liczbę facings lub wynegocjuj lepszą przestrzeń', 'estimated_impact': '+25% widoczności', 'time_to_fix': '10-30 minut', 'difficulty': 'Trudne' }) # Overall score recommendations overall_score = analysis_results.get('overall_score', 5) if overall_score < 4: recommendations.append({ 'type': 'general', 'priority': 1, 'title': '🚀 Kompleksowa poprawa', 'description': 'Niska ogólna ocena ekspozycji wymaga kompleksowej poprawy.', 'action': 'Zastosuj wszystkie powyższe rekomendacje w kolejności priorytetów', 'estimated_impact': '+50% ogólnej efektywności', 'time_to_fix': '15-30 minut', 'difficulty': 'Średnie' }) # Sort recommendations by priority recommendations.sort(key=lambda x: x['priority']) return recommendations def calculate_total_impact(recommendations: List[Dict]) -> Dict: """ Calculate estimated total impact of all recommendations Args: recommendations: List of recommendation dictionaries Returns: Dictionary with total impact estimates """ total_time = 0 impact_categories = { 'sprzedaż': [], 'widoczność': [], 'dostępność': [], 'jakość': [] } for rec in recommendations: # Extract time (assuming format like "2-3 minuty") time_str = rec.get('time_to_fix', '0') try: # Extract first number from time string time_parts = time_str.split('-') if time_parts: total_time += int(''.join(filter(str.isdigit, time_parts[0]))) except: total_time += 5 # Default 5 minutes # Categorize impact impact = rec.get('estimated_impact', '') if 'sprzedaż' in impact.lower(): impact_categories['sprzedaż'].append(impact) elif 'widoczność' in impact.lower(): impact_categories['widoczność'].append(impact) elif 'dostępność' in impact.lower(): impact_categories['dostępność'].append(impact) elif any(word in impact.lower() for word in ['jakość', 'percepcj']): impact_categories['jakość'].append(impact) return { 'total_time_minutes': total_time, 'impact_categories': impact_categories, 'total_recommendations': len(recommendations), 'high_priority_count': len([r for r in recommendations if r['priority'] <= 2]) }