Ejemplo n.º 1
0
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)
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
        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.