def make_email_event_for_test(domain, schedule_name, user_ids, utcnow=None): content = EmailContent( subject={'*': 'New messaging API goes live!'}, message={'*': 'Check out the new API.'}, ) schedule = AlertSchedule.create_simple_alert(domain, content) broadcast = ImmediateBroadcast.objects.create( domain=domain, name=schedule_name, schedule=schedule, recipients=[(ScheduleInstance.RECIPIENT_TYPE_MOBILE_WORKER, user_id) for user_id in user_ids], ) for user_id in user_ids: instance = AlertScheduleInstance.create_for_recipient( schedule, ScheduleInstance.RECIPIENT_TYPE_MOBILE_WORKER, user_id, move_to_next_event_not_in_the_past=False, ) instance.send_current_event_content_to_recipients() subevents = {} for event in MessagingEvent.objects.filter(source_id=broadcast.id): for subevent in MessagingSubEvent.objects.filter(parent=event): handle_email_messaging_subevent( { "eventType": "Delivery", "delivery": { "timestamp": "2021-05-27T07:09:42.318Z" } }, subevent.id) subevents[subevent.recipient_id] = subevent return subevents
def migrate_custom_alert_schedule(handler): return AlertSchedule.create_custom_alert( handler.domain, [(get_event(handler, event), get_content(handler, event)) for event in handler.events], extra_options=get_extra_scheduling_options(handler), )
def post(self, request, *args, **kwargs): if self.async_response is not None: return self.async_response if self.message_form.is_valid(): # TODO editing should not create a new one values = self.message_form.cleaned_data if values['send_frequency'] == 'immediately': if values['translate']: messages = {} for lang in self.project_languages: key = 'message_%s' % lang if key in values: messages[lang] = values[key] content = SMSContent(message=messages) else: content = SMSContent(message={'*': values['non_translated_message']}) with transaction.atomic(): schedule = AlertSchedule.create_simple_alert(self.domain, content) broadcast = ImmediateBroadcast( domain=self.domain, name=values['schedule_name'], schedule=schedule ) broadcast.save() recipients = [('CommCareUser', r_id) for r_id in values['recipients']] refresh_alert_schedule_instances.delay(schedule, recipients) return HttpResponseRedirect(reverse(BroadcastListView.urlname, args=[self.domain])) return self.get(request, *args, **kwargs)
def _add_custom_immediate_rule(self, content_list): event_and_content_objects = [(AlertEvent(minutes_to_wait=i * 10), content) for i, content in enumerate(content_list)] schedule = AlertSchedule.create_custom_alert( self.domain, event_and_content_objects) return self._add_rule(alert_schedule_id=schedule.schedule_id)
def test_run_messaging_rule(self, task_patch): schedule = AlertSchedule.create_simple_alert( self.domain, SMSContent(message={'en': 'Hello'}) ) rule = create_empty_rule(self.domain, AutomaticUpdateRule.WORKFLOW_SCHEDULING) rule.add_action( CreateScheduleInstanceActionDefinition, alert_schedule_id=schedule.schedule_id, recipients=(('Self', None),), ) AutomaticUpdateRule.clear_caches(self.domain, AutomaticUpdateRule.WORKFLOW_SCHEDULING) with create_case(self.domain, 'person') as case1, create_case(self.domain, 'person') as case2: run_messaging_rule(self.domain, rule.pk) self.assertEqual(task_patch.call_count, 2) task_patch.assert_has_calls( [ call(self.domain, case1.case_id, rule.pk), call(self.domain, case2.case_id, rule.pk), ], any_order=True )
def create_immediate_broadcast(self, domain, content): schedule = AlertSchedule.create_simple_alert(domain, content) return ImmediateBroadcast.objects.create( domain=domain, name='', schedule=schedule, recipients=[['CommCareUser', uuid.uuid4().hex]], )
def setUpClass(cls): super(AlertTest, cls).setUpClass() cls.domain = 'alert-test' cls.domain_obj = Domain(name=cls.domain, default_timezone='America/New_York') cls.domain_obj.save() cls.user1 = CommCareUser.create(cls.domain, 'user1', 'password') cls.user2 = CommCareUser.create(cls.domain, 'user2', 'password') cls.schedule = AlertSchedule.create_simple_alert(cls.domain, SMSContent())
def create_conditional_alert(self, domain, content): schedule = AlertSchedule.create_simple_alert(domain, content) rule = create_empty_rule(domain, AutomaticUpdateRule.WORKFLOW_SCHEDULING) rule.add_action( CreateScheduleInstanceActionDefinition, alert_schedule_id=schedule.schedule_id, recipients=[['CommCareUser', uuid.uuid4().hex]], ) return rule
def test_alert_schedule_instance_creation(self, utcnow_patch): schedule = AlertSchedule.create_simple_alert( self.domain, SMSContent(message={'en': 'Hello'}) ) rule = create_empty_rule(self.domain, AutomaticUpdateRule.WORKFLOW_SCHEDULING) rule.add_criteria( MatchPropertyDefinition, property_name='start_sending', property_value='Y', match_type=MatchPropertyDefinition.MATCH_EQUAL, ) rule.add_action( CreateScheduleInstanceActionDefinition, alert_schedule_id=schedule.schedule_id, recipients=(('CommCareUser', self.user.get_id),) ) AutomaticUpdateRule.clear_caches(self.domain, AutomaticUpdateRule.WORKFLOW_SCHEDULING) utcnow_patch.return_value = datetime(2017, 5, 1, 7, 0) with create_case(self.domain, 'person') as case: # Rule does not match, no instances created instances = get_case_alert_schedule_instances_for_schedule(case.case_id, schedule) self.assertEqual(instances.count(), 0) # Make the rule match. On the first iteration, the instance is created. On the second, # no new instance is created since it already exists. for minute in range(1, 3): utcnow_patch.return_value = datetime(2017, 5, 1, 7, minute) update_case(self.domain, case.case_id, case_properties={'start_sending': 'Y'}) instances = get_case_alert_schedule_instances_for_schedule(case.case_id, schedule) self.assertEqual(instances.count(), 1) self.assertEqual(instances[0].case_id, case.case_id) self.assertEqual(instances[0].rule_id, rule.pk) self.assertEqual(instances[0].alert_schedule_id, schedule.schedule_id) self.assertEqual(instances[0].domain, self.domain) self.assertEqual(instances[0].recipient_type, 'CommCareUser') self.assertEqual(instances[0].recipient_id, self.user.get_id) self.assertEqual(instances[0].current_event_num, 0) self.assertEqual(instances[0].schedule_iteration_num, 1) self.assertEqual(instances[0].next_event_due, datetime(2017, 5, 1, 7, 1)) self.assertTrue(instances[0].active) # Make the rule not match. Instance should no longer exist. utcnow_patch.return_value = datetime(2017, 5, 1, 7, 3) update_case(self.domain, case.case_id, case_properties={'start_sending': 'N'}) instances = get_case_alert_schedule_instances_for_schedule(case.case_id, schedule) self.assertEqual(instances.count(), 0)
def migrate_past_immediate_broadcast(handler): schedule = AlertSchedule.create_simple_alert( handler.domain, get_content(handler, handler.events[0], translated=False), extra_options=get_extra_scheduling_options(handler, translated=False), ) broadcast = ImmediateBroadcast.objects.create( domain=handler.domain, name=handler.nickname, last_sent_timestamp=handler.start_datetime, schedule=schedule, recipients=get_broadcast_recipients(handler), ) return broadcast, schedule
def test_sms_content(self): from corehq.messaging.scheduling.models import AlertSchedule, SMSContent, AlertEvent from corehq.messaging.scheduling.scheduling_partitioned.dbaccessors import \ delete_alert_schedule_instances_for_schedule schedule = AlertSchedule.create_simple_alert(self.domain, SMSContent()) schedule.set_custom_alert( [ (AlertEvent(minutes_to_wait=5), SMSContent()), (AlertEvent(minutes_to_wait=15), SMSContent()), ] ) self.addCleanup(lambda: delete_alert_schedule_instances_for_schedule(AlertScheduleInstance, schedule.schedule_id)) self._dump_and_load(Counter({AlertSchedule: 1, AlertEvent: 2, SMSContent: 2}))
def test_get_alert_schedule_instances_for_schedule(self): self.assertEqual( set( get_alert_schedule_instances_for_schedule( AlertSchedule(schedule_id=self.schedule_id1))), set([self.alert_instance2, self.alert_instance3]))
def _add_immediate_rule(self, content): schedule = AlertSchedule.create_simple_alert(self.domain, content) return self._add_rule(alert_schedule_id=schedule.schedule_id)
def handle(self, domain, filename, **options): domain_obj = Domain.get_by_name(domain) if domain_obj is None: raise CommandError("Project space '%s' not found" % domain) if not project_is_on_new_reminders(domain_obj): raise CommandError( "Project space '%s' does not have new reminders enabled" % domain) json_rules = [] with open_for_json_read(filename) as f: for line in f: json_rules.append(json.loads(line)) print("Importing %s rules..." % len(json_rules)) rules = [] with transaction.atomic(): for entry in json_rules: json_rule = SimpleSchedulingRule(entry['rule']) schedule_type = entry['schedule']['schedule_type'] if schedule_type == SIMPLE_SMS_DAILY_SCHEDULE_WITH_TIME: json_schedule = SimpleSMSDailyScheduleWithTime( entry['schedule']) schedule = TimedSchedule.create_simple_daily_schedule( domain, TimedEvent(time=json_schedule.time), SMSContent(message=json_schedule.message), total_iterations=json_schedule.total_iterations, start_offset=json_schedule.start_offset, start_day_of_week=json_schedule.start_day_of_week, extra_options=json_schedule.extra_options.to_json(), repeat_every=json_schedule.repeat_every, ) elif schedule_type == SIMPLE_SMS_ALERT_SCHEDULE: json_schedule = SimpleSMSAlertSchedule(entry['schedule']) schedule = AlertSchedule.create_simple_alert( domain, SMSContent(message=json_schedule.message), extra_options=json_schedule.extra_options.to_json(), ) else: raise CommandError("Unexpected schedule_type: %s" % schedule_type) rule = AutomaticUpdateRule.objects.create( domain=domain, name=json_rule.name, case_type=json_rule.case_type, active=True, filter_on_server_modified=False, workflow=AutomaticUpdateRule.WORKFLOW_SCHEDULING, ) for criterion in json_rule.criteria: rule.add_criteria( MatchPropertyDefinition, property_name=criterion.property_name, property_value=criterion.property_value, match_type=criterion.match_type, ) rule.add_action( CreateScheduleInstanceActionDefinition, alert_schedule_id=schedule.schedule_id if isinstance( schedule, AlertSchedule) else None, timed_schedule_id=schedule.schedule_id if isinstance( schedule, TimedSchedule) else None, recipients=json_rule.recipients, reset_case_property_name=json_rule. reset_case_property_name, start_date_case_property=json_rule. start_date_case_property, specific_start_date=json_rule.specific_start_date, scheduler_module_info=json_rule.scheduler_module_info. to_json(), ) rules.append(rule) print("Import complete. Starting instance refresh tasks...") for rule in rules: initiate_messaging_rule_run(rule.domain, rule.pk) print("Done.")
def migrate_simple_alert_schedule(handler): return AlertSchedule.create_simple_alert( handler.domain, get_content(handler, handler.events[0]), extra_options=get_extra_scheduling_options(handler), )
def test_get_alert_schedule_instances_for_schedule(self): self.assertItemsEqual( get_alert_schedule_instances_for_schedule( AlertSchedule(schedule_id=self.schedule_id1)), [self.alert_instance2_p2, self.alert_instance3_p1])
def handle(self, domain, filename, **options): domain_obj = Domain.get_by_name(domain) if domain_obj is None: raise CommandError("Project space '%s' not found" % domain) json_rules = [] with open_for_json_read(filename) as f: for line in f: json_rules.append(json.loads(line)) print("Importing %s rules..." % len(json_rules)) rules = [] with transaction.atomic(): for entry in json_rules: json_rule = SimpleSchedulingRule(entry['rule']) schedule_type = entry['schedule']['schedule_type'] if schedule_type == SIMPLE_SMS_DAILY_SCHEDULE_WITH_TIME: json_schedule = SimpleSMSDailyScheduleWithTime(entry['schedule']) schedule = TimedSchedule.create_simple_daily_schedule( domain, TimedEvent(time=json_schedule.time), SMSContent(message=json_schedule.message), total_iterations=json_schedule.total_iterations, start_offset=json_schedule.start_offset, start_day_of_week=json_schedule.start_day_of_week, extra_options=json_schedule.extra_options.to_json(), repeat_every=json_schedule.repeat_every, ) elif schedule_type == SIMPLE_SMS_ALERT_SCHEDULE: json_schedule = SimpleSMSAlertSchedule(entry['schedule']) schedule = AlertSchedule.create_simple_alert( domain, SMSContent(message=json_schedule.message), extra_options=json_schedule.extra_options.to_json(), ) else: raise CommandError("Unexpected schedule_type: %s" % schedule_type) rule = AutomaticUpdateRule.objects.create( domain=domain, name=json_rule.name, case_type=json_rule.case_type, active=True, filter_on_server_modified=False, workflow=AutomaticUpdateRule.WORKFLOW_SCHEDULING, ) for criterion in json_rule.criteria: rule.add_criteria( MatchPropertyDefinition, property_name=criterion.property_name, property_value=criterion.property_value, match_type=criterion.match_type, ) rule.add_action( CreateScheduleInstanceActionDefinition, alert_schedule_id=schedule.schedule_id if isinstance(schedule, AlertSchedule) else None, timed_schedule_id=schedule.schedule_id if isinstance(schedule, TimedSchedule) else None, recipients=json_rule.recipients, reset_case_property_name=json_rule.reset_case_property_name, start_date_case_property=json_rule.start_date_case_property, specific_start_date=json_rule.specific_start_date, scheduler_module_info=json_rule.scheduler_module_info.to_json(), ) rules.append(rule) print("Import complete. Starting instance refresh tasks...") for rule in rules: initiate_messaging_rule_run(rule.domain, rule.pk) print("Done.")