# ================================================================ # services/orchestrator/app/models/orchestration_run.py # ================================================================ """ Orchestration Run Models - Audit trail for orchestration executions """ import uuid import enum from datetime import datetime, timezone from sqlalchemy import Column, String, DateTime, Integer, Text, Boolean, Enum as SQLEnum from sqlalchemy.dialects.postgresql import UUID, JSONB from sqlalchemy.sql import func from shared.database.base import Base class OrchestrationStatus(enum.Enum): """Orchestration run status""" pending = "pending" running = "running" completed = "completed" partial_success = "partial_success" failed = "failed" cancelled = "cancelled" class OrchestrationRun(Base): """Audit trail for orchestration executions""" __tablename__ = "orchestration_runs" # Primary identification id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) run_number = Column(String(50), nullable=False, unique=True, index=True) # Run details tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True) status = Column(SQLEnum(OrchestrationStatus), nullable=False, default=OrchestrationStatus.pending, index=True) run_type = Column(String(50), nullable=False, default="scheduled") # scheduled, manual, test priority = Column(String(20), nullable=False, default="normal") # normal, high, critical # Timing started_at = Column(DateTime(timezone=True), nullable=False, default=lambda: datetime.now(timezone.utc)) completed_at = Column(DateTime(timezone=True), nullable=True) duration_seconds = Column(Integer, nullable=True) # Step tracking forecasting_started_at = Column(DateTime(timezone=True), nullable=True) forecasting_completed_at = Column(DateTime(timezone=True), nullable=True) forecasting_status = Column(String(20), nullable=True) # success, failed, skipped forecasting_error = Column(Text, nullable=True) production_started_at = Column(DateTime(timezone=True), nullable=True) production_completed_at = Column(DateTime(timezone=True), nullable=True) production_status = Column(String(20), nullable=True) # success, failed, skipped production_error = Column(Text, nullable=True) procurement_started_at = Column(DateTime(timezone=True), nullable=True) procurement_completed_at = Column(DateTime(timezone=True), nullable=True) procurement_status = Column(String(20), nullable=True) # success, failed, skipped procurement_error = Column(Text, nullable=True) notification_started_at = Column(DateTime(timezone=True), nullable=True) notification_completed_at = Column(DateTime(timezone=True), nullable=True) notification_status = Column(String(20), nullable=True) # success, failed, skipped notification_error = Column(Text, nullable=True) # Results summary forecasts_generated = Column(Integer, nullable=False, default=0) production_batches_created = Column(Integer, nullable=False, default=0) procurement_plans_created = Column(Integer, nullable=False, default=0) purchase_orders_created = Column(Integer, nullable=False, default=0) notifications_sent = Column(Integer, nullable=False, default=0) # Forecast data passed between services forecast_data = Column(JSONB, nullable=True) # Store forecast results for downstream services # Error handling retry_count = Column(Integer, nullable=False, default=0) max_retries_reached = Column(Boolean, nullable=False, default=False) error_message = Column(Text, nullable=True) error_details = Column(JSONB, nullable=True) # External references production_schedule_id = Column(UUID(as_uuid=True), nullable=True) procurement_plan_id = Column(UUID(as_uuid=True), nullable=True) # Audit fields created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now(), nullable=False) triggered_by = Column(String(100), nullable=True) # scheduler, user_id, api # Performance metrics fulfillment_rate = Column(Integer, nullable=True) # Percentage as integer (0-100) on_time_delivery_rate = Column(Integer, nullable=True) # Percentage as integer (0-100) cost_accuracy = Column(Integer, nullable=True) # Percentage as integer (0-100) quality_score = Column(Integer, nullable=True) # Rating as integer (0-100) # Metadata run_metadata = Column(JSONB, nullable=True)