Initial commit - production deployment
This commit is contained in:
141
services/suppliers/migrations/env.py
Normal file
141
services/suppliers/migrations/env.py
Normal file
@@ -0,0 +1,141 @@
|
||||
"""Alembic environment configuration for suppliers service"""
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import sys
|
||||
from logging.config import fileConfig
|
||||
from sqlalchemy import pool
|
||||
from sqlalchemy.engine import Connection
|
||||
from sqlalchemy.ext.asyncio import async_engine_from_config
|
||||
from alembic import context
|
||||
|
||||
# Add the service directory to the Python path
|
||||
service_path = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
|
||||
if service_path not in sys.path:
|
||||
sys.path.insert(0, service_path)
|
||||
|
||||
# Add shared modules to path
|
||||
shared_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "shared"))
|
||||
if shared_path not in sys.path:
|
||||
sys.path.insert(0, shared_path)
|
||||
|
||||
try:
|
||||
from app.core.config import settings
|
||||
from shared.database.base import Base
|
||||
|
||||
# Import all models to ensure they are registered with Base.metadata
|
||||
from app.models import * # noqa: F401, F403
|
||||
|
||||
except ImportError as e:
|
||||
print(f"Import error in migrations env.py: {e}")
|
||||
print(f"Current Python path: {sys.path}")
|
||||
raise
|
||||
|
||||
# this is the Alembic Config object
|
||||
config = context.config
|
||||
|
||||
# Determine service name from file path
|
||||
service_name = os.path.basename(os.path.dirname(os.path.dirname(__file__)))
|
||||
service_name_upper = service_name.upper().replace('-', '_')
|
||||
|
||||
# Set database URL from environment variables with multiple fallback strategies
|
||||
database_url = (
|
||||
os.getenv(f'{service_name_upper}_DATABASE_URL') or # Service-specific
|
||||
os.getenv('DATABASE_URL') # Generic fallback
|
||||
)
|
||||
|
||||
# If DATABASE_URL is not set, construct from individual components
|
||||
if not database_url:
|
||||
# Try generic PostgreSQL environment variables first
|
||||
postgres_host = os.getenv('POSTGRES_HOST')
|
||||
postgres_port = os.getenv('POSTGRES_PORT', '5432')
|
||||
postgres_db = os.getenv('POSTGRES_DB')
|
||||
postgres_user = os.getenv('POSTGRES_USER')
|
||||
postgres_password = os.getenv('POSTGRES_PASSWORD')
|
||||
|
||||
if all([postgres_host, postgres_db, postgres_user, postgres_password]):
|
||||
database_url = f"postgresql+asyncpg://{postgres_user}:{postgres_password}@{postgres_host}:{postgres_port}/{postgres_db}"
|
||||
else:
|
||||
# Try service-specific environment variables
|
||||
db_host = os.getenv(f'{service_name_upper}_DB_HOST', f'{service_name}-db-service')
|
||||
db_port = os.getenv(f'{service_name_upper}_DB_PORT', '5432')
|
||||
db_name = os.getenv(f'{service_name_upper}_DB_NAME', f'{service_name.replace("-", "_")}_db')
|
||||
db_user = os.getenv(f'{service_name_upper}_DB_USER', f'{service_name.replace("-", "_")}_user')
|
||||
db_password = os.getenv(f'{service_name_upper}_DB_PASSWORD')
|
||||
|
||||
if db_password:
|
||||
database_url = f"postgresql+asyncpg://{db_user}:{db_password}@{db_host}:{db_port}/{db_name}"
|
||||
else:
|
||||
# Final fallback: try to get from settings object
|
||||
try:
|
||||
database_url = getattr(settings, 'DATABASE_URL', None)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not database_url:
|
||||
error_msg = f"ERROR: No database URL configured for {service_name} service"
|
||||
print(error_msg)
|
||||
raise Exception(error_msg)
|
||||
|
||||
config.set_main_option("sqlalchemy.url", database_url)
|
||||
|
||||
# Interpret the config file for Python logging
|
||||
if config.config_file_name is not None:
|
||||
fileConfig(config.config_file_name)
|
||||
|
||||
# Set target metadata
|
||||
target_metadata = Base.metadata
|
||||
|
||||
|
||||
def run_migrations_offline() -> None:
|
||||
"""Run migrations in 'offline' mode."""
|
||||
url = config.get_main_option("sqlalchemy.url")
|
||||
context.configure(
|
||||
url=url,
|
||||
target_metadata=target_metadata,
|
||||
literal_binds=True,
|
||||
dialect_opts={"paramstyle": "named"},
|
||||
compare_type=True,
|
||||
compare_server_default=True,
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
def do_run_migrations(connection: Connection) -> None:
|
||||
"""Execute migrations with the given connection."""
|
||||
context.configure(
|
||||
connection=connection,
|
||||
target_metadata=target_metadata,
|
||||
compare_type=True,
|
||||
compare_server_default=True,
|
||||
)
|
||||
|
||||
with context.begin_transaction():
|
||||
context.run_migrations()
|
||||
|
||||
|
||||
async def run_async_migrations() -> None:
|
||||
"""Run migrations in 'online' mode with async support."""
|
||||
connectable = async_engine_from_config(
|
||||
config.get_section(config.config_ini_section, {}),
|
||||
prefix="sqlalchemy.",
|
||||
poolclass=pool.NullPool,
|
||||
)
|
||||
|
||||
async with connectable.connect() as connection:
|
||||
await connection.run_sync(do_run_migrations)
|
||||
|
||||
await connectable.dispose()
|
||||
|
||||
|
||||
def run_migrations_online() -> None:
|
||||
"""Run migrations in 'online' mode."""
|
||||
asyncio.run(run_async_migrations())
|
||||
|
||||
|
||||
if context.is_offline_mode():
|
||||
run_migrations_offline()
|
||||
else:
|
||||
run_migrations_online()
|
||||
26
services/suppliers/migrations/script.py.mako
Normal file
26
services/suppliers/migrations/script.py.mako
Normal file
@@ -0,0 +1,26 @@
|
||||
"""${message}
|
||||
|
||||
Revision ID: ${up_revision}
|
||||
Revises: ${down_revision | comma,n}
|
||||
Create Date: ${create_date}
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
${imports if imports else ""}
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = ${repr(up_revision)}
|
||||
down_revision: Union[str, None] = ${repr(down_revision)}
|
||||
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
||||
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
${upgrades if upgrades else "pass"}
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
${downgrades if downgrades else "pass"}
|
||||
@@ -0,0 +1,531 @@
|
||||
"""initial_schema_20251015_1229
|
||||
|
||||
Revision ID: 93d6ea3dc888
|
||||
Revises:
|
||||
Create Date: 2025-10-15 12:29:52.767171+02:00
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from sqlalchemy.dialects import postgresql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '93d6ea3dc888'
|
||||
down_revision: Union[str, None] = None
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.create_table('alert_rules',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('rule_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('rule_description', sa.Text(), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('alert_type', sa.Enum('POOR_QUALITY', 'LATE_DELIVERY', 'PRICE_INCREASE', 'LOW_PERFORMANCE', 'CONTRACT_EXPIRY', 'COMPLIANCE_ISSUE', 'FINANCIAL_RISK', 'COMMUNICATION_ISSUE', 'CAPACITY_CONSTRAINT', 'CERTIFICATION_EXPIRY', name='alerttype'), nullable=False),
|
||||
sa.Column('severity', sa.Enum('CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO', name='alertseverity'), nullable=False),
|
||||
sa.Column('metric_type', sa.Enum('DELIVERY_PERFORMANCE', 'QUALITY_SCORE', 'PRICE_COMPETITIVENESS', 'COMMUNICATION_RATING', 'ORDER_ACCURACY', 'RESPONSE_TIME', 'COMPLIANCE_SCORE', 'FINANCIAL_STABILITY', name='performancemetrictype'), nullable=True),
|
||||
sa.Column('trigger_condition', sa.String(length=50), nullable=False),
|
||||
sa.Column('threshold_value', sa.Float(), nullable=False),
|
||||
sa.Column('consecutive_violations', sa.Integer(), nullable=False),
|
||||
sa.Column('supplier_categories', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('supplier_ids', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('exclude_suppliers', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('evaluation_period', sa.Enum('DAILY', 'WEEKLY', 'MONTHLY', 'QUARTERLY', 'YEARLY', name='performanceperiod'), nullable=False),
|
||||
sa.Column('time_window_hours', sa.Integer(), nullable=True),
|
||||
sa.Column('business_hours_only', sa.Boolean(), nullable=False),
|
||||
sa.Column('auto_resolve', sa.Boolean(), nullable=False),
|
||||
sa.Column('auto_resolve_threshold', sa.Float(), nullable=True),
|
||||
sa.Column('auto_resolve_duration_hours', sa.Integer(), nullable=True),
|
||||
sa.Column('notification_enabled', sa.Boolean(), nullable=False),
|
||||
sa.Column('notification_recipients', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('escalation_minutes', sa.Integer(), nullable=True),
|
||||
sa.Column('escalation_recipients', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('recommended_actions', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('auto_actions', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('priority', sa.Integer(), nullable=False),
|
||||
sa.Column('tags', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_by', sa.UUID(), nullable=False),
|
||||
sa.Column('last_triggered', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('trigger_count', sa.Integer(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_alert_rules_alert_type'), 'alert_rules', ['alert_type'], unique=False)
|
||||
op.create_index('ix_alert_rules_metric_type', 'alert_rules', ['metric_type'], unique=False)
|
||||
op.create_index('ix_alert_rules_priority', 'alert_rules', ['priority'], unique=False)
|
||||
op.create_index('ix_alert_rules_tenant_active', 'alert_rules', ['tenant_id', 'is_active'], unique=False)
|
||||
op.create_index(op.f('ix_alert_rules_tenant_id'), 'alert_rules', ['tenant_id'], unique=False)
|
||||
op.create_index('ix_alert_rules_type_severity', 'alert_rules', ['alert_type', 'severity'], unique=False)
|
||||
op.create_table('audit_logs',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('user_id', sa.UUID(), nullable=False),
|
||||
sa.Column('action', sa.String(length=100), nullable=False),
|
||||
sa.Column('resource_type', sa.String(length=100), nullable=False),
|
||||
sa.Column('resource_id', sa.String(length=255), nullable=True),
|
||||
sa.Column('severity', sa.String(length=20), nullable=False),
|
||||
sa.Column('service_name', sa.String(length=100), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('changes', postgresql.JSON(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('audit_metadata', postgresql.JSON(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('ip_address', sa.String(length=45), nullable=True),
|
||||
sa.Column('user_agent', sa.Text(), nullable=True),
|
||||
sa.Column('endpoint', sa.String(length=255), nullable=True),
|
||||
sa.Column('method', sa.String(length=10), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('idx_audit_resource_type_action', 'audit_logs', ['resource_type', 'action'], unique=False)
|
||||
op.create_index('idx_audit_service_created', 'audit_logs', ['service_name', 'created_at'], unique=False)
|
||||
op.create_index('idx_audit_severity_created', 'audit_logs', ['severity', 'created_at'], unique=False)
|
||||
op.create_index('idx_audit_tenant_created', 'audit_logs', ['tenant_id', 'created_at'], unique=False)
|
||||
op.create_index('idx_audit_user_created', 'audit_logs', ['user_id', 'created_at'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_action'), 'audit_logs', ['action'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_created_at'), 'audit_logs', ['created_at'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_resource_id'), 'audit_logs', ['resource_id'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_resource_type'), 'audit_logs', ['resource_type'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_service_name'), 'audit_logs', ['service_name'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_severity'), 'audit_logs', ['severity'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_tenant_id'), 'audit_logs', ['tenant_id'], unique=False)
|
||||
op.create_index(op.f('ix_audit_logs_user_id'), 'audit_logs', ['user_id'], unique=False)
|
||||
op.create_table('supplier_benchmarks',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('benchmark_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('benchmark_type', sa.String(length=50), nullable=False),
|
||||
sa.Column('supplier_category', sa.String(length=100), nullable=True),
|
||||
sa.Column('metric_type', sa.Enum('DELIVERY_PERFORMANCE', 'QUALITY_SCORE', 'PRICE_COMPETITIVENESS', 'COMMUNICATION_RATING', 'ORDER_ACCURACY', 'RESPONSE_TIME', 'COMPLIANCE_SCORE', 'FINANCIAL_STABILITY', name='performancemetrictype'), nullable=False),
|
||||
sa.Column('excellent_threshold', sa.Float(), nullable=False),
|
||||
sa.Column('good_threshold', sa.Float(), nullable=False),
|
||||
sa.Column('acceptable_threshold', sa.Float(), nullable=False),
|
||||
sa.Column('poor_threshold', sa.Float(), nullable=False),
|
||||
sa.Column('data_source', sa.String(length=255), nullable=True),
|
||||
sa.Column('sample_size', sa.Integer(), nullable=True),
|
||||
sa.Column('confidence_level', sa.Float(), nullable=True),
|
||||
sa.Column('effective_date', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('expiry_date', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('methodology', sa.Text(), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_by', sa.UUID(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_benchmarks_active', 'supplier_benchmarks', ['is_active'], unique=False)
|
||||
op.create_index('ix_benchmarks_category', 'supplier_benchmarks', ['supplier_category'], unique=False)
|
||||
op.create_index('ix_benchmarks_metric_type', 'supplier_benchmarks', ['metric_type'], unique=False)
|
||||
op.create_index('ix_benchmarks_tenant_type', 'supplier_benchmarks', ['tenant_id', 'benchmark_type'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_benchmarks_benchmark_type'), 'supplier_benchmarks', ['benchmark_type'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_benchmarks_metric_type'), 'supplier_benchmarks', ['metric_type'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_benchmarks_supplier_category'), 'supplier_benchmarks', ['supplier_category'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_benchmarks_tenant_id'), 'supplier_benchmarks', ['tenant_id'], unique=False)
|
||||
op.create_table('suppliers',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('name', sa.String(length=255), nullable=False),
|
||||
sa.Column('supplier_code', sa.String(length=50), nullable=True),
|
||||
sa.Column('tax_id', sa.String(length=50), nullable=True),
|
||||
sa.Column('registration_number', sa.String(length=100), nullable=True),
|
||||
sa.Column('supplier_type', sa.Enum('ingredients', 'packaging', 'equipment', 'services', 'utilities', 'multi', name='suppliertype'), nullable=False),
|
||||
sa.Column('status', sa.Enum('active', 'inactive', 'pending_approval', 'suspended', 'blacklisted', name='supplierstatus'), nullable=False),
|
||||
sa.Column('contact_person', sa.String(length=200), nullable=True),
|
||||
sa.Column('email', sa.String(length=254), nullable=True),
|
||||
sa.Column('phone', sa.String(length=30), nullable=True),
|
||||
sa.Column('mobile', sa.String(length=30), nullable=True),
|
||||
sa.Column('website', sa.String(length=255), nullable=True),
|
||||
sa.Column('address_line1', sa.String(length=255), nullable=True),
|
||||
sa.Column('address_line2', sa.String(length=255), nullable=True),
|
||||
sa.Column('city', sa.String(length=100), nullable=True),
|
||||
sa.Column('state_province', sa.String(length=100), nullable=True),
|
||||
sa.Column('postal_code', sa.String(length=20), nullable=True),
|
||||
sa.Column('country', sa.String(length=100), nullable=True),
|
||||
sa.Column('payment_terms', sa.Enum('cod', 'net_15', 'net_30', 'net_45', 'net_60', 'prepaid', 'credit_terms', name='paymentterms'), nullable=False),
|
||||
sa.Column('credit_limit', sa.Numeric(precision=12, scale=2), nullable=True),
|
||||
sa.Column('currency', sa.String(length=3), nullable=False),
|
||||
sa.Column('standard_lead_time', sa.Integer(), nullable=False),
|
||||
sa.Column('minimum_order_amount', sa.Numeric(precision=10, scale=2), nullable=True),
|
||||
sa.Column('delivery_area', sa.String(length=255), nullable=True),
|
||||
sa.Column('quality_rating', sa.Float(), nullable=True),
|
||||
sa.Column('delivery_rating', sa.Float(), nullable=True),
|
||||
sa.Column('total_orders', sa.Integer(), nullable=False),
|
||||
sa.Column('total_amount', sa.Numeric(precision=12, scale=2), nullable=False),
|
||||
sa.Column('trust_score', sa.Float(), nullable=False, server_default='0.0'),
|
||||
sa.Column('is_preferred_supplier', sa.Boolean(), nullable=False, server_default='false'),
|
||||
sa.Column('auto_approve_enabled', sa.Boolean(), nullable=False, server_default='false'),
|
||||
sa.Column('total_pos_count', sa.Integer(), nullable=False, server_default='0'),
|
||||
sa.Column('approved_pos_count', sa.Integer(), nullable=False, server_default='0'),
|
||||
sa.Column('on_time_delivery_rate', sa.Float(), nullable=False, server_default='0.0'),
|
||||
sa.Column('fulfillment_rate', sa.Float(), nullable=False, server_default='0.0'),
|
||||
sa.Column('last_performance_update', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('approved_by', sa.UUID(), nullable=True),
|
||||
sa.Column('approved_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('rejection_reason', sa.Text(), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('certifications', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('business_hours', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('specializations', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_by', sa.UUID(), nullable=False),
|
||||
sa.Column('updated_by', sa.UUID(), nullable=False),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_suppliers_name'), 'suppliers', ['name'], unique=False)
|
||||
op.create_index('ix_suppliers_quality_rating', 'suppliers', ['quality_rating'], unique=False)
|
||||
op.create_index(op.f('ix_suppliers_status'), 'suppliers', ['status'], unique=False)
|
||||
op.create_index(op.f('ix_suppliers_supplier_code'), 'suppliers', ['supplier_code'], unique=False)
|
||||
op.create_index(op.f('ix_suppliers_supplier_type'), 'suppliers', ['supplier_type'], unique=False)
|
||||
op.create_index(op.f('ix_suppliers_tenant_id'), 'suppliers', ['tenant_id'], unique=False)
|
||||
op.create_index('ix_suppliers_tenant_name', 'suppliers', ['tenant_id', 'name'], unique=False)
|
||||
op.create_index('ix_suppliers_tenant_status', 'suppliers', ['tenant_id', 'status'], unique=False)
|
||||
op.create_index('ix_suppliers_tenant_type', 'suppliers', ['tenant_id', 'supplier_type'], unique=False)
|
||||
op.create_index('ix_suppliers_trust_score', 'suppliers', ['trust_score'], unique=False)
|
||||
op.create_index('ix_suppliers_preferred', 'suppliers', ['is_preferred_supplier'], unique=False)
|
||||
op.create_index('ix_suppliers_auto_approve', 'suppliers', ['auto_approve_enabled'], unique=False)
|
||||
op.create_table('supplier_performance_metrics',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('supplier_id', sa.UUID(), nullable=False),
|
||||
sa.Column('metric_type', sa.Enum('DELIVERY_PERFORMANCE', 'QUALITY_SCORE', 'PRICE_COMPETITIVENESS', 'COMMUNICATION_RATING', 'ORDER_ACCURACY', 'RESPONSE_TIME', 'COMPLIANCE_SCORE', 'FINANCIAL_STABILITY', name='performancemetrictype'), nullable=False),
|
||||
sa.Column('period', sa.Enum('DAILY', 'WEEKLY', 'MONTHLY', 'QUARTERLY', 'YEARLY', name='performanceperiod'), nullable=False),
|
||||
sa.Column('period_start', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('period_end', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('metric_value', sa.Float(), nullable=False),
|
||||
sa.Column('target_value', sa.Float(), nullable=True),
|
||||
sa.Column('previous_value', sa.Float(), nullable=True),
|
||||
sa.Column('total_orders', sa.Integer(), nullable=False),
|
||||
sa.Column('total_deliveries', sa.Integer(), nullable=False),
|
||||
sa.Column('on_time_deliveries', sa.Integer(), nullable=False),
|
||||
sa.Column('late_deliveries', sa.Integer(), nullable=False),
|
||||
sa.Column('quality_issues', sa.Integer(), nullable=False),
|
||||
sa.Column('total_amount', sa.Numeric(precision=12, scale=2), nullable=False),
|
||||
sa.Column('metrics_data', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('trend_direction', sa.String(length=20), nullable=True),
|
||||
sa.Column('trend_percentage', sa.Float(), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('external_factors', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('calculated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('calculated_by', sa.UUID(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_performance_metrics_period_dates', 'supplier_performance_metrics', ['period_start', 'period_end'], unique=False)
|
||||
op.create_index('ix_performance_metrics_tenant_supplier', 'supplier_performance_metrics', ['tenant_id', 'supplier_id'], unique=False)
|
||||
op.create_index('ix_performance_metrics_type_period', 'supplier_performance_metrics', ['metric_type', 'period'], unique=False)
|
||||
op.create_index('ix_performance_metrics_value', 'supplier_performance_metrics', ['metric_value'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_performance_metrics_metric_type'), 'supplier_performance_metrics', ['metric_type'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_performance_metrics_period'), 'supplier_performance_metrics', ['period'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_performance_metrics_period_end'), 'supplier_performance_metrics', ['period_end'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_performance_metrics_period_start'), 'supplier_performance_metrics', ['period_start'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_performance_metrics_supplier_id'), 'supplier_performance_metrics', ['supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_performance_metrics_tenant_id'), 'supplier_performance_metrics', ['tenant_id'], unique=False)
|
||||
op.create_table('supplier_price_lists',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('supplier_id', sa.UUID(), nullable=False),
|
||||
sa.Column('inventory_product_id', sa.UUID(), nullable=False),
|
||||
sa.Column('product_code', sa.String(length=100), nullable=True),
|
||||
sa.Column('unit_price', sa.Numeric(precision=10, scale=4), nullable=False),
|
||||
sa.Column('unit_of_measure', sa.String(length=20), nullable=False),
|
||||
sa.Column('minimum_order_quantity', sa.Integer(), nullable=True),
|
||||
sa.Column('price_per_unit', sa.Numeric(precision=10, scale=4), nullable=False),
|
||||
sa.Column('tier_pricing', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('effective_date', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('expiry_date', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('is_active', sa.Boolean(), nullable=False),
|
||||
sa.Column('brand', sa.String(length=100), nullable=True),
|
||||
sa.Column('packaging_size', sa.String(length=50), nullable=True),
|
||||
sa.Column('origin_country', sa.String(length=100), nullable=True),
|
||||
sa.Column('shelf_life_days', sa.Integer(), nullable=True),
|
||||
sa.Column('storage_requirements', sa.Text(), nullable=True),
|
||||
sa.Column('quality_specs', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('allergens', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_by', sa.UUID(), nullable=False),
|
||||
sa.Column('updated_by', sa.UUID(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_price_lists_active', 'supplier_price_lists', ['is_active'], unique=False)
|
||||
op.create_index('ix_price_lists_effective_date', 'supplier_price_lists', ['effective_date'], unique=False)
|
||||
op.create_index('ix_price_lists_inventory_product', 'supplier_price_lists', ['inventory_product_id'], unique=False)
|
||||
op.create_index('ix_price_lists_tenant_supplier', 'supplier_price_lists', ['tenant_id', 'supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_price_lists_inventory_product_id'), 'supplier_price_lists', ['inventory_product_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_price_lists_supplier_id'), 'supplier_price_lists', ['supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_price_lists_tenant_id'), 'supplier_price_lists', ['tenant_id'], unique=False)
|
||||
op.create_table('supplier_scorecards',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('supplier_id', sa.UUID(), nullable=False),
|
||||
sa.Column('scorecard_name', sa.String(length=255), nullable=False),
|
||||
sa.Column('period', sa.Enum('DAILY', 'WEEKLY', 'MONTHLY', 'QUARTERLY', 'YEARLY', name='performanceperiod'), nullable=False),
|
||||
sa.Column('period_start', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('period_end', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('overall_score', sa.Float(), nullable=False),
|
||||
sa.Column('quality_score', sa.Float(), nullable=False),
|
||||
sa.Column('delivery_score', sa.Float(), nullable=False),
|
||||
sa.Column('cost_score', sa.Float(), nullable=False),
|
||||
sa.Column('service_score', sa.Float(), nullable=False),
|
||||
sa.Column('overall_rank', sa.Integer(), nullable=True),
|
||||
sa.Column('category_rank', sa.Integer(), nullable=True),
|
||||
sa.Column('total_suppliers_evaluated', sa.Integer(), nullable=True),
|
||||
sa.Column('on_time_delivery_rate', sa.Float(), nullable=False),
|
||||
sa.Column('quality_rejection_rate', sa.Float(), nullable=False),
|
||||
sa.Column('order_accuracy_rate', sa.Float(), nullable=False),
|
||||
sa.Column('response_time_hours', sa.Float(), nullable=False),
|
||||
sa.Column('cost_variance_percentage', sa.Float(), nullable=False),
|
||||
sa.Column('total_orders_processed', sa.Integer(), nullable=False),
|
||||
sa.Column('total_amount_processed', sa.Numeric(precision=12, scale=2), nullable=False),
|
||||
sa.Column('average_order_value', sa.Numeric(precision=10, scale=2), nullable=False),
|
||||
sa.Column('cost_savings_achieved', sa.Numeric(precision=10, scale=2), nullable=False),
|
||||
sa.Column('score_trend', sa.String(length=20), nullable=True),
|
||||
sa.Column('score_change_percentage', sa.Float(), nullable=True),
|
||||
sa.Column('strengths', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('improvement_areas', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('recommended_actions', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('is_final', sa.Boolean(), nullable=False),
|
||||
sa.Column('approved_by', sa.UUID(), nullable=True),
|
||||
sa.Column('approved_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('notes', sa.Text(), nullable=True),
|
||||
sa.Column('attachments', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('generated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('generated_by', sa.UUID(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_scorecards_final', 'supplier_scorecards', ['is_final'], unique=False)
|
||||
op.create_index('ix_scorecards_overall_score', 'supplier_scorecards', ['overall_score'], unique=False)
|
||||
op.create_index('ix_scorecards_period', 'supplier_scorecards', ['period'], unique=False)
|
||||
op.create_index('ix_scorecards_period_dates', 'supplier_scorecards', ['period_start', 'period_end'], unique=False)
|
||||
op.create_index('ix_scorecards_tenant_supplier', 'supplier_scorecards', ['tenant_id', 'supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_scorecards_period'), 'supplier_scorecards', ['period'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_scorecards_period_end'), 'supplier_scorecards', ['period_end'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_scorecards_period_start'), 'supplier_scorecards', ['period_start'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_scorecards_supplier_id'), 'supplier_scorecards', ['supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_scorecards_tenant_id'), 'supplier_scorecards', ['tenant_id'], unique=False)
|
||||
op.create_table('supplier_alerts',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('supplier_id', sa.UUID(), nullable=False),
|
||||
sa.Column('alert_type', sa.Enum('POOR_QUALITY', 'LATE_DELIVERY', 'PRICE_INCREASE', 'LOW_PERFORMANCE', 'CONTRACT_EXPIRY', 'COMPLIANCE_ISSUE', 'FINANCIAL_RISK', 'COMMUNICATION_ISSUE', 'CAPACITY_CONSTRAINT', 'CERTIFICATION_EXPIRY', name='alerttype'), nullable=False),
|
||||
sa.Column('severity', sa.Enum('CRITICAL', 'HIGH', 'MEDIUM', 'LOW', 'INFO', name='alertseverity'), nullable=False),
|
||||
sa.Column('status', sa.Enum('ACTIVE', 'ACKNOWLEDGED', 'IN_PROGRESS', 'RESOLVED', 'DISMISSED', name='alertstatus'), nullable=False),
|
||||
sa.Column('title', sa.String(length=255), nullable=False),
|
||||
sa.Column('message', sa.Text(), nullable=False),
|
||||
sa.Column('description', sa.Text(), nullable=True),
|
||||
sa.Column('trigger_value', sa.Float(), nullable=True),
|
||||
sa.Column('threshold_value', sa.Float(), nullable=True),
|
||||
sa.Column('metric_type', sa.Enum('DELIVERY_PERFORMANCE', 'QUALITY_SCORE', 'PRICE_COMPETITIVENESS', 'COMMUNICATION_RATING', 'ORDER_ACCURACY', 'RESPONSE_TIME', 'COMPLIANCE_SCORE', 'FINANCIAL_STABILITY', name='performancemetrictype'), nullable=True),
|
||||
sa.Column('purchase_order_id', sa.UUID(), nullable=True),
|
||||
sa.Column('delivery_id', sa.UUID(), nullable=True),
|
||||
sa.Column('performance_metric_id', sa.UUID(), nullable=True),
|
||||
sa.Column('triggered_at', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('acknowledged_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('acknowledged_by', sa.UUID(), nullable=True),
|
||||
sa.Column('resolved_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('resolved_by', sa.UUID(), nullable=True),
|
||||
sa.Column('recommended_actions', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('actions_taken', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('resolution_notes', sa.Text(), nullable=True),
|
||||
sa.Column('auto_resolve', sa.Boolean(), nullable=False),
|
||||
sa.Column('auto_resolve_condition', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('escalated', sa.Boolean(), nullable=False),
|
||||
sa.Column('escalated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('escalated_to', sa.UUID(), nullable=True),
|
||||
sa.Column('notification_sent', sa.Boolean(), nullable=False),
|
||||
sa.Column('notification_sent_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('notification_recipients', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('priority_score', sa.Integer(), nullable=False),
|
||||
sa.Column('business_impact', sa.String(length=50), nullable=True),
|
||||
sa.Column('tags', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('updated_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('created_by', sa.UUID(), nullable=True),
|
||||
sa.ForeignKeyConstraint(['performance_metric_id'], ['supplier_performance_metrics.id'], ),
|
||||
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index(op.f('ix_supplier_alerts_alert_type'), 'supplier_alerts', ['alert_type'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_delivery_id'), 'supplier_alerts', ['delivery_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_metric_type'), 'supplier_alerts', ['metric_type'], unique=False)
|
||||
op.create_index('ix_supplier_alerts_priority', 'supplier_alerts', ['priority_score'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_purchase_order_id'), 'supplier_alerts', ['purchase_order_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_severity'), 'supplier_alerts', ['severity'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_status'), 'supplier_alerts', ['status'], unique=False)
|
||||
op.create_index('ix_supplier_alerts_status_triggered', 'supplier_alerts', ['status', 'triggered_at'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_supplier_id'), 'supplier_alerts', ['supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_alerts_tenant_id'), 'supplier_alerts', ['tenant_id'], unique=False)
|
||||
op.create_index('ix_supplier_alerts_tenant_supplier', 'supplier_alerts', ['tenant_id', 'supplier_id'], unique=False)
|
||||
op.create_index('ix_supplier_alerts_type_severity', 'supplier_alerts', ['alert_type', 'severity'], unique=False)
|
||||
op.create_table('supplier_quality_reviews',
|
||||
sa.Column('id', sa.UUID(), nullable=False),
|
||||
sa.Column('tenant_id', sa.UUID(), nullable=False),
|
||||
sa.Column('supplier_id', sa.UUID(), nullable=False),
|
||||
sa.Column('purchase_order_id', sa.UUID(), nullable=True),
|
||||
sa.Column('delivery_id', sa.UUID(), nullable=True),
|
||||
sa.Column('review_date', sa.DateTime(timezone=True), nullable=False),
|
||||
sa.Column('review_type', sa.String(length=50), nullable=False),
|
||||
sa.Column('quality_rating', sa.Enum('excellent', 'good', 'average', 'poor', 'very_poor', name='qualityrating'), nullable=False),
|
||||
sa.Column('delivery_rating', sa.Enum('excellent', 'good', 'average', 'poor', 'very_poor', name='deliveryrating'), nullable=False),
|
||||
sa.Column('communication_rating', sa.Integer(), nullable=False),
|
||||
sa.Column('overall_rating', sa.Float(), nullable=False),
|
||||
sa.Column('quality_comments', sa.Text(), nullable=True),
|
||||
sa.Column('delivery_comments', sa.Text(), nullable=True),
|
||||
sa.Column('communication_comments', sa.Text(), nullable=True),
|
||||
sa.Column('improvement_suggestions', sa.Text(), nullable=True),
|
||||
sa.Column('quality_issues', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
||||
sa.Column('corrective_actions', sa.Text(), nullable=True),
|
||||
sa.Column('follow_up_required', sa.Boolean(), nullable=False),
|
||||
sa.Column('follow_up_date', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('is_final', sa.Boolean(), nullable=False),
|
||||
sa.Column('approved_by', sa.UUID(), nullable=True),
|
||||
sa.Column('created_at', sa.DateTime(timezone=True), nullable=True),
|
||||
sa.Column('reviewed_by', sa.UUID(), nullable=False),
|
||||
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
|
||||
sa.PrimaryKeyConstraint('id')
|
||||
)
|
||||
op.create_index('ix_quality_reviews_date', 'supplier_quality_reviews', ['review_date'], unique=False)
|
||||
op.create_index('ix_quality_reviews_overall_rating', 'supplier_quality_reviews', ['overall_rating'], unique=False)
|
||||
op.create_index('ix_quality_reviews_tenant_supplier', 'supplier_quality_reviews', ['tenant_id', 'supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_quality_reviews_delivery_id'), 'supplier_quality_reviews', ['delivery_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_quality_reviews_purchase_order_id'), 'supplier_quality_reviews', ['purchase_order_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_quality_reviews_supplier_id'), 'supplier_quality_reviews', ['supplier_id'], unique=False)
|
||||
op.create_index(op.f('ix_supplier_quality_reviews_tenant_id'), 'supplier_quality_reviews', ['tenant_id'], unique=False)
|
||||
|
||||
# Initialize trust scores for existing suppliers based on their ratings and history
|
||||
op.execute("""
|
||||
UPDATE suppliers
|
||||
SET
|
||||
trust_score = LEAST(1.0, GREATEST(0.0,
|
||||
(COALESCE(quality_rating, 0) / 5.0 * 0.4) +
|
||||
(COALESCE(delivery_rating, 0) / 5.0 * 0.4) +
|
||||
(CASE WHEN total_orders > 10 THEN 0.2 ELSE total_orders / 50.0 END)
|
||||
)),
|
||||
is_preferred_supplier = (
|
||||
total_orders >= 10 AND
|
||||
quality_rating >= 4.0 AND
|
||||
delivery_rating >= 4.0 AND
|
||||
status = 'active'
|
||||
),
|
||||
auto_approve_enabled = (
|
||||
total_orders >= 20 AND
|
||||
quality_rating >= 4.5 AND
|
||||
delivery_rating >= 4.5 AND
|
||||
status = 'active'
|
||||
),
|
||||
total_pos_count = total_orders,
|
||||
approved_pos_count = total_orders,
|
||||
on_time_delivery_rate = COALESCE(delivery_rating / 5.0, 0.0),
|
||||
fulfillment_rate = COALESCE(quality_rating / 5.0, 0.0),
|
||||
last_performance_update = NOW()
|
||||
WHERE status = 'active'
|
||||
""")
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
# ### commands auto generated by Alembic - please adjust! ###
|
||||
op.drop_index(op.f('ix_supplier_quality_reviews_tenant_id'), table_name='supplier_quality_reviews')
|
||||
op.drop_index(op.f('ix_supplier_quality_reviews_supplier_id'), table_name='supplier_quality_reviews')
|
||||
op.drop_index(op.f('ix_supplier_quality_reviews_purchase_order_id'), table_name='supplier_quality_reviews')
|
||||
op.drop_index(op.f('ix_supplier_quality_reviews_delivery_id'), table_name='supplier_quality_reviews')
|
||||
op.drop_index('ix_quality_reviews_tenant_supplier', table_name='supplier_quality_reviews')
|
||||
op.drop_index('ix_quality_reviews_overall_rating', table_name='supplier_quality_reviews')
|
||||
op.drop_index('ix_quality_reviews_date', table_name='supplier_quality_reviews')
|
||||
op.drop_table('supplier_quality_reviews')
|
||||
op.drop_index('ix_supplier_alerts_type_severity', table_name='supplier_alerts')
|
||||
op.drop_index('ix_supplier_alerts_tenant_supplier', table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_tenant_id'), table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_supplier_id'), table_name='supplier_alerts')
|
||||
op.drop_index('ix_supplier_alerts_status_triggered', table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_status'), table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_severity'), table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_purchase_order_id'), table_name='supplier_alerts')
|
||||
op.drop_index('ix_supplier_alerts_priority', table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_metric_type'), table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_delivery_id'), table_name='supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_alerts_alert_type'), table_name='supplier_alerts')
|
||||
op.drop_table('supplier_alerts')
|
||||
op.drop_index(op.f('ix_supplier_scorecards_tenant_id'), table_name='supplier_scorecards')
|
||||
op.drop_index(op.f('ix_supplier_scorecards_supplier_id'), table_name='supplier_scorecards')
|
||||
op.drop_index(op.f('ix_supplier_scorecards_period_start'), table_name='supplier_scorecards')
|
||||
op.drop_index(op.f('ix_supplier_scorecards_period_end'), table_name='supplier_scorecards')
|
||||
op.drop_index(op.f('ix_supplier_scorecards_period'), table_name='supplier_scorecards')
|
||||
op.drop_index('ix_scorecards_tenant_supplier', table_name='supplier_scorecards')
|
||||
op.drop_index('ix_scorecards_period_dates', table_name='supplier_scorecards')
|
||||
op.drop_index('ix_scorecards_period', table_name='supplier_scorecards')
|
||||
op.drop_index('ix_scorecards_overall_score', table_name='supplier_scorecards')
|
||||
op.drop_index('ix_scorecards_final', table_name='supplier_scorecards')
|
||||
op.drop_table('supplier_scorecards')
|
||||
op.drop_index(op.f('ix_supplier_price_lists_tenant_id'), table_name='supplier_price_lists')
|
||||
op.drop_index(op.f('ix_supplier_price_lists_supplier_id'), table_name='supplier_price_lists')
|
||||
op.drop_index(op.f('ix_supplier_price_lists_inventory_product_id'), table_name='supplier_price_lists')
|
||||
op.create_index('ix_price_lists_tenant_supplier', 'supplier_price_lists', ['tenant_id', 'supplier_id'], unique=False)
|
||||
op.drop_index('ix_price_lists_inventory_product', table_name='supplier_price_lists')
|
||||
op.drop_index('ix_price_lists_effective_date', table_name='supplier_price_lists')
|
||||
op.drop_index('ix_price_lists_active', table_name='supplier_price_lists')
|
||||
op.drop_table('supplier_price_lists')
|
||||
op.drop_index(op.f('ix_supplier_performance_metrics_tenant_id'), table_name='supplier_performance_metrics')
|
||||
op.drop_index(op.f('ix_supplier_performance_metrics_supplier_id'), table_name='supplier_performance_metrics')
|
||||
op.drop_index(op.f('ix_supplier_performance_metrics_period_start'), table_name='supplier_performance_metrics')
|
||||
op.drop_index(op.f('ix_supplier_performance_metrics_period_end'), table_name='supplier_performance_metrics')
|
||||
op.drop_index(op.f('ix_supplier_performance_metrics_period'), table_name='supplier_performance_metrics')
|
||||
op.drop_index(op.f('ix_supplier_performance_metrics_metric_type'), table_name='supplier_performance_metrics')
|
||||
op.drop_index('ix_performance_metrics_value', table_name='supplier_performance_metrics')
|
||||
op.drop_index('ix_performance_metrics_type_period', table_name='supplier_performance_metrics')
|
||||
op.drop_index('ix_performance_metrics_tenant_supplier', table_name='supplier_performance_metrics')
|
||||
op.drop_index('ix_performance_metrics_period_dates', table_name='supplier_performance_metrics')
|
||||
op.drop_table('supplier_performance_metrics')
|
||||
op.drop_index('ix_suppliers_auto_approve', table_name='suppliers')
|
||||
op.drop_index('ix_suppliers_preferred', table_name='suppliers')
|
||||
op.drop_index('ix_suppliers_trust_score', table_name='suppliers')
|
||||
op.drop_index('ix_suppliers_tenant_type', table_name='suppliers')
|
||||
op.drop_index('ix_suppliers_tenant_status', table_name='suppliers')
|
||||
op.drop_index('ix_suppliers_tenant_name', table_name='suppliers')
|
||||
op.drop_index(op.f('ix_suppliers_tenant_id'), table_name='suppliers')
|
||||
op.drop_index(op.f('ix_suppliers_supplier_type'), table_name='suppliers')
|
||||
op.drop_index(op.f('ix_suppliers_supplier_code'), table_name='suppliers')
|
||||
op.drop_index(op.f('ix_suppliers_status'), table_name='suppliers')
|
||||
op.drop_index('ix_suppliers_quality_rating', table_name='suppliers')
|
||||
op.drop_index(op.f('ix_suppliers_name'), table_name='suppliers')
|
||||
op.drop_table('suppliers')
|
||||
op.drop_index(op.f('ix_supplier_benchmarks_tenant_id'), table_name='supplier_benchmarks')
|
||||
op.drop_index(op.f('ix_supplier_benchmarks_supplier_category'), table_name='supplier_benchmarks')
|
||||
op.drop_index(op.f('ix_supplier_benchmarks_metric_type'), table_name='supplier_benchmarks')
|
||||
op.drop_index(op.f('ix_supplier_benchmarks_benchmark_type'), table_name='supplier_benchmarks')
|
||||
op.drop_index('ix_benchmarks_tenant_type', table_name='supplier_benchmarks')
|
||||
op.drop_index('ix_benchmarks_metric_type', table_name='supplier_benchmarks')
|
||||
op.drop_index('ix_benchmarks_category', table_name='supplier_benchmarks')
|
||||
op.drop_index('ix_benchmarks_active', table_name='supplier_benchmarks')
|
||||
op.drop_table('supplier_benchmarks')
|
||||
op.drop_index(op.f('ix_audit_logs_user_id'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_tenant_id'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_severity'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_service_name'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_resource_type'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_resource_id'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_created_at'), table_name='audit_logs')
|
||||
op.drop_index(op.f('ix_audit_logs_action'), table_name='audit_logs')
|
||||
op.drop_index('idx_audit_user_created', table_name='audit_logs')
|
||||
op.drop_index('idx_audit_tenant_created', table_name='audit_logs')
|
||||
op.drop_index('idx_audit_severity_created', table_name='audit_logs')
|
||||
op.drop_index('idx_audit_service_created', table_name='audit_logs')
|
||||
op.drop_index('idx_audit_resource_type_action', table_name='audit_logs')
|
||||
op.drop_table('audit_logs')
|
||||
op.drop_index('ix_alert_rules_type_severity', table_name='alert_rules')
|
||||
op.drop_index(op.f('ix_alert_rules_tenant_id'), table_name='alert_rules')
|
||||
op.drop_index('ix_alert_rules_tenant_active', table_name='alert_rules')
|
||||
op.drop_index('ix_alert_rules_priority', table_name='alert_rules')
|
||||
op.drop_index('ix_alert_rules_metric_type', table_name='alert_rules')
|
||||
op.drop_index(op.f('ix_alert_rules_alert_type'), table_name='alert_rules')
|
||||
op.drop_table('alert_rules')
|
||||
# ### end Alembic commands ###
|
||||
Reference in New Issue
Block a user