Пример #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
    """
    domain = getattr(case_db, 'domain', None)
    touched_cases = FormProcessorInterface(domain).get_cases_from_forms(case_db, xforms)
    _validate_indices(case_db, touched_cases.values())
    return CaseProcessingResult(
        domain,
        [update.case for update in touched_cases.values()],
    )
Пример #2
0
def _get_case_and_ledger_updates(domain, sql_form):
    """
    Get a CaseStockProcessingResult with the appropriate cases and ledgers to
    be saved.

    See SubmissionPost.process_xforms_for_cases and methods it calls for the equivalent
    section of the form-processing code.
    """
    from corehq.apps.commtrack.processing import process_stock

    interface = FormProcessorInterface(domain)

    assert sql_form.domain
    xforms = [sql_form]

    with interface.casedb_cache(
            domain=domain,
            lock=False,
            deleted_ok=True,
            xforms=xforms,
            load_src="couchsqlmigration",
    ) as case_db:
        touched_cases = FormProcessorInterface(domain).get_cases_from_forms(
            case_db, xforms)
        extensions_to_close = get_all_extensions_to_close(
            domain, list(touched_cases.values()))
        case_result = CaseProcessingResult(
            domain,
            [update.case for update in touched_cases.values()],
            [],  # ignore dirtiness_flags,
            extensions_to_close)
        for case in case_result.cases:
            case_db.post_process_case(case, sql_form)
            case_db.mark_changed(case)
        cases = case_result.cases

        try:
            stock_result = process_stock(xforms, case_db)
            cases = case_db.get_cases_for_saving(sql_form.received_on)
            stock_result.populate_models()
        except MissingFormXml:
            stock_result = None

    return CaseStockProcessingResult(
        case_result=case_result,
        case_models=cases,
        stock_result=stock_result,
    )
Пример #3
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
    """
    domain = getattr(case_db, 'domain', None)
    touched_cases = FormProcessorInterface(domain).get_cases_from_forms(case_db, xforms)
    _validate_indices(case_db, [case_update_meta.case for case_update_meta in touched_cases.values()])
    dirtiness_flags = _get_all_dirtiness_flags_from_cases(case_db, touched_cases)
    extensions_to_close = get_all_extensions_to_close(domain, touched_cases.values())
    return CaseProcessingResult(
        domain,
        [update.case for update in touched_cases.values()],
        dirtiness_flags,
        extensions_to_close
    )
Пример #4
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
    """
    domain = getattr(case_db, 'domain', None)
    touched_cases = FormProcessorInterface(domain).get_cases_from_forms(case_db, xforms)
    _validate_indices(case_db, [case_update_meta.case for case_update_meta in touched_cases.values()])
    dirtiness_flags = _get_all_dirtiness_flags_from_cases(case_db, touched_cases)
    extensions_to_close = get_all_extensions_to_close(domain, list(touched_cases.values()))
    return CaseProcessingResult(
        domain,
        [update.case for update in touched_cases.values()],
        dirtiness_flags,
        extensions_to_close
    )
Пример #5
0
def _get_case_and_ledger_updates(domain, sql_form):
    """
    Get a CaseStockProcessingResult with the appropriate cases and ledgers to
    be saved.

    See SubmissionPost.process_xforms_for_cases and methods it calls for the equivalent
    section of the form-processing code.
    """
    from casexml.apps.case.xform import get_and_check_xform_domain
    from corehq.apps.commtrack.processing import process_stock

    interface = FormProcessorInterface(domain)

    get_and_check_xform_domain(sql_form)
    xforms = [sql_form]

    # todo: I think this can be changed to lock=False
    with interface.casedb_cache(domain=domain,
                                lock=True,
                                deleted_ok=True,
                                xforms=xforms) as case_db:
        touched_cases = FormProcessorInterface(domain).get_cases_from_forms(
            case_db, xforms)
        extensions_to_close = get_all_extensions_to_close(
            domain, touched_cases.values())
        case_result = CaseProcessingResult(
            domain,
            [update.case for update in touched_cases.values()],
            [],  # ignore dirtiness_flags,
            extensions_to_close)
        # todo: is this necessary?
        for case in case_result.cases:
            case_db.mark_changed(case)

        stock_result = process_stock(xforms, case_db)
        cases = case_db.get_cases_for_saving(sql_form.received_on)
        stock_result.populate_models()

    return CaseStockProcessingResult(
        case_result=case_result,
        case_models=cases,
        stock_result=stock_result,
    )
Пример #6
0
def _get_case_and_ledger_updates(domain, sql_form):
    """
    Get a CaseStockProcessingResult with the appropriate cases and ledgers to
    be saved.

    See SubmissionPost.process_xforms_for_cases and methods it calls for the equivalent
    section of the form-processing code.
    """
    from corehq.apps.commtrack.processing import process_stock

    interface = FormProcessorInterface(domain)

    assert sql_form.domain
    xforms = [sql_form]

    with interface.casedb_cache(
        domain=domain, lock=False, deleted_ok=True, xforms=xforms,
        load_src="couchsqlmigration",
    ) as case_db:
        touched_cases = FormProcessorInterface(domain).get_cases_from_forms(case_db, xforms)
        extensions_to_close = get_all_extensions_to_close(domain, list(touched_cases.values()))
        case_result = CaseProcessingResult(
            domain,
            [update.case for update in touched_cases.values()],
            [],  # ignore dirtiness_flags,
            extensions_to_close
        )
        for case in case_result.cases:
            case_db.post_process_case(case, sql_form)
            case_db.mark_changed(case)

        stock_result = process_stock(xforms, case_db)
        cases = case_db.get_cases_for_saving(sql_form.received_on)
        stock_result.populate_models()

    return CaseStockProcessingResult(
        case_result=case_result,
        case_models=cases,
        stock_result=stock_result,
    )
Пример #7
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
    """
    domain = getattr(case_db, 'domain', None)
    touched_cases = FormProcessorInterface(domain).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):
        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,
                    )

    def _get_dirtiness_flags_for_outgoing_indices(case, tree_owners=None):
        """ if the outgoing indices touch cases owned by another user this cases owner is dirty """
        if tree_owners is None:
            tree_owners = set()

        extension_indices = [index for index in case.indices if index.relationship == CASE_INDEX_EXTENSION]

        unowned_host_cases = []
        for index in extension_indices:
            host_case = case_db.get(index.referenced_id)
            if (
                host_case
                and host_case.owner_id == UNOWNED_EXTENSION_OWNER_ID
                and host_case not in unowned_host_cases
            ):
                unowned_host_cases.append(host_case)

        owner_ids = {case_db.get(index.referenced_id).owner_id
                     for index in case.indices if case_db.get(index.referenced_id)} | tree_owners
        potential_clean_owner_ids = owner_ids | set([UNOWNED_EXTENSION_OWNER_ID])
        more_than_one_owner_touched = len(owner_ids) > 1
        touches_different_owner = len(owner_ids) == 1 and case.owner_id not in potential_clean_owner_ids

        if (more_than_one_owner_touched or touches_different_owner):
            yield DirtinessFlag(case.case_id, case.owner_id)
            if extension_indices:
                # If this case is an extension, each of the touched cases is also dirty
                for index in case.indices:
                    referenced_case = case_db.get(index.referenced_id)
                    yield DirtinessFlag(referenced_case.case_id, referenced_case.owner_id)

        if case.owner_id != UNOWNED_EXTENSION_OWNER_ID:
            tree_owners.add(case.owner_id)
        for unowned_host_case in unowned_host_cases:
            # A host case of this extension is unowned, which means it could potentially touch an owned case
            # Check these unowned cases' outgoing indices and mark dirty if appropriate
            for dirtiness_flag in _get_dirtiness_flags_for_outgoing_indices(unowned_host_case,
                                                                            tree_owners=tree_owners):
                yield dirtiness_flag

    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)

    def _get_dirtiness_flags_for_reassigned_case(case_metas):
        # for reassigned cases, we mark them temporarily dirty to allow phones to sync
        # the latest changes. these will get cleaned up when the weekly rebuild triggers
        for case_update_meta in case_metas:
            if _is_change_of_ownership(case_update_meta.previous_owner_id, case_update_meta.case.owner_id):
                yield DirtinessFlag(case_update_meta.case.case_id, case_update_meta.previous_owner_id)

    dirtiness_flags = []
    extensions_to_close = set()

    # process the temporary dirtiness flags first so that any hints for real dirtiness get overridden
    dirtiness_flags += list(_get_dirtiness_flags_for_reassigned_case(touched_cases.values()))
    for case_update_meta in touched_cases.values():
        _validate_indices(case_update_meta.case)
        extensions_to_close = extensions_to_close | get_extensions_to_close(case_update_meta.case, domain)
        dirtiness_flags += list(_get_dirtiness_flags_for_outgoing_indices(case_update_meta.case))
    dirtiness_flags += list(_get_dirtiness_flags_for_child_cases([meta.case for meta in touched_cases.values()]))

    return CaseProcessingResult(
        domain,
        [update.case for update in touched_cases.values()],
        dirtiness_flags,
        extensions_to_close
    )