def run_case_update_rules_for_domain(domain, now=None): now = now or datetime.utcnow() start_run = datetime.utcnow() all_rules = AutomaticUpdateRule.by_domain(domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(all_rules) for case_type, rules in rules_by_case_type.iteritems(): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_id_chunks = AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date) for case_ids in case_id_chunks: for case in CaseAccessors(domain).iter_cases(case_ids): time_elapsed = datetime.utcnow() - start_run if time_elapsed.seconds > HALT_AFTER: notify_error( "Halting rule run for domain %s as it's been running for more than a day." % domain ) return for rule in rules: stop_processing = rule.apply_rule(case, now) if stop_processing: break for rule in rules: rule.last_run = now rule.save()
def run_case_update_rules_for_domain(domain, now=None): now = now or datetime.utcnow() domain_rules = AutomaticUpdateRule.by_domain( domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE) all_rule_case_types = set(domain_rules.values_list('case_type', flat=True)) for case_type in all_rule_case_types: run_record = DomainCaseRuleRun.objects.create( domain=domain, started_on=datetime.utcnow(), status=DomainCaseRuleRun.STATUS_RUNNING, case_type=case_type) if should_use_sql_backend(domain): for db in get_db_aliases_for_partitioned_query(): run_case_update_rules_for_domain_and_db.delay(domain, now, run_record.pk, case_type, db=db) else: # explicitly pass db=None so that the serial task decorator has access to db in the key generation run_case_update_rules_for_domain_and_db.delay(domain, now, run_record.pk, case_type, db=None)
def response_data_cleanup(domain, new_plan_version): """ Any active automatic case update rules should be deactivated. """ try: AutomaticUpdateRule.by_domain( domain.name, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, ).update(active=False) AutomaticUpdateRule.clear_caches( domain.name, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE) return True except Exception: log_accounting_error("Failed to deactivate automatic update rules " "for domain %s." % domain.name) return False
def test_get_rules_from_domain(self): rules = AutomaticUpdateRule.by_domain(self.domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type( rules) expected_case_types = [ 'test-case-type', 'test-case-type-2', 'test-case-type-3' ] actual_case_types = rules_by_case_type.keys() self.assertEqual(set(expected_case_types), set(actual_case_types)) expected_rule_ids = [self.rule.pk, self.rule4.pk] actual_rule_ids = [ rule.pk for rule in rules_by_case_type['test-case-type'] ] self.assertEqual(set(expected_rule_ids), set(actual_rule_ids)) expected_rule_ids = [self.rule2.pk, self.rule3.pk] actual_rule_ids = [ rule.pk for rule in rules_by_case_type['test-case-type-2'] ] self.assertEqual(set(expected_rule_ids), set(actual_rule_ids)) expected_rule_ids = [self.rule5.pk] actual_rule_ids = [ rule.pk for rule in rules_by_case_type['test-case-type-3'] ] self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))
def get_pagination_data(self, in_data): try: limit = int(in_data['limit']) page = int(in_data['page']) except (TypeError, KeyError, ValueError): return { 'success': False, 'error': _("Please provide pagination info."), } start = (page - 1) * limit stop = limit * page rules = AutomaticUpdateRule.by_domain( self.domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, active_only=False, ) rule_page = rules.order_by('name')[start:stop] total = rules.count() return { 'response': { 'itemList': map(self._format_rule, rule_page), 'total': total, 'page': page, }, 'success': True, }
def response_data_cleanup(domain, new_plan_version): """ Any active automatic case update rules should be deactivated. """ try: AutomaticUpdateRule.by_domain( domain.name, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, ).update(active=False) AutomaticUpdateRule.clear_caches(domain.name, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE) return True except Exception: log_accounting_error( "Failed to deactivate automatic update rules " "for domain %s." % domain.name ) return False
def _get_active_scheduling_rules(domain, survey_only=False): rules = AutomaticUpdateRule.by_domain(domain.name, AutomaticUpdateRule.WORKFLOW_SCHEDULING, active_only=False) result = [] for rule in rules: schedule = rule.get_messaging_rule_schedule() if schedule.active and (not survey_only or schedule.memoized_uses_sms_survey): result.append(rule) return result
def get_auto_update_rules(domain): rules = AutomaticUpdateRule.by_domain( domain, # For now only grab those rules that update cases, not conditional alerts for messaging AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, active_only=False) data = [] for rule in rules: criterias = rule.caserulecriteria_set.all() actions = rule.caseruleaction_set.all() rule_data = { "rule": rule.to_json(), "criteria": [{ "match_property_definition": { "property_name": case_rule_criter.match_property_definition.property_name, "property_value": case_rule_criter.match_property_definition.property_value, "match_type": case_rule_criter.match_property_definition.match_type } if case_rule_criter.match_property_definition is not None else None, "custom_match_definition": { "name": case_rule_criter.custom_match_definition.name, } if case_rule_criter.custom_match_definition is not None else None, "closed_parent_definition": case_rule_criter.closed_parent_definition is not None } for case_rule_criter in criterias], "actions": [{ "update_case_definition": { "properties_to_update": case_rule_action.update_case_definition. properties_to_update, "close_case": case_rule_action.update_case_definition.close_case } if case_rule_action.update_case_definition is not None else None, "custom_action_definition": { "name": case_rule_action.custom_action_definition.name } if case_rule_action.custom_action_definition is not None else None, } for case_rule_action in actions] } # Delete unnecessary data for running rules del rule_data['rule']['last_run'] del rule_data['rule']['locked_for_editing'] data.append(rule_data) return data
def test_boundary_date(self): rules = AutomaticUpdateRule.by_domain(self.domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules) boundary_date = AutomaticUpdateRule.get_boundary_date( rules_by_case_type['test-case-type'], datetime(2016, 1, 1)) self.assertEqual(boundary_date, datetime(2015, 12, 2)) boundary_date = AutomaticUpdateRule.get_boundary_date( rules_by_case_type['test-case-type-2'], datetime(2016, 1, 1)) self.assertEqual(boundary_date, datetime(2015, 12, 2))
def test_boundary_date(self): rules = AutomaticUpdateRule.by_domain(self.domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type( rules) boundary_date = AutomaticUpdateRule.get_boundary_date( rules_by_case_type['test-case-type'], datetime(2016, 1, 1)) self.assertEqual(boundary_date, datetime(2015, 12, 2)) boundary_date = AutomaticUpdateRule.get_boundary_date( rules_by_case_type['test-case-type-2'], datetime(2016, 1, 1)) self.assertEqual(boundary_date, datetime(2015, 12, 2))
def run_case_update_rules_on_save(case): key = 'case-update-on-save-case-{case}'.format(case=case.case_id) with CriticalSection([key]): update_case = True if case.xform_ids: last_form = FormAccessors(case.domain).get_form(case.xform_ids[-1]) update_case = last_form.xmlns != AUTO_UPDATE_XMLNS if update_case: rules = AutomaticUpdateRule.by_domain(case.domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE).filter(case_type=case.type) now = datetime.utcnow() run_rules_for_case(case, rules, now)
def run_case_update_rules_for_domain_and_db(domain, now, run_id, db=None): domain_obj = Domain.get_by_name(domain) max_allowed_updates = domain_obj.auto_case_update_limit or settings.MAX_RULE_UPDATES_IN_ONE_RUN start_run = datetime.utcnow() last_migration_check_time = None cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = list( AutomaticUpdateRule.by_domain( domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE)) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type( all_rules) for case_type, rules in six.iteritems(rules_by_case_type): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = list( AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date, db=db)) for case in CaseAccessors(domain).iter_cases(case_ids): migration_in_progress, last_migration_check_time = check_data_migration_in_progress( domain, last_migration_check_time) time_elapsed = datetime.utcnow() - start_run if (time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= max_allowed_updates or migration_in_progress): DomainCaseRuleRun.done(run_id, DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result, db=db) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 run = DomainCaseRuleRun.done(run_id, DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result, db=db) if run.status == DomainCaseRuleRun.STATUS_FINISHED: for rule in all_rules: AutomaticUpdateRule.objects.filter(pk=rule.pk).update(last_run=now)
def run_case_update_rules_on_save(case): key = 'case-update-on-save-case-{case}'.format(case=case.case_id) with CriticalSection([key]): update_case = True if case.xform_ids: last_form = FormAccessors(case.domain).get_form(case.xform_ids[-1]) update_case = last_form.xmlns != AUTO_UPDATE_XMLNS if update_case: rules = AutomaticUpdateRule.by_domain(case.domain).filter(case_type=case.type) now = datetime.utcnow() for rule in rules: stop_processing = rule.apply_rule(case, now) if stop_processing: break
def test_get_rules_from_domain(self): rules = AutomaticUpdateRule.by_domain(self.domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules) expected_case_types = ['test-case-type', 'test-case-type-2'] actual_case_types = rules_by_case_type.keys() self.assertEqual(set(expected_case_types), set(actual_case_types)) expected_rule_ids = [self.rule.pk] actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type']] self.assertEqual(set(expected_rule_ids), set(actual_rule_ids)) expected_rule_ids = [self.rule2.pk, self.rule3.pk] actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type-2']] self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))
def run_case_update_rules_for_domain(domain, now=None): domain_obj = Domain.get_by_name(domain) max_allowed_updates = domain_obj.auto_case_update_limit or settings.MAX_RULE_UPDATES_IN_ONE_RUN now = now or datetime.utcnow() start_run = datetime.utcnow() last_migration_check_time = None run_record = DomainCaseRuleRun.objects.create( domain=domain, started_on=start_run, status=DomainCaseRuleRun.STATUS_RUNNING, ) cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = AutomaticUpdateRule.by_domain( domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type( all_rules) for case_type, rules in six.iteritems(rules_by_case_type): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = list( AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date)) for case in CaseAccessors(domain).iter_cases(case_ids): migration_in_progress, last_migration_check_time = check_data_migration_in_progress( domain, last_migration_check_time) time_elapsed = datetime.utcnow() - start_run if (time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= max_allowed_updates or migration_in_progress): run_record.done(DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 for rule in rules: rule.last_run = now rule.save() run_record.done(DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result)
def run_case_update_rules_for_domain(domain, now=None): now = now or datetime.utcnow() all_rules = AutomaticUpdateRule.by_domain(domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(all_rules) for case_type, rules in rules_by_case_type.iteritems(): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = AutomaticUpdateRule.get_case_ids(domain, boundary_date, case_type) for doc in iter_docs(CommCareCase.get_db(), case_ids): case = CommCareCase.wrap(doc) for rule in rules: rule.apply_rule(case, now) for rule in rules: rule.last_run = now rule.save()
def run_case_update_rules_for_domain(domain, now=None): now = now or datetime.utcnow() all_rules = AutomaticUpdateRule.by_domain(domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(all_rules) for case_type, rules in rules_by_case_type.iteritems(): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date) for case in CaseAccessors(domain).iter_cases(case_ids): for rule in rules: stop_processing = rule.apply_rule(case, now) if stop_processing: break for rule in rules: rule.last_run = now rule.save()
def response_data_cleanup(domain, new_plan_version): """ Any active automatic case update rules should be deactivated. """ rule_count = AutomaticUpdateRule.by_domain( domain.name, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, ).count() if rule_count > 0: return _fmt_alert( ungettext( "You have %(rule_count)d automatic case update rule " "configured in your project. If you select this plan, " "this rule will be deactivated.", "You have %(rule_count)d automatic case update rules " "configured in your project. If you select this plan, " "these rules will be deactivated.", rule_count) % { 'rule_count': rule_count, })
def handle(self, domain, **options): result = [] for rule in AutomaticUpdateRule.by_domain( domain, AutomaticUpdateRule.WORKFLOW_SCHEDULING, active_only=False, ): json_rule = self.get_json_rule(rule) action = rule.memoized_actions[0].definition if action.schedule.location_type_filter: raise CommandError( "Expected location_type_filter to be empty for rule %s. Location type filtering " "references primary keys of LocationType objects which aren't guaranteed to be " "the same in the imported project. This rule must be excluded from export." % rule.pk) if isinstance(action.schedule, TimedSchedule): json_schedule = self.get_json_timed_schedule(action.schedule) elif isinstance(action.schedule, AlertSchedule): json_schedule = self.get_json_alert_schedule(action.schedule) else: raise CommandError( "Unexpected Schedule type for rule %s. Support must be added to this script for " "anything other than TimedSchedules or AlertSchedules." % rule.pk) result.append( json.dumps({ 'rule': json_rule.to_json(), 'schedule': json_schedule.to_json(), })) with open('conditional_alerts_for_%s.txt' % domain, 'w', encoding='utf-8') as f: for line in result: f.write(line) f.write('\n') print("Done")
def run_case_update_rules_for_domain_and_db(domain, now, run_id, db=None): domain_obj = Domain.get_by_name(domain) max_allowed_updates = domain_obj.auto_case_update_limit or settings.MAX_RULE_UPDATES_IN_ONE_RUN start_run = datetime.utcnow() last_migration_check_time = None cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = list(AutomaticUpdateRule.by_domain(domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE)) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(all_rules) for case_type, rules in six.iteritems(rules_by_case_type): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_ids = list(AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date, db=db)) for case in CaseAccessors(domain).iter_cases(case_ids): migration_in_progress, last_migration_check_time = check_data_migration_in_progress(domain, last_migration_check_time) time_elapsed = datetime.utcnow() - start_run if ( time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= max_allowed_updates or migration_in_progress ): DomainCaseRuleRun.done(run_id, DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result, db=db) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 run = DomainCaseRuleRun.done(run_id, DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result, db=db) if run.status == DomainCaseRuleRun.STATUS_FINISHED: for rule in all_rules: AutomaticUpdateRule.objects.filter(pk=rule.pk).update(last_run=now)
def response_data_cleanup(domain, new_plan_version): """ Any active automatic case update rules should be deactivated. """ rule_count = AutomaticUpdateRule.by_domain( domain.name, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, ).count() if rule_count > 0: return _fmt_alert( ungettext( "You have %(rule_count)d automatic case update rule " "configured in your project. If you select this plan, " "this rule will be deactivated.", "You have %(rule_count)d automatic case update rules " "configured in your project. If you select this plan, " "these rules will be deactivated.", rule_count ) % { 'rule_count': rule_count, } )
def run_case_update_rules_for_domain(domain, now=None): now = now or datetime.utcnow() start_run = datetime.utcnow() run_record = DomainCaseRuleRun.objects.create( domain=domain, started_on=start_run, status=DomainCaseRuleRun.STATUS_RUNNING, ) cases_checked = 0 case_update_result = CaseRuleActionResult() all_rules = AutomaticUpdateRule.by_domain(domain) rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(all_rules) for case_type, rules in rules_by_case_type.iteritems(): boundary_date = AutomaticUpdateRule.get_boundary_date(rules, now) case_id_chunks = AutomaticUpdateRule.get_case_ids(domain, case_type, boundary_date) for case_ids in case_id_chunks: for case in CaseAccessors(domain).iter_cases(case_ids): time_elapsed = datetime.utcnow() - start_run if ( time_elapsed.seconds > HALT_AFTER or case_update_result.total_updates >= settings.MAX_RULE_UPDATES_IN_ONE_RUN ): run_record.done(DomainCaseRuleRun.STATUS_HALTED, cases_checked, case_update_result) notify_error("Halting rule run for domain %s." % domain) return case_update_result.add_result(run_rules_for_case(case, rules, now)) cases_checked += 1 for rule in rules: rule.last_run = now rule.save() run_record.done(DomainCaseRuleRun.STATUS_FINISHED, cases_checked, case_update_result)
def _rules(self): return AutomaticUpdateRule.by_domain( self.domain, self.rule_workflow, active_only=False, ).order_by('name', 'id')
def update_auto_update_rules(domain_link): if domain_link.is_remote: upstream_rules = remote_get_auto_update_rules(domain_link) else: upstream_rules = local_get_auto_update_rules(domain_link.master_domain) downstream_rules = AutomaticUpdateRule.by_domain( domain_link.linked_domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, active_only=False ) for upstream_rule_def in upstream_rules: # Grab local rule by upstream ID (preferred) or by name try: downstream_rule = downstream_rules.get(upstream_id=upstream_rule_def['rule']['id']) except AutomaticUpdateRule.DoesNotExist: try: downstream_rule = downstream_rules.get(name=upstream_rule_def['rule']['name']) except AutomaticUpdateRule.MultipleObjectsReturned: # If there are multiple rules with the same name, overwrite the first. downstream_rule = downstream_rules.filter(name=upstream_rule_def['rule']['name']).first() except AutomaticUpdateRule.DoesNotExist: downstream_rule = None # If no corresponding local rule, make a new rule if not downstream_rule: downstream_rule = AutomaticUpdateRule( domain=domain_link.linked_domain, active=upstream_rule_def['rule']['active'], workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, upstream_id=upstream_rule_def['rule']['id'] ) # Copy all the contents from old rule to new rule with transaction.atomic(): downstream_rule.name = upstream_rule_def['rule']['name'] downstream_rule.case_type = upstream_rule_def['rule']['case_type'] downstream_rule.filter_on_server_modified = upstream_rule_def['rule']['filter_on_server_modified'] downstream_rule.server_modified_boundary = upstream_rule_def['rule']['server_modified_boundary'] downstream_rule.active = upstream_rule_def['rule']['active'] downstream_rule.save() downstream_rule.delete_criteria() downstream_rule.delete_actions() # Largely from data_interfaces/forms.py - save_criteria() for criteria in upstream_rule_def['criteria']: definition = None if criteria['match_property_definition']: definition = MatchPropertyDefinition.objects.create( property_name=criteria['match_property_definition']['property_name'], property_value=criteria['match_property_definition']['property_value'], match_type=criteria['match_property_definition']['match_type'], ) elif criteria['custom_match_definition']: definition = CustomMatchDefinition.objects.create( name=criteria['custom_match_definition']['name'], ) elif criteria['closed_parent_definition']: definition = ClosedParentDefinition.objects.create() new_criteria = CaseRuleCriteria(rule=downstream_rule) new_criteria.definition = definition new_criteria.save() # Largely from data_interfacees/forms.py - save_actions() for action in upstream_rule_def['actions']: definition = None if action['update_case_definition']: definition = UpdateCaseDefinition(close_case=action['update_case_definition']['close_case']) properties = [] for propertyItem in action['update_case_definition']['properties_to_update']: properties.append( UpdateCaseDefinition.PropertyDefinition( name=propertyItem['name'], value_type=propertyItem['value_type'], value=propertyItem['value'], ) ) definition.set_properties_to_update(properties) definition.save() elif action['custom_action_definition']: definition = CustomActionDefinition.objects.create( name=action['custom_action_definition']['name'], ) action = CaseRuleAction(rule=downstream_rule) action.definition = definition action.save()
def test_update_auto_update_rules(self): self.assertFalse( AutomaticUpdateRule.by_domain(domain=self.linked_domain, workflow="CASE_UPDATE").exists()) update_auto_update_rules(self.domain_link) linked_domain_rules = AutomaticUpdateRule.by_domain( self.linked_domain, active_only=False, workflow=AutomaticUpdateRule.WORKFLOW_CASE_UPDATE) self.assertEqual(3, linked_domain_rules.count()) for rule in linked_domain_rules: self.assertTrue( rule.name in ["Norway rule", "Is it hot enough?", "Closed parent case"]) if (rule.name == "Closed parent case"): self.assertEqual(rule.case_type, "family_member") else: self.assertEqual(rule.case_type, "person") if (rule.name == "Is it hot enough?"): self.assertFalse(rule.filter_on_server_modified) self.assertEqual(2, rule.server_modified_boundary) else: self.assertTrue(rule.filter_on_server_modified) self.assertFalse(rule.server_modified_boundary) caseRuleCriterias = CaseRuleCriteria.objects.filter(rule=rule) if (rule.name == "Is it hot enough?"): criteria = caseRuleCriterias.first() self.assertEqual( criteria.match_property_definition.property_name, "temperature") self.assertEqual( criteria.match_property_definition.property_value, "96") self.assertEqual(criteria.match_property_definition.match_type, MatchPropertyDefinition.MATCH_EQUAL) self.assertFalse(criteria.closed_parent_definition) elif (rule.name == "Norway rule"): self.assertEqual(2, caseRuleCriterias.count()) for criteria in caseRuleCriterias: self.assertTrue(criteria.match_property_definition or criteria.custom_match_definition) if (criteria.match_property_definition is not None): self.assertEqual( criteria.match_property_definition.property_value, "Norway") elif (criteria.custom_match_definition is not None): self.assertEqual(criteria.custom_match_definition.name, "COVID_US_ASSOCIATED_USER_CASES") elif (rule.name == "Closed parent case"): criteria = caseRuleCriterias.first() self.assertTrue(criteria.closed_parent_definition) caseRuleActions = CaseRuleAction.objects.filter(rule=rule) if (rule.name == "Norway rule"): action = caseRuleActions.first() self.assertEqual(action.update_case_definition.close_case, True) if (rule.name == "Is it hot enough?"): self.assertEqual(2, caseRuleActions.count()) for action in caseRuleActions: if (action.update_case_definition is not None): self.assertEqual( 2, len(action.update_case_definition. properties_to_update)) for property in action.update_case_definition.properties_to_update: self.assertTrue( property['name'] in ["hot_enough", "territory_hot_enough"]) if (property['name'] == "hot_enough"): self.assertEqual(property['value_type'], "EXACT") elif (property['name'] == "territory_hot_enough"): self.assertEqual(property['value'], "current_territory") elif (action.custom_action_definition is not None): self.assertEqual( action.custom_action_definition.name, "COVID_US_CLOSE_CASES_ASSIGNED_CHECKIN")
def _rules(self): return AutomaticUpdateRule.by_domain( self.domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, active_only=False, ).order_by('name', 'id')
def _rules(self): return AutomaticUpdateRule.by_domain( self.domain, AutomaticUpdateRule.WORKFLOW_CASE_UPDATE, active_only=False, ).order_by('name', 'id')
def save_copy(self, new_domain_name=None, new_hr_name=None, user=None, copy_by_id=None, share_reminders=True, share_user_roles=True): from corehq.apps.app_manager.dbaccessors import get_app from corehq.apps.data_interfaces.models import AutomaticUpdateRule from corehq.apps.reminders.models import CaseReminderHandler from corehq.apps.fixtures.models import FixtureDataItem from corehq.apps.app_manager.dbaccessors import get_brief_apps_in_domain from corehq.apps.domain.dbaccessors import get_doc_ids_in_domain_by_class from corehq.apps.fixtures.models import FixtureDataType from corehq.apps.users.models import UserRole db = Domain.get_db() new_id = db.copy_doc(self.get_id)['id'] if new_domain_name is None: new_domain_name = new_id uses_new_reminders = project_is_on_new_reminders(self) with CriticalSection(['request_domain_name_{}'.format(new_domain_name)]): new_domain_name = Domain.generate_name(new_domain_name) new_domain = Domain.get(new_id) new_domain.name = new_domain_name new_domain.hr_name = new_hr_name new_domain.copy_history = self.get_updated_history() new_domain.is_snapshot = False new_domain.snapshot_time = None new_domain.organization = None # TODO: use current user's organization (?) # reset stuff new_domain.cda.signed = False new_domain.cda.date = None new_domain.cda.type = None new_domain.cda.user_id = None new_domain.cda.user_ip = None new_domain.is_test = "none" new_domain.internal = InternalProperties() new_domain.creating_user = user.username if user else None new_domain.date_created = datetime.utcnow() new_domain.use_sql_backend = True new_domain.granted_messaging_access = False for field in self._dirty_fields: if hasattr(new_domain, field): delattr(new_domain, field) # Saving the domain should happen before we import any apps since # importing apps can update the domain object (for example, if user # as a case needs to be enabled) try: new_domain.save() except PreconditionFailed: # This is a hack to resolve http://manage.dimagi.com/default.asp?241492 # Following solution in # https://github.com/dimagi/commcare-hq/commit/d59b1e403060ade599cc4a03db0aabc4da62b668 time.sleep(0.5) new_domain.save() new_app_components = {} # a mapping of component's id to its copy def copy_data_items(old_type_id, new_type_id): for item in FixtureDataItem.by_data_type(self.name, old_type_id): comp = self.copy_component( item.doc_type, item._id, new_domain_name, user=user) comp.data_type_id = new_type_id comp.save() def get_latest_app_id(doc_id): app = get_app(self.name, doc_id).get_latest_saved() if app: return app._id, app.doc_type for app in get_brief_apps_in_domain(self.name): doc_id, doc_type = app.get_id, app.doc_type original_doc_id = doc_id if copy_by_id and doc_id not in copy_by_id: continue if not self.is_snapshot: doc_id, doc_type = get_latest_app_id(doc_id) or (doc_id, doc_type) component = self.copy_component(doc_type, doc_id, new_domain_name, user=user) if component: new_app_components[original_doc_id] = component for doc_id in get_doc_ids_in_domain_by_class(self.name, FixtureDataType): if copy_by_id and doc_id not in copy_by_id: continue component = self.copy_component( 'FixtureDataType', doc_id, new_domain_name, user=user) copy_data_items(doc_id, component._id) def convert_form_unique_id_function(form_unique_id): from corehq.apps.app_manager.models import FormBase form = FormBase.get_form(form_unique_id) form_app = form.get_app() m_index, f_index = form_app.get_form_location(form.unique_id) form_copy = new_app_components[form_app._id].get_module(m_index).get_form(f_index) return form_copy.unique_id if share_reminders: if uses_new_reminders: for rule in AutomaticUpdateRule.by_domain( self.name, AutomaticUpdateRule.WORKFLOW_SCHEDULING, active_only=False, ): rule.copy_conditional_alert( new_domain_name, convert_form_unique_id_function=convert_form_unique_id_function, ) else: for doc_id in get_doc_ids_in_domain_by_class(self.name, CaseReminderHandler): self.copy_component( 'CaseReminderHandler', doc_id, new_domain_name, user=user) if share_user_roles: for doc_id in get_doc_ids_in_domain_by_class(self.name, UserRole): self.copy_component('UserRole', doc_id, new_domain_name, user=user) if user: def add_dom_to_user(user): user.add_domain_membership(new_domain_name, is_admin=True) apply_update(user, add_dom_to_user) if not uses_new_reminders: # When uses_new_reminders is True, all of this is already taken care of # in the copy process def update_events(handler): """ Change the form_unique_id to the proper form for each event in a newly copied CaseReminderHandler """ for event in handler.events: if not event.form_unique_id: continue event.form_unique_id = convert_form_unique_id_function(event.form_unique_id) def update_for_copy(handler): handler.active = False update_events(handler) if share_reminders: for handler in CaseReminderHandler.get_handlers(new_domain_name): apply_update(handler, update_for_copy) return new_domain
def save_copy(self, new_domain_name=None, new_hr_name=None, user=None, copy_by_id=None, share_reminders=True, share_user_roles=True): from corehq.apps.app_manager.dbaccessors import get_app from corehq.apps.data_interfaces.models import AutomaticUpdateRule from corehq.apps.fixtures.models import FixtureDataItem from corehq.apps.app_manager.dbaccessors import get_brief_apps_in_domain from corehq.apps.domain.dbaccessors import get_doc_ids_in_domain_by_class from corehq.apps.fixtures.models import FixtureDataType from corehq.apps.users.models import UserRole db = Domain.get_db() new_id = db.copy_doc(self.get_id)['id'] if new_domain_name is None: new_domain_name = new_id with CriticalSection(['request_domain_name_{}'.format(new_domain_name)]): new_domain_name = Domain.generate_name(new_domain_name) new_domain = Domain.get(new_id) new_domain.name = new_domain_name new_domain.hr_name = new_hr_name new_domain.copy_history = self.get_updated_history() new_domain.is_snapshot = False new_domain.snapshot_time = None new_domain.organization = None # TODO: use current user's organization (?) # reset stuff new_domain.cda.signed = False new_domain.cda.date = None new_domain.cda.type = None new_domain.cda.user_id = None new_domain.cda.user_ip = None new_domain.is_test = "none" new_domain.internal = InternalProperties() new_domain.creating_user = user.username if user else None new_domain.date_created = datetime.utcnow() new_domain.use_sql_backend = True new_domain.granted_messaging_access = False for field in self._dirty_fields: if hasattr(new_domain, field): delattr(new_domain, field) # Saving the domain should happen before we import any apps since # importing apps can update the domain object (for example, if user # as a case needs to be enabled) try: new_domain.save() except PreconditionFailed: # This is a hack to resolve http://manage.dimagi.com/default.asp?241492 # Following solution in # https://github.com/dimagi/commcare-hq/commit/d59b1e403060ade599cc4a03db0aabc4da62b668 time.sleep(0.5) new_domain.save() new_app_components = {} # a mapping of component's id to its copy def copy_data_items(old_type_id, new_type_id): for item in FixtureDataItem.by_data_type(self.name, old_type_id): comp = self.copy_component( item.doc_type, item._id, new_domain_name, user=user) comp.data_type_id = new_type_id comp.save() def get_latest_app_id(doc_id): app = get_app(self.name, doc_id).get_latest_saved() if app: return app._id, app.doc_type for app in get_brief_apps_in_domain(self.name): doc_id, doc_type = app.get_id, app.doc_type original_doc_id = doc_id if copy_by_id and doc_id not in copy_by_id: continue if not self.is_snapshot: doc_id, doc_type = get_latest_app_id(doc_id) or (doc_id, doc_type) component = self.copy_component(doc_type, doc_id, new_domain_name, user=user) if component: new_app_components[original_doc_id] = component for doc_id in get_doc_ids_in_domain_by_class(self.name, FixtureDataType): if copy_by_id and doc_id not in copy_by_id: continue component = self.copy_component( 'FixtureDataType', doc_id, new_domain_name, user=user) copy_data_items(doc_id, component._id) def convert_form_unique_id_function(form_unique_id): from corehq.apps.app_manager.models import FormBase form = FormBase.get_form(form_unique_id) form_app = form.get_app() m_index, f_index = form_app.get_form_location(form.unique_id) form_copy = new_app_components[form_app._id].get_module(m_index).get_form(f_index) return form_copy.unique_id if share_reminders: for rule in AutomaticUpdateRule.by_domain( self.name, AutomaticUpdateRule.WORKFLOW_SCHEDULING, active_only=False, ): rule.copy_conditional_alert( new_domain_name, convert_form_unique_id_function=convert_form_unique_id_function, ) if share_user_roles: for doc_id in get_doc_ids_in_domain_by_class(self.name, UserRole): self.copy_component('UserRole', doc_id, new_domain_name, user=user) if user: def add_dom_to_user(user): user.add_domain_membership(new_domain_name, is_admin=True) apply_update(user, add_dom_to_user) return new_domain