Multi-tenant factory inspection system (SpiFox, Enkid, Alpet): - FastAPI backend with JWT auth, PostgreSQL (asyncpg) - Next.js 16 frontend with App Router, SWR data fetching - Machines CRUD with equipment parts management - Part lifecycle tracking (hours/count/date) with counters - Partial unique index for soft-delete support - 24 pytest tests passing, E2E verified Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
43 lines
1.1 KiB
Python
43 lines
1.1 KiB
Python
"""fix_unique_constraint_to_partial_index_active_only
|
|
|
|
Revision ID: a3b1c2d3e4f5
|
|
Revises: 247755b06e67
|
|
Create Date: 2026-02-10 22:40:00.000000
|
|
|
|
"""
|
|
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
|
|
revision: str = "a3b1c2d3e4f5"
|
|
down_revision: Union[str, None] = "247755b06e67"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# Drop the old full unique constraint
|
|
op.drop_constraint(
|
|
"uq_equipment_part_tenant_machine_name",
|
|
"equipment_parts",
|
|
type_="unique",
|
|
)
|
|
# Create partial unique index (active records only)
|
|
op.execute(
|
|
"""
|
|
CREATE UNIQUE INDEX uq_equipment_part_active_tenant_machine_name
|
|
ON equipment_parts (tenant_id, machine_id, name)
|
|
WHERE is_active = true
|
|
"""
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP INDEX IF EXISTS uq_equipment_part_active_tenant_machine_name")
|
|
op.create_unique_constraint(
|
|
"uq_equipment_part_tenant_machine_name",
|
|
"equipment_parts",
|
|
["tenant_id", "machine_id", "name"],
|
|
)
|