Aug 17 - Update forms will be assigned per contract
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
"""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')
|
||||
Reference in New Issue
Block a user