def test_edit_submissions_simple(self): initial_quantity = 100 form_id = submit_case_blocks( case_blocks=get_single_balance_block(quantity=initial_quantity, **self._stock_state_key), domain=self.domain, ) stock_state, latest_txn, all_txns = self._get_stats() self.assertEqual(stock_state.stock_on_hand, initial_quantity) self.assertEqual(latest_txn.stock_on_hand, initial_quantity) self.assertEqual(all_txns.count(), 1) case = CommCareCase.get(id=self.case.case_id) self.assertEqual(1, len(case.actions)) self.assertEqual([form_id], case.xform_ids) # change the value to 50 edit_quantity = 50 submit_case_blocks( case_blocks=get_single_balance_block(quantity=edit_quantity, **self._stock_state_key), domain=self.domain, form_id=form_id, ) case = CommCareCase.get(id=self.case.case_id) self.assertEqual(1, len(case.actions)) stock_state, latest_txn, all_txns = self._get_stats() self.assertEqual(stock_state.stock_on_hand, edit_quantity) self.assertEqual(latest_txn.stock_on_hand, edit_quantity) self.assertEqual(all_txns.count(), 1) self.assertEqual([form_id], case.xform_ids)
def test_fire_signals(self): from corehq.apps.receiverwrapper.tests.test_submit_errors import failing_signal_handler case_id = uuid.uuid4().hex form_id = uuid.uuid4().hex with failing_signal_handler('signal death'): submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_string().decode('utf-8'), self.domain, form_id=form_id ) form = self.formdb.get_form(form_id) with catch_signal(successful_form_received) as form_handler, catch_signal(case_post_save) as case_handler: submit_form_locally( instance=form.get_xml(), domain=self.domain, ) case = self.casedb.get_case(case_id) if should_use_sql_backend(self.domain): self.assertEqual(form, form_handler.call_args[1]['xform']) self.assertEqual(case, case_handler.call_args[1]['case']) else: signal_form = form_handler.call_args[1]['xform'] self.assertEqual(form.form_id, signal_form.form_id) self.assertEqual(form.get_rev, signal_form.get_rev) signal_case = case_handler.call_args[1]['case'] self.assertEqual(case.case_id, signal_case.case_id) self.assertEqual(case.get_rev, signal_case.get_rev)
def test_error_saving(self): case_id = uuid.uuid4().hex form_id = uuid.uuid4().hex with _patch_save_to_raise_error(self): submit_case_blocks( CaseBlock(case_id=case_id, create=True, case_type='box').as_string().decode('utf-8'), self.domain, form_id=form_id ) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form = self.formdb.get_form(form_id) self.assertTrue(form.is_error) with self.assertRaises(CaseNotFound): self.casedb.get_case(case_id) result = submit_form_locally( instance=form.get_xml(), domain=self.domain, ) duplicate_form = result.xform self.assertTrue(duplicate_form.is_duplicate) case = self.casedb.get_case(case_id) self.assertIsNotNone(case) form = self.formdb.get_form(form_id) self.assertTrue(form.is_normal) self.assertIsNone(getattr(form, 'problem', None)) self.assertEqual(duplicate_form.orig_id, form.form_id)
def update_supply_points(domain): device_id = __name__ + ".update_supply_points" case_blocks = (case_block(c) for c in get_cases(domain) if needs_update(c)) if case_blocks: for chunk in chunked(case_blocks, 100): submit_case_blocks(chunk, domain, device_id=device_id) print("updated {} cases on domain {}".format(len(chunk), domain))
def test_xform_ids_diff(self): case_id = uuid.uuid4().hex submit_case_blocks( CaseBlock( case_id, case_type='migrate', create=True, update={'p1': 1}, ).as_string(), self.domain_name ) submit_case_blocks( CaseBlock( case_id, update={'p2': 2}, ).as_string(), self.domain_name ) case = CaseAccessors(self.domain_name).get_case(case_id) removed_form_id = case.xform_ids.pop(1) case.save() self.assertEqual(1, len(self._get_case_ids())) self._do_migration_and_assert_flags(self.domain_name) self.assertEqual(1, len(self._get_case_ids())) self._compare_diffs([ (u'CommCareCase', FormJsonDiff( diff_type=u'set_mismatch', path=[u'xform_ids', u'[*]'], old_value=u'', new_value=removed_form_id )) ])
def test_multiple_case_blocks_some_deleted(self, rebuild_case): """ Don't rebuild deleted cases """ case_ids = [uuid.uuid4().hex, uuid.uuid4().hex, uuid.uuid4().hex] for i, case_id in enumerate(case_ids): if i == 0: # only the first case is owned by the user getting retired owner_id = self.other_user._id else: owner_id = self.commcare_user._id caseblock = CaseBlock( create=True, case_id=case_id, owner_id=owner_id, user_id=self.commcare_user._id, ) submit_case_blocks(caseblock.as_string().decode('utf-8'), self.domain, user_id=self.other_user._id) self.other_user.retire() detail = UserArchivedRebuild(user_id=self.other_user.user_id) expected_call_args = [ mock.call(self.domain, case_id, detail) for case_id in case_ids[1:] ] self.assertEqual(rebuild_case.call_count, len(case_ids) - 1) self.assertItemsEqual(rebuild_case.call_args_list, expected_call_args)
def test_multiple_case_blocks_all_rebuilt(self, rebuild_case): """ Rebuild all cases in forms with multiple case blocks """ case_ids = [uuid.uuid4().hex, uuid.uuid4().hex, uuid.uuid4().hex] caseblocks = [ CaseBlock( create=True, case_id=case_id, owner_id=self.commcare_user._id, user_id=self.commcare_user._id, ) for case_id in case_ids ] casexmls = [ ElementTree.tostring(caseblock.as_xml()).decode('utf-8') for caseblock in caseblocks ] submit_case_blocks(casexmls, self.domain, user_id=self.other_user._id) self.other_user.retire() detail = UserArchivedRebuild(user_id=self.other_user.user_id) expected_call_args = [ mock.call(self.domain, case_id, detail) for case_id in case_ids ] self.assertEqual(rebuild_case.call_count, len(case_ids)) self.assertItemsEqual(rebuild_case.call_args_list, expected_call_args)
def test_second_edit_fails(self): form_id = uuid.uuid4().hex case_id = uuid.uuid4().hex case_block = CaseBlock( create=True, case_id=case_id, case_type='person', version=V2, ).as_string() submit_case_blocks(case_block, domain=self.domain, form_id=form_id) # submit an edit form with a bad case update (for example a bad ID) case_block = CaseBlock( create=True, case_id='', case_type='person', version=V2, ).as_string() submit_case_blocks(case_block, domain=self.domain, form_id=form_id) form = XFormInstance.get(form_id) self.assertEqual('XFormError', form.doc_type) deprecated_form = XFormInstance.get(form.deprecated_form_id) self.assertEqual('XFormDeprecated', deprecated_form.doc_type)
def test_multiple_case_blocks_some_deleted(self, rebuild_case): """ Don't rebuild deleted cases """ case_ids = [uuid.uuid4().hex, uuid.uuid4().hex, uuid.uuid4().hex] for i, case_id in enumerate(case_ids): if i == 0: # only the first case is owned by the user getting retired owner_id = self.other_user._id else: owner_id = self.commcare_user._id caseblock = CaseBlock( create=True, case_id=case_id, owner_id=owner_id, user_id=self.commcare_user._id, ) submit_case_blocks(caseblock.as_string(), self.domain, user_id=self.other_user._id) self.other_user.retire() detail = UserArchivedRebuild(user_id=self.other_user.user_id) expected_call_args = [mock.call(self.domain, case_id, detail) for case_id in case_ids[1:]] self.assertEqual(rebuild_case.call_count, len(case_ids) - 1) self.assertItemsEqual(rebuild_case.call_args_list, expected_call_args)
def new_update_case_properties(): """ Submits case blocks in chunks of up to importer CASEBLOCK_CHUNKSIZE """ case_blocks = [] last_domain = None for case, domain in iter_cases_to_modify(): if not last_domain: last_domain = domain if len(case_blocks) == CASEBLOCK_CHUNKSIZE or domain != last_domain: submit_case_blocks(case_blocks, last_domain) last_domain = domain case_blocks = [] kwargs = { 'create': False, 'case_id': case['case_id'], 'update': case['update'], 'close': case['close'], } if case.get('owner_id', None): kwargs['owner_id'] = case['owner_id'] case_blocks.append(ElementTree.tostring(CaseBlock(**kwargs).as_xml())) if case_blocks: submit_case_blocks(case_blocks, last_domain)
def test_multiple_case_blocks_some_deleted(self, rebuild_case): """ Don't rebuild deleted cases """ case_ids = [uuid.uuid4().hex, uuid.uuid4().hex, uuid.uuid4().hex] caseblocks = [CaseBlock( create=True, case_id=case_id, owner_id=self.commcare_user._id, user_id=self.commcare_user._id, ) for case_id in case_ids] casexmls = [ElementTree.tostring(caseblock.as_xml()) for caseblock in caseblocks] submit_case_blocks(casexmls, self.domain, user_id=self.other_user._id) # This case will get deleted when the user is retired case = CommCareCase.get(case_ids[0]) case.owner_id = self.other_user._id case.save() self.other_user.retire() expected_call_args = [mock.call(case_id) for case_id in case_ids[1:]] self.assertEqual(rebuild_case.call_count, len(case_ids) - 1) self.assertItemsEqual(rebuild_case.call_args_list, expected_call_args)
def test_edit_form_that_removes_ledgers(self): from corehq.apps.commtrack.tests.util import get_single_balance_block form_id = uuid.uuid4().hex submit_case_blocks([ get_single_balance_block(self.case.case_id, self.product_a._id, 100)], DOMAIN, form_id=form_id ) self._assert_ledger_state(100) transactions = CaseAccessorSQL.get_transactions(self.case.case_id) self.assertEqual(2, len(transactions)) self.assertTrue(transactions[0].is_form_transaction) self.assertTrue(transactions[1].is_form_transaction) self.assertTrue(transactions[1].is_ledger_transaction) submit_case_blocks([ CaseBlock(case_id=self.case.case_id).as_string().decode('utf-8')], DOMAIN, form_id=form_id ) self._assert_ledger_state(0) transactions = CaseAccessorSQL.get_transactions(self.case.case_id) self.assertEqual(3, len(transactions)) self.assertTrue(transactions[0].is_form_transaction) # ordering not guaranteed since they have the same date self.assertTrue(transactions[1].is_form_transaction) self.assertFalse(transactions[1].is_ledger_transaction) # no longer a ledger transaction self.assertTrue(transactions[2].is_case_rebuild) self._assert_transactions([])
def test_get_ledger_values_for_case_as_of(self): case_id = uuid.uuid4().hex form_xml = get_simple_form_xml(uuid.uuid4().hex, case_id) submit_form_locally(form_xml, domain=self.domain)[1] # submit ledger data balances = ( (self.product_a._id, 100), (self.product_b._id, 50), ) ledger_blocks = [ get_single_balance_block(case_id, prod_id, balance) for prod_id, balance in balances ] submit_case_blocks(ledger_blocks, self.domain) # check results results = get_ledger_values_for_case_as_of(domain=self.domain, case_id=case_id, section_id='stock', as_of=datetime.utcnow()) self.assertEqual(2, len(results)) self.assertEqual(100, results[self.product_a._id]) self.assertEqual(50, results[self.product_b._id]) # check the date filter works before_data = datetime.utcnow() - timedelta(days=2) self.assertEqual({}, get_ledger_values_for_case_as_of(domain=self.domain, case_id=case_id, section_id='stock', as_of=before_data))
def test_forms_touching_live_case_not_deleted(self): case_id = uuid.uuid4().hex caseblock = CaseBlock( create=True, case_id=case_id, owner_id=self.commcare_user._id, user_id=self.commcare_user._id, ) xform, _ = submit_case_blocks(caseblock.as_string().decode('utf-8'), self.domain) # other user submits form against the case and another case not owned by the user # should NOT get deleted since this form touches a case that's still 'alive' double_case_xform, _ = submit_case_blocks([ CaseBlock( create=False, case_id=case_id, ).as_string().decode('utf-8'), CaseBlock( create=True, case_id=uuid.uuid4().hex, owner_id=self.other_user._id, user_id=self.other_user._id, ).as_string().decode('utf-8') ], self.domain, user_id=self.other_user._id) self.commcare_user.retire() self.assertTrue(FormAccessors(self.domain).get_form(xform.form_id).is_deleted) self.assertFalse(FormAccessors(self.domain).get_form(double_case_xform.form_id).is_deleted) # When the other user is deleted then the form should get deleted since it no-longer touches # any 'live' cases. self.other_user.retire() self.assertTrue(FormAccessors(self.domain).get_form(double_case_xform.form_id).is_deleted)
def test_get_document_archived(self): from corehq.apps.commtrack.tests.util import get_single_balance_block from corehq.apps.commtrack.models import StockState from corehq.apps.products.models import SQLProduct block = get_single_balance_block(self.case.case_id, self.product_a._id, 100) submit_case_blocks(block, DOMAIN) stock_states = StockState.include_archived.all() self.assertEquals(1, len(stock_states)) def toggle_product_archive(): sql_product = SQLProduct.objects.get(code=self.product_a.code) sql_product.is_archived = not sql_product.is_archived sql_product.save() toggle_product_archive() self.addCleanup(toggle_product_archive) self.assertTrue(SQLProduct.objects.get(code=self.product_a.code).is_archived) state = stock_states[0] store = LedgerV1DocumentStore(DOMAIN) doc = store.get_document(state.id) self.assertEquals(int(doc['_id']), state.id) self.assertEquals(doc['case_id'], state.case_id)
def test_all_case_forms_deleted(self): from corehq.apps.callcenter.sync_user_case import sync_usercase sync_usercase(self.commcare_user) user_case_id = self.commcare_user.get_usercase_id() # other user submits form against the case (should get deleted) caseblock = CaseBlock( create=False, case_id=user_case_id, ) submit_case_blocks(caseblock.as_string().decode('utf-8'), self.domain, user_id=self.other_user._id) case_ids = CaseAccessors(self.domain).get_case_ids_by_owners([self.commcare_user._id]) self.assertEqual(1, len(case_ids)) form_ids = FormAccessors(self.domain).get_form_ids_for_user(self.commcare_user._id) self.assertEqual(0, len(form_ids)) user_case = self.commcare_user.get_usercase() self.assertEqual(2, len(user_case.xform_ids)) self.commcare_user.retire() for form_id in user_case.xform_ids: self.assertTrue(FormAccessors(self.domain).get_form(form_id).is_deleted) self.assertTrue(CaseAccessors(self.domain).get_case(user_case_id).is_deleted)
def explode_cases(request, domain, template="hqcase/explode_cases.html"): if request.method == 'POST': user_id = request.POST['user_id'] user = CommCareUser.get_by_user_id(user_id, domain) factor = request.POST.get('factor', '2') try: factor = int(factor) except ValueError: messages.error(request, 'factor must be an int; was: %s' % factor) else: keys = [[domain, owner_id, False] for owner_id in user.get_owner_ids()] for case in CommCareCase.view('hqcase/by_owner', keys=keys, include_docs=True, reduce=False ): # we'll be screwing with this guy, so make him unsaveable case.save = None for i in range(factor - 1): case._id = uuid.uuid4().hex case_block = get_case_xml(case, (const.CASE_ACTION_CREATE, const.CASE_ACTION_UPDATE), version='2.0') submit_case_blocks(case_block, domain) messages.success(request, "All of %s's cases were exploded by a factor of %d" % (user.raw_username, factor)) return render(request, template, { 'domain': domain, 'users': CommCareUser.by_domain(domain), })
def submit_mapping_case_block(user, index): mapping = user.get_location_map_case() if mapping: caseblock = CaseBlock( create=False, case_id=mapping._id, version=V2, index=index ) else: caseblock = CaseBlock( create=True, case_type=const.USER_LOCATION_OWNER_MAP_TYPE, case_id=location_map_case_id(user), version=V2, owner_id=user._id, index=index, case_name=const.USER_LOCATION_OWNER_MAP_TYPE.replace('-', ' '), user_id=const.COMMTRACK_USERNAME, ) submit_case_blocks( ElementTree.tostring( caseblock.as_xml(format_datetime=json_format_datetime) ), user.domain, )
def make_supply_point_product(supply_point_case, product_uuid): domain = supply_point_case.domain id = uuid.uuid4().hex user_id = get_commtrack_user_id(domain) username = const.COMMTRACK_USERNAME caseblock = CaseBlock( case_id=id, create=True, version=V2, user_id=user_id, case_type=const.SUPPLY_POINT_PRODUCT_CASE_TYPE, update={ "product": product_uuid }, index={ const.PARENT_CASE_REF: (const.SUPPLY_POINT_CASE_TYPE, supply_point_case._id), } ) casexml = ElementTree.tostring(caseblock.as_xml()) submit_case_blocks(casexml, domain, username, user_id) pc = CommCareCase.get(id) pc.location_ = supply_point_case.location_ pc.save() return pc
def create_requisition(user_id, product_stock_case, transaction): req = RequisitionState.from_transactions(user_id, product_stock_case, [transaction]) submit_case_blocks(req.to_xml(), req.domain, req.username, req.user_id) case = RequisitionCase.get(req.id) case.location_ = product_stock_case.location_ return case
def test_edit_submissions_simple(self): initial_quantity = 100 form = submit_case_blocks( case_blocks=get_single_balance_block(quantity=initial_quantity, **self._stock_state_key), domain=self.domain, )[0] self._assert_stats(1, initial_quantity, initial_quantity) case_accessors = CaseAccessors(self.domain) case = case_accessors.get_case(self.case.case_id) try: self.assertTrue(any([action.is_ledger_transaction for action in case.actions])) except AttributeError: self.assertTrue('commtrack' in [action.action_type for action in case.actions]) self.assertEqual([form.form_id], case.xform_ids[1:]) # change the value to 50 edit_quantity = 50 submit_case_blocks( case_blocks=get_single_balance_block(quantity=edit_quantity, **self._stock_state_key), domain=self.domain, form_id=form.form_id, ) case = case_accessors.get_case(self.case.case_id) try: # CaseTransaction self.assertTrue(any([action.is_ledger_transaction for action in case.actions])) except AttributeError: # CaseAction self.assertTrue('commtrack' in [action.action_type for action in case.actions]) self._assert_stats(1, edit_quantity, edit_quantity) self.assertEqual([form.form_id], case.xform_ids[1:])
def submit_location_block(self, caseblock): submit_case_blocks( ElementTree.tostring(caseblock.as_xml(format_datetime=json_format_datetime)), self.domain, self.username, self._id )
def create_case_from_dhis2(dhis2_child, domain, user): """ Create a new case using the data pulled from DHIS2 :param dhis2_child: TRACKED_ENTITY (i.e. "Child") from DHIS2 :param domain: (str) The name of the domain :param user: (Document) The owner of the new case :return: New case ID """ case_id = uuid.uuid4().hex update = {k: dhis2_child[v] for k, v in NUTRITION_ASSESSMENT_PROGRAM_FIELDS.iteritems()} update['dhis_org_id'] = dhis2_child['Org unit'] # Do the inverse of push_case() to 'Gender' / 'child_gender' if 'child_gender' in update: if update['child_gender'] == 'Undefined': del update['child_gender'] else: update['child_gender'] = update['child_gender'].lower() caseblock = CaseBlock( create=True, case_id=case_id, owner_id=user.userID, user_id=user.userID, case_type=CASE_TYPE, case_name=update[CASE_NAME] if CASE_NAME else '', external_id=dhis2_child['Instance'], update=update ) casexml = ElementTree.tostring(caseblock.as_xml()) submit_case_blocks(casexml, domain) return case_id
def test_get_ledger_values_for_case_as_of(self): case_id = uuid.uuid4().hex form_xml = get_simple_form_xml(uuid.uuid4().hex, case_id) submit_form_locally(form_xml, domain=self.domain)[1] # submit ledger data balances = ( (self.product_a._id, 100), (self.product_b._id, 50), ) ledger_blocks = [ get_single_balance_block(case_id, prod_id, balance) for prod_id, balance in balances ] submit_case_blocks(ledger_blocks, self.domain) # check results results = get_ledger_values_for_case_as_of( domain=self.domain, case_id=case_id, section_id='stock', as_of=datetime.utcnow()) self.assertEqual(2, len(results)) self.assertEqual(100, results[self.product_a._id]) self.assertEqual(50, results[self.product_b._id]) # check the date filter works before_data = datetime.utcnow() - timedelta(days=2) self.assertEqual({}, get_ledger_values_for_case_as_of( domain=self.domain, case_id=case_id, section_id='stock', as_of=before_data))
def explode_cases(request, domain, template="hqcase/explode_cases.html"): if request.method == 'POST': user_id = request.POST['user_id'] user = CommCareUser.get_by_user_id(user_id, domain) factor = request.POST.get('factor', '2') try: factor = int(factor) except ValueError: messages.error(request, 'factor must be an int; was: %s' % factor) else: keys = [[domain, owner_id, False] for owner_id in user.get_owner_ids()] for case in CommCareCase.view('hqcase/by_owner', keys=keys, include_docs=True, reduce=False ): for i in range(factor - 1): new_case_id = uuid.uuid4().hex case_block, attachments = make_creating_casexml(case, new_case_id) submit_case_blocks(case_block, domain, attachments=attachments) messages.success(request, "All of %s's cases were exploded by a factor of %d" % (user.raw_username, factor)) return render(request, template, { 'domain': domain, 'users': CommCareUser.by_domain(domain), })
def set_schedule_case_properties(pact_case): """ Sets the required schedule case properties on the case if they are different from the current case properties. See the README for more information. """ SCHEDULE_CASE_PROPERTY_PREFIX = 'dotSchedule' DAYS = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'] current_schedule = pact_case.current_schedule if current_schedule is not None: to_change = {} for day in DAYS: case_property_name = '{}{}'.format(SCHEDULE_CASE_PROPERTY_PREFIX, day) from_case = getattr(pact_case, case_property_name, None) from_schedule = current_schedule[day] if (from_case or from_schedule) and from_case != from_schedule: to_change[case_property_name] = current_schedule[day] if to_change: case_block = CaseBlock( case_id=pact_case._id, update=to_change, ).as_xml() submit_case_blocks( [ElementTree.tostring(case_block)], 'pact', device_id=__name__ + ".set_schedule_case_properties", )
def test_ledger_pillow(self): factory = CaseFactory(domain=self.domain) case = factory.create_case() consumer = get_test_kafka_consumer(topics.LEDGER) # have to get the seq id before the change is processed kafka_seq = get_topic_offset(topics.LEDGER) from corehq.apps.commtrack.tests.util import get_single_balance_block from corehq.apps.hqcase.utils import submit_case_blocks submit_case_blocks([ get_single_balance_block(case.case_id, self.product_id, 100)], self.domain ) ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id) # confirm change made it to kafka message = consumer.next() change_meta = change_meta_from_kafka_message(message.value) if should_use_sql_backend(self.domain): self.assertEqual(ref.as_id(), change_meta.document_id) else: from corehq.apps.commtrack.models import StockState state = StockState.objects.all() self.assertEqual(1, len(state)) self.assertEqual(state[0].pk, change_meta.document_id) # self.assertEqual(self.domain, change_meta.domain) # send to elasticsearch self.pillow.process_changes(since=kafka_seq, forever=False) self.elasticsearch.indices.refresh(LEDGER_INDEX_INFO.index) # confirm change made it to elasticserach self._assert_ledger_in_es(ref)
def test_get_ledger_values_for_case_as_of_same_date(self): case_id = uuid.uuid4().hex form_xml = get_simple_form_xml(uuid.uuid4().hex, case_id) submit_form_locally(form_xml, domain=self.domain)[1] # submit ledger data balances = ((self.product_a._id, 100), ) ledger_blocks = [ get_single_balance_block(case_id, prod_id, balance) for prod_id, balance in balances ] submit_case_blocks(ledger_blocks, self.domain) # submit two transfers at the same time transfer_date = json_format_datetime(datetime.utcnow()) transfers = [ (self.product_a._id, 1, transfer_date), (self.product_a._id, 2, transfer_date), ] for prod_id, transfer, date in transfers: submit_case_blocks( get_single_transfer_block(case_id, None, prod_id, transfer, date), self.domain) # check results results = get_ledger_values_for_case_as_of(domain=self.domain, case_id=case_id, section_id='stock', as_of=datetime.utcnow()) self.assertEqual(1, len(results)) self.assertEqual(97, results[self.product_a._id])
def submit_location_block(self, caseblock): submit_case_blocks( ElementTree.tostring(caseblock.as_xml()), self.domain, self.username, self._id )
def submit_mapping_case_block(user, index): mapping = user.get_location_map_case() if mapping: caseblock = CaseBlock( create=False, case_id=mapping._id, version=V2, index=index ) else: caseblock = CaseBlock( create=True, case_type=USER_LOCATION_OWNER_MAP_TYPE, case_id=location_map_case_id(user), version=V2, owner_id=user._id, index=index ) submit_case_blocks( ElementTree.tostring(caseblock.as_xml()), user.domain, user.username, user._id )
def test_get_ledger_values_for_case_as_of_same_date(self): case_id = uuid.uuid4().hex form_xml = get_simple_form_xml(uuid.uuid4().hex, case_id) submit_form_locally(form_xml, domain=self.domain)[1] # submit ledger data balances = ( (self.product_a._id, 100), ) ledger_blocks = [ get_single_balance_block(case_id, prod_id, balance) for prod_id, balance in balances ] submit_case_blocks(ledger_blocks, self.domain) # submit two transfers at the same time transfer_date = json_format_datetime(datetime.utcnow()) transfers = [ (self.product_a._id, 1, transfer_date), (self.product_a._id, 2, transfer_date), ] for prod_id, transfer, date in transfers: submit_case_blocks(get_single_transfer_block(case_id, None, prod_id, transfer, date), self.domain) # check results results = get_ledger_values_for_case_as_of( domain=self.domain, case_id=case_id, section_id='stock', as_of=datetime.utcnow()) self.assertEqual(1, len(results)) self.assertEqual(97, results[self.product_a._id])
def _from_caseblock(cls, domain, caseblock): username = const.COMMTRACK_USERNAME casexml = ElementTree.tostring(caseblock.as_xml()) submit_case_blocks( casexml, domain, username, const.get_commtrack_user_id(domain), xmlns=const.COMMTRACK_SUPPLY_POINT_XMLNS ) return cls.get(caseblock._id)
def make_supply_point_product(supply_point_case, product_uuid, owner_id=None): domain = supply_point_case.domain id = uuid.uuid4().hex user_id = const.get_commtrack_user_id(domain) owner_id = owner_id or get_owner_id(supply_point_case) or user_id username = const.COMMTRACK_USERNAME product_name = Product.get(product_uuid).name caseblock = CaseBlock( case_id=id, create=True, version=V2, case_name=product_name, user_id=user_id, owner_id=owner_id, case_type=const.SUPPLY_POINT_PRODUCT_CASE_TYPE, update={ "product": product_uuid }, index={ const.PARENT_CASE_REF: (const.SUPPLY_POINT_CASE_TYPE, supply_point_case._id), } ) casexml = ElementTree.tostring(caseblock.as_xml()) submit_case_blocks(casexml, domain, username, user_id, xmlns=const.COMMTRACK_SUPPLY_POINT_PRODUCT_XMLNS) sppc = SupplyPointProductCase.get(id) sppc.bind_to_location(supply_point_case.location) sppc.save() return sppc
def update_patient(repeater, patient_uuid): """ Fetch patient from OpenMRS, submit case update for all mapped case properties. .. NOTE:: OpenMRS UUID must be saved to "external_id" case property """ _assert( len(repeater.white_listed_case_types) == 1, 'Unable to update patients from OpenMRS unless a single case type is ' 'specified. domain: "{}". repeater: "{}".'.format( repeater.domain, repeater.get_id ) ) case_type = repeater.white_listed_case_types[0] patient = get_patient_by_uuid(repeater.requests, patient_uuid) case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if error == LookupErrors.NotFound: owner = get_one_commcare_user_at_location(repeater.domain, repeater.location_id) _assert( owner, 'No users found at location "{}" to own patients added from ' 'OpenMRS atom feed. domain: "{}". repeater: "{}".'.format( repeater.location_id, repeater.domain, repeater.get_id ) ) case_block = get_addpatient_caseblock(case_type, owner, patient, repeater) else: _assert( error != LookupErrors.MultipleResults, # Multiple cases matched to the same patient. # Could be caused by: # * The cases were given the same identifier value. It could # be user error, or case config assumed identifier was # unique but it wasn't. # * PatientFinder matched badly. # * Race condition where a patient was previously added to # both CommCare and OpenMRS. 'More than one case found matching unique OpenMRS UUID. ' 'domain: "{}". case external_id: "{}". repeater: "{}".'.format( repeater.domain, patient_uuid, repeater.get_id ) ) case_block = get_updatepatient_caseblock(case, patient, repeater) if case_block: submit_case_blocks( [case_block.as_string()], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def process_bulk_docs(self, docs, progress_logger): if docs: updates = {doc['_id']: {PHONE_NUMBER_PROPERTY: ''} for doc in docs} for doc in docs: progress_logger.document_processed(doc, updates[doc['_id']]) submit_case_blocks(self._create_case_blocks(updates), self.domain, user_id=SYSTEM_USER_ID) return True
def _submit_caseblocks(caseblocks): if caseblocks: submit_case_blocks( [ElementTree.tostring(cb.as_xml()) for cb in caseblocks], domain, username, user_id, )
def save_cases(clays: List[CassiusMarcellus]): today = date.today().isoformat() submit_case_blocks( [clay.case_block.as_text() for clay in clays], DOMAIN, xmlns='http://commcarehq.org/dhis2-import', device_id=f"dhis2-import-{DOMAIN}-{today}", )
def update_patient(repeater, patient_uuid): """ Fetch patient from OpenMRS, submit case update for all mapped case properties. .. NOTE:: OpenMRS UUID must be saved to "external_id" case property """ if len(repeater.white_listed_case_types) != 1: raise ConfigurationError( _(f'{repeater.domain}: {repeater}: Error in settings: Unable to update ' f'patients from OpenMRS unless only one case type is specified.') ) case_type = repeater.white_listed_case_types[0] try: patient = get_patient_by_uuid(repeater.requests, patient_uuid) except (RequestException, ValueError) as err: raise OpenmrsException( _(f'{repeater.domain}: {repeater}: Error fetching Patient ' f'{patient_uuid!r}: {err}')) from err case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if error == LookupErrors.NotFound: if not repeater.openmrs_config.case_config.import_creates_cases: # We can't create cases via the Atom feed, just update them. # Nothing to do here. return default_owner: Optional[CommCareUser] = repeater.first_user case_block = get_addpatient_caseblock(case_type, default_owner, patient, repeater) elif error == LookupErrors.MultipleResults: # Multiple cases have been matched to the same patient. # Could be caused by: # * The cases were given the same identifier value. It could # be user error, or case config assumed identifier was # unique but it wasn't. # * PatientFinder matched badly. # * Race condition where a patient was previously added to # both CommCare and OpenMRS. raise DuplicateCaseMatch( _(f'{repeater.domain}: {repeater}: More than one case found ' f'matching unique OpenMRS UUID. case external_id: "{patient_uuid}"' )) else: case_block = get_updatepatient_caseblock(case, patient, repeater) if case_block: submit_case_blocks( [case_block.as_text()], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def setUpClass(cls): super(ImmunizationUtilTestCase, cls).setUpClass() cls.ccs_record = cls.create_case('ccs_record', update={'edd': '2017-08-01'}) cls.tasks_pregnancy = cls.create_case( 'tasks', parent_case_id=cls.ccs_record.case_id, parent_case_type='ccs_record', parent_identifier='parent', parent_relationship='extension', update={ 'tasks_type': 'pregnancy', 'schedule_flag': 'tt_norm' }) cls.person_child = cls.create_case('person', update={'dob': '2017-08-10'}) cls.child_health = cls.create_case( 'child_health', parent_case_id=cls.person_child.case_id, parent_case_type='person', parent_identifier='parent', parent_relationship='extension') cls.tasks_child = cls.create_case( 'tasks', parent_case_id=cls.child_health.case_id, parent_case_type='child_health', parent_identifier='parent', parent_relationship='extension', update={'tasks_type': 'child'}) cls.lone_tasks_case = cls.create_case('tasks', update={'tasks_type': 'child'}) cls.dpt2 = cls.create_product('2g_dpt_2', 'child', '70', '730', '1g_dpt_1', '28') cls.dpt3 = cls.create_product('3g_dpt_3', 'child', '98', '730', '2g_dpt_2', '28') cls.tt1 = cls.create_product('tt_1', 'pregnancy', '-274', '180', schedule_flag='tt_norm') cls.ttbooster = cls.create_product('tt_booster', 'pregnancy', '-1096', '180', schedule_flag='tt_boost') cls.anc1 = cls.create_product('anc_1', 'pregnancy', '-274', '180') cls.anc2 = cls.create_product('anc_2', 'pregnancy', '-274', '180', 'anc_1', '30') submit_case_blocks( get_single_balance_block(cls.lone_tasks_case.case_id, cls.dpt2.get_id, 17400, section_id='immuns'), cls.domain)
def _submit_commtrack_caseblock(domain, caseblock, source): submit_case_blocks( caseblock.as_text(), domain, const.COMMTRACK_USERNAME, const.get_commtrack_user_id(domain), xmlns=const.COMMTRACK_SUPPLY_POINT_XMLNS, device_id=__name__ + "." + source, )
def test_parent_and_child_cases(self): fake_case_es = FakeXFormES(ESCase) v0_3.MOCK_CASE_ES = fake_case_es # Create cases parent_case_id = uuid.uuid4().hex parent_type = 'parent_case_type' parent_case = submit_case_blocks( CaseBlock( case_id=parent_case_id, create=True, case_type=parent_type, ).as_text(), self.domain.name)[1][0] child_case_id = uuid.uuid4().hex child_case = submit_case_blocks( CaseBlock(case_id=child_case_id, create=True, index={ 'parent': (parent_type, parent_case_id) }).as_text(), self.domain.name)[1][0] fake_case_es.add_doc( parent_case_id, transform_case_for_elasticsearch(parent_case.to_json())) fake_case_es.add_doc( child_case_id, transform_case_for_elasticsearch(child_case.to_json())) # Fetch the child case through the API response = self._assert_auth_get_resource( self.single_endpoint(child_case_id) + "?parent_cases__full=true") self.assertEqual( response.status_code, 200, "Status code was not 200. Response content was {}".format( response.content)) parent_cases = list( json.loads(response.content)['parent_cases'].values()) # Confirm that the case appears in the resource self.assertEqual(len(parent_cases), 1) self.assertEqual(parent_cases[0]['id'], parent_case_id) # Fetch the parent case through the API response = self._assert_auth_get_resource( self.single_endpoint(parent_case_id) + "?child_cases__full=true") self.assertEqual( response.status_code, 200, "Status code was not 200. Response content was {}".format( response.content)) child_cases = list( json.loads(response.content)['child_cases'].values()) # Confirm that the case appears in the resource self.assertEqual(len(child_cases), 1) self.assertEqual(child_cases[0]['id'], child_case_id)
def save_cases(case_blocks): today = date.today().isoformat() for chunk in chunked(case_blocks, 1000, collection=list): submit_case_blocks( [cb.as_text() for cb in chunk], DOMAIN, xmlns='http://commcarehq.org/dhis2-import', device_id=f"dhis2-import-{DOMAIN}-{today}", )
def create_cases_for_types(domain, case_types): for i, case_type in enumerate(case_types): submit_case_blocks( CaseBlock( create=True, case_id=uuid.uuid4().hex, case_type=case_type, user_id=uuid.uuid4().hex, ).as_string(), domain)
def bulk_update_ledger_cases(domain, ledger_updates): case_blocks = [] for episode_case_id, entry_id, balance in ledger_updates: balance = _ledger_update_xml(episode_case_id, entry_id, balance) case_blocks.append(balance.as_string()) if case_blocks: submit_case_blocks(case_blocks, domain, device_id=LEDGER_UPDATE_DEVICE_ID)
def queue_case(new_case, queue, progress): queue.append(new_case) if len(queue) >= 500: # submit 500 cases at a time submit_case_blocks(queue, domain, user_id=user_id, device_id="explode_cases") progress += len(queue) if task: DownloadBase.set_progress(explode_case_task, progress, total_cases) del queue[:] return progress
def _receipt_report(domain, case_id, product_id, amount, days_ago): from corehq.apps.commtrack.tests.util import get_single_transfer_block from dimagi.utils.parsing import json_format_date from corehq.apps.hqcase.utils import submit_case_blocks date_string = json_format_date(ago(days_ago)) stock_block = get_single_transfer_block( src_id=None, dest_id=case_id, product_id=product_id, quantity=amount, date_string=date_string ) submit_case_blocks(stock_block, domain=domain)
def create_person_cases(owner_id): """ Creates cases for Fred Foo and Barbara Bar. """ different_owner_id = uuid4().hex submit_case_blocks([ get_foo_caseblock(owner_id).as_text(), get_bar_caseblock(owner_id).as_text(), get_baz_caseblock(different_owner_id).as_text(), ], DOMAIN)
def create_cases_for_types(domain, case_types): for i, case_type in enumerate(case_types): submit_case_blocks( CaseBlock( create=True, case_id='person%s' % i, case_type=case_type, user_id='user%s' % i, version=V2, ).as_string(), domain)
def reassign_cases(domain, case_ids, new_owner_id): case_blocks = [] for case_id in case_ids: case_block = CaseBlock(case_id, owner_id=new_owner_id, user_id=SYSTEM_USER_ID) case_block = ElementTree.tostring(case_block.as_xml()).decode('utf-8') case_blocks.append(case_block) if case_blocks: submit_case_blocks(case_blocks, domain, user_id=SYSTEM_USER_ID)
def test_parent_and_child_cases(self): # Create cases parent_case_id = uuid.uuid4().hex parent_type = 'parent_case_type' parent_case = submit_case_blocks( CaseBlock( case_id=parent_case_id, create=True, case_type=parent_type, ).as_text(), self.domain.name)[1][0] child_case_id = uuid.uuid4().hex child_case = submit_case_blocks( CaseBlock(case_id=child_case_id, create=True, index={ 'parent': (parent_type, parent_case_id) }).as_text(), self.domain.name)[1][0] self.addCleanup(child_case.delete) self.addCleanup(parent_case.delete) send_to_elasticsearch( 'cases', transform_case_for_elasticsearch(parent_case.to_json())) send_to_elasticsearch( 'cases', transform_case_for_elasticsearch(child_case.to_json())) self.es.indices.refresh(CASE_INDEX_INFO.index) # Fetch the child case through the API response = self._assert_auth_get_resource( self.single_endpoint(child_case_id) + "?parent_cases__full=true") self.assertEqual( response.status_code, 200, f"Status code was not 200. Response content was {response.content!r}" ) parent_cases = list( json.loads(response.content)['parent_cases'].values()) # Confirm that the case appears in the resource self.assertEqual(len(parent_cases), 1) self.assertEqual(parent_cases[0]['id'], parent_case_id) # Fetch the parent case through the API response = self._assert_auth_get_resource( self.single_endpoint(parent_case_id) + "?child_cases__full=true") self.assertEqual( response.status_code, 200, f"Status code was not 200. Response content was {response.content!r}" ) child_cases = list( json.loads(response.content)['child_cases'].values()) # Confirm that the case appears in the resource self.assertEqual(len(child_cases), 1) self.assertEqual(child_cases[0]['id'], child_case_id)
def test_reprocess_unfinished_submission_ledger_rebuild(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex form_ids = [] form_ids.append( submit_case_blocks([ CaseBlock(case_id=case_id, create=True, case_type='shop').as_text(), get_single_balance_block(case_id, 'product1', 100), ], self.domain)[0].form_id) with _patch_save_to_raise_error(self): submit_case_blocks( get_single_balance_block(case_id, 'product1', 50), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) form_ids.append(stubs[0].xform_id) # submit another form afterwards form_ids.append( submit_case_blocks( get_single_balance_block(case_id, 'product1', 25), self.domain)[0].form_id) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) self.assertEqual(25, ledgers[0].balance) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case( case_id) self.assertEqual(2, len(ledger_transactions)) # should rebuild ledger transactions result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(1, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = self.ledgerdb.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) # still only 1 self.assertEqual(25, ledgers[0].balance) ledger_transactions = self.ledgerdb.get_ledger_transactions_for_case( case_id) self.assertEqual(3, len(ledger_transactions)) # make sure transactions are in correct order self.assertEqual(form_ids, [trans.form_id for trans in ledger_transactions]) self.assertEqual(100, ledger_transactions[0].updated_balance) self.assertEqual(100, ledger_transactions[0].delta) self.assertEqual(50, ledger_transactions[1].updated_balance) self.assertEqual(-50, ledger_transactions[1].delta) self.assertEqual(25, ledger_transactions[2].updated_balance) self.assertEqual(-25, ledger_transactions[2].delta)
def update_patient(repeater, patient_uuid): """ Fetch patient from OpenMRS, submit case update for all mapped case properties. .. NOTE:: OpenMRS UUID must be saved to "external_id" case property """ _assert( len(repeater.white_listed_case_types) == 1, 'Unable to update patients from OpenMRS unless a single case type is ' 'specified. domain: "{}". repeater: "{}".'.format( repeater.domain, repeater.get_id)) case_type = repeater.white_listed_case_types[0] patient = get_patient_by_uuid(repeater.requests, patient_uuid) case, error = importer_util.lookup_case( EXTERNAL_ID, patient_uuid, repeater.domain, case_type=case_type, ) if error == LookupErrors.NotFound: owner = get_one_commcare_user_at_location(repeater.domain, repeater.location_id) _assert( owner, 'No users found at location "{}" to own patients added from ' 'OpenMRS atom feed. domain: "{}". repeater: "{}".'.format( repeater.location_id, repeater.domain, repeater.get_id)) case_block = get_addpatient_caseblock(case_type, owner, patient, repeater) else: _assert( error != LookupErrors.MultipleResults, # Multiple cases matched to the same patient. # Could be caused by: # * The cases were given the same identifier value. It could # be user error, or case config assumed identifier was # unique but it wasn't. # * PatientFinder matched badly. # * Race condition where a patient was previously added to # both CommCare and OpenMRS. 'More than one case found matching unique OpenMRS UUID. ' 'domain: "{}". case external_id: "{}". repeater: "{}".'.format( repeater.domain, patient_uuid, repeater.get_id)) case_block = get_updatepatient_caseblock(case, patient, repeater) if case_block: submit_case_blocks( [case_block.as_text()], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def test_conflicting_ids(self): """ If a form and a case share an ID it's a conflict """ conflict_id = uuid.uuid4().hex case_block = CaseBlock( case_id=conflict_id, create=True, ).as_string() with self.assertRaises(BulkSaveError): submit_case_blocks(case_block, 'test-conflicts', form_id=conflict_id)
def _submit_caseblocks(caseblocks): if caseblocks: submit_case_blocks( [ ElementTree.tostring( cb.as_xml(format_datetime=json_format_datetime)) for cb in caseblocks ], domain, username, user_id, )
def test_reprocess_unfinished_submission_ledger_create(self): from corehq.apps.commtrack.tests.util import get_single_balance_block case_id = uuid.uuid4().hex self.factory.create_or_update_cases([ CaseStructure(case_id=case_id, attrs={ 'case_type': 'parent', 'create': True }) ]) transaction_patch = patch( 'corehq.form_processor.backends.sql.processor.transaction') ledger_save_patch = patch( 'corehq.form_processor.backends.sql.dbaccessors.LedgerAccessorSQL.save_ledger_values', side_effect=InternalError) with transaction_patch, ledger_save_patch, self.assertRaises( InternalError): submit_case_blocks( get_single_balance_block(case_id, 'product1', 100), self.domain) stubs = UnfinishedSubmissionStub.objects.filter(domain=self.domain, saved=False).all() self.assertEqual(1, len(stubs)) ledgers = LedgerAccessorSQL.get_ledger_values_for_case(case_id) self.assertEqual(0, len(ledgers)) # case transaction got saved case = CaseAccessorSQL.get_case(case_id) self.assertEqual(2, len(case.transactions)) self.assertTrue(case.transactions[0].is_case_create) self.assertTrue(case.transactions[1].is_ledger_transaction) ledger_transactions = LedgerAccessorSQL.get_ledger_transactions_for_case( case_id) self.assertEqual(0, len(ledger_transactions)) result = reprocess_unfinished_stub(stubs[0]) self.assertEqual(0, len(result.cases)) self.assertEqual(1, len(result.ledgers)) ledgers = LedgerAccessorSQL.get_ledger_values_for_case(case_id) self.assertEqual(1, len(ledgers)) ledger_transactions = LedgerAccessorSQL.get_ledger_transactions_for_case( case_id) self.assertEqual(1, len(ledger_transactions)) # case still only has 2 transactions case = CaseAccessorSQL.get_case(case_id) self.assertEqual(2, len(case.transactions))
def commit(cls, helpers): case_blocks = list(chain.from_iterable([h.case_blocks for h in helpers])) if not case_blocks: assert not any(h.tasks for h in helpers), [h.tasks for h in helpers] return assert len({h.user_id for h in helpers}) == 1 assert len({h.domain for h in helpers}) == 1 case_blocks = [cb.as_text() for cb in case_blocks] submit_case_blocks(case_blocks, helpers[0].domain, device_id=cls.CASE_SOURCE_ID) for task, task_args in chain.from_iterable([h.tasks for h in helpers]): task.delay(*task_args)
def update_case(repeater, case_id, case_block_kwargs, case_blocks): case_blocks.append(CaseBlock( case_id=case_id, create=False, **case_block_kwargs, )) submit_case_blocks( [cb.as_text() for cb in case_blocks], repeater.domain, xmlns=XMLNS_OPENMRS, device_id=OPENMRS_ATOM_FEED_DEVICE_ID + repeater.get_id, )
def save_case_updates(domain, case_id, case_updates): case_update = {} kwargs = {} for case_property, value in case_updates.items(): if case_property == "external_id": kwargs[case_property] = value else: case_update[case_property] = value case_block = CaseBlock(case_id=case_id, create=False, update=case_update, **kwargs) submit_case_blocks([case_block.as_text()], domain, xmlns=XMLNS_DHIS2)
def test_get_document(self): from corehq.apps.commtrack.tests.util import get_single_balance_block block = get_single_balance_block(self.case.case_id, self.product_a._id, 100) submit_case_blocks(block, DOMAIN) from corehq.apps.commtrack.models import StockState stock_states = StockState.include_archived.all() self.assertEquals(1, len(stock_states)) state = stock_states[0] store = LedgerV1DocumentStore(DOMAIN) doc = store.get_document(state.id) self.assertEquals(int(doc['_id']), state.id) self.assertEquals(doc['case_id'], state.case_id)