def test_expand_location_recipients_without_descendants(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'}) ) schedule.include_descendant_locations = False schedule.save() instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Location', recipient_id=self.country_location.location_id ) self.assertEqual( list(instance.expand_recipients()), [] ) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Location', recipient_id=self.state_location.location_id ) self.assertEqual( self.user_ids(instance.expand_recipients()), [self.mobile_user2.get_id] )
def test_case_group_recipient_with_user_data_filter(self): # The user data filter should have no effect here because all # the recipients are cases. schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'}) ) schedule.user_data_filter = {'role': ['nurse']} schedule.save() with create_case(self.domain, 'person') as case: case_group = CommCareCaseGroup(domain=self.domain, cases=[case.case_id]) case_group.save() self.addCleanup(case_group.delete) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type=ScheduleInstance.RECIPIENT_TYPE_CASE_GROUP, recipient_id=case_group.get_id, ) recipients = list(instance.expand_recipients()) self.assertEqual(len(recipients), 1) self.assertEqual(recipients[0].case_id, case.case_id)
def migrate_case_timed_schedule_instances(self): seen_case_ids = set() recipient = self.rule.memoized_actions[0].definition.recipients[0] for reminder in self.get_source_instances(): if reminder.case_id in seen_case_ids: self.source_duplicate_count += 1 continue seen_case_ids.add(reminder.case_id) instance = CaseTimedScheduleInstance( domain=self.rule.domain, recipient_type=recipient[0], recipient_id=recipient[1], current_event_num=reminder.current_event_sequence_num, schedule_iteration_num=reminder.schedule_iteration_num, next_event_due=reminder.next_fire, active=reminder.active, timed_schedule_id=self.schedule.schedule_id, start_date=reminder.start_date, case_id=reminder.case_id, rule_id=self.rule.pk, ) if reminder.active and reminder.error: self.schedule.move_to_next_event_not_in_the_past(instance) instance.save(force_insert=True)
def test_child_case_recipient(self): with create_case(self.domain, 'person') as child_1, \ create_case(self.domain, 'person') as child_2, \ create_case(self.domain, 'person') as parent: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=parent.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_ALL_CHILD_CASES) self.assertIsInstance(instance.recipient, list) self.assertEqual(len(instance.recipient), 0) set_parent_case(self.domain, child_1, parent, relationship='child', identifier='parent') set_parent_case(self.domain, child_2, parent, relationship='child', identifier='parent') instance = CaseTimedScheduleInstance( domain=self.domain, case_id=parent.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_ALL_CHILD_CASES) self.assertIsInstance(instance.recipient, list) self.assertEqual(len(instance.recipient), 2) self.assertItemsEqual([c.case_id for c in instance.recipient], [child_1.case_id, child_2.case_id])
def test_expand_group_recipients(self): instance = CaseTimedScheduleInstance(domain=self.domain, recipient_type='Group', recipient_id=self.group.get_id) self.assertEqual( self.user_ids(instance.expand_recipients()), [self.mobile_user.get_id] )
def test_email_case_property_recipient(self): with create_case(self.domain, 'person', owner_id=self.city_location.location_id, update={ 'recipient': '*****@*****.**', 'language_code': 'en', 'time_zone': 'sast' }) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_EMAIL, recipient_id='recipient') self.assertEqual(instance.recipient.get_email(), '*****@*****.**') self.assertEqual(instance.recipient.get_language_code(), 'en') self.assertEqual(instance.recipient.get_time_zone(), 'sast') # test that cases without the properties don't fail with create_case(self.domain, 'person', owner_id=self.city_location.location_id) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_EMAIL, recipient_id='recipient') self.assertIsNone(instance.recipient.get_email()) self.assertIsNone(instance.recipient.get_language_code()) self.assertIsNone(instance.recipient.get_time_zone())
def test_last_submitting_user_recipient(self): with create_test_case(self.domain, 'person', 'Joe', user_id=self.mobile_user.get_id) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_LAST_SUBMITTING_USER) self.assertTrue(isinstance(instance.recipient, CommCareUser)) self.assertEqual(instance.recipient.get_id, self.mobile_user.get_id) with create_test_case(self.domain, 'person', 'Joe', user_id=self.web_user.get_id) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_LAST_SUBMITTING_USER) self.assertTrue(isinstance(instance.recipient, WebUser)) self.assertEqual(instance.recipient.get_id, self.web_user.get_id) with create_test_case(self.domain, 'person', 'Joe', user_id='system') as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_LAST_SUBMITTING_USER) self.assertIsNone(instance.recipient)
def test_web_user_recipient_with_user_data_filter(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'}) ) schedule.user_data_filter = {'role': ['nurse']} schedule.save() instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type=ScheduleInstance.RECIPIENT_TYPE_WEB_USER, recipient_id=self.web_user.get_id, ) self.assertEqual(list(instance.expand_recipients()), []) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type=ScheduleInstance.RECIPIENT_TYPE_WEB_USER, recipient_id=self.web_user2.get_id, ) recipients = list(instance.expand_recipients()) self.assertEqual(len(recipients), 1) self.assertIsInstance(recipients[0], WebUser) self.assertEqual(recipients[0].get_id, self.web_user2.get_id)
def test_host_case_owner_location(self): with create_test_case(self.domain, 'test-extension-case', 'name') as extension_case: with create_test_case(self.domain, 'test-host-case', 'name') as host_case: update_case(self.domain, host_case.case_id, case_properties={ 'owner_id': self.city_location.location_id }) set_parent_case(self.domain, extension_case, host_case, relationship='extension') # Test the recipient is returned correctly instance = CaseTimedScheduleInstance( domain=self.domain, case_id=extension_case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CUSTOM, recipient_id='HOST_CASE_OWNER_LOCATION', ) self.assertIsInstance(instance.recipient, SQLLocation) self.assertEqual(instance.recipient.location_id, self.city_location.location_id) # Test location that does not exist update_case(self.domain, host_case.case_id, case_properties={'owner_id': 'does-not-exist'}) instance = CaseTimedScheduleInstance( domain=self.domain, case_id=extension_case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CUSTOM, recipient_id='HOST_CASE_OWNER_LOCATION', ) self.assertIsNone(instance.recipient) # Test on a case that is not an extension case instance = CaseTimedScheduleInstance( domain=self.domain, case_id=host_case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CUSTOM, recipient_id='HOST_CASE_OWNER_LOCATION', ) self.assertIsNone(instance.recipient) # Test with case id that doesn't exist instance = CaseTimedScheduleInstance( domain=self.domain, case_id='does-not-exist', recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CUSTOM, recipient_id='HOST_CASE_OWNER_LOCATION', ) self.assertIsNone(instance.recipient)
def test_parent_case_recipient(self): with create_case(self.domain, 'person') as child, create_case(self.domain, 'person') as parent: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=child.case_id, recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_PARENT_CASE) self.assertIsNone(instance.recipient) set_parent_case(self.domain, child, parent, relationship='child', identifier='parent') instance = CaseTimedScheduleInstance(domain=self.domain, case_id=child.case_id, recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_PARENT_CASE) self.assertEqual(instance.recipient.case_id, parent.case_id)
def test_expand_location_recipients(self): schedule_without_descendants = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'})) schedule_without_descendants.include_descendant_locations = False schedule_without_descendants.save() schedule_with_descendants = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'})) schedule_with_descendants.include_descendant_locations = True schedule_with_descendants.save() instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule_without_descendants.schedule_id, recipient_type='Location', recipient_id=self.city_location.location_id) self.assertEqual(self.user_ids(instance.expand_recipients()), [self.mobile_user.get_id]) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule_without_descendants.schedule_id, recipient_type='Location', recipient_id=self.state_location.location_id) self.assertEqual(list(instance.expand_recipients()), []) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule_with_descendants.schedule_id, recipient_type='Location', recipient_id=self.state_location.location_id) self.assertEqual(self.user_ids(instance.expand_recipients()), [self.mobile_user.get_id])
def test_expand_group_recipients(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'})) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Group', recipient_id=self.group.get_id) self.assertEqual(self.user_ids(instance.expand_recipients()), [self.mobile_user.get_id])
def test_mobile_worker_recipients_with_user_data_filter(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'})) schedule.user_data_filter = {'role': ['nurse']} schedule.save() instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Group', recipient_id=self.group2.get_id) self.assertEqual(self.user_ids(instance.expand_recipients()), [self.mobile_user4.get_id, self.mobile_user5.get_id])
def test_expand_location_recipients_with_location_type_filter(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'})) schedule.include_descendant_locations = True schedule.location_type_filter = [self.city_location.location_type_id] schedule.save() instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Location', recipient_id=self.country_location.location_id) self.assertItemsEqual(self.user_ids(instance.expand_recipients()), [self.mobile_user.get_id])
def create_case_timed_schedule_instance(self, domain, case_id): instance = CaseTimedScheduleInstance( domain=domain, recipient_type=CaseScheduleInstanceMixin.RECIPIENT_TYPE_SELF, current_event_num=0, schedule_iteration_num=1, next_event_due=datetime(2018, 7, 1), active=True, timed_schedule_id=uuid.uuid4(), start_date=date(2018, 7, 1), case_id=case_id, rule_id=1, ) instance.save() self.addCleanup(instance.delete)
def instance(case_id=''): # recipient is memoized return CaseTimedScheduleInstance( domain=self.domain, case_id=case_id or case.case_id, recipient_type='CustomRecipient', recipient_id='CASE_OWNER_LOCATION_PARENT')
def test_expand_group_recipients(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'}) ) instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Group', recipient_id=self.group.get_id ) self.assertEqual( self.user_ids(instance.expand_recipients()), [self.mobile_user.get_id] )
def test_case_recipient(self): with create_case(self.domain, 'person') as case: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=case.case_id, recipient_type='Self') self.assertTrue(is_commcarecase(instance.recipient)) self.assertEqual(instance.recipient.case_id, case.case_id)
def test_static_negative_growth_indicator(self): c = CustomContent( custom_content_id='ICDS_STATIC_NEGATIVE_GROWTH_MESSAGE') schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.child_health_case.case_id, ) c.set_context(schedule_instance=schedule_instance) # Test when current weight is greater than previous submit_growth_form(self.domain, self.child_health_case.case_id, '10.1', '10.4') self.assertEqual(c.get_list_of_messages(self.mother_person_case), []) # Test when current weight is equal to previous submit_growth_form(self.domain, self.child_health_case.case_id, '10.1', '10.1') self.assertEqual(c.get_list_of_messages(self.mother_person_case), [ "As per the latest records of your AWC, the weight of your child Joe has remained static in the last " "month. Please consult your AWW for necessary advice." ]) # Test when current weight is less than previous submit_growth_form(self.domain, self.child_health_case.case_id, '10.1', '9.9') self.assertEqual(c.get_list_of_messages(self.mother_person_case), [ "As per the latest records of your AWC, the weight of your child Joe has reduced in the last month. " "Please consult your AWW for necessary advice." ]) # Test ignoring forms with the wrong xmlns update_case(self.domain, self.child_health_case.case_id, {'property': 'value1'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value2'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value3'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value4'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value5'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value6'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value7'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value8'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value9'}) update_case(self.domain, self.child_health_case.case_id, {'property': 'value10'}) self.assertEqual(c.get_list_of_messages(self.mother_person_case), [ "As per the latest records of your AWC, the weight of your child Joe has reduced in the last month. " "Please consult your AWW for necessary advice." ])
def test_mobile_worker_recipients_with_user_data_filter(self): schedule = TimedSchedule.create_simple_daily_schedule( self.domain, TimedEvent(time=time(9, 0)), SMSContent(message={'en': 'Hello'}) ) schedule.user_data_filter = {'role': ['nurse']} schedule.save() instance = CaseTimedScheduleInstance( domain=self.domain, timed_schedule_id=schedule.schedule_id, recipient_type='Group', recipient_id=self.group2.get_id ) self.assertEqual( self.user_ids(instance.expand_recipients()), [self.mobile_user4.get_id, self.mobile_user5.get_id] )
def test_cf_visits_complete(self): schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.ccs_record_case.case_id, ) self.assertEqual( cf_visits_complete(self.user1, schedule_instance), ["Congratulations! You've done all the Complementary Feeding Visits for Sam"], )
def test_missed_pnc_visit_to_ls(self): schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.ccs_record_case.case_id, ) self.assertEqual( missed_pnc_visit_to_ls(self.user3, schedule_instance), ["AWC awc1 has not reported a visit during the PNC within one week of delivery for Sam"], )
def test_missed_cf_visit_to_ls(self): schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.ccs_record_case.case_id, ) self.assertEqual( missed_cf_visit_to_ls(self.user3, schedule_instance), ["AWC awc1 has not reported a visit during complementary feeding initiation period for Sam"], )
def test_owner_recipient(self): with create_case(self.domain, 'person', owner_id=self.city_location.location_id) as case: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=case.case_id, recipient_type='Owner') self.assertTrue(isinstance(instance.recipient, SQLLocation)) self.assertEqual(instance.recipient.location_id, self.city_location.location_id) with create_case(self.domain, 'person', owner_id=self.group.get_id) as case: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=case.case_id, recipient_type='Owner') self.assertTrue(isinstance(instance.recipient, Group)) self.assertEqual(instance.recipient.get_id, self.group.get_id) with create_case(self.domain, 'person', owner_id=self.mobile_user.get_id) as case: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=case.case_id, recipient_type='Owner') self.assertTrue(isinstance(instance.recipient, CommCareUser)) self.assertEqual(instance.recipient.get_id, self.mobile_user.get_id) with create_case(self.domain, 'person', owner_id=self.web_user.get_id) as case: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=case.case_id, recipient_type='Owner') self.assertTrue(isinstance(instance.recipient, WebUser)) self.assertEqual(instance.recipient.get_id, self.web_user.get_id) with create_case(self.domain, 'person') as case: instance = CaseTimedScheduleInstance(domain=self.domain, case_id=case.case_id, recipient_type='Owner') self.assertIsNone(instance.recipient)
def test_child_illness_reported(self): schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.child_person_case.case_id, ) self.assertEqual( child_illness_reported(self.user3, schedule_instance), ["AWC awc1 has reported illness for the child Joe. Please ensure that AWW follows up with mother " "immediately"], )
def create_new_instance_for_recipient(self, recipient_type, recipient_id): return CaseTimedScheduleInstance.create_for_recipient( self.schedule, recipient_type, recipient_id, start_date=self.start_date, move_to_next_event_not_in_the_past=True, case_id=self.case.case_id, rule_id=self.rule.pk, last_reset_case_property_value=self.reset_case_property_value, schedule_revision=self.schedule_revision, )
def test_static_negative_growth_indicator_with_red_status(self): schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.red_child_health_case.case_id, ) # Current weight is less than previous, but grade is red, so no messages are sent submit_growth_form(self.domain, self.red_child_health_case.case_id, '10.1', '9.9') self.assertEqual( static_negative_growth_indicator(self.mother_person_case, schedule_instance), [] )
def test_username_case_property_recipient(self): # test valid username with create_case(self.domain, 'person', owner_id=self.city_location.location_id, update={'recipient': 'mobile'}) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_USER, recipient_id='recipient') self.assertEqual(instance.recipient.get_id, self.full_mobile_user.get_id) # test invalid username with create_case(self.domain, 'person', owner_id=self.city_location.location_id, update={'recipient': 'mobile10'}) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_USER, recipient_id='recipient') self.assertIsNone(instance.recipient) # test no username with create_case(self.domain, 'person', owner_id=self.city_location.location_id) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_USER, recipient_id='recipient') self.assertIsNone(instance.recipient)
def test_child_vaccinations_complete(self, language_code_patch): c = CustomContent(custom_content_id='ICDS_CHILD_VACCINATIONS_COMPLETE') schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.child_tasks_case.case_id, ) language_code_patch.return_value = ENGLISH self.assertEqual( c.get_list_of_messages(self.user1, schedule_instance), ["Congratulations! You've given all the vaccines to Joe"], )
def test_email_case_property_recipient(self): with create_case(self.domain, 'person', owner_id=self.city_location.location_id, update={'recipient': '*****@*****.**'}) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_EMAIL, recipient_id='recipient') self.assertEqual(instance.recipient.get_email(), '*****@*****.**') with create_case(self.domain, 'person', owner_id=self.city_location.location_id) as case: instance = CaseTimedScheduleInstance( domain=self.domain, case_id=case.case_id, recipient_type=CaseScheduleInstanceMixin. RECIPIENT_TYPE_CASE_PROPERTY_EMAIL, recipient_id='recipient') self.assertIsNone(instance.recipient.get_email())
def test_cf_visits_complete(self, language_code_patch): c = CustomContent(custom_content_id='ICDS_CF_VISITS_COMPLETE') schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.ccs_record_case.case_id, ) language_code_patch.return_value = ENGLISH self.assertEqual( c.get_list_of_messages(self.user1, schedule_instance), [ "Congratulations! You've done all the Complementary Feeding Visits for Sam" ], )
def test_missed_pnc_visit_to_ls(self, language_code_patch): c = CustomContent(custom_content_id='ICDS_MISSED_PNC_VISIT_TO_LS') schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.ccs_record_case.case_id, ) language_code_patch.return_value = ENGLISH self.assertEqual( c.get_list_of_messages(self.user3, schedule_instance), [ "AWC awc1 has not reported a visit during the PNC within one week of delivery for Sam" ], )
def test_missed_cf_visit_to_ls(self, language_code_patch): c = CustomContent(custom_content_id='ICDS_MISSED_CF_VISIT_TO_LS') schedule_instance = CaseTimedScheduleInstance( domain=self.domain, case_id=self.ccs_record_case.case_id, ) language_code_patch.return_value = ENGLISH self.assertEqual( c.get_list_of_messages(self.user3, schedule_instance), [ "AWC awc1 has not reported a visit during complementary feeding initiation period for Sam" ], )
def create_new_instance_for_recipient(self, recipient_type, recipient_id): start_date = self.start_date if not start_date and self.model_instance: start_date = self.model_instance.start_date return CaseTimedScheduleInstance.create_for_recipient( self.schedule, recipient_type, recipient_id, start_date=start_date, move_to_next_event_not_in_the_past=True, case_id=self.case.case_id, rule_id=self.rule.pk, last_reset_case_property_value=self.reset_case_property_value, schedule_revision=self.schedule_revision, )