"""initial schema Revision ID: 001 Revises: Create Date: 2026-05-08 """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import postgresql revision: str = '001' 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: op.create_table('users', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('wechat_openid', sa.String(length=255), nullable=True), sa.Column('phone', sa.String(length=20), nullable=True), sa.Column('username', sa.String(length=100), nullable=True), sa.Column('password_hash', sa.String(length=255), nullable=True), sa.Column('tier', sa.String(length=50), nullable=True), sa.Column('is_active', sa.Boolean(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.Column('settings', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_users_phone'), 'users', ['phone'], unique=True) op.create_index(op.f('ix_users_wechat_openid'), 'users', ['wechat_openid'], unique=True) op.create_table('products', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('name', sa.String(length=255), nullable=False), sa.Column('name_en', sa.String(length=255), nullable=True), sa.Column('description', sa.Text(), nullable=True), sa.Column('description_en', sa.Text(), nullable=True), sa.Column('category', sa.String(length=100), nullable=True), sa.Column('price', sa.String(length=50), nullable=True), sa.Column('price_unit', sa.String(length=20), nullable=True), sa.Column('moq', sa.String(length=50), nullable=True), sa.Column('keywords', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('specifications', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('images', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('is_active', sa.Boolean(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_products_user_id'), 'products', ['user_id'], unique=False) op.create_table('customers', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('name', sa.String(length=255), nullable=False), sa.Column('company', sa.String(length=255), nullable=True), sa.Column('country', sa.String(length=100), nullable=True), sa.Column('phone', sa.String(length=50), nullable=True), sa.Column('email', sa.String(length=255), nullable=True), sa.Column('whatsapp_id', sa.String(length=255), nullable=True), sa.Column('source', sa.String(length=100), nullable=True), sa.Column('tags', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('notes', sa.Text(), nullable=True), sa.Column('preference', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('status', sa.String(length=50), nullable=True), sa.Column('last_contact_at', sa.DateTime(), nullable=True), sa.Column('silence_started_at', sa.DateTime(), nullable=True), sa.Column('next_followup_at', sa.DateTime(), nullable=True), sa.Column('estimated_value', sa.String(length=50), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_customers_user_id'), 'customers', ['user_id'], unique=False) op.create_table('conversations', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('customer_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('channel', sa.String(length=50), nullable=True), sa.Column('topic', sa.String(length=255), nullable=True), sa.Column('status', sa.String(length=50), nullable=True), sa.Column('message_count', sa.Integer(), nullable=True), sa.Column('last_message_at', sa.DateTime(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['customer_id'], ['customers.id'], ), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_conversations_customer_id'), 'conversations', ['customer_id'], unique=False) op.create_index(op.f('ix_conversations_user_id'), 'conversations', ['user_id'], unique=False) op.create_table('messages', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('conversation_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('direction', sa.String(length=20), nullable=False), sa.Column('content', sa.Text(), nullable=False), sa.Column('content_translated', sa.Text(), nullable=True), sa.Column('content_type', sa.String(length=50), nullable=True), sa.Column('ai_suggestions', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('selected_suggestion', sa.Integer(), nullable=True), sa.Column('user_edited', sa.Text(), nullable=True), sa.Column('status', sa.String(length=50), nullable=True), sa.Column('metadata', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['conversation_id'], ['conversations.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_messages_conversation_id'), 'messages', ['conversation_id'], unique=False) op.create_table('quotations', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('user_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('customer_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('title', sa.String(length=255), nullable=True), sa.Column('status', sa.String(length=50), nullable=True), sa.Column('currency', sa.String(length=10), nullable=True), sa.Column('exchange_rate', sa.Float(), nullable=True), sa.Column('payment_terms', sa.String(length=255), nullable=True), sa.Column('delivery_terms', sa.String(length=255), nullable=True), sa.Column('lead_time', sa.String(length=100), nullable=True), sa.Column('valid_until', sa.String(length=100), nullable=True), sa.Column('subtotal', sa.Float(), nullable=True), sa.Column('discount', sa.Float(), nullable=True), sa.Column('shipping', sa.Float(), nullable=True), sa.Column('total', sa.Float(), nullable=True), sa.Column('notes', sa.Text(), nullable=True), sa.Column('pdf_url', sa.Text(), nullable=True), sa.Column('sent_at', sa.DateTime(), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.Column('updated_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['customer_id'], ['customers.id'], ), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_quotations_user_id'), 'quotations', ['user_id'], unique=False) op.create_table('quotation_items', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('quotation_id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('product_name', sa.String(length=255), nullable=False), sa.Column('description', sa.Text(), nullable=True), sa.Column('quantity', sa.Integer(), nullable=False), sa.Column('unit_price', sa.Float(), nullable=False), sa.Column('total_price', sa.Float(), nullable=True), sa.Column('unit', sa.String(length=50), nullable=True), sa.ForeignKeyConstraint(['quotation_id'], ['quotations.id'], ), sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_quotation_items_quotation_id'), 'quotation_items', ['quotation_id'], unique=False) op.create_table('corpus_entries', sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False), sa.Column('source_text', sa.Text(), nullable=False), sa.Column('target_text', sa.Text(), nullable=False), sa.Column('source_lang', sa.String(length=20), nullable=True), sa.Column('target_lang', sa.String(length=20), nullable=True), sa.Column('task_type', sa.String(length=50), nullable=False), sa.Column('domain', sa.String(length=100), nullable=True), sa.Column('provider_used', sa.String(length=50), nullable=True), sa.Column('quality_score', sa.Float(), nullable=True), sa.Column('user_edited', sa.Boolean(), nullable=True), sa.Column('user_rating', sa.Integer(), nullable=True), sa.Column('usage_count', sa.Integer(), nullable=True), sa.Column('embedding', postgresql.Vector(length=768), nullable=True), sa.Column('metadata', postgresql.JSONB(astext_type=sa.Text()), nullable=True), sa.Column('created_at', sa.DateTime(), nullable=True), sa.PrimaryKeyConstraint('id') ) def downgrade() -> None: op.drop_table('corpus_entries') op.drop_table('quotation_items') op.drop_table('quotations') op.drop_table('messages') op.drop_table('conversations') op.drop_table('customers') op.drop_table('products') op.drop_table('users')