174 lines
10 KiB
Python
174 lines
10 KiB
Python
"""
|
|
Initial schema for Distribution Service
|
|
|
|
Revision ID: 001
|
|
Revises:
|
|
Create Date: 2024-12-01 13:00:00.000000
|
|
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = '001'
|
|
down_revision = None
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade():
|
|
# Create enum types
|
|
op.execute("CREATE TYPE deliveryroutestatus AS ENUM ('planned', 'in_progress', 'completed', 'cancelled')")
|
|
op.execute("CREATE TYPE shipmentstatus AS ENUM ('pending', 'packed', 'in_transit', 'delivered', 'failed')")
|
|
op.execute("CREATE TYPE deliveryschedulefrequency AS ENUM ('daily', 'weekly', 'biweekly', 'monthly')")
|
|
|
|
# Create delivery_routes table
|
|
op.create_table('delivery_routes',
|
|
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('route_number', sa.String(length=50), nullable=False),
|
|
sa.Column('route_date', sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column('vehicle_id', sa.String(length=100), nullable=True),
|
|
sa.Column('driver_id', postgresql.UUID(as_uuid=True), nullable=True),
|
|
sa.Column('total_distance_km', sa.Float(), nullable=True),
|
|
sa.Column('estimated_duration_minutes', sa.Integer(), nullable=True),
|
|
sa.Column('route_sequence', postgresql.JSONB(astext_type=sa.Text()), nullable=True),
|
|
sa.Column('notes', sa.Text(), nullable=True),
|
|
sa.Column('status', postgresql.ENUM('planned', 'in_progress', 'completed', 'cancelled', name='deliveryroutestatus', create_type=False), nullable=False, server_default='planned'),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('created_by', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.PrimaryKeyConstraint('id'),
|
|
sa.UniqueConstraint('route_number')
|
|
)
|
|
|
|
# Create indexes for delivery_routes
|
|
op.create_index('ix_delivery_routes_tenant_id', 'delivery_routes', ['tenant_id'])
|
|
op.create_index('ix_delivery_routes_route_date', 'delivery_routes', ['route_date'])
|
|
op.create_index('ix_delivery_routes_route_number', 'delivery_routes', ['route_number'])
|
|
op.create_index('ix_delivery_routes_status', 'delivery_routes', ['status'])
|
|
op.create_index('ix_delivery_routes_driver_id', 'delivery_routes', ['driver_id'])
|
|
op.create_index('ix_delivery_routes_tenant_date', 'delivery_routes', ['tenant_id', 'route_date'])
|
|
op.create_index('ix_delivery_routes_date_tenant_status', 'delivery_routes', ['route_date', 'tenant_id', 'status'])
|
|
|
|
|
|
# Create shipments table
|
|
op.create_table('shipments',
|
|
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('parent_tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('child_tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('purchase_order_id', postgresql.UUID(as_uuid=True), nullable=True),
|
|
sa.Column('delivery_route_id', postgresql.UUID(as_uuid=True), nullable=True),
|
|
sa.Column('shipment_number', sa.String(length=50), nullable=False),
|
|
sa.Column('shipment_date', sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column('current_location_lat', sa.Float(), nullable=True),
|
|
sa.Column('current_location_lng', sa.Float(), nullable=True),
|
|
sa.Column('last_tracked_at', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('status', postgresql.ENUM('pending', 'packed', 'in_transit', 'delivered', 'failed', name='shipmentstatus', create_type=False), nullable=False, server_default='pending'),
|
|
sa.Column('actual_delivery_time', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('signature', sa.Text(), nullable=True),
|
|
sa.Column('photo_url', sa.String(length=500), nullable=True),
|
|
sa.Column('received_by_name', sa.String(length=200), nullable=True),
|
|
sa.Column('delivery_notes', sa.Text(), nullable=True),
|
|
sa.Column('total_weight_kg', sa.Float(), nullable=True),
|
|
sa.Column('total_volume_m3', sa.Float(), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('created_by', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.ForeignKeyConstraint(['delivery_route_id'], ['delivery_routes.id'], ondelete='SET NULL'),
|
|
sa.PrimaryKeyConstraint('id'),
|
|
sa.UniqueConstraint('shipment_number')
|
|
)
|
|
|
|
# Create indexes for shipments
|
|
op.create_index('ix_shipments_tenant_id', 'shipments', ['tenant_id'])
|
|
op.create_index('ix_shipments_parent_tenant_id', 'shipments', ['parent_tenant_id'])
|
|
op.create_index('ix_shipments_child_tenant_id', 'shipments', ['child_tenant_id'])
|
|
op.create_index('ix_shipments_purchase_order_id', 'shipments', ['purchase_order_id'])
|
|
op.create_index('ix_shipments_delivery_route_id', 'shipments', ['delivery_route_id'])
|
|
op.create_index('ix_shipments_shipment_number', 'shipments', ['shipment_number'])
|
|
op.create_index('ix_shipments_shipment_date', 'shipments', ['shipment_date'])
|
|
op.create_index('ix_shipments_status', 'shipments', ['status'])
|
|
op.create_index('ix_shipments_tenant_status', 'shipments', ['tenant_id', 'status'])
|
|
op.create_index('ix_shipments_parent_child', 'shipments', ['parent_tenant_id', 'child_tenant_id'])
|
|
op.create_index('ix_shipments_date_tenant', 'shipments', ['shipment_date', 'tenant_id'])
|
|
|
|
|
|
# Create delivery_schedules table
|
|
op.create_table('delivery_schedules',
|
|
sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('name', sa.String(length=200), nullable=False),
|
|
sa.Column('delivery_days', sa.String(length=200), nullable=False),
|
|
sa.Column('delivery_time', sa.String(length=20), nullable=False),
|
|
sa.Column('frequency', postgresql.ENUM('daily', 'weekly', 'biweekly', 'monthly', name='deliveryschedulefrequency', create_type=False), nullable=False, server_default='weekly'),
|
|
sa.Column('auto_generate_orders', sa.Boolean(), nullable=False, server_default='false'),
|
|
sa.Column('lead_time_days', sa.Integer(), nullable=False, server_default='1'),
|
|
sa.Column('target_parent_tenant_id', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('target_child_tenant_ids', postgresql.JSONB(astext_type=sa.Text()), nullable=False),
|
|
sa.Column('is_active', sa.Boolean(), nullable=False, server_default='true'),
|
|
sa.Column('notes', sa.Text(), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('now()'), nullable=False),
|
|
sa.Column('created_by', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column('updated_by', postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.PrimaryKeyConstraint('id')
|
|
)
|
|
|
|
# Create indexes for delivery_schedules
|
|
op.create_index('ix_delivery_schedules_tenant_id', 'delivery_schedules', ['tenant_id'])
|
|
op.create_index('ix_delivery_schedules_target_parent_tenant_id', 'delivery_schedules', ['target_parent_tenant_id'])
|
|
op.create_index('ix_delivery_schedules_is_active', 'delivery_schedules', ['is_active'])
|
|
op.create_index('ix_delivery_schedules_tenant_active', 'delivery_schedules', ['tenant_id', 'is_active'])
|
|
op.create_index('ix_delivery_schedules_parent_tenant', 'delivery_schedules', ['target_parent_tenant_id'])
|
|
|
|
|
|
def downgrade():
|
|
# Drop indexes for delivery_schedules
|
|
op.drop_index('ix_delivery_schedules_parent_tenant', table_name='delivery_schedules')
|
|
op.drop_index('ix_delivery_schedules_tenant_active', table_name='delivery_schedules')
|
|
op.drop_index('ix_delivery_schedules_is_active', table_name='delivery_schedules')
|
|
op.drop_index('ix_delivery_schedules_target_parent_tenant_id', table_name='delivery_schedules')
|
|
op.drop_index('ix_delivery_schedules_tenant_id', table_name='delivery_schedules')
|
|
|
|
# Drop delivery_schedules table
|
|
op.drop_table('delivery_schedules')
|
|
|
|
# Drop indexes for shipments
|
|
op.drop_index('ix_shipments_date_tenant', table_name='shipments')
|
|
op.drop_index('ix_shipments_parent_child', table_name='shipments')
|
|
op.drop_index('ix_shipments_tenant_status', table_name='shipments')
|
|
op.drop_index('ix_shipments_status', table_name='shipments')
|
|
op.drop_index('ix_shipments_shipment_date', table_name='shipments')
|
|
op.drop_index('ix_shipments_shipment_number', table_name='shipments')
|
|
op.drop_index('ix_shipments_delivery_route_id', table_name='shipments')
|
|
op.drop_index('ix_shipments_purchase_order_id', table_name='shipments')
|
|
op.drop_index('ix_shipments_child_tenant_id', table_name='shipments')
|
|
op.drop_index('ix_shipments_parent_tenant_id', table_name='shipments')
|
|
op.drop_index('ix_shipments_tenant_id', table_name='shipments')
|
|
|
|
# Drop shipments table
|
|
op.drop_table('shipments')
|
|
|
|
# Drop indexes for delivery_routes
|
|
op.drop_index('ix_delivery_routes_date_tenant_status', table_name='delivery_routes')
|
|
op.drop_index('ix_delivery_routes_tenant_date', table_name='delivery_routes')
|
|
op.drop_index('ix_delivery_routes_driver_id', table_name='delivery_routes')
|
|
op.drop_index('ix_delivery_routes_status', table_name='delivery_routes')
|
|
op.drop_index('ix_delivery_routes_route_number', table_name='delivery_routes')
|
|
op.drop_index('ix_delivery_routes_route_date', table_name='delivery_routes')
|
|
op.drop_index('ix_delivery_routes_tenant_id', table_name='delivery_routes')
|
|
|
|
# Drop delivery_routes table
|
|
op.drop_table('delivery_routes')
|
|
|
|
# Drop enum types
|
|
op.execute("DROP TYPE IF EXISTS deliveryschedulefrequency")
|
|
op.execute("DROP TYPE IF EXISTS shipmentstatus")
|
|
op.execute("DROP TYPE IF EXISTS deliveryroutestatus")
|