Пример #1
0
def test_patch_opened_by_with_xform_ids():
    diffs = [
        Diff("diff", ["opened_by"], "old", "new"),
        Diff("set_mismatch", ["xform_ids", "[*]"], "old", "new"),
    ]
    case = mod.PatchCase(FakeCase(), diffs)
    check_diff_block(case, diffs)
Пример #2
0
def test_can_patch_opened_by_with_user_id():
    diffs = [
        Diff("diff", ["opened_by"], "old", "new"),
        Diff("diff", ["user_id"], "old", "new"),
    ]
    case = mod.PatchCase(FakeCase(), diffs)
    eq(case.dynamic_case_properties(), {})
    check_diff_block(case, diffs)
Пример #3
0
def add_cases_missing_from_couch(data, case_ids):
    sql_cases = {c.case_id: c for c in get_sql_cases(list(case_ids))}
    data.doc_ids.extend(case_ids)
    for case_id in case_ids:
        if case_id in sql_cases:
            new = "present"
            if sql_cases[case_id].deleted:
                miss = Diff("missing", path=["*"], old_value=MISSING, new_value=new)
                data.diffs.append(("CommCareCase-Deleted", case_id, [miss]))
                new = None
        else:
            forms = find_processed_and_unmigrated_form_ids(case_id)
            new = f"missing with forms {forms}" if forms else None
        diff = Diff("missing", path=["*"], old_value=MISSING, new_value=new)
        data.diffs.append(("CommCareCase", case_id, [diff] if new else []))
Пример #4
0
    def _load_cases(self, pending):
        """Load cases and establish total and processed form counts

        Cases for which all forms have been processed are enqueued to be
        diffed.

        :param pending: dict `{<case_id>: <processed_form_count>, ...}`
        """
        log.debug("enqueue or load %s", pending)
        cases = self.cases
        case_ids = list(pending)
        loaded_case_ids = set()
        case_records = []
        stock_forms = get_stock_forms_by_case_id(case_ids)
        for case in get_couch_cases(case_ids):
            loaded_case_ids.add(case.case_id)
            case_stock_forms = stock_forms.get(case.case_id, [])
            rec = CaseRecord(case, case_stock_forms, pending[case.case_id])
            case_records.append(rec)
            if rec.should_memorize_case:
                log.debug("memorize %s", rec)
                cases[case.case_id] = case
        if case_records:
            result = self.statedb.update_cases(case_records)
            for case_id, total_forms, processed_forms in result:
                if total_forms <= processed_forms:
                    self.enqueue(case_id, processed_forms)
        missing = set(case_ids) - loaded_case_ids
        if missing:
            log.error("Found %s missing Couch cases", len(missing))
            self.statedb.replace_case_diffs([(
                "CommCareCase",
                case_id,
                [Diff("missing", path=["*"], old_value=MISSING, new_value="?")],
            ) for case_id in missing])
Пример #5
0
def add_missing_docs(data, couch_cases, sql_case_ids, dd_count):
    def as_change(item, reason):
        kind, doc_id, diffs = item
        return kind, doc_id, diffs_to_changes(diffs, reason)
    if len(couch_cases) != len(sql_case_ids):
        only_in_sql = sql_case_ids - couch_cases.keys()
        assert not only_in_sql, only_in_sql
        only_in_couch = couch_cases.keys() - sql_case_ids
        data.doc_ids.extend(only_in_couch)
        dd_count("commcare.couchsqlmigration.case.missing_from_sql", value=len(only_in_couch))
        for case_id in only_in_couch:
            couch_case = couch_cases[case_id]
            diff = change = (couch_case["doc_type"], case_id, [])
            item = (
                couch_case["doc_type"],
                case_id,
                [Diff("missing", path=["*"], old_value="*", new_value=MISSING)],
            )
            if has_only_deleted_forms(couch_case):
                change = as_change(item, "deleted forms")
            elif is_orphaned_case(couch_case):
                change = as_change(item, "orphaned case")
            else:
                diff = item
            data.diffs.append(diff)
            data.changes.append(change)
Пример #6
0
def add_cases_missing_from_couch(data, case_ids):
    sql_ids = {c.case_id for c in CaseAccessorSQL.get_cases(list(case_ids))}
    data.doc_ids.extend(case_ids)
    for case_id in case_ids:
        new = "present" if case_id in sql_ids else MISSING
        data.diffs.append((
            "CommCareCase",
            case_id,
            [Diff("missing", path=["*"], old_value=MISSING, new_value=new)],
        ))
Пример #7
0
    def diff_missing_ledger(self, ledger, *, sql_miss=False):
        """Get the state of the form reference by ledger

        :param ledger: Object having `last_modified_form_id` attribute
        (`LedgerValue` or `StockState`).
        """
        form_id = ledger.last_modified_form_id
        old, new = diff_form_state(form_id, in_couch=form_id in self.ledger_refs)
        if sql_miss:
            old["ledger"] = ledger.to_json()
        else:
            new["ledger"] = ledger.to_json()
        return Diff("missing", path=["*"], old_value=old, new_value=new)
Пример #8
0
def assert_patched(form, diffs, expect_patched=True):
    patch_diffs = [
        diff for diff in diffs
        if not mod.is_patchable(diff) or diff.old_value is MISSING
    ]
    if not any(d.path[0] == "xform_ids" for d in patch_diffs):
        patch_diffs.append(
            Diff("set_mismatch", ["xform_ids", "[*]"], "old", "new"))
    with patch.object(casediff, "get_sql_forms", lambda x, **k: [form]):
        actual_patched = casediff.is_case_patched(FakeCase.case_id,
                                                  patch_diffs)
    sep = "\n"
    assert actual_patched == expect_patched, (
        f"is_case_patched(case_id, diffs) -> {actual_patched}\n"
        f"{sep.join(repr(d) for d in patch_diffs)}\n\n{form.diff_block}")
Пример #9
0
def add_missing_docs(data, couch_cases, sql_case_ids, dd_count):
    if len(couch_cases) != len(sql_case_ids):
        only_in_sql = sql_case_ids - couch_cases.keys()
        assert not only_in_sql, only_in_sql
        only_in_couch = couch_cases.keys() - sql_case_ids
        data.doc_ids.extend(only_in_couch)
        dd_count("commcare.couchsqlmigration.case.missing_from_sql", value=len(only_in_couch))
        for case_id in only_in_couch:
            couch_case = couch_cases[case_id]
            if is_orphaned_case(couch_case):
                log.info("Ignoring orphaned case: %s", couch_case["_id"])
                continue
            data.diffs.append((
                couch_case["doc_type"],
                case_id,
                [Diff("missing", path=["*"], old_value="*", new_value=MISSING)],
            ))
Пример #10
0
def diff_case_forms(couch_json, sql_json):
    couch_ids = {a["xform_id"] for a in couch_json["actions"] if a["xform_id"]}
    sql_ids = {t["xform_id"] for t in sql_json["actions"] if t["xform_id"]}
    only_in_couch = couch_ids - sql_ids
    if not only_in_couch:
        return []
    old_forms = {}
    new_forms = {}
    for form_id in only_in_couch:
        old, new = diff_form_state(form_id)
        old_forms[form_id] = old["form_state"]
        new_forms[form_id] = new["form_state"]
    if any(v != FORM_PRESENT for v in old_forms.values()):
        return [Diff(
            "diff",
            path=["?"],
            old_value={"forms": old_forms},
            new_value={"forms": new_forms},
        )]
    return []
Пример #11
0
def test_patch_missing_case_property():
    diffs = [Diff("diff", ["gone"], MISSING, "new")]
    case = mod.PatchCase(FakeCase(), diffs)
    eq(case.dynamic_case_properties(), {"gone": ""})
    check_diff_block(case, diffs, [Diff("diff", ["gone"], MISSING, "")])
Пример #12
0
def test_patch_modified_by():
    diffs = [Diff("diff", ["modified_by"], "old", "new")]
    case = mod.PatchCase(FakeCase(), diffs)
    check_diff_block(case, diffs)
Пример #13
0
def ledger_diff(*args):
    ref = mod.UniqueLedgerReference.from_id("led/ger/ref")
    return mod.LedgerDiff(Diff(*args), ref)