diff --git a/app/api/inspections.py b/app/api/inspections.py index 7dfa3f4..b91021a 100644 --- a/app/api/inspections.py +++ b/app/api/inspections.py @@ -401,18 +401,7 @@ def create_inspection(): f'#{inspection.id} via mobile API)', ) - # ── Commit inspection + any staged rows ─────────────────────────────── - # Commit BEFORE firing notifications so the inspection record is always - # persisted even if notify_by_matrix raises (e.g. a DB hiccup querying - # the notification matrix, a missing table from a pending migration, or - # any other transient error). Without this ordering, a notification - # failure would 500 the entire request, roll back the transaction, and - # leave the inspection unsaved — causing the iPad to retry indefinitely. - db.session.commit() - # ── Notifications ───────────────────────────────────────────────────── - # Best-effort: log and continue on any failure. The inspection is already - # committed above, so notification errors never prevent saving. if status == 'completed': score_display = f'{overall_score:.1f}%' if overall_score is not None else 'N/A' try: @@ -422,27 +411,20 @@ def create_inspection(): except RuntimeError: inspection_link = f'/inspections/{inspection.id}' - try: - notify_by_matrix( - event_type = 'inspection_completed', - title = f'Inspection #{inspection.id} Completed (Mobile)', - body = ( - f'{user.username} completed an inspection at ' - f'{facility.name} using the "{template.name}" template. ' - f'Overall score: {score_display}.' - ), - link = inspection_link, - inspection_id = inspection.id, - facility_id = facility_id, - exclude_user_ids = {user.id}, - ) - db.session.commit() # persist notification rows added by notify() - except Exception as exc: - logger.error( - 'API INSPECTIONS | notification error | inspection_id=%d | error=%s', - inspection.id, exc, - ) - db.session.rollback() # discard any partial notification rows + notify_by_matrix( + event_type = 'inspection_completed', + title = f'Inspection #{inspection.id} Completed (Mobile)', + body = ( + f'{user.display_name} completed an inspection at ' + f'{facility.name} using the "{template.name}" template. ' + f'Overall score: {score_display}.' + ), + link = inspection_link, + inspection_id = inspection.id, + facility_id = facility_id, + ) + + db.session.commit() # ── Post-commit audit logging ────────────────────────────────────────── # All log_action() calls must come AFTER db.session.commit() because @@ -533,7 +515,6 @@ def update_inspection(inspection_id): db.session.commit() # Notify when a draft transitions to completed — mirrors the POST handler. - # Best-effort: log and continue on any failure so the PATCH always succeeds. transitioning_to_complete = ( data.get('status') == 'completed' and prev_status != 'completed' ) @@ -548,26 +529,19 @@ def update_inspection(inspection_id): inspection_id=inspection.id, _external=False) except RuntimeError: inspection_link = f'/inspections/{inspection.id}' - try: - notify_by_matrix( - event_type = 'inspection_completed', - title = f'Inspection #{inspection.id} Completed (Mobile)', - body = ( - f'{user.display_name} completed an inspection at ' - f'{facility_name} using the "{template_name}" template. ' - f'Overall score: {score_display}.' - ), - link = inspection_link, - inspection_id = inspection.id, - facility_id = inspection.facility_id, - ) - db.session.commit() # persist notification rows added by notify() - except Exception as exc: - logger.error( - 'API INSPECTIONS | PATCH notification error | inspection_id=%d | error=%s', - inspection.id, exc, - ) - db.session.rollback() + notify_by_matrix( + event_type = 'inspection_completed', + title = f'Inspection #{inspection.id} Completed (Mobile)', + body = ( + f'{user.display_name} completed an inspection at ' + f'{facility_name} using the "{template_name}" template. ' + f'Overall score: {score_display}.' + ), + link = inspection_link, + inspection_id = inspection.id, + facility_id = inspection.facility_id, + ) + db.session.commit() # persist notification rows added by notify() log_action(ACTION_UPDATE, 'Inspection', inspection.id, f'{inspection.template.name} @ {inspection.facility.name}',