# shared/alerts/templates.py """ Alert and recommendation templates in Spanish for the bakery platform """ from typing import Dict, Any ITEM_TEMPLATES = { # ALERTS - Critical Issues Requiring Immediate Action 'critical_stock_shortage': { 'es': { 'title': '🚨 Stock Crítico: {ingredient_name}', 'message': 'Solo {current_stock}kg disponibles, necesarios {required_stock}kg para producción de mañana. Acción inmediata requerida.', 'actions': ['Realizar pedido de emergencia', 'Contactar proveedor', 'Ajustar plan de producción'] }, 'en': { 'title': '🚨 Critical Stock: {ingredient_name}', 'message': 'Only {current_stock}kg available, {required_stock}kg needed for tomorrow\'s production. Immediate action required.', 'actions': ['Place emergency order', 'Contact supplier', 'Adjust production plan'] } }, 'temperature_breach': { 'es': { 'title': '🌡️ ALERTA TEMPERATURA', 'message': '{location}: {temperature}°C durante {duration} minutos. Revisar productos inmediatamente para evitar deterioro.', 'actions': ['Verificar productos', 'Llamar técnico refrigeración', 'Documentar incidencia', 'Mover productos'] }, 'en': { 'title': '🌡️ TEMPERATURE ALERT', 'message': '{location}: {temperature}°C for {duration} minutes. Check products immediately to prevent spoilage.', 'actions': ['Check products', 'Call refrigeration technician', 'Document incident', 'Move products'] } }, 'production_delay': { 'es': { 'title': '⏰ Retraso en Producción', 'message': 'Lote {batch_name} con {delay_minutes} minutos de retraso. Impacto en entregas del día.', 'actions': ['Acelerar producción', 'Notificar clientes', 'Reorganizar horarios', 'Buscar capacidad adicional'] } }, 'expired_products': { 'es': { 'title': '📅 Productos Caducados', 'message': '{product_count} productos han caducado hoy. Retirar inmediatamente por seguridad alimentaria.', 'actions': ['Retirar productos', 'Revisar inventario', 'Ajustar pedidos', 'Documentar pérdidas'] } }, 'equipment_failure': { 'es': { 'title': '⚙️ Fallo de Equipo', 'message': '{equipment_name} no está funcionando correctamente. Producción afectada.', 'actions': ['Parar producción', 'Llamar mantenimiento', 'Usar equipo alternativo', 'Documentar fallo'] } }, 'maintenance_required': { 'es': { 'title': '🔧 Mantenimiento Requerido: {equipment_name}', 'message': 'Equipo {equipment_name} requiere mantenimiento en {days_until_maintenance} días.', 'actions': ['Programar mantenimiento', 'Revisar historial', 'Preparar repuestos', 'Planificar parada'] } }, 'low_equipment_efficiency': { 'es': { 'title': '📉 Baja Eficiencia: {equipment_name}', 'message': 'Eficiencia del {equipment_name} bajó a {efficiency_percent}%. Revisar funcionamiento.', 'actions': ['Revisar configuración', 'Limpiar equipo', 'Calibrar sensores', 'Revisar mantenimiento'] } }, 'order_overload': { 'es': { 'title': '📋 Sobrecarga de Pedidos', 'message': 'Capacidad excedida en {percentage}%. Riesgo de no cumplir entregas.', 'actions': ['Priorizar pedidos', 'Aumentar turnos', 'Rechazar nuevos pedidos', 'Buscar ayuda externa'] } }, 'supplier_delay': { 'es': { 'title': '🚚 Retraso de Proveedor', 'message': 'Entrega de {supplier_name} retrasada {hours} horas. Impacto en producción de {products}.', 'actions': ['Contactar proveedor', 'Buscar alternativas', 'Ajustar producción', 'Usar stock reserva'] } }, # RECOMMENDATIONS - Proactive Suggestions for Optimization 'inventory_optimization': { 'es': { 'title': '📈 Optimización de Stock: {ingredient_name}', 'message': 'Basado en tendencias de {period} días, sugerimos aumentar stock mínimo en {suggested_increase}kg para reducir costos.', 'actions': ['Revisar niveles mínimos', 'Analizar proveedores', 'Actualizar configuración', 'Programar pedido mayor'] }, 'en': { 'title': '📈 Stock Optimization: {ingredient_name}', 'message': 'Based on {period} day trends, suggest increasing minimum stock by {suggested_increase}kg to reduce costs.', 'actions': ['Review minimum levels', 'Analyze suppliers', 'Update configuration', 'Schedule larger order'] } }, 'production_efficiency': { 'es': { 'title': '⚙️ Mejora de Eficiencia', 'message': 'Cambiar horarios de horneado a {suggested_time} puede reducir costos energéticos en {savings_percent}%.', 'actions': ['Revisar horarios', 'Consultar personal', 'Probar nuevo horario', 'Medir resultados'] } }, 'sales_opportunity': { 'es': { 'title': '💰 Oportunidad de Venta', 'message': '{product_name} tiene alta demanda los {days}. Incrementar producción puede aumentar ventas {increase_percent}%.', 'actions': ['Aumentar producción', 'Promocionar producto', 'Revisar precios', 'Planificar ingredientes'] } }, 'seasonal_adjustment': { 'es': { 'title': '🍂 Ajuste Estacional', 'message': 'Época de {season}: ajustar producción de {products} según patrones históricos.', 'actions': ['Revisar recetas estacionales', 'Ajustar inventario', 'Planificar promociones', 'Entrenar personal'] } }, 'cost_reduction': { 'es': { 'title': '💡 Reducción de Costos', 'message': 'Cambiar a proveedor {supplier_name} para {ingredient} puede ahorrar {savings_euros}€/mes.', 'actions': ['Evaluar calidad', 'Negociar precios', 'Probar muestras', 'Cambiar proveedor gradualmente'] } }, 'waste_reduction': { 'es': { 'title': '♻️ Reducción de Desperdicio', 'message': 'Ajustar tamaños de lote de {product} puede reducir desperdicio en {waste_reduction_percent}%.', 'actions': ['Analizar ventas', 'Ajustar recetas', 'Cambiar lotes', 'Monitorear resultados'] } }, 'quality_improvement': { 'es': { 'title': '⭐ Mejora de Calidad', 'message': 'Temperatura de horneado de {product} puede optimizarse para mejor textura y sabor.', 'actions': ['Probar temperaturas', 'Documentar cambios', 'Entrenar panaderos', 'Obtener feedback'] } }, 'customer_satisfaction': { 'es': { 'title': '😊 Satisfacción del Cliente', 'message': 'Clientes solicitan más {product} los {days}. Considerar aumentar disponibilidad.', 'actions': ['Revisar comentarios', 'Aumentar producción', 'Crear promociones', 'Mejorar exhibición'] } }, 'energy_optimization': { 'es': { 'title': '⚡ Optimización Energética', 'message': 'Consolidar horneado entre {start_time} y {end_time} puede reducir costos energéticos {savings_euros}€/día.', 'actions': ['Revisar horarios energía', 'Reorganizar producción', 'Optimizar hornos', 'Medir consumo'] } }, 'staff_optimization': { 'es': { 'title': '👥 Optimización de Personal', 'message': 'Picos de trabajo los {days} a las {hours}. Considerar ajustar turnos para mejor eficiencia.', 'actions': ['Analizar cargas trabajo', 'Reorganizar turnos', 'Entrenar polivalencia', 'Contratar temporal'] } }, # FORECASTING ALERTS - Demand prediction and planning alerts 'demand_surge_weekend': { 'es': { 'title': '📈 Fin de semana con alta demanda: {product_name}', 'message': '📈 Fin de semana con alta demanda: {product_name} +{percentage}%', 'actions': ['Aumentar producción', 'Pedir ingredientes extra', 'Programar personal'] } }, 'weather_impact_alert': { 'es': { 'title': '🌧️ Impacto climático previsto', 'message': '🌧️ Lluvia prevista: -20% tráfico peatonal esperado', 'actions': ['Reducir producción fresca', 'Enfoque productos comfort', 'Promoción delivery'] } }, 'holiday_preparation': { 'es': { 'title': '🎉 {holiday_name} en {days} días', 'message': '🎉 {holiday_name} en {days} días: pedidos especiales aumentan {percentage}%', 'actions': ['Preparar menú especial', 'Stock decoraciones', 'Extender horarios'] } }, 'demand_pattern_optimization': { 'es': { 'title': '📊 Optimización de Patrones: {product_name}', 'message': 'Demanda de {product_name} varía {variation_percent}% durante la semana. Oportunidad de optimización.', 'actions': ['Analizar patrones semanales', 'Ajustar producción diaria', 'Optimizar inventario', 'Planificar promociones'] } }, 'severe_weather_impact': { 'es': { 'title': '⛈️ Impacto Climático Severo', 'message': 'Tormenta severa prevista: reducir producción de productos frescos y activar delivery.', 'actions': ['Reducir producción fresca', 'Activar delivery', 'Asegurar displays exteriores'] } }, 'unexpected_demand_spike': { 'es': { 'title': '📈 Pico de Demanda Inesperado', 'message': 'Ventas de {product_name} {spike_percentage}% sobre pronóstico.', 'actions': ['Aumentar producción', 'Revisar inventario', 'Actualizar pronóstico'] } } } def format_item_message(template_key: str, language: str, **kwargs) -> Dict[str, Any]: """Format item message using template with validation""" template = ITEM_TEMPLATES.get(template_key, {}).get(language, {}) if not template: # Fallback for missing templates return { 'title': f'Notificación: {template_key}', 'message': f'Información: {", ".join([f"{k}: {v}" for k, v in kwargs.items()])}', 'actions': ['Revisar', 'Documentar'] } try: # Format with provided kwargs, handling missing values gracefully formatted_title = template['title'].format(**kwargs) formatted_message = template['message'].format(**kwargs) return { 'title': formatted_title, 'message': formatted_message, 'actions': template.get('actions', []) } except KeyError as e: # Handle missing format parameters return { 'title': template.get('title', f'Notificación: {template_key}'), 'message': f"Error en plantilla - parámetro faltante: {e}. Datos: {kwargs}", 'actions': template.get('actions', ['Revisar configuración']) } def get_severity_emoji(severity: str) -> str: """Get emoji for severity level""" emoji_map = { 'urgent': '🚨', 'high': '⚠️', 'medium': '💡', 'low': 'ℹ️' } return emoji_map.get(severity, '📋') def get_item_type_emoji(item_type: str) -> str: """Get emoji for item type""" emoji_map = { 'alert': '🚨', 'recommendation': '💡' } return emoji_map.get(item_type, '📋') def format_business_time(hour: int) -> str: """Format hour in Spanish business context""" if hour == 0: return "medianoche" elif hour < 12: return f"{hour}:00 AM" elif hour == 12: return "12:00 PM (mediodía)" else: return f"{hour-12}:00 PM" def get_spanish_day_name(day_number: int) -> str: """Get Spanish day name (0=Monday)""" days = ["lunes", "martes", "miércoles", "jueves", "viernes", "sábado", "domingo"] return days[day_number] if 0 <= day_number <= 6 else "día desconocido" def format_currency(amount: float) -> str: """Format currency in Spanish Euro format""" return f"{amount:.2f}€" def format_percentage(value: float) -> str: """Format percentage in Spanish format""" return f"{value:.1f}%"