82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
"""Add product_render_positions table and render_position_id on order_lines.
|
|
|
|
Revision ID: 028
|
|
Revises: 027
|
|
Create Date: 2026-03-04
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
revision = "028"
|
|
down_revision = "027"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
NIL_UUID = "00000000-0000-0000-0000-000000000000"
|
|
|
|
|
|
def upgrade() -> None:
|
|
# ── New table: product_render_positions ──────────────────────────────────
|
|
op.execute("""
|
|
CREATE TABLE product_render_positions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
|
|
name VARCHAR(200) NOT NULL,
|
|
rotation_x DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
rotation_y DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
rotation_z DOUBLE PRECISION NOT NULL DEFAULT 0,
|
|
is_default BOOLEAN NOT NULL DEFAULT false,
|
|
sort_order INTEGER NOT NULL DEFAULT 0,
|
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
)
|
|
""")
|
|
op.execute(
|
|
"CREATE UNIQUE INDEX uq_render_positions_product_name "
|
|
"ON product_render_positions (product_id, lower(name))"
|
|
)
|
|
op.execute("CREATE INDEX ix_render_positions_product_id ON product_render_positions (product_id)")
|
|
|
|
# ── Add render_position_id to order_lines ────────────────────────────────
|
|
op.execute(
|
|
"ALTER TABLE order_lines ADD COLUMN render_position_id UUID "
|
|
"REFERENCES product_render_positions(id) ON DELETE SET NULL"
|
|
)
|
|
|
|
# ── Update unique indexes to include position ─────────────────────────────
|
|
op.execute("DROP INDEX IF EXISTS uq_order_lines_tracking")
|
|
op.execute("DROP INDEX IF EXISTS uq_order_lines_render")
|
|
|
|
op.execute(
|
|
f"CREATE UNIQUE INDEX uq_order_lines_tracking "
|
|
f"ON order_lines (order_id, product_id, COALESCE(render_position_id, '{NIL_UUID}'::uuid)) "
|
|
f"WHERE output_type_id IS NULL"
|
|
)
|
|
op.execute(
|
|
f"CREATE UNIQUE INDEX uq_order_lines_render "
|
|
f"ON order_lines (order_id, product_id, output_type_id, "
|
|
f"COALESCE(render_position_id, '{NIL_UUID}'::uuid)) "
|
|
f"WHERE output_type_id IS NOT NULL"
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
# Restore original unique indexes (without position)
|
|
op.execute("DROP INDEX IF EXISTS uq_order_lines_tracking")
|
|
op.execute("DROP INDEX IF EXISTS uq_order_lines_render")
|
|
|
|
op.execute("ALTER TABLE order_lines DROP COLUMN IF EXISTS render_position_id")
|
|
|
|
op.execute(
|
|
"CREATE UNIQUE INDEX uq_order_lines_tracking "
|
|
"ON order_lines (order_id, product_id) "
|
|
"WHERE output_type_id IS NULL"
|
|
)
|
|
op.execute(
|
|
"CREATE UNIQUE INDEX uq_order_lines_render "
|
|
"ON order_lines (order_id, product_id, output_type_id) "
|
|
"WHERE output_type_id IS NOT NULL"
|
|
)
|
|
|
|
op.execute("DROP TABLE IF EXISTS product_render_positions CASCADE")
|