# services/suppliers/app/main.py """ Supplier & Procurement Service FastAPI Application """ import os from fastapi import FastAPI from sqlalchemy import text from app.core.config import settings from app.core.database import database_manager from shared.service_base import StandardFastAPIService # Import API routers from app.api import suppliers, supplier_operations, analytics, internal_demo, audit # REMOVED: purchase_orders, deliveries - PO and delivery management moved to Procurement Service # from app.api import purchase_orders, deliveries class SuppliersService(StandardFastAPIService): """Suppliers Service with standardized setup""" expected_migration_version = "00001" async def on_startup(self, app): """Custom startup logic including migration verification""" await self.verify_migrations() await super().on_startup(app) async def verify_migrations(self): """Verify database schema matches the latest migrations.""" try: async with self.database_manager.get_session() as session: result = await session.execute(text("SELECT version_num FROM alembic_version")) version = result.scalar() if version != self.expected_migration_version: self.logger.error(f"Migration version mismatch: expected {self.expected_migration_version}, got {version}") raise RuntimeError(f"Migration version mismatch: expected {self.expected_migration_version}, got {version}") self.logger.info(f"Migration verification successful: {version}") except Exception as e: self.logger.error(f"Migration verification failed: {e}") raise def __init__(self): # Define expected database tables for health checks # NOTE: PO, delivery, and invoice tables moved to Procurement Service suppliers_expected_tables = [ 'suppliers', 'supplier_price_lists', 'supplier_quality_reviews', 'supplier_performance_metrics', 'supplier_alerts', 'supplier_scorecards', 'supplier_benchmarks', 'alert_rules' ] super().__init__( service_name="suppliers-service", app_name=settings.APP_NAME, description=settings.DESCRIPTION, version=settings.VERSION, cors_origins=settings.CORS_ORIGINS, api_prefix="", # Empty because RouteBuilder already includes /api/v1 database_manager=database_manager, expected_tables=suppliers_expected_tables ) async def on_startup(self, app: FastAPI): """Custom startup logic for suppliers service""" # Custom startup completed pass async def on_shutdown(self, app: FastAPI): """Custom shutdown logic for suppliers service""" # Database cleanup is handled by the base class pass def get_service_features(self): """Return suppliers-specific features""" return [ "supplier_management", "vendor_onboarding", # REMOVED: "purchase_orders", "delivery_tracking", "invoice_tracking" - moved to Procurement Service "quality_reviews", "price_list_management", "supplier_ratings", "performance_tracking", "performance_analytics", "supplier_scorecards", "performance_alerts", "business_model_detection", "dashboard_analytics", "cost_optimization", "risk_assessment", "benchmarking" ] # Create service instance service = SuppliersService() # Create FastAPI app with standardized setup app = service.create_app() # Setup standard endpoints service.setup_standard_endpoints() # Include API routers # IMPORTANT: Order matters! More specific routes must come first # to avoid path parameter matching issues # REMOVED: purchase_orders.router, deliveries.router - PO and delivery management moved to Procurement Service service.add_router(audit.router) # /suppliers/audit-logs - must be FIRST service.add_router(supplier_operations.router) # /suppliers/operations/... service.add_router(analytics.router) # /suppliers/analytics/... service.add_router(suppliers.router) # /suppliers/{supplier_id} - catch-all, must be last service.add_router(internal_demo.router) if __name__ == "__main__": import uvicorn uvicorn.run( "app.main:app", host="0.0.0.0", port=8000, reload=os.getenv("RELOAD", "false").lower() == "true", log_level="info" )