Jul 30 - Allow customer to flag follow-up a inspection

This commit is contained in:
2026-07-30 20:44:38 -04:00
parent 5ed433aabe
commit 0808f8eaff
8 changed files with 256 additions and 21 deletions
@@ -0,0 +1,74 @@
"""phase46 — follow-up request attribution (customer-raised follow-ups)
Adds to `inspections`:
follow_up_requested_by INT NULL FK → users(id) ON DELETE SET NULL
follow_up_requested_at DATETIME NULL
Customers can now request a follow-up re-inspection of a completed inspection at
their own facilities (previously admin/director only), so `follow_up_required`
alone is no longer enough — staff need to see WHO is waiting on the
re-inspection, and a client request must be visibly distinct from an internal
one. `flag_followup()` sets both columns; `clear_followup()` nulls them.
No backfill: legacy rows keep NULL, which the UI renders as an unattributed
follow-up exactly as it did before. FK is SET NULL so deleting a user never
deletes inspection history.
Uses INFORMATION_SCHEMA checks — safe to re-run.
"""
revision = 'phase46_followup_req_by'
down_revision = 'phase45_sched_parent_insp'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
_FK_NAME = 'fk_inspections_follow_up_requested_by'
def _column_exists(conn, table, column):
return conn.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS "
"WHERE TABLE_SCHEMA = DATABASE() "
"AND TABLE_NAME = :t AND COLUMN_NAME = :c"
), {"t": table, "c": column}).scalar() > 0
def _fk_exists(conn, table, name):
return conn.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = :t "
"AND CONSTRAINT_NAME = :n AND CONSTRAINT_TYPE = 'FOREIGN KEY'"
), {"t": table, "n": name}).scalar() > 0
def upgrade():
bind = op.get_bind()
if not _column_exists(bind, 'inspections', 'follow_up_requested_by'):
op.execute(sa.text(
"ALTER TABLE inspections ADD COLUMN follow_up_requested_by INT NULL"
))
if not _column_exists(bind, 'inspections', 'follow_up_requested_at'):
op.execute(sa.text(
"ALTER TABLE inspections ADD COLUMN follow_up_requested_at DATETIME NULL"
))
if not _fk_exists(bind, 'inspections', _FK_NAME):
op.execute(sa.text(
f"ALTER TABLE inspections ADD CONSTRAINT {_FK_NAME} "
"FOREIGN KEY (follow_up_requested_by) REFERENCES users(id) "
"ON DELETE SET NULL"
))
def downgrade():
bind = op.get_bind()
if _fk_exists(bind, 'inspections', _FK_NAME):
op.execute(sa.text(f"ALTER TABLE inspections DROP FOREIGN KEY {_FK_NAME}"))
for col in ('follow_up_requested_at', 'follow_up_requested_by'):
if _column_exists(bind, 'inspections', col):
op.execute(sa.text(f"ALTER TABLE inspections DROP COLUMN {col}"))