diff --git a/portal/views/patient.py b/portal/views/patient.py index 09a39ce89..374ac9e5e 100644 --- a/portal/views/patient.py +++ b/portal/views/patient.py @@ -4,6 +4,7 @@ for staff """ +from collections import defaultdict from datetime import datetime import json @@ -359,6 +360,10 @@ def patient_timeline(patient_id): except ValueError as ve: abort(500, str(ve)) + consents = [ + {"research_study_id": c.research_study_id, + "acceptance_date": c.acceptance_date, + "status": c.status} for c in user.valid_consents] results = [] # We order by at (to get the latest status for a given QB) and # secondly by id, as on rare occasions, the time (`at`) of @@ -458,6 +463,7 @@ def get_recur_id(qnr): if trace: return jsonify( + conents=consents, rps=rps, status=status, posted=posted, @@ -465,7 +471,7 @@ def get_recur_id(qnr): adherence_data=adherence_data, trace=dump_trace("END time line lookup")) return jsonify( - rps=rps, status=status, posted=posted, timeline=results, + consents=consents, rps=rps, status=status, posted=posted, timeline=results, adherence_data=adherence_data) @@ -484,7 +490,41 @@ def patient_timewarp(patient_id, days): from copy import deepcopy from portal.models.questionnaire_response import QuestionnaireResponse from portal.models.user_consent import UserConsent - + from ..trigger_states.models import TriggerState + + def sanity_check(): + """confirm user state before / after timewarp""" + # User should have one valid consent + patient = get_user(patient_id, 'view') + consents = patient.valid_consents + rps = [c for c in consents if c.research_study_id == 0] + assert len(rps) == 1 + + rp1s = [c for c in consents if c.research_study_id == 1] + if not len(rp1s): + return + assert len(rp1s) == 1 + + # Confirm valid trigger_states. No data prior to consent. + ts = TriggerState.query.filter( + TriggerState.user_id == patient_id, + TriggerState.timestamp < rp1s[0].acceptance_date).count() + assert ts == 0 + + # should never be more than a single row for any given state + ts = TriggerState.query.filter( + TriggerState.user_id == patient_id + ) + data = defaultdict(int) + for row in ts: + key = f"{row.visit_month}:{row.state}" + data[key] += 1 + for k, v in data.items(): + if v > 1: + raise RuntimeError( + f"Unique visit_month:state {k} broken in trigger_states for {patient}") + + sanity_check() if current_app.config['SYSTEM_TYPE'] == "production": abort(404) @@ -510,7 +550,6 @@ def patient_timewarp(patient_id, days): # trigger_state if current_app.config['GIL'] is None: - from ..trigger_states.models import TriggerState for ts in TriggerState.query.filter( TriggerState.user_id == user.id): changed.append(f"trigger_state {ts.id}") @@ -544,6 +583,7 @@ def patient_timewarp(patient_id, days): ar.timestamp = ar.timestamp - delta db.session.commit() + sanity_check() # Recalculate users timeline & qnr associations cache.delete_memoized(trigger_date)