143 lines
6.1 KiB
Python
143 lines
6.1 KiB
Python
"""Initial database schema
|
|
|
|
Revision ID: 001_initial
|
|
Revises:
|
|
Create Date: 2026-01-29
|
|
|
|
"""
|
|
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 = "001_initial"
|
|
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:
|
|
# Customers table
|
|
op.create_table(
|
|
"customers",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("email", sa.String(255), nullable=False),
|
|
sa.Column("stripe_customer_id", sa.String(255), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(), nullable=True),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index("ix_customers_email", "customers", ["email"], unique=True)
|
|
|
|
# Carts table
|
|
op.create_table(
|
|
"carts",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("customer_id", postgresql.UUID(as_uuid=True), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(), nullable=True),
|
|
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
|
sa.Column("expires_at", sa.DateTime(), nullable=True),
|
|
sa.ForeignKeyConstraint(["customer_id"], ["customers.id"]),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
|
|
# Cart items table
|
|
op.create_table(
|
|
"cart_items",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("cart_id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("product_slug", sa.String(100), nullable=False),
|
|
sa.Column("product_name", sa.String(255), nullable=False),
|
|
sa.Column("variant", sa.String(50), nullable=True),
|
|
sa.Column("quantity", sa.Integer(), nullable=False),
|
|
sa.Column("unit_price", sa.Numeric(10, 2), nullable=False),
|
|
sa.Column("created_at", sa.DateTime(), nullable=True),
|
|
sa.ForeignKeyConstraint(["cart_id"], ["carts.id"], ondelete="CASCADE"),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
|
|
# Orders table
|
|
op.create_table(
|
|
"orders",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("customer_id", postgresql.UUID(as_uuid=True), nullable=True),
|
|
sa.Column("stripe_session_id", sa.String(255), nullable=True),
|
|
sa.Column("stripe_payment_intent_id", sa.String(255), nullable=True),
|
|
sa.Column("status", sa.String(50), nullable=True),
|
|
sa.Column("shipping_name", sa.String(255), nullable=True),
|
|
sa.Column("shipping_email", sa.String(255), nullable=True),
|
|
sa.Column("shipping_address_line1", sa.String(255), nullable=True),
|
|
sa.Column("shipping_address_line2", sa.String(255), nullable=True),
|
|
sa.Column("shipping_city", sa.String(100), nullable=True),
|
|
sa.Column("shipping_state", sa.String(100), nullable=True),
|
|
sa.Column("shipping_postal_code", sa.String(20), nullable=True),
|
|
sa.Column("shipping_country", sa.String(2), nullable=True),
|
|
sa.Column("subtotal", sa.Numeric(10, 2), nullable=True),
|
|
sa.Column("shipping_cost", sa.Numeric(10, 2), nullable=True),
|
|
sa.Column("tax", sa.Numeric(10, 2), nullable=True),
|
|
sa.Column("total", sa.Numeric(10, 2), nullable=True),
|
|
sa.Column("currency", sa.String(3), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(), nullable=True),
|
|
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
|
sa.Column("paid_at", sa.DateTime(), nullable=True),
|
|
sa.Column("shipped_at", sa.DateTime(), nullable=True),
|
|
sa.Column("delivered_at", sa.DateTime(), nullable=True),
|
|
sa.ForeignKeyConstraint(["customer_id"], ["customers.id"]),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
|
|
# Order items table
|
|
op.create_table(
|
|
"order_items",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("order_id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("product_slug", sa.String(100), nullable=False),
|
|
sa.Column("product_name", sa.String(255), nullable=False),
|
|
sa.Column("variant", sa.String(50), nullable=True),
|
|
sa.Column("quantity", sa.Integer(), nullable=False),
|
|
sa.Column("unit_price", sa.Numeric(10, 2), nullable=False),
|
|
sa.Column("pod_provider", sa.String(50), nullable=True),
|
|
sa.Column("pod_order_id", sa.String(255), nullable=True),
|
|
sa.Column("pod_status", sa.String(50), nullable=True),
|
|
sa.Column("pod_tracking_number", sa.String(100), nullable=True),
|
|
sa.Column("pod_tracking_url", sa.Text(), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(), nullable=True),
|
|
sa.ForeignKeyConstraint(["order_id"], ["orders.id"], ondelete="CASCADE"),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
|
|
# Admin users table
|
|
op.create_table(
|
|
"admin_users",
|
|
sa.Column("id", postgresql.UUID(as_uuid=True), nullable=False),
|
|
sa.Column("email", sa.String(255), nullable=False),
|
|
sa.Column("password_hash", sa.String(255), nullable=False),
|
|
sa.Column("is_active", sa.Boolean(), nullable=True),
|
|
sa.Column("created_at", sa.DateTime(), nullable=True),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
op.create_index("ix_admin_users_email", "admin_users", ["email"], unique=True)
|
|
|
|
# Product overrides table
|
|
op.create_table(
|
|
"product_overrides",
|
|
sa.Column("slug", sa.String(100), nullable=False),
|
|
sa.Column("is_active", sa.Boolean(), nullable=True),
|
|
sa.Column("price_override", sa.Numeric(10, 2), nullable=True),
|
|
sa.Column("updated_at", sa.DateTime(), nullable=True),
|
|
sa.PrimaryKeyConstraint("slug"),
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_table("product_overrides")
|
|
op.drop_index("ix_admin_users_email", table_name="admin_users")
|
|
op.drop_table("admin_users")
|
|
op.drop_table("order_items")
|
|
op.drop_table("orders")
|
|
op.drop_table("cart_items")
|
|
op.drop_table("carts")
|
|
op.drop_index("ix_customers_email", table_name="customers")
|
|
op.drop_table("customers")
|