Files

62 lines
2.3 KiB
Python

"""phase52 — restrict forms to specific contracts
Creates `template_contracts`: one row = "this inspection template is available
on this contract". Backs per-customer forms — a customer's bespoke form must
not be visible to, or startable against, another customer's facilities.
**No rows for a template means SHARED (available on every contract)**, not
"available nowhere". That convention is why this migration needs no backfill
and cannot change behaviour on deploy: every template that exists today has no
rows and therefore stays available everywhere, exactly as before. A form only
becomes customer-specific once an admin attaches it to at least one contract.
Inverting that default later would silently hide every shared form from every
contract, so it is enforced in one place — InspectionTemplate.available_query()
— which the pickers, their POST validation, and the mobile API all use.
Table-existence check — safe to re-run.
"""
revision = 'phase52_template_contracts'
down_revision = 'phase51_user_notif_matrix'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def _has_table(conn, name):
return conn.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :t"
), {'t': name}).scalar() > 0
def upgrade():
conn = op.get_bind()
if _has_table(conn, 'template_contracts'):
return
op.create_table(
'template_contracts',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('template_id', sa.Integer,
sa.ForeignKey('inspection_templates.id', ondelete='CASCADE'),
nullable=False, index=True),
sa.Column('project_id', sa.Integer,
sa.ForeignKey('projects.id', ondelete='CASCADE'),
nullable=False, index=True),
sa.Column('created_at', sa.DateTime, nullable=False,
server_default=sa.func.now()),
sa.UniqueConstraint('template_id', 'project_id', name='uq_template_contract'),
)
def downgrade():
conn = op.get_bind()
if _has_table(conn, 'template_contracts'):
# Dropping the table returns every form to shared — no form becomes
# unusable, they just stop being restricted.
op.drop_table('template_contracts')