Skip to content

Commit

Permalink
IRONN-264 visit_month was being cached in translated form. (#4424)
Browse files Browse the repository at this point in the history
looking up visit_month now always returns english version, which may be
cached. `translate_visit_month()` used by front end where needed.

---------

Co-authored-by: Amy Chen <clone@cesium.cirg.washington.edu>
  • Loading branch information
pbugni and Amy Chen authored Dec 3, 2024
1 parent f269a29 commit d2c319d
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 14 deletions.
24 changes: 24 additions & 0 deletions portal/migrations/versions/4f5daa2b48db_.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""remove non english rows from report data (IRONN-264)
Revision ID: 4f5daa2b48db
Revises: 5a300be640fb
Create Date: 2024-11-25 13:48:01.321510
"""
from alembic import op


# revision identifiers, used by Alembic.
revision = '4f5daa2b48db'
down_revision = '5a300be640fb'


def upgrade():
connection = op.get_bind()
connection.execute("DELETE FROM research_data WHERE NOT (data->>'timepoint' ~ '^(Baseline|Month)');")
# next run of `cache_research_data()` will pick up those just deleted.


def downgrade():
# no point in bringing those back
pass
4 changes: 2 additions & 2 deletions portal/models/qb_timeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -1316,8 +1316,8 @@ def qb_status_visit_name(user_id, research_study_id, as_of_date):
:returns: dictionary with key/values for:
status: string like 'expired'
visit_name: for the period, i.e. '3 months'
action_state: 'not applicable', or status of follow up action
visit_name: for the period, i.e. '3 months'. ALWAYS in english, clients must translate
action_state: 'not applicable', or status of follow-up action
"""
from .research_study import EMPRO_RS_ID
Expand Down
22 changes: 18 additions & 4 deletions portal/models/questionnaire_bank.py
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,10 @@ def qbs_by_rp(rp_id, classification):


def visit_name(qbd):
"""returns string repr of visit, i.e. 'Month 3' or 'Baseline'
NB - only returns english version. See `translate_visit_name()`
"""
from .research_study import (
EMPRO_RS_ID,
research_study_id_from_questionnaire,
Expand All @@ -617,12 +621,22 @@ def visit_name(qbd):
clm += (clrd.years * 12) if clrd.years else 0
total = clm * qbd.iteration + sm
if rs_id == EMPRO_RS_ID:
return _('Month %(month_total)d', month_total=total+1)
return _('Month %(month_total)d', month_total=total)
return f'Month {total+1}'
return f'Month {total}'

if rs_id == EMPRO_RS_ID:
return _('Month %(month_total)d', month_total=1)
return _(qbd.questionnaire_bank.classification.title())
return 'Month 1'
return qbd.questionnaire_bank.classification.title()


def translate_visit_name(visit_name):
"""parse the english version of visit name for front end translation needs"""
if not visit_name:
return visit_name
if visit_name.startswith('Month '):
number = int(visit_name[6:])
return _('Month %(month_total)d', month_total=number)
return _(visit_name)


def add_static_questionnaire_bank():
Expand Down
3 changes: 2 additions & 1 deletion portal/models/questionnaire_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
QuestionnaireBank,
QuestionnaireBankQuestionnaire,
trigger_date,
translate_visit_name,
visit_name,
)
from .research_data import ResearchData
Expand Down Expand Up @@ -401,7 +402,7 @@ def extensions(self):
relative_start=None, iteration=self.qb_iteration,
recur_id=recur_id, qb_id=self.questionnaire_bank_id)
results.append({
'visit_name': visit_name(qbd),
'visit_name': translate_visit_name(visit_name(qbd)),
'url': TRUENTH_VISIT_NAME_EXTENSION})

expires_at = expires(self.subject_id, qbd)
Expand Down
3 changes: 2 additions & 1 deletion portal/static/js/src/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,7 @@ let requestTimerId = 0;
this.filterOptionsList.forEach((o) => {
for (const [key, values] of Object.entries(o)) {
values.forEach((value) => {
if (!value[1]) return true;
if (
$(
`#adminTable .bootstrap-table-filter-control-${key} option[value='${value[0]}']`
Expand Down Expand Up @@ -1412,7 +1413,7 @@ let requestTimerId = 0;
max_attempts: 1,
},
function (result) {
if (!result?.error) self.currentTablePreference = data;
if (result && !result.error) self.currentTablePreference = data;
if (callback) callback();
}
);
Expand Down
1 change: 1 addition & 0 deletions portal/templates/admin/admin_base.html
Original file line number Diff line number Diff line change
Expand Up @@ -107,5 +107,6 @@
// placeholder variables
var qStatusFilterOptions = {};
var clinicianActionStateFilterOptions = {};
var visitOptions = {};
</script>
{%- endmacro -%}
2 changes: 1 addition & 1 deletion portal/templates/admin/patients_by_org.html
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ <h4 class="tnth-headline">{{_("Patient List")}}</h4>
<th data-field="email" data-sortable="true" data-class="email-field" data-filter-control="input">{{ _("Email") }}</th>
{% if 'status' in config.PATIENT_LIST_ADDL_FIELDS %}
<th data-field="questionnaire_status" data-sortable="true" data-card-visible="false" data-searchable="true" data-width="5%" data-class="status-field" data-filter-control="select" data-filter-strict-search="true" data-filter-data="var:qStatusFilterOptions">{{ _("Questionnaire Status") }}</th>
<th data-field="visit" data-sortable="true" data-card-visible="false" data-searchable="true" data-width="5%" data-class="visit-field" data-filter-control="input">{{ _("Visit") }}</th>
<th data-field="visit" data-sortable="true" data-card-visible="false" data-searchable="true" data-width="5%" data-class="visit-field" data-filter-control="select" data-filter-data="var:visitOptions">{{ _("Visit") }}</th>
{% endif %}
{% if 'study_id' in config.PATIENT_LIST_ADDL_FIELDS %}<th data-field="study_id" data-sortable="true" data-searchable="true" data-class="study-id-field" data-filter-control="input" data-sorter="tnthTables.alphanumericSorter" data-width="5%">{{ _("Study ID") }}</th>{% endif %}
<th data-field="consentdate" data-sortable="true" data-card-visible="false" data-sorter="tnthTables.dateSorter" data-searchable="true" data-class="consentdate-field text-center">{{ _("Study Consent Date") }}</th>
Expand Down
2 changes: 1 addition & 1 deletion portal/templates/admin/patients_substudy.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ <h2>{{list_title}}</h2>
<th data-field="birthdate" data-sortable="true" data-class="birthdate-field" data-visible="false">{{ _("Date of Birth") }}</th>
<th data-field="clinician" data-sortable="true" data-class="clinician-field" data-filter-control="input">{{ _("Treating Clinician") }}</th>
<th data-field="empro_status" data-sortable="true" data-card-visible="true" data-searchable="true" data-width="5%" data-class="status-field" data-filter-control="select" data-filter-strict-search="true" data-filter-data="var:qStatusFilterOptions">{{_("EMPRO Questionnaire Status")}}</th>
<th data-field="empro_visit" data-sortable="true" data-card-visible="false" data-searchable="true" data-width="5%" data-class="visit-field" data-filter-control="input" data-visible="false">{{ _("Visit") }}</th>
<th data-field="empro_visit" data-sortable="true" data-card-visible="false" data-searchable="true" data-width="5%" data-class="visit-field" data-filter-control="select" data-visible="false" data-filter-data="var:visitOptions">{{ _("Visit") }}</th>
<th data-field="action_state" data-sortable="true" data-class="intervention-actions-field" data-filter-control="select" data-filter-data="var:clinicianActionStateFilterOptions">{{ _("Clinician Action Status") }}</th>
<th data-field="study_id" data-sortable="true" data-searchable="true" data-class="study-id-field" data-filter-control="input" data-visible="false" data-sorter="tnthTables.alphanumericSorter" data-width="5%">{{ _("Study ID") }}</th>
<th data-field="empro_consentdate" data-sortable="true" data-card-visible="false" data-sorter="tnthTables.dateSorter" data-searchable="true" data-visible="false" data-class="consentdate-field text-center" data-visible="true">{{ _("Study Consent Date") }}</th>
Expand Down
4 changes: 2 additions & 2 deletions portal/views/patient.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ def patient_timeline(patient_id):
)
from ..models.qbd import QBD
from ..models.qb_status import QB_Status
from ..models.questionnaire_bank import visit_name
from ..models.questionnaire_bank import translate_visit_name, visit_name
from ..models.questionnaire_response import aggregate_responses
from ..models.research_protocol import ResearchProtocol
from ..tasks import cache_single_patient_adherence_data
Expand Down Expand Up @@ -392,7 +392,7 @@ def patient_timeline(patient_id):
'at': FHIR_datetime.as_fhir(qbt.at),
'qb (id, iteration)': "{} ({}, {})".format(
qbd.questionnaire_bank.name, qbd.qb_id, qbd.iteration),
'visit': visit_name(qbd)}
'visit': translate_visit_name(visit_name(qbd))}
if qbt.status == OverallStatus.due:
data['questionnaires'] = ','.join(
[q.name for q in qbd.questionnaire_bank.questionnaires])
Expand Down
19 changes: 17 additions & 2 deletions portal/views/patients.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from ..models.intervention import Intervention
from ..models.organization import Organization, OrgTree
from ..models.patient_list import PatientList
from ..models.questionnaire_bank import translate_visit_name
from ..models.qb_status import patient_research_study_status
from ..models.role import ROLE
from ..models.research_study import EMPRO_RS_ID, ResearchStudy
Expand Down Expand Up @@ -181,11 +182,25 @@ def requested_orgs(user, research_study_id):
distinct_action = PatientList.query.distinct(PatientList.action_state).with_entities(
PatientList.action_state)
options.append({"action_state": [(state[0], _(state[0])) for state in distinct_action]})
distinct_visits = PatientList.query.distinct(PatientList.empro_visit).with_entities(
PatientList.empro_visit)
sorted_visits = sorted(
[v[0] for v in distinct_visits if v[0]],
key=lambda x: (0 if not x.split()[-1].isdigit() else int(x.split()[-1]))
)
options.append({"empro_visit": [(visit, translate_visit_name(visit)) for visit in sorted_visits]})
else:
distinct_status = PatientList.query.distinct(
PatientList.questionnaire_status).with_entities(PatientList.questionnaire_status)
options.append(
{"questionnaire_status": [(status[0], _(status[0])) for status in distinct_status]})
distinct_visits = PatientList.query.distinct(PatientList.visit).with_entities(
PatientList.visit)
sorted_visits = sorted(
[v[0] for v in distinct_visits if v[0]],
key=lambda x: (0 if not x.split()[-1].isdigit() else int(x.split()[-1]))
)
options.append({"visit": [(visit, translate_visit_name(visit)) for visit in sorted_visits]})

viewable_orgs = requested_orgs(user, research_study_id)
query = PatientList.query.filter(PatientList.org_id.in_(viewable_orgs))
Expand Down Expand Up @@ -222,8 +237,8 @@ def requested_orgs(user, research_study_id):
"questionnaire_status": _(row.questionnaire_status),
"empro_status": _(row.empro_status),
"action_state": _(row.action_state),
"visit": row.visit,
"empro_visit": row.empro_visit,
"visit": translate_visit_name(row.visit),
"empro_visit": translate_visit_name(row.empro_visit),
"study_id": row.study_id,
"consentdate": row.consentdate,
"empro_consentdate": row.empro_consentdate,
Expand Down

0 comments on commit d2c319d

Please sign in to comment.