Aug 27 - Update code to follow-up with ST functions

This commit is contained in:
2026-08-27 11:54:07 -04:00
parent 3bfd81c84c
commit 2d68bad966
10 changed files with 617 additions and 16 deletions
+49 -2
View File
@@ -228,6 +228,11 @@ def _inspection_payload(inspection):
'inspector_notes': inspector_notes,
# ── Follow-up / re-inspection fields ──────────────────────────────
'follow_up_required': inspection.follow_up_required,
# phase56 — who is to perform the follow-up. NULL means the
# inspection's own inspector, which is what it always meant.
'follow_up_assigned_to': inspection.follow_up_assigned_to,
'follow_up_assigned_to_name': (inspection.follow_up_assignee.display_name
if inspection.follow_up_assignee else None),
'follow_up_note': inspection.follow_up_note,
'parent_inspection_id': inspection.parent_inspection_id,
# ── Originating schedule (MT-14) ──────────────────────────────────
@@ -257,6 +262,9 @@ def list_inspections():
offset int default 0
facility_id int filter by facility
status str filter by status (completed, in_progress, flagged)
follow_up_required
bool 'true'/'1' — only inspections awaiting a re-inspection,
scoped to the caller's own follow-ups (see below)
from_date str ISO date (YYYY-MM-DD) — include inspections on/after this date
to_date str ISO date (YYYY-MM-DD) — include inspections on/before this date
@@ -282,8 +290,15 @@ def list_inspections():
query = Inspection.query
# Inspectors only see their own inspections
if user.is_inspector:
# Inspectors only see their own inspections.
#
# EXCEPT when asking for follow-up requests: a follow-up can now be handed
# to a different inspector (phase56), and that request lives on an
# inspection somebody ELSE performed. Applying this filter first would hide
# exactly the rows the assignee needs, so it is deferred to the follow-up
# block below, which applies ownership instead of authorship.
wants_follow_ups = request.args.get('follow_up_required', '').lower() in ('true', '1')
if user.is_inspector and not wants_follow_ups:
query = query.filter(Inspection.inspector_id == user.id)
# Optional filters
@@ -295,6 +310,38 @@ def list_inspections():
if status:
query = query.filter(Inspection.status == status)
if wants_follow_ups:
# MT had no follow_up_required filter at all, so the iPad's Follow-up
# Requests screen — which calls ?follow_up_required=true — received the
# inspector's ENTIRE history and presented it as outstanding requests.
#
# "Follow-up" must mean exactly what it means everywhere on the web
# (inspections.index / reports status_filter == 'follow_up'): flagged,
# completed, and not yet answered by a linked re-inspection.
#
# The ~follow_ups.any() clause is the one that matters. The web execute
# route never clears follow_up_required on the parent — it only stops
# listing it once a child exists — so filtering on the flag alone would
# return follow-ups that were already satisfied on the web, forever.
# On the iPad those rows are undismissable: pull_follow_up_requests()
# keeps receiving them and update(from:) resets fulfilledLocally, so the
# FOLLOW-UP REQUESTED card would never clear. (The mobile POST path does
# clear the parent flag, so only web-completed re-inspections stick.)
query = query.filter(
Inspection.follow_up_required.is_(True),
Inspection.status == 'completed',
).filter(~Inspection.follow_ups.any())
# Ownership, not authorship (phase56). Mirrors
# Inspection.follow_up_owner: an assigned follow-up belongs to the
# assignee ALONE, an unassigned one to the inspection's own inspector.
#
# The two arms are mutually exclusive on purpose. Without the second
# arm's `is_(None)` an inspector would keep seeing a follow-up that had
# been handed to someone else, and two people would turn up to do it.
if user.is_inspector:
query = query.filter(Inspection.follow_up_owned_by(user.id))
from_date_str = request.args.get('from_date')
if from_date_str:
try: