# ================================================================ # services/notification/app/core/database.py - COMPLETE IMPLEMENTATION # ================================================================ """ Database configuration and initialization for notification service """ import structlog from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker from sqlalchemy import text from shared.database.base import Base, DatabaseManager from app.core.config import settings logger = structlog.get_logger() # Initialize database manager with notification service configuration database_manager = DatabaseManager(settings.DATABASE_URL) # Convenience alias for dependency injection get_db = database_manager.get_db async def init_db(): """Initialize database tables and seed data""" try: logger.info("Initializing notification service database...") # Import all models to ensure they're registered with SQLAlchemy from app.models.notifications import ( Notification, NotificationTemplate, NotificationPreference, NotificationLog ) # Import template models (these are separate and optional) try: from app.models.templates import EmailTemplate, WhatsAppTemplate logger.info("Template models imported successfully") except ImportError: logger.warning("Template models not found, using basic templates only") logger.info("Models imported successfully") # Create all tables await database_manager.create_tables() logger.info("Database tables created successfully") # Seed default templates await _seed_default_templates() logger.info("Default templates seeded successfully") # Test database connection await _test_database_connection() logger.info("Database connection test passed") logger.info("Notification service database initialization completed") except Exception as e: logger.error(f"Failed to initialize notification database: {e}") raise async def _seed_default_templates(): """Seed default notification templates""" try: async for db in get_db(): # Check if templates already exist from sqlalchemy import select from app.models.notifications import NotificationTemplate result = await db.execute( select(NotificationTemplate).where( NotificationTemplate.is_system == True ).limit(1) ) if result.scalar_one_or_none(): logger.info("Default templates already exist, skipping seeding") return # Create default email templates default_templates = [ { "template_key": "welcome_email", "name": "Bienvenida - Email", "description": "Email de bienvenida para nuevos usuarios", "category": "transactional", "type": "email", "subject_template": "¡Bienvenido a Bakery Forecast, {{user_name}}!", "body_template": """ ¡Hola {{user_name}}! Bienvenido a Bakery Forecast, la plataforma de pronóstico de demanda para panaderías. Tu cuenta ha sido creada exitosamente. Ya puedes: - Subir datos de ventas históricos - Generar pronósticos de demanda - Optimizar tu producción diaria Para comenzar, visita tu dashboard: {{dashboard_url}} Si tienes alguna pregunta, nuestro equipo está aquí para ayudarte. ¡Éxito en tu panadería! Saludos, El equipo de Bakery Forecast """.strip(), "html_template": """ Bienvenido a Bakery Forecast

🥖 Bakery Forecast

Pronósticos inteligentes para tu panadería

¡Hola {{user_name}}!

Bienvenido a Bakery Forecast, la plataforma de pronóstico de demanda diseñada especialmente para panaderías como la tuya.

🎯 Tu cuenta está lista

Ya puedes comenzar a:

🚀 Ir al Dashboard

💡 Consejo: Para obtener mejores pronósticos, te recomendamos subir al menos 3 meses de datos históricos de ventas.

Si tienes alguna pregunta o necesitas ayuda, nuestro equipo está aquí para apoyarte en cada paso.

¡Éxito en tu panadería! 🥐
El equipo de Bakery Forecast

© 2025 Bakery Forecast. Todos los derechos reservados.

Madrid, España 🇪🇸

""".strip(), "language": "es", "is_system": True, "is_active": True, "default_priority": "normal" }, { "template_key": "forecast_alert_email", "name": "Alerta de Pronóstico - Email", "description": "Alerta por email cuando hay cambios significativos en la demanda", "category": "alert", "type": "email", "subject_template": "🚨 Alerta: Variación significativa en {{product_name}}", "body_template": """ ALERTA DE PRONÓSTICO - {{bakery_name}} Se ha detectado una variación significativa en la demanda prevista: 📦 Producto: {{product_name}} 📅 Fecha: {{forecast_date}} 📊 Demanda prevista: {{predicted_demand}} unidades 📈 Variación: {{variation_percentage}}% {{alert_message}} Te recomendamos revisar los pronósticos y ajustar la producción según sea necesario. Ver pronósticos completos: {{dashboard_url}} Saludos, El equipo de Bakery Forecast """.strip(), "html_template": """ Alerta de Pronóstico

🚨 Alerta de Pronóstico

{{bakery_name}}

⚠️ Variación Significativa Detectada

Se requiere tu atención para ajustar la producción.

📦 Producto: {{product_name}}
📅 Fecha: {{forecast_date}}
📊 Demanda prevista: {{predicted_demand}} unidades
📈 Variación: {{variation_percentage}}%

💡 Recomendación:

{{alert_message}}

📊 Ver Pronósticos Completos

El equipo de Bakery Forecast

""".strip(), "language": "es", "is_system": True, "is_active": True, "default_priority": "high" }, { "template_key": "weekly_report_email", "name": "Reporte Semanal - Email", "description": "Reporte semanal de rendimiento y estadísticas", "category": "transactional", "type": "email", "subject_template": "📊 Reporte Semanal - {{bakery_name}} ({{week_start}} - {{week_end}})", "body_template": """ REPORTE SEMANAL - {{bakery_name}} Período: {{week_start}} - {{week_end}} RESUMEN DE VENTAS: - Total de ventas: {{total_sales}} unidades - Precisión del pronóstico: {{forecast_accuracy}}% - Productos más vendidos: {{#top_products}} • {{name}}: {{quantity}} unidades {{/top_products}} ANÁLISIS: {{recommendations}} Ver reporte completo: {{report_url}} Saludos, El equipo de Bakery Forecast """.strip(), "html_template": """ Reporte Semanal

📊 Reporte Semanal

{{bakery_name}}

{{week_start}} - {{week_end}}

{{total_sales}}

Ventas Totales

{{forecast_accuracy}}%

Precisión

🏆 Productos más vendidos:

{{#top_products}}
{{name}} {{quantity}} unidades
{{/top_products}}

📈 Análisis y Recomendaciones:

{{recommendations}}

📋 Ver Reporte Completo

El equipo de Bakery Forecast
Optimizando panaderías en Madrid desde 2025

""".strip(), "language": "es", "is_system": True, "is_active": True, "default_priority": "normal" } ] # Create template objects from app.models.notifications import NotificationTemplate, NotificationType, NotificationPriority for template_data in default_templates: template = NotificationTemplate( template_key=template_data["template_key"], name=template_data["name"], description=template_data["description"], category=template_data["category"], type=NotificationType(template_data["type"]), subject_template=template_data["subject_template"], body_template=template_data["body_template"], html_template=template_data["html_template"], language=template_data["language"], is_system=template_data["is_system"], is_active=template_data["is_active"], default_priority=NotificationPriority(template_data["default_priority"]) ) db.add(template) await db.commit() logger.info(f"Created {len(default_templates)} default templates") except Exception as e: logger.error(f"Failed to seed default templates: {e}") raise async def _test_database_connection(): """Test database connection""" try: async for db in get_db(): result = await db.execute(text("SELECT 1")) if result.scalar() == 1: logger.info("Database connection test successful") else: raise Exception("Database connection test failed") except Exception as e: logger.error(f"Database connection test failed: {e}") raise # Health check function for the database async def check_database_health() -> bool: """Check if database is healthy""" try: await _test_database_connection() return True except Exception as e: logger.error(f"Database health check failed: {e}") return False