diff --git a/portal/trigger_states/empro_states.py b/portal/trigger_states/empro_states.py index b20927882..e9798445e 100644 --- a/portal/trigger_states/empro_states.py +++ b/portal/trigger_states/empro_states.py @@ -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 @@ -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) @@ -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: @@ -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( diff --git a/portal/trigger_states/models.py b/portal/trigger_states/models.py index 300c2aff5..e943b0934 100644 --- a/portal/trigger_states/models.py +++ b/portal/trigger_states/models.py @@ -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', @@ -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( @@ -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 diff --git a/tests/test_trigger_states.py b/tests/test_trigger_states.py index f190ec46a..df35beaed 100644 --- a/tests/test_trigger_states.py +++ b/tests/test_trigger_states.py @@ -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