# services/tenant/app/models/tenant_settings.py """ Tenant Settings Model Centralized configuration storage for all tenant-specific operational settings """ from sqlalchemy import Column, String, Boolean, DateTime, ForeignKey, JSON from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import relationship from datetime import datetime, timezone import uuid from shared.database.base import Base class TenantSettings(Base): """ Centralized tenant settings model Stores all operational configurations for a tenant across all services """ __tablename__ = "tenant_settings" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) tenant_id = Column(UUID(as_uuid=True), ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, unique=True, index=True) # Procurement & Auto-Approval Settings (Orders Service) procurement_settings = Column(JSON, nullable=False, default=lambda: { "auto_approve_enabled": True, "auto_approve_threshold_eur": 500.0, "auto_approve_min_supplier_score": 0.80, "require_approval_new_suppliers": True, "require_approval_critical_items": True, "procurement_lead_time_days": 3, "demand_forecast_days": 14, "safety_stock_percentage": 20.0, "po_approval_reminder_hours": 24, "po_critical_escalation_hours": 12 }) # Inventory Management Settings (Inventory Service) inventory_settings = Column(JSON, nullable=False, default=lambda: { "low_stock_threshold": 10, "reorder_point": 20, "reorder_quantity": 50, "expiring_soon_days": 7, "expiration_warning_days": 3, "quality_score_threshold": 8.0, "temperature_monitoring_enabled": True, "refrigeration_temp_min": 1.0, "refrigeration_temp_max": 4.0, "freezer_temp_min": -20.0, "freezer_temp_max": -15.0, "room_temp_min": 18.0, "room_temp_max": 25.0, "temp_deviation_alert_minutes": 15, "critical_temp_deviation_minutes": 5 }) # Production Settings (Production Service) production_settings = Column(JSON, nullable=False, default=lambda: { "planning_horizon_days": 7, "minimum_batch_size": 1.0, "maximum_batch_size": 100.0, "production_buffer_percentage": 10.0, "working_hours_per_day": 12, "max_overtime_hours": 4, "capacity_utilization_target": 0.85, "capacity_warning_threshold": 0.95, "quality_check_enabled": True, "minimum_yield_percentage": 85.0, "quality_score_threshold": 8.0, "schedule_optimization_enabled": True, "prep_time_buffer_minutes": 30, "cleanup_time_buffer_minutes": 15, "labor_cost_per_hour_eur": 15.0, "overhead_cost_percentage": 20.0 }) # Supplier Settings (Suppliers Service) supplier_settings = Column(JSON, nullable=False, default=lambda: { "default_payment_terms_days": 30, "default_delivery_days": 3, "excellent_delivery_rate": 95.0, "good_delivery_rate": 90.0, "excellent_quality_rate": 98.0, "good_quality_rate": 95.0, "critical_delivery_delay_hours": 24, "critical_quality_rejection_rate": 10.0, "high_cost_variance_percentage": 15.0 }) # POS Integration Settings (POS Service) pos_settings = Column(JSON, nullable=False, default=lambda: { "sync_interval_minutes": 5, "auto_sync_products": True, "auto_sync_transactions": True }) # Order & Business Rules Settings (Orders Service) order_settings = Column(JSON, nullable=False, default=lambda: { "max_discount_percentage": 50.0, "default_delivery_window_hours": 48, "dynamic_pricing_enabled": False, "discount_enabled": True, "delivery_tracking_enabled": True }) # Timestamps created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False) updated_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False) # Relationships tenant = relationship("Tenant", backref="settings") def __repr__(self): return f"" @staticmethod def get_default_settings() -> dict: """ Get default settings for all categories Returns a dictionary with default values for all setting categories """ return { "procurement_settings": { "auto_approve_enabled": True, "auto_approve_threshold_eur": 500.0, "auto_approve_min_supplier_score": 0.80, "require_approval_new_suppliers": True, "require_approval_critical_items": True, "procurement_lead_time_days": 3, "demand_forecast_days": 14, "safety_stock_percentage": 20.0, "po_approval_reminder_hours": 24, "po_critical_escalation_hours": 12 }, "inventory_settings": { "low_stock_threshold": 10, "reorder_point": 20, "reorder_quantity": 50, "expiring_soon_days": 7, "expiration_warning_days": 3, "quality_score_threshold": 8.0, "temperature_monitoring_enabled": True, "refrigeration_temp_min": 1.0, "refrigeration_temp_max": 4.0, "freezer_temp_min": -20.0, "freezer_temp_max": -15.0, "room_temp_min": 18.0, "room_temp_max": 25.0, "temp_deviation_alert_minutes": 15, "critical_temp_deviation_minutes": 5 }, "production_settings": { "planning_horizon_days": 7, "minimum_batch_size": 1.0, "maximum_batch_size": 100.0, "production_buffer_percentage": 10.0, "working_hours_per_day": 12, "max_overtime_hours": 4, "capacity_utilization_target": 0.85, "capacity_warning_threshold": 0.95, "quality_check_enabled": True, "minimum_yield_percentage": 85.0, "quality_score_threshold": 8.0, "schedule_optimization_enabled": True, "prep_time_buffer_minutes": 30, "cleanup_time_buffer_minutes": 15, "labor_cost_per_hour_eur": 15.0, "overhead_cost_percentage": 20.0 }, "supplier_settings": { "default_payment_terms_days": 30, "default_delivery_days": 3, "excellent_delivery_rate": 95.0, "good_delivery_rate": 90.0, "excellent_quality_rate": 98.0, "good_quality_rate": 95.0, "critical_delivery_delay_hours": 24, "critical_quality_rejection_rate": 10.0, "high_cost_variance_percentage": 15.0 }, "pos_settings": { "sync_interval_minutes": 5, "auto_sync_products": True, "auto_sync_transactions": True }, "order_settings": { "max_discount_percentage": 50.0, "default_delivery_window_hours": 48, "dynamic_pricing_enabled": False, "discount_enabled": True, "delivery_tracking_enabled": True } }