Skip to content

Commit

Permalink
trigger_states now considering previous month's opt_out domains, as per
Browse files Browse the repository at this point in the history
TN-3252 comments.
  • Loading branch information
pbugni committed Mar 22, 2024
1 parent 07a8cf3 commit d8b4caf
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 13 deletions.
18 changes: 12 additions & 6 deletions portal/trigger_states/empro_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

from .empro_domains import DomainManifold
from .empro_messages import invite_email, patient_email, staff_emails
from .models import TriggerState
from .models import TriggerState, opted_out_previous_key
from ..database import db
from ..date_tools import FHIR_datetime
from ..models.qb_status import QB_Status
Expand Down Expand Up @@ -295,6 +295,13 @@ def process_processed(ts):
# on hard triggers. Patient gets 'thank you' email regardless.
hard_triggers = ts.hard_trigger_list()
soft_triggers = ts.soft_trigger_list()
opted_out = ts.opted_out_domains()
actionable_triggers = list(set(hard_triggers) - set(opted_out))
# persist all opted out for front-end use as well
for domain, link_triggers in triggers['domain'].items():
if domain in opted_out:
link_triggers[opted_out_previous_key] = True

pending_emails = []
patient = User.query.get(ts.user_id)

Expand All @@ -307,11 +314,10 @@ def process_processed(ts):
current_app.logger.error(
f"EMPRO Patient({patient.id}) w/o email! Can't send message")

if hard_triggers:
if actionable_triggers:
triggers['action_state'] = 'required'

# In the event of hard_triggers, clinicians/staff get mail
for msg in staff_emails(patient, hard_triggers, True):
for msg in staff_emails(patient, actionable_triggers, True):
pending_emails.append((msg, "initial staff alert"))

for em, context in pending_emails:
Expand All @@ -322,8 +328,8 @@ def process_processed(ts):
sm = EMPRO_state(ts)
sm.fired_events()

# Without hard triggers, no further action is necessary
if not hard_triggers:
# Without actionable triggers, no further action is necessary
if not actionable_triggers:
sm.resolve()

current_app.logger.debug(
Expand Down
33 changes: 28 additions & 5 deletions portal/trigger_states/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from ..date_tools import FHIR_datetime, weekday_delta
from ..models.audit import Audit

opt_out_key = '_opt_out_next_visit'
opt_out_next_visit_key = '_opt_out_next_visit'
opted_out_previous_key = '_opted_out_previous_visit'


trigger_state_enum = ENUM(
'unstarted',
Expand Down Expand Up @@ -108,16 +110,16 @@ def apply_opt_out(self, opt_out_dict):

opt_out_of_domains = set()
for d, vals in opt_out_dict['triggers']['domains'].items():
if vals.get(opt_out_key) is True:
if vals.get(opt_out_next_visit_key) is True:
opt_out_of_domains.add(d)

tc = deepcopy(self.triggers)
for domain, link_triggers in tc['domain'].items():
if domain in opt_out_of_domains:
link_triggers[opt_out_key] = True
link_triggers[opt_out_next_visit_key] = True
opt_out_of_domains.remove(domain)
elif opt_out_key in link_triggers:
link_triggers.pop(opt_out_key)
elif opt_out_next_visit_key in link_triggers:
link_triggers.pop(opt_out_next_visit_key)

if opt_out_of_domains:
raise ValueError(
Expand All @@ -143,6 +145,27 @@ def hard_trigger_list(self):
results.append(domain)
return sorted(results)

def opted_out_domains(self):
"""Convenience function to return list of opted out previous visit domains
:returns: list of domains user opted out of on previous visit, or empty list.
"""
results = []
if not self.triggers:
return results

# need previous month triggers for this one
prev = self.query.filter(TriggerState.user_id == self.user_id).filter(
TriggerState.visit_month == self.visit_month - 1).filter(
TriggerState.state == 'resolved').first()
if not (prev and prev.triggers):
return results

for domain, link_triggers in prev.triggers['domain'].items():
if opt_out_next_visit_key in link_triggers:
results.append(domain)
return results

def reminder_due(self, as_of_date=None):
"""Determine if reminder is due from internal state"""
# locate first and most recent *staff* email
Expand Down
4 changes: 2 additions & 2 deletions tests/test_trigger_states.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,12 +182,12 @@ def test_worsening_baseline():


def test_apply_opt_out(initialized_patient, processed_ts, opt_out_submission):
from portal.trigger_states.models import opt_out_key
from portal.trigger_states.models import opt_out_next_visit_key
# apply opt out request
user = db.session.merge(initialized_patient)
ts = users_trigger_state(user.id)
result = ts.apply_opt_out(opt_out_submission)
found = [k for k,v in result.triggers['domain'].items() if opt_out_key in v]
found = [k for k,v in result.triggers['domain'].items() if opt_out_next_visit_key in v]
assert len(found) == 2


Expand Down

0 comments on commit d8b4caf

Please sign in to comment.