def _get_or_update_cases(xforms, case_db): """ Given an xform document, update any case blocks found within it, returning a dictionary mapping the case ids affected to the couch case document objects """ touched_cases = get_cases_from_forms(case_db, xforms) # once we've gotten through everything, validate all indices # and check for new dirtiness flags def _validate_indices(case): dirtiness_flags = [] is_dirty = False if case.indices: for index in case.indices: # call get and not doc_exists to force domain checking # see CaseDbCache._validate_case referenced_case = case_db.get(index.referenced_id) if not referenced_case: # just log, don't raise an error or modify the index logging.error( "Case '%s' references non-existent case '%s'", case.case_id, index.referenced_id, ) else: if referenced_case.owner_id != case.owner_id: is_dirty = True if is_dirty: dirtiness_flags.append(DirtinessFlag(case.case_id, case.owner_id)) return dirtiness_flags def _get_dirtiness_flags_for_child_cases(cases): child_cases = case_db.get_reverse_indexed_cases([c.case_id for c in cases]) case_owner_map = dict((case.case_id, case.owner_id) for case in cases) for child_case in child_cases: for index in child_case.indices: if (index.referenced_id in case_owner_map and child_case.owner_id != case_owner_map[index.referenced_id]): yield DirtinessFlag(child_case.case_id, child_case.owner_id) dirtiness_flags = [flag for case in touched_cases.values() for flag in _validate_indices(case)] domain = getattr(case_db, 'domain', None) track_cleanliness = should_track_cleanliness(domain) if track_cleanliness: # only do this extra step if the toggle is enabled since we know we aren't going to # care about the dirtiness flags otherwise. dirtiness_flags += list(_get_dirtiness_flags_for_child_cases(touched_cases.values())) return CaseProcessingResult(domain, touched_cases.values(), dirtiness_flags, track_cleanliness)
def _get_or_update_cases(xforms, case_db): """ Given an xform document, update any case blocks found within it, returning a dictionary mapping the case ids affected to the couch case document objects """ # have to apply the deprecations before the updates sorted_forms = sorted(xforms, key=lambda f: 0 if is_deprecation(f) else 1) touched_cases = {} for xform in sorted_forms: for case_update in get_case_updates(xform): case_doc = _get_or_update_model(case_update, xform, case_db) touched_cases[case_doc['_id']] = case_doc if case_doc: # todo: legacy behavior, should remove after new case processing # is fully enabled. if xform._id not in case_doc.xform_ids: case_doc.xform_ids.append(xform.get_id) else: logging.error( "XForm %s had a case block that wasn't able to create a case! " "This usually means it had a missing ID" % xform.get_id ) # once we've gotten through everything, validate all indices # and check for new dirtiness flags def _validate_indices(case): dirtiness_flags = [] is_dirty = False if case.indices: for index in case.indices: # call get and not doc_exists to force domain checking # see CaseDbCache.validate_doc referenced_case = case_db.get(index.referenced_id) if not referenced_case: # just log, don't raise an error or modify the index logging.error( "Case '%s' references non-existent case '%s'", case.get_id, index.referenced_id, ) else: if referenced_case.owner_id != case.owner_id: is_dirty = True if is_dirty: dirtiness_flags.append(DirtinessFlag(case._id, case.owner_id)) return dirtiness_flags def _get_dirtiness_flags_for_child_cases(domain, cases): child_cases = get_reverse_indexed_cases(domain, [c['_id'] for c in cases]) case_owner_map = dict((case._id, case.owner_id) for case in cases) for child_case in child_cases: for index in child_case.indices: if (index.referenced_id in case_owner_map and child_case.owner_id != case_owner_map[index.referenced_id]): yield DirtinessFlag(child_case._id, child_case.owner_id) dirtiness_flags = [flag for case in touched_cases.values() for flag in _validate_indices(case)] domain = getattr(case_db, 'domain', None) track_cleanliness = should_track_cleanliness(domain) if track_cleanliness: # only do this extra step if the toggle is enabled since we know we aren't going to # care about the dirtiness flags otherwise. dirtiness_flags += list(_get_dirtiness_flags_for_child_cases(domain, touched_cases.values())) return CaseProcessingResult(domain, touched_cases.values(), dirtiness_flags, track_cleanliness)
child_cases = get_reverse_indexed_cases(domain, [c['_id'] for c in cases]) case_owner_map = dict((case._id, case.owner_id) for case in cases) for child_case in child_cases: for index in child_case.indices: if (index.referenced_id in case_owner_map and child_case.owner_id != case_owner_map[index.referenced_id]): yield DirtinessFlag(child_case._id, child_case.owner_id) dirtiness_flags = [ flag for case in touched_cases.values() for flag in _validate_indices(case) ] domain = getattr(case_db, 'domain', None) track_cleanliness = should_track_cleanliness(domain) if track_cleanliness: # only do this extra step if the toggle is enabled since we know we aren't going to # care about the dirtiness flags otherwise. dirtiness_flags += list( _get_dirtiness_flags_for_child_cases(domain, touched_cases.values())) return CaseProcessingResult(domain, touched_cases.values(), dirtiness_flags, track_cleanliness) def _get_or_update_model(case_update, xform, case_db): """ Gets or updates an existing case, based on a block of data in a submitted form. Doesn't save anything.