Improve the frontend 3

This commit is contained in:
Urtzi Alfaro
2025-10-30 21:08:07 +01:00
parent 36217a2729
commit 63f5c6d512
184 changed files with 21512 additions and 7442 deletions

View File

@@ -1,7 +1,7 @@
"""initial_schema_20251015_1229
Revision ID: 93d6ea3dc888
Revises:
Revises:
Create Date: 2025-10-15 12:29:52.767171+02:00
"""
@@ -157,6 +157,14 @@ def upgrade() -> None:
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),
@@ -179,52 +187,9 @@ def upgrade() -> None:
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_table('purchase_orders',
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('po_number', sa.String(length=50), nullable=False),
sa.Column('reference_number', sa.String(length=100), nullable=True),
sa.Column('status', sa.Enum('draft', 'pending_approval', 'approved', 'sent_to_supplier', 'confirmed', 'partially_received', 'completed', 'cancelled', 'disputed', name='purchaseorderstatus'), nullable=False),
sa.Column('priority', sa.String(length=20), nullable=False),
sa.Column('order_date', sa.DateTime(timezone=True), nullable=False),
sa.Column('required_delivery_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('estimated_delivery_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('subtotal', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('tax_amount', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('shipping_cost', sa.Numeric(precision=10, scale=2), nullable=False),
sa.Column('discount_amount', sa.Numeric(precision=10, scale=2), nullable=False),
sa.Column('total_amount', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('currency', sa.String(length=3), nullable=False),
sa.Column('delivery_address', sa.Text(), nullable=True),
sa.Column('delivery_instructions', sa.Text(), nullable=True),
sa.Column('delivery_contact', sa.String(length=200), nullable=True),
sa.Column('delivery_phone', sa.String(length=30), nullable=True),
sa.Column('requires_approval', sa.Boolean(), nullable=False),
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('sent_to_supplier_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('supplier_confirmation_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('supplier_reference', sa.String(length=100), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('internal_notes', sa.Text(), nullable=True),
sa.Column('terms_and_conditions', 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_purchase_orders_delivery_date', 'purchase_orders', ['required_delivery_date'], unique=False)
op.create_index('ix_purchase_orders_order_date', 'purchase_orders', ['order_date'], unique=False)
op.create_index('ix_purchase_orders_po_number', 'purchase_orders', ['po_number'], unique=False)
op.create_index(op.f('ix_purchase_orders_status'), 'purchase_orders', ['status'], unique=False)
op.create_index(op.f('ix_purchase_orders_supplier_id'), 'purchase_orders', ['supplier_id'], unique=False)
op.create_index(op.f('ix_purchase_orders_tenant_id'), 'purchase_orders', ['tenant_id'], unique=False)
op.create_index('ix_purchase_orders_tenant_status', 'purchase_orders', ['tenant_id', 'status'], unique=False)
op.create_index('ix_purchase_orders_tenant_supplier', 'purchase_orders', ['tenant_id', 'supplier_id'], 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),
@@ -347,71 +312,6 @@ def upgrade() -> None:
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('deliveries',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('tenant_id', sa.UUID(), nullable=False),
sa.Column('purchase_order_id', sa.UUID(), nullable=False),
sa.Column('supplier_id', sa.UUID(), nullable=False),
sa.Column('delivery_number', sa.String(length=50), nullable=False),
sa.Column('supplier_delivery_note', sa.String(length=100), nullable=True),
sa.Column('status', sa.Enum('scheduled', 'in_transit', 'out_for_delivery', 'delivered', 'partially_delivered', 'failed_delivery', 'returned', name='deliverystatus'), nullable=False),
sa.Column('scheduled_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('estimated_arrival', sa.DateTime(timezone=True), nullable=True),
sa.Column('actual_arrival', sa.DateTime(timezone=True), nullable=True),
sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('delivery_address', sa.Text(), nullable=True),
sa.Column('delivery_contact', sa.String(length=200), nullable=True),
sa.Column('delivery_phone', sa.String(length=30), nullable=True),
sa.Column('carrier_name', sa.String(length=200), nullable=True),
sa.Column('tracking_number', sa.String(length=100), nullable=True),
sa.Column('inspection_passed', sa.Boolean(), nullable=True),
sa.Column('inspection_notes', sa.Text(), nullable=True),
sa.Column('quality_issues', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
sa.Column('received_by', sa.UUID(), nullable=True),
sa.Column('received_at', sa.DateTime(timezone=True), nullable=True),
sa.Column('notes', sa.Text(), nullable=True),
sa.Column('photos', 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.ForeignKeyConstraint(['purchase_order_id'], ['purchase_orders.id'], ),
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_deliveries_delivery_number', 'deliveries', ['delivery_number'], unique=False)
op.create_index(op.f('ix_deliveries_purchase_order_id'), 'deliveries', ['purchase_order_id'], unique=False)
op.create_index('ix_deliveries_scheduled_date', 'deliveries', ['scheduled_date'], unique=False)
op.create_index(op.f('ix_deliveries_status'), 'deliveries', ['status'], unique=False)
op.create_index(op.f('ix_deliveries_supplier_id'), 'deliveries', ['supplier_id'], unique=False)
op.create_index(op.f('ix_deliveries_tenant_id'), 'deliveries', ['tenant_id'], unique=False)
op.create_index('ix_deliveries_tenant_status', 'deliveries', ['tenant_id', 'status'], unique=False)
op.create_table('purchase_order_items',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('tenant_id', sa.UUID(), nullable=False),
sa.Column('purchase_order_id', sa.UUID(), nullable=False),
sa.Column('price_list_item_id', sa.UUID(), nullable=True),
sa.Column('inventory_product_id', sa.UUID(), nullable=False),
sa.Column('product_code', sa.String(length=100), nullable=True),
sa.Column('ordered_quantity', sa.Integer(), nullable=False),
sa.Column('unit_of_measure', sa.String(length=20), nullable=False),
sa.Column('unit_price', sa.Numeric(precision=10, scale=4), nullable=False),
sa.Column('line_total', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('received_quantity', sa.Integer(), nullable=False),
sa.Column('remaining_quantity', sa.Integer(), nullable=False),
sa.Column('quality_requirements', sa.Text(), nullable=True),
sa.Column('item_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.ForeignKeyConstraint(['price_list_item_id'], ['supplier_price_lists.id'], ),
sa.ForeignKeyConstraint(['purchase_order_id'], ['purchase_orders.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_po_items_inventory_product', 'purchase_order_items', ['inventory_product_id'], unique=False)
op.create_index('ix_po_items_tenant_po', 'purchase_order_items', ['tenant_id', 'purchase_order_id'], unique=False)
op.create_index(op.f('ix_purchase_order_items_inventory_product_id'), 'purchase_order_items', ['inventory_product_id'], unique=False)
op.create_index(op.f('ix_purchase_order_items_price_list_item_id'), 'purchase_order_items', ['price_list_item_id'], unique=False)
op.create_index(op.f('ix_purchase_order_items_purchase_order_id'), 'purchase_order_items', ['purchase_order_id'], unique=False)
op.create_index(op.f('ix_purchase_order_items_tenant_id'), 'purchase_order_items', ['tenant_id'], unique=False)
op.create_table('supplier_alerts',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('tenant_id', sa.UUID(), nullable=False),
@@ -466,75 +366,6 @@ def upgrade() -> None:
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_invoices',
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('invoice_number', sa.String(length=50), nullable=False),
sa.Column('supplier_invoice_number', sa.String(length=100), nullable=False),
sa.Column('status', sa.Enum('pending', 'approved', 'paid', 'overdue', 'disputed', 'cancelled', name='invoicestatus'), nullable=False),
sa.Column('invoice_date', sa.DateTime(timezone=True), nullable=False),
sa.Column('due_date', sa.DateTime(timezone=True), nullable=False),
sa.Column('received_date', sa.DateTime(timezone=True), nullable=False),
sa.Column('subtotal', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('tax_amount', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('shipping_cost', sa.Numeric(precision=10, scale=2), nullable=False),
sa.Column('discount_amount', sa.Numeric(precision=10, scale=2), nullable=False),
sa.Column('total_amount', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('currency', sa.String(length=3), nullable=False),
sa.Column('paid_amount', sa.Numeric(precision=12, scale=2), nullable=False),
sa.Column('payment_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('payment_reference', sa.String(length=100), 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('invoice_document_url', sa.String(length=500), 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.ForeignKeyConstraint(['purchase_order_id'], ['purchase_orders.id'], ),
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index('ix_invoices_due_date', 'supplier_invoices', ['due_date'], unique=False)
op.create_index('ix_invoices_invoice_number', 'supplier_invoices', ['invoice_number'], unique=False)
op.create_index('ix_invoices_tenant_status', 'supplier_invoices', ['tenant_id', 'status'], unique=False)
op.create_index('ix_invoices_tenant_supplier', 'supplier_invoices', ['tenant_id', 'supplier_id'], unique=False)
op.create_index(op.f('ix_supplier_invoices_invoice_number'), 'supplier_invoices', ['invoice_number'], unique=False)
op.create_index(op.f('ix_supplier_invoices_purchase_order_id'), 'supplier_invoices', ['purchase_order_id'], unique=False)
op.create_index(op.f('ix_supplier_invoices_status'), 'supplier_invoices', ['status'], unique=False)
op.create_index(op.f('ix_supplier_invoices_supplier_id'), 'supplier_invoices', ['supplier_id'], unique=False)
op.create_index(op.f('ix_supplier_invoices_tenant_id'), 'supplier_invoices', ['tenant_id'], unique=False)
op.create_table('delivery_items',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('tenant_id', sa.UUID(), nullable=False),
sa.Column('delivery_id', sa.UUID(), nullable=False),
sa.Column('purchase_order_item_id', sa.UUID(), nullable=False),
sa.Column('inventory_product_id', sa.UUID(), nullable=False),
sa.Column('ordered_quantity', sa.Integer(), nullable=False),
sa.Column('delivered_quantity', sa.Integer(), nullable=False),
sa.Column('accepted_quantity', sa.Integer(), nullable=False),
sa.Column('rejected_quantity', sa.Integer(), nullable=False),
sa.Column('batch_lot_number', sa.String(length=100), nullable=True),
sa.Column('expiry_date', sa.DateTime(timezone=True), nullable=True),
sa.Column('quality_grade', sa.String(length=20), nullable=True),
sa.Column('quality_issues', sa.Text(), nullable=True),
sa.Column('rejection_reason', sa.Text(), nullable=True),
sa.Column('item_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.ForeignKeyConstraint(['delivery_id'], ['deliveries.id'], ),
sa.ForeignKeyConstraint(['purchase_order_item_id'], ['purchase_order_items.id'], ),
sa.PrimaryKeyConstraint('id')
)
op.create_index(op.f('ix_delivery_items_delivery_id'), 'delivery_items', ['delivery_id'], unique=False)
op.create_index('ix_delivery_items_inventory_product', 'delivery_items', ['inventory_product_id'], unique=False)
op.create_index(op.f('ix_delivery_items_inventory_product_id'), 'delivery_items', ['inventory_product_id'], unique=False)
op.create_index(op.f('ix_delivery_items_purchase_order_item_id'), 'delivery_items', ['purchase_order_item_id'], unique=False)
op.create_index('ix_delivery_items_tenant_delivery', 'delivery_items', ['tenant_id', 'delivery_id'], unique=False)
op.create_index(op.f('ix_delivery_items_tenant_id'), 'delivery_items', ['tenant_id'], unique=False)
op.create_table('supplier_quality_reviews',
sa.Column('id', sa.UUID(), nullable=False),
sa.Column('tenant_id', sa.UUID(), nullable=False),
@@ -559,8 +390,6 @@ def upgrade() -> None:
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(['delivery_id'], ['deliveries.id'], ),
sa.ForeignKeyConstraint(['purchase_order_id'], ['purchase_orders.id'], ),
sa.ForeignKeyConstraint(['supplier_id'], ['suppliers.id'], ),
sa.PrimaryKeyConstraint('id')
)
@@ -571,6 +400,35 @@ def upgrade() -> None:
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 ###
@@ -584,23 +442,6 @@ def downgrade() -> None:
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(op.f('ix_delivery_items_tenant_id'), table_name='delivery_items')
op.drop_index('ix_delivery_items_tenant_delivery', table_name='delivery_items')
op.drop_index(op.f('ix_delivery_items_purchase_order_item_id'), table_name='delivery_items')
op.drop_index(op.f('ix_delivery_items_inventory_product_id'), table_name='delivery_items')
op.drop_index('ix_delivery_items_inventory_product', table_name='delivery_items')
op.drop_index(op.f('ix_delivery_items_delivery_id'), table_name='delivery_items')
op.drop_table('delivery_items')
op.drop_index(op.f('ix_supplier_invoices_tenant_id'), table_name='supplier_invoices')
op.drop_index(op.f('ix_supplier_invoices_supplier_id'), table_name='supplier_invoices')
op.drop_index(op.f('ix_supplier_invoices_status'), table_name='supplier_invoices')
op.drop_index(op.f('ix_supplier_invoices_purchase_order_id'), table_name='supplier_invoices')
op.drop_index(op.f('ix_supplier_invoices_invoice_number'), table_name='supplier_invoices')
op.drop_index('ix_invoices_tenant_supplier', table_name='supplier_invoices')
op.drop_index('ix_invoices_tenant_status', table_name='supplier_invoices')
op.drop_index('ix_invoices_invoice_number', table_name='supplier_invoices')
op.drop_index('ix_invoices_due_date', table_name='supplier_invoices')
op.drop_table('supplier_invoices')
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')
@@ -614,21 +455,6 @@ def downgrade() -> None:
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_purchase_order_items_tenant_id'), table_name='purchase_order_items')
op.drop_index(op.f('ix_purchase_order_items_purchase_order_id'), table_name='purchase_order_items')
op.drop_index(op.f('ix_purchase_order_items_price_list_item_id'), table_name='purchase_order_items')
op.drop_index(op.f('ix_purchase_order_items_inventory_product_id'), table_name='purchase_order_items')
op.drop_index('ix_po_items_tenant_po', table_name='purchase_order_items')
op.drop_index('ix_po_items_inventory_product', table_name='purchase_order_items')
op.drop_table('purchase_order_items')
op.drop_index('ix_deliveries_tenant_status', table_name='deliveries')
op.drop_index(op.f('ix_deliveries_tenant_id'), table_name='deliveries')
op.drop_index(op.f('ix_deliveries_supplier_id'), table_name='deliveries')
op.drop_index(op.f('ix_deliveries_status'), table_name='deliveries')
op.drop_index('ix_deliveries_scheduled_date', table_name='deliveries')
op.drop_index(op.f('ix_deliveries_purchase_order_id'), table_name='deliveries')
op.drop_index('ix_deliveries_delivery_number', table_name='deliveries')
op.drop_table('deliveries')
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')
@@ -643,7 +469,7 @@ def downgrade() -> None:
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.drop_index('ix_price_lists_tenant_supplier', 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')
@@ -659,15 +485,9 @@ def downgrade() -> None:
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_purchase_orders_tenant_supplier', table_name='purchase_orders')
op.drop_index('ix_purchase_orders_tenant_status', table_name='purchase_orders')
op.drop_index(op.f('ix_purchase_orders_tenant_id'), table_name='purchase_orders')
op.drop_index(op.f('ix_purchase_orders_supplier_id'), table_name='purchase_orders')
op.drop_index(op.f('ix_purchase_orders_status'), table_name='purchase_orders')
op.drop_index('ix_purchase_orders_po_number', table_name='purchase_orders')
op.drop_index('ix_purchase_orders_order_date', table_name='purchase_orders')
op.drop_index('ix_purchase_orders_delivery_date', table_name='purchase_orders')
op.drop_table('purchase_orders')
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')

View File

@@ -1,84 +0,0 @@
"""add_supplier_trust_metrics
Revision ID: add_supplier_trust_metrics
Revises: 93d6ea3dc888
Create Date: 2025-10-20 12:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'add_supplier_trust_metrics'
down_revision = '93d6ea3dc888'
branch_labels = None
depends_on = None
def upgrade() -> None:
"""Add trust and auto-approval metrics to suppliers table"""
# Add trust and auto-approval metric columns
op.add_column('suppliers', sa.Column('trust_score', sa.Float(), nullable=False, server_default='0.0'))
op.add_column('suppliers', sa.Column('is_preferred_supplier', sa.Boolean(), nullable=False, server_default='false'))
op.add_column('suppliers', sa.Column('auto_approve_enabled', sa.Boolean(), nullable=False, server_default='false'))
op.add_column('suppliers', sa.Column('total_pos_count', sa.Integer(), nullable=False, server_default='0'))
op.add_column('suppliers', sa.Column('approved_pos_count', sa.Integer(), nullable=False, server_default='0'))
op.add_column('suppliers', sa.Column('on_time_delivery_rate', sa.Float(), nullable=False, server_default='0.0'))
op.add_column('suppliers', sa.Column('fulfillment_rate', sa.Float(), nullable=False, server_default='0.0'))
op.add_column('suppliers', sa.Column('last_performance_update', sa.DateTime(timezone=True), nullable=True))
# Create index for trust score queries
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)
# Update existing active suppliers to have reasonable default trust scores
# Suppliers with good ratings and history get higher initial trust
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'
""")
def downgrade() -> None:
"""Remove trust and auto-approval metrics from suppliers table"""
# Drop indexes
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')
# Drop columns
op.drop_column('suppliers', 'last_performance_update')
op.drop_column('suppliers', 'fulfillment_rate')
op.drop_column('suppliers', 'on_time_delivery_rate')
op.drop_column('suppliers', 'approved_pos_count')
op.drop_column('suppliers', 'total_pos_count')
op.drop_column('suppliers', 'auto_approve_enabled')
op.drop_column('suppliers', 'is_preferred_supplier')
op.drop_column('suppliers', 'trust_score')