def get(self, case_id): if not case_id: raise IllegalCaseId('case_id must not be empty') if case_id in self.cache: return self.cache[case_id] try: if self.strip_history: case_doc = CommCareCase.get_lite(case_id, wrap=self.wrap) elif self.lock: try: case_doc, lock = CommCareCase.get_locked_obj(_id=case_id) except redis.RedisError: case_doc = CommCareCase.get(case_id) else: self.locks.append(lock) else: if self.wrap: case_doc = CommCareCase.get(case_id) else: case_doc = CommCareCase.get_db().get(case_id) except ResourceNotFound: return None self.validate_doc(case_doc) self.cache[case_id] = case_doc return case_doc
def test_couch_action_equality(self): case_id = _post_util(create=True) _post_util(case_id=case_id, p1='p1', p2='p2') case = CommCareCase.get(case_id) self.assertEqual(3, len(case.actions)) # (1) create & (2) update date opened (3) update properties self.assertTrue(case.actions[0] != case.actions[1]) self.assertTrue(case.actions[1] == case.actions[1]) orig = case.actions[1] copy = CommCareCaseAction.wrap(orig._doc.copy()) self.assertTrue(copy != case.actions[0]) self.assertTrue(copy == orig) copy.server_date = copy.server_date + timedelta(seconds=1) self.assertTrue(copy != orig) copy.server_date = orig.server_date self.assertTrue(copy == orig) copy.updated_unknown_properties['p1'] = 'not-p1' self.assertTrue(copy != orig) copy.updated_unknown_properties['p1'] = 'p1' self.assertTrue(copy == orig) copy.updated_unknown_properties['pnew'] = '' self.assertTrue(copy != orig)
def testDuplicateCasePropertiesBug(self): """ How do we do when submitting multiple values for the same property in an update block """ file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property is there, but empty self.assertEqual("", case.foo) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties_2.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property takes the last defined value self.assertEqual("2", case.bar)
def testArchivingOnlyForm(self): """ Checks that archiving the only form associated with the case archives the case and unarchiving unarchives it. """ case_id = _post_util(create=True, p1='p1-1', p2='p2-1') case = CommCareCase.get(case_id) self.assertEqual('CommCareCase', case._doc['doc_type']) self.assertEqual(2, len(case.actions)) [form_id] = case.xform_ids form = XFormInstance.get(form_id) form.archive() case = CommCareCase.get(case_id) self.assertEqual('CommCareCase-Deleted', case._doc['doc_type']) # should just have the 'rebuild' action self.assertEqual(1, len(case.actions)) self.assertEqual(const.CASE_ACTION_REBUILD, case.actions[0].action_type) form.unarchive() case = CommCareCase.get(case_id) self.assertEqual('CommCareCase', case._doc['doc_type']) self.assertEqual(3, len(case.actions)) self.assertEqual(const.CASE_ACTION_REBUILD, case.actions[-1].action_type)
def test_date_case_properties_for_inequality(self): case = CommCareCase( domain=self.domain, type='test-case-type-2', ) self.rule2.automaticupdaterulecriteria_set = [ AutomaticUpdateRuleCriteria( property_name='property1', property_value='2016-02-24', match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL, ), ] case.set_case_property('property1', '2016-02-24') case.save() case = CommCareCase.get(case.get_id) case.server_modified_on = datetime(2015, 1, 1) self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1))) case.set_case_property('property1', '2016-02-25') case.save() case = CommCareCase.get(case.get_id) case.server_modified_on = datetime(2015, 1, 1) self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1))) case.delete()
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 testDuplicateCasePropertiesBug(self): """ How do we do when submitting multiple values for the same property in an update block """ self.assertEqual( 0, len(CommCareCase.view("case/by_user", reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property is there, but empty self.assertEqual("", case.foo) file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", "duplicate_case_properties_2.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get(form.xpath("form/case/@case_id")) # make sure the property takes the last defined value self.assertEqual("2", case.bar)
def testSubmitToDeletedCase(self): # submitting to a deleted case should succeed and affect the case case_id = 'immagetdeleted' deleted_doc_type = 'CommCareCase-Deleted' post_case_blocks([ CaseBlock(create=True, case_id=case_id, user_id='whatever', version=V2, update={ 'foo': 'bar' }).as_xml() ]) case = CommCareCase.get(case_id) self.assertEqual('bar', case.foo) # hack copy how we delete things case.doc_type = deleted_doc_type case.save() self.assertEqual(deleted_doc_type, case.doc_type) post_case_blocks([ CaseBlock(create=False, case_id=case_id, user_id='whatever', version=V2, update={ 'foo': 'not_bar' }).as_xml() ]) case = CommCareCase.get(case_id) self.assertEqual('not_bar', case.foo) self.assertEqual(deleted_doc_type, case.doc_type)
def get_cases(request, domain): if request.couch_user.is_commcare_user(): user_id = request.couch_user.get_id else: user_id = request.REQUEST.get("user_id", "") if not user_id and not request.couch_user.is_web_user(): return HttpResponseBadRequest("Must specify user_id!") ids_only = string_to_boolean(request.REQUEST.get("ids_only", "false")) case_id = request.REQUEST.get("case_id", "") footprint = string_to_boolean(request.REQUEST.get("footprint", "false")) if toggles.HSPH_HACK.enabled(domain): hsph_case_id = request.REQUEST.get('hsph_hack', None) if hsph_case_id != 'None' and hsph_case_id: case = CommCareCase.get(hsph_case_id) usercase_id = CommCareUser.get_by_user_id( user_id).get_usercase_id() usercase = CommCareCase.get(usercase_id) if usercase_id else None return json_response( map( lambda case: CaseAPIResult( id=case['_id'], couch_doc=case, id_only=ids_only), filter(None, [case, case.parent, usercase])))
def testBasicRebuild(self): case_id = post_util(create=True) post_util(case_id=case_id, p1='p1-1', p2='p2-1') post_util(case_id=case_id, p2='p2-2', p3='p3-2') # check initial state case = CommCareCase.get(case_id) self.assertEqual(case.p1, 'p1-1') # original self.assertEqual(case.p2, 'p2-2') # updated self.assertEqual(case.p3, 'p3-2') # new self.assertEqual(3, len(case.actions)) # create + 2 updates a1 = case.actions[1] self.assertEqual(a1.updated_unknown_properties['p1'], 'p1-1') self.assertEqual(a1.updated_unknown_properties['p2'], 'p2-1') a2 = case.actions[2] self.assertEqual(a2.updated_unknown_properties['p2'], 'p2-2') self.assertEqual(a2.updated_unknown_properties['p3'], 'p3-2') # rebuild by flipping the actions case.actions = [case.actions[0], a2, a1] case.xform_ids = [ case.xform_ids[0], case.xform_ids[2], case.xform_ids[1] ] case.rebuild() self.assertEqual(case.p1, 'p1-1') # original self.assertEqual(case.p2, 'p2-1') # updated (back!) self.assertEqual(case.p3, 'p3-2') # new
def test_couch_soft_rebuild(self): user_id = 'test-basic-rebuild-user' now = datetime.utcnow() case_id = _post_util(create=True, user_id=user_id, date_modified=now) _post_util(case_id=case_id, p1='p1-1', p2='p2-1', user_id=user_id, date_modified=now) _post_util(case_id=case_id, p2='p2-2', p3='p3-2', user_id=user_id, date_modified=now) # check initial state case = CommCareCase.get(case_id) self.assertEqual(case.p1, 'p1-1') # original self.assertEqual(case.p2, 'p2-2') # updated self.assertEqual(case.p3, 'p3-2') # new self.assertEqual(4, len(case.actions)) # create + update (2 actions) + 2 updates a0 = case.actions[1] self.assertEqual(a0.updated_known_properties['opened_on'], case.opened_on.date()) a1 = case.actions[2] self.assertEqual(a1.updated_unknown_properties['p1'], 'p1-1') self.assertEqual(a1.updated_unknown_properties['p2'], 'p2-1') a2 = case.actions[3] self.assertEqual(a2.updated_unknown_properties['p2'], 'p2-2') self.assertEqual(a2.updated_unknown_properties['p3'], 'p3-2') # rebuild by flipping the actions case.actions = [case.actions[0], a2, a1] case.xform_ids = [case.xform_ids[0], case.xform_ids[2], case.xform_ids[1]] CouchCaseUpdateStrategy(case).soft_rebuild_case() self.assertEqual(case.p1, 'p1-1') # original self.assertEqual(case.p2, 'p2-1') # updated (back!) self.assertEqual(case.p3, 'p3-2') # new
def change_transform(self, doc_dict): txs = doc_dict['form'].get('transaction', []) if not isinstance(txs, collections.Sequence): txs = [txs] touched_products = set(tx['product_entry'] for tx in txs) action_defs = Domain.get_by_name( doc_dict['domain']).commtrack_settings.all_actions_by_name def get_base_action(action): try: return action_defs[action].action_type except KeyError: # this arises because inferred transactions might not map cleanly to user-defined action types # need to find a more understandable solution if action in ACTION_TYPES: return action else: raise for case_id in touched_products: rate = compute_consumption(case_id, from_ts(doc_dict['received_on']), get_base_action) try: case = CommCareCase.get(case_id) set_computed(case, 'consumption_rate', rate) case.save() except ResourceNotFound: # maybe the case was deleted. for now we don't care about this pillow_logging.info( 'skipping commtrack update for deleted case %s' % case_id)
def testRecursiveUpdates(self): parent_case = self._make_case(self.other_user._id, self.other_user._id) case = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', parent_case._id)}) subcase1 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', case._id)}) subcase2 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', case._id)}) subsub1 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', subcase1._id)}) subsub2 = self._make_case(self.other_user._id, self.other_user._id, index={'parent': ('parent-case', subcase1._id)}) cases = [case, subcase1, subcase2, subsub1, subsub2] for c in cases: self.assertEqual(self.other_user._id, c.owner_id) reconcile_ownership(case, self.user, recursive=True) case = CommCareCase.get(case._id) owner = get_wrapped_owner(get_owner_id(case)) self.assertTrue(isinstance(owner, Group)) self.assertTrue(self.other_user._id in owner.users) self.assertTrue(self.user._id in owner.users) self.assertTrue(owner.case_sharing) self.assertFalse(owner.reporting) for c in cases: c = CommCareCase.get(c._id) self.assertEqual(owner._id, c.owner_id) parent_case = CommCareCase.get(parent_case._id) self.assertEqual(self.other_user._id, parent_case.owner_id)
def testAttachments(self): self.assertEqual(len(CommCareCase.get(self.case_id).case_attachments), 0) scan_path = os.path.join(os.path.dirname(__file__), "data", "vscan", "VH014466XK_000016_20130722T175057") files = self.pack_directory(scan_path) utils.attach_images_to_case(self.case_id, files) self.assertEqual(len(CommCareCase.get(self.case_id).case_attachments), 3)
def get_cases(request, domain): if request.couch_user.is_commcare_user(): user_id = request.couch_user.get_id else: user_id = request.REQUEST.get("user_id", "") if not user_id and not request.couch_user.is_web_user(): return HttpResponseBadRequest("Must specify user_id!") ids_only = string_to_boolean(request.REQUEST.get("ids_only", "false")) case_id = request.REQUEST.get("case_id", "") footprint = string_to_boolean(request.REQUEST.get("footprint", "false")) include_children = string_to_boolean( request.REQUEST.get("include_children", "false")) if case_id and not footprint and not include_children: # short circuit everything else and just return the case # NOTE: this allows any user in the domain to access any case given # they know its ID, which is slightly different from the previous # behavior (can only access things you own + footprint). If we want to # change this contract we would need to update this to check the # owned case list + footprint case = CommCareCase.get(case_id) assert case.domain == domain cases = [CaseAPIResult(id=case_id, couch_doc=case, id_only=ids_only)]
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(custom_format_args): case_id = uuid.uuid4().hex format_args = { 'case_id': case_id, 'form_id': uuid.uuid4().hex, 'user_id': uuid.uuid4().hex, 'case_name': 'data corner cases', 'case_type': 'datatype-check', } format_args.update(custom_format_args) for filename in [ 'bugs_in_case_create_datatypes.xml', 'bugs_in_case_update_datatypes.xml' ]: file_path = os.path.join(os.path.dirname(__file__), "data", "bugs", filename) with open(file_path, "rb") as f: xml_data = f.read() xml_data = xml_data.format(**format_args) form = post_xform_to_couch(xml_data) # before the bug was fixed this call failed process_cases(form) case = CommCareCase.get(case_id) self.assertEqual(format_args['user_id'], case.user_id) self.assertEqual(format_args['case_name'], case.name) self.assertEqual(format_args['case_type'], case.type)
def test_date_case_properties_for_equality(self): """ Date case properties are automatically converted from string to date when fetching from the db, so here we want to make sure this doesn't interfere with our ability to compare dates for equality. """ case = CommCareCase( domain=self.domain, type='test-case-type-2', ) self.rule2.automaticupdaterulecriteria_set = [ AutomaticUpdateRuleCriteria( property_name='property1', property_value='2016-02-24', match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL, ), ] case.set_case_property('property1', '2016-02-24') case.save() case = CommCareCase.get(case.get_id) case.server_modified_on = datetime(2015, 1, 1) self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1))) case.set_case_property('property1', '2016-02-25') case.save() case = CommCareCase.get(case.get_id) case.server_modified_on = datetime(2015, 1, 1) self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1))) case.delete()
def test_couch_reconcile_actions_different_ordering(self): created_at = datetime(2017, 12, 2, 10, 23, 14) case_id = _post_util(create=True, form_extras={'received_on': created_at}) # this case update is processed much later than the created date, # but the time on the phone (date_modified) is much before the time the server received it _post_util( case_id=case_id, p1='p1-1', date_modifed=datetime(2018, 1, 26, 20, 22, 20), form_extras={'received_on': datetime(2018, 2, 2, 8, 41, 53)} ) # this case update was received by the server before the previous update # however the date_modified is after the previous updates _post_util( case_id=case_id, p2='p2-2', date_modifed=datetime(2018, 2, 2, 8, 40, 43), form_extras={'received_on': datetime(2018, 2, 2, 8, 41, 0)} ) case = CommCareCase.get(case_id) update_strategy = CouchCaseUpdateStrategy(case) original_actions = [deepcopy(a) for a in case.actions] self._assertListEqual(original_actions, case.actions) # assert that the actions should not be reorder self.assertTrue(update_strategy.check_action_order()) # assert that if a re-ordering is attempted, it results in the same output update_strategy.reconcile_actions() self._assertListEqual(original_actions, case.actions)
def filter_cases(request, domain, app_id, module_id): app = Application.get(app_id) module = app.get_module(module_id) delegation = request.GET.get('task-list') == 'true' auth_cookie = request.COOKIES.get('sessionid') xpath = SuiteGenerator(app).get_filter_xpath(module, delegation=delegation) # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) if delegation: case_type = DELEGATION_STUB_CASE_TYPE else: case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } result = touchforms_api.filter_cases(domain, request.couch_user, xpath, additional_filters, auth=DjangoAuth(auth_cookie)) if result.get('status', None) == 'error': return HttpResponseServerError( result.get("message", _("Something went wrong filtering your cases."))) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [ res.id for res in get_filtered_cases(domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, footprint=True, ids_only=True) ] cases = [CommCareCase.get(id) for id in case_ids] # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json() for c in cases if c] parents = [] if delegation: for case in cases: parent_id = case['indices']['parent']['case_id'] parents.append(CommCareCase.get(parent_id)) return json_response({'cases': cases, 'parents': parents}) else: return json_response(cases)
def tearDown(self): try: # delete case, so that post of xform_xml creates new case as expected multiple-times CommCareCase.get(case_id).delete() except: pass for repeat_record in self.repeat_records(self.domain_name): repeat_record.delete()
def _check_state(self, new_owner_id, expected_changed): expected_ids = set(c._id for c in expected_changed) for case in expected_changed: expected = CommCareCase.get(case._id) self.assertEqual(new_owner_id, expected.owner_id) for case in (c for c in self.all if c._id not in expected_ids): remaining = CommCareCase.get(case._id) self.assertEqual(self.original_owner._id, remaining.owner_id)
def create_and_test(case_id, user, owner, should_have, should_not_have, version): case_block = self.get_create_block( case_id=case_id, type="case", user_id=user.user_id, owner_id=owner.get_id, version=version ) post_case_blocks([case_block], {"domain": self.domain}) CommCareCase.get(case_id) check_has_block(case_block, should_have, should_not_have, version=version)
def test_couch_reconcile_actions(self): now = datetime.utcnow() # make sure we timestamp everything so they have the right order case_id = _post_util(create=True, form_extras={'received_on': now}) _post_util(case_id=case_id, p1='p1-1', p2='p2-1', form_extras={'received_on': now + timedelta(seconds=1)}) _post_util(case_id=case_id, p2='p2-2', p3='p3-2', form_extras={'received_on': now + timedelta(seconds=2)}) case = CommCareCase.get(case_id) update_strategy = CouchCaseUpdateStrategy(case) original_actions = [deepcopy(a) for a in case.actions] original_form_ids = [id for id in case.xform_ids] self.assertEqual(4, len(original_actions)) self.assertEqual(3, len(original_form_ids)) self._assertListEqual(original_actions, case.actions) # test reordering case.actions = [ case.actions[3], case.actions[2], case.actions[1], case.actions[0] ] self._assertListNotEqual(original_actions, case.actions) update_strategy.reconcile_actions() self._assertListEqual(original_actions, case.actions) # test duplication case.actions = case.actions * 3 self.assertEqual(12, len(case.actions)) self._assertListNotEqual(original_actions, case.actions) update_strategy.reconcile_actions() self._assertListEqual(original_actions, case.actions) # test duplication, even when dates are off case.actions = original_actions + [deepcopy(case.actions[2])] case.actions[-1].server_date = case.actions[ -1].server_date + timedelta(seconds=1) self._assertListNotEqual(original_actions, case.actions) update_strategy.reconcile_actions() self._assertListEqual(original_actions, case.actions) # test duplication with different properties is actually # treated differently case.actions = original_actions + [deepcopy(case.actions[2])] case.actions[-1].updated_unknown_properties['new'] = 'mismatch' self.assertEqual(5, len(case.actions)) self._assertListNotEqual(original_actions, case.actions) update_strategy.reconcile_actions() self._assertListNotEqual(original_actions, case.actions) # test clean slate rebuild case = rebuild_case_from_forms(REBUILD_TEST_DOMAIN, case_id, RebuildWithReason(reason='test')) self._assertListEqual(original_actions, primary_actions(case)) self._assertListEqual(original_form_ids, case.xform_ids)
def test_repeater(self): CommCareCase.get(case_id) def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) self.clear_log() for repeat_record in repeat_records: repeat_record.fire(post_fn=self.make_post_fn([404, 404, 404])) repeat_record.save() for (url, status, data) in self.log: self.assertEqual(status, 404) self.clear_log() next_check_time = now() + timedelta(minutes=60) repeat_records = RepeatRecord.all(domain=self.domain, due_before=now() + timedelta(minutes=15)) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all(domain=self.domain, due_before=next_check_time + timedelta(seconds=2)) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: self.assertLess(abs(next_check_time - repeat_record.next_check), timedelta(seconds=2)) repeat_record.fire(post_fn=self.make_post_fn([404, 200])) repeat_record.save() self.assertEqual(len(self.log), 4) self.assertEqual(self.log[1], (self.form_repeater.url, 200, xform_xml)) self.assertEqual(self.log[3][:2], (self.case_repeater.url, 200)) check_xml_line_by_line(self, self.log[3][2], case_block) repeat_records = RepeatRecord.all(domain=self.domain, due_before=next_check_time) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 0) self.post_xml(update_xform_xml) repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2)
def test_repeater(self): CommCareCase.get(case_id) def now(): return datetime.utcnow() repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2) self.clear_log() for repeat_record in repeat_records: repeat_record.fire(post_fn=self.make_post_fn([404, 404, 404])) repeat_record.save() for (url, status, data, headers) in self.log: self.assertEqual(status, 404) self.clear_log() next_check_time = now() + timedelta(minutes=60) repeat_records = RepeatRecord.all(domain=self.domain, due_before=now() + timedelta(minutes=15)) self.assertEqual(len(repeat_records), 0) repeat_records = RepeatRecord.all(domain=self.domain, due_before=next_check_time + timedelta(seconds=2)) self.assertEqual(len(repeat_records), 2) for repeat_record in repeat_records: self.assertLess(abs(next_check_time - repeat_record.next_check), timedelta(seconds=2)) repeat_record.fire(post_fn=self.make_post_fn([404, 200])) repeat_record.save() self.assertEqual(len(self.log), 4) self.assertEqual(self.log[1][:3], (self.form_repeater.url, 200, xform_xml)) self.assertIn('received-on', self.log[1][3]) self.assertEqual(self.log[3][:2], (self.case_repeater.url, 200)) self.assertIn('server-modified-on', self.log[3][3]) check_xml_line_by_line(self, self.log[3][2], case_block) repeat_records = RepeatRecord.all(domain=self.domain, due_before=next_check_time) for repeat_record in repeat_records: self.assertEqual(repeat_record.succeeded, True) self.assertEqual(repeat_record.next_check, None) repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 0) self.post_xml(update_xform_xml) repeat_records = RepeatRecord.all(domain=self.domain, due_before=now()) self.assertEqual(len(repeat_records), 2)
def testAttachments(self): self.assertEqual(len(CommCareCase.get(self.case_id).case_attachments), 0) scan_path = os.path.join(os.path.dirname(__file__), 'data', 'vscan', 'VH014466XK_000016_20130722T175057') files = self.pack_directory(scan_path) utils.attach_images_to_case(self.case_id, files) self.assertEqual(len(CommCareCase.get(self.case_id).case_attachments), 3)
def rebuild_case(case_id): """ Given a case ID, rebuild the entire case state based on all existing forms referencing it. Useful when things go wrong or when you need to manually rebuild a case after archiving / deleting it """ try: case = CommCareCase.get(case_id) found = True
def filter_cases(request, domain, app_id, module_id): app = Application.get(app_id) module = app.get_module(module_id) delegation = request.GET.get('task-list') == 'true' auth_cookie = request.COOKIES.get('sessionid') xpath = SuiteGenerator(app).get_filter_xpath(module, delegation=delegation) # touchforms doesn't like this to be escaped xpath = HTMLParser.HTMLParser().unescape(xpath) if delegation: case_type = DELEGATION_STUB_CASE_TYPE else: case_type = module.case_type if xpath: # if we need to do a custom filter, send it to touchforms for processing additional_filters = { "properties/case_type": case_type, "footprint": True } result = touchforms_api.filter_cases(domain, request.couch_user, xpath, additional_filters, auth=DjangoAuth(auth_cookie)) if result.get('status', None) == 'error': return HttpResponseServerError( result.get("message", _("Something went wrong filtering your cases."))) case_ids = result.get("cases", []) else: # otherwise just use our built in api with the defaults case_ids = [res.id for res in get_filtered_cases( domain, status=CASE_STATUS_OPEN, case_type=case_type, user_id=request.couch_user._id, ids_only=True )] cases = [CommCareCase.get(id) for id in case_ids] # refilter these because we might have accidentally included footprint cases # in the results from touchforms. this is a little hacky but the easiest # (quick) workaround. should be revisted when we optimize the case list. cases = filter(lambda c: c.type == case_type, cases) cases = [c.get_json() for c in cases if c] parents = [] if delegation: for case in cases: parent_id = case['indices']['parent']['case_id'] parents.append(CommCareCase.get(parent_id)) return json_response({ 'cases': cases, 'parents': parents }) else: return json_response(cases)
def _check_state(self, new_owner_id, expected_changed, update=None): expected_ids = set(c._id for c in expected_changed) for case in expected_changed: expected = CommCareCase.get(case._id) self.assertEqual(new_owner_id, expected.owner_id) if update: for prop, value in update.items(): self.assertEqual(getattr(expected, prop), value) for case in (c for c in self.all if c._id not in expected_ids): remaining = CommCareCase.get(case._id) self.assertEqual(self.original_owner._id, remaining.owner_id)
def testParseClose(self): self.testParseCreate() file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "basic_close.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("foo-case-id") self.assertTrue(case.closed) self.assertEqual("bar-user-id", case.closed_by)
def create_and_test(case_id, user, owner, should_have, should_not_have, version): case_block = self.get_create_block( case_id=case_id, type="case", user_id=user.user_id, owner_id=owner.get_id, version=version ) post_case_blocks([case_block], {'domain': self.domain}) CommCareCase.get(case_id) check_has_block(case_block, should_have, should_not_have, version=version)
def _new_case(self, properties): id = uuid.uuid4().hex case_block = CaseBlock( create=True, case_id=id, case_type=self.case_type, update=properties, ).as_xml() post_case_blocks([case_block], {'domain': self.domain}) case = CommCareCase.get(id) self.addCleanup(case.delete) return case
def test_close(self): case_id = 'uid_blah_3' domain = "test.domain" case = bootstrap_case_from_xml(self, 'create.xml', case_id_override=case_id) case.domain = domain case.save() referral_indexes = [] case = CommCareCase.get(case_id) for i in referral_indexes: case.force_close_referral(case.referrals[i])
def testImportTrailingWhitespace(self): cols = ['case_id', 'age', u'sex\xa0', 'location'] config = self._config(cols, named_columns=True) file = MockExcelFile(header_columns=cols, num_rows=2) res = do_import(file, config, self.domain) # we create 1 less since we knock off the header column self.assertEqual(1, res['created_count']) case_ids = get_case_ids_in_domain(self.domain) self.assertEqual(1, len(case_ids)) case = CommCareCase.get(case_ids[0]) self.assertTrue(bool( case.sex)) # make sure the value also got properly set
def _case_changed(case_id, handler_ids): subcases = None case = CommCareCase.get(case_id) for handler_id in handler_ids: handler = CaseReminderHandler.get(handler_id) if handler.start_condition_type == CASE_CRITERIA: handler.case_changed(case) if handler.uses_parent_case_property: if subcases is None: subcases = get_subcases(case) for subcase in subcases: handler.case_changed(subcase)
def testArchiveAfterAttach(self): single_attach = 'fruity_file' self._doCreateCaseWithMultimedia(attachments=[single_attach]) case = CommCareCase.get(TEST_CASE_ID) for xform in case.xform_ids: form = XFormInstance.get(xform) form.archive() self.assertEqual('XFormArchived', form.doc_type) form.unarchive() self.assertEqual('XFormInstance', form.doc_type)
def testActionComparison(self): user_id = 'test-action-comparison-user' case_id = _post_util(create=True, property='a1 wins', user_id=user_id) _post_util(case_id=case_id, property='a2 wins', user_id=user_id) _post_util(case_id=case_id, property='a3 wins', user_id=user_id) # check initial state case = CommCareCase.get(case_id) create, a1, a2, a3 = deepcopy(list(case.actions)) self.assertEqual('a3 wins', case.property) self.assertEqual(a1.updated_unknown_properties['property'], 'a1 wins') self.assertEqual(a2.updated_unknown_properties['property'], 'a2 wins') self.assertEqual(a3.updated_unknown_properties['property'], 'a3 wins') def _confirm_action_order(case, expected_actions): actual_actions = case.actions[1:] # always assume create is first and removed for expected, actual in zip(expected_actions, actual_actions): self.assertEqual(expected.updated_unknown_properties['property'], actual.updated_unknown_properties['property']) _confirm_action_order(case, [a1, a2, a3]) # test initial rebuild does nothing update_strategy = ActionsUpdateStrategy(case) update_strategy.soft_rebuild_case() _confirm_action_order(case, [a1, a2, a3]) # test sorting by server date case.actions[2].server_date = case.actions[2].server_date + timedelta(days=1) update_strategy.soft_rebuild_case() _confirm_action_order(case, [a1, a3, a2]) # test sorting by date within the same day case = CommCareCase.get(case_id) _confirm_action_order(case, [a1, a2, a3]) case.actions[2].date = case.actions[3].date + timedelta(minutes=1) ActionsUpdateStrategy(case).soft_rebuild_case() _confirm_action_order(case, [a1, a3, a2]) # test original form order case = CommCareCase.get(case_id) case.actions[3].server_date = case.actions[2].server_date case.actions[3].date = case.actions[2].date case.xform_ids = [a1.xform_id, a3.xform_id, a2.xform_id] ActionsUpdateStrategy(case).soft_rebuild_case() _confirm_action_order(case, [a1, a3, a2]) # test create comes before update case = CommCareCase.get(case_id) case.actions = [a1, create, a2, a3] ActionsUpdateStrategy(case).soft_rebuild_case() _confirm_action_order(case, [a1, a2, a3])
def testActionComparison(self): user_id = "test-action-comparison-user" case_id = post_util(create=True, property="a1 wins", user_id=user_id) post_util(case_id=case_id, property="a2 wins", user_id=user_id) post_util(case_id=case_id, property="a3 wins", user_id=user_id) # check initial state case = CommCareCase.get(case_id) create, a1, a2, a3 = deepcopy(list(case.actions)) self.assertEqual("a3 wins", case.property) self.assertEqual(a1.updated_unknown_properties["property"], "a1 wins") self.assertEqual(a2.updated_unknown_properties["property"], "a2 wins") self.assertEqual(a3.updated_unknown_properties["property"], "a3 wins") def _confirm_action_order(case, expected_actions): actual_actions = case.actions[1:] # always assume create is first and removed for expected, actual in zip(expected_actions, actual_actions): self.assertEqual( expected.updated_unknown_properties["property"], actual.updated_unknown_properties["property"] ) _confirm_action_order(case, [a1, a2, a3]) # test initial rebuild does nothing case.rebuild() _confirm_action_order(case, [a1, a2, a3]) # test sorting by server date case.actions[2].server_date = case.actions[2].server_date + timedelta(days=1) case.rebuild() _confirm_action_order(case, [a1, a3, a2]) # test sorting by date within the same day case = CommCareCase.get(case_id) _confirm_action_order(case, [a1, a2, a3]) case.actions[2].date = case.actions[3].date + timedelta(minutes=1) case.rebuild() _confirm_action_order(case, [a1, a3, a2]) # test original form order case = CommCareCase.get(case_id) case.actions[3].server_date = case.actions[2].server_date case.actions[3].date = case.actions[2].date case.xform_ids = [a1.xform_id, a3.xform_id, a2.xform_id] case.rebuild() _confirm_action_order(case, [a1, a3, a2]) # test create comes before update case = CommCareCase.get(case_id) case.actions = [a1, create, a2, a3] case.rebuild() _confirm_action_order(case, [a1, a2, a3])
def testParseWithIndices(self): self.testParseCreate() user_id = "bar-user-id" for prereq in ["some_referenced_id", "some_other_referenced_id"]: post_case_blocks([ CaseBlock( create=True, case_id=prereq, user_id=user_id, version=V2).as_xml(format_datetime=json_format_datetime) ]) file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "index_update.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("foo-case-id") self.assertEqual(2, len(case.indices)) self.assertTrue(case.has_index("foo_ref")) self.assertTrue(case.has_index("baz_ref")) self.assertEqual("bar", case.get_index("foo_ref").referenced_type) self.assertEqual("some_referenced_id", case.get_index("foo_ref").referenced_id) self.assertEqual("bop", case.get_index("baz_ref").referenced_type) self.assertEqual("some_other_referenced_id", case.get_index("baz_ref").referenced_id) # check the action self.assertEqual(2, len(case.actions)) [_, index_action] = case.actions self.assertEqual(const.CASE_ACTION_INDEX, index_action.action_type) self.assertEqual(2, len(index_action.indices)) # quick test for ota restore v2response = phone_views.xml_for_case(HttpRequest(), case.get_id, version="2.0") expected_v2_response = """ <case case_id="foo-case-id" date_modified="2011-12-07T13:42:50Z" user_id="bar-user-id" xmlns="http://commcarehq.org/case/transaction/v2"> <create> <case_type>v2_case_type</case_type> <case_name>test case name</case_name> <owner_id>bar-user-id</owner_id> </create> <index> <baz_ref case_type="bop">some_other_referenced_id</baz_ref> <foo_ref case_type="bar">some_referenced_id</foo_ref> </index> </case>""" check_xml_line_by_line(self, expected_v2_response, v2response.content)
def testNestedExclusion(self): """ Blocks inside forms tagged as device logs should be excluded """ self.assertEqual(0, len(CommCareCase.view("case/by_user", include_docs=True, reduce=False).all())) file_path = os.path.join(os.path.dirname(__file__), "data", "exclusion", "nested_device_report.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) self.assertEqual(1, len(CommCareCase.view("case/by_user", include_docs=True, reduce=False).all())) case = CommCareCase.get("case_in_form") self.assertEqual("form case", case.name)
def test_close(self): case_id = 'uid_blah_3' domain = "test.domain" case = bootstrap_case_from_xml(self, 'create.xml', case_id_override=case_id) case.domain = domain case.save() referral_indexes=[] case = CommCareCase.get(case_id) for i in referral_indexes: case.force_close_referral(case.referrals[i]) case.force_close("/a/{domain}/receiver".format(domain=domain)) case = CommCareCase.get(case_id) self.failUnless(case.closed)
def testNestedExclusion(self): """ Blocks inside forms tagged as device logs should be excluded """ file_path = os.path.join(os.path.dirname(__file__), "data", "exclusion", "nested_device_report.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) self.assertEqual(1, get_total_case_count()) case = CommCareCase.get("case_in_form") self.assertEqual("form case", case.name)
def testParseNamedNamespace(self): file_path = os.path.join(os.path.dirname(__file__), "data", "v2", "named_namespace.xml") with open(file_path, "rb") as f: xml_data = f.read() form = post_xform_to_couch(xml_data) process_cases(form) case = CommCareCase.get("14cc2770-2d1c-49c2-b252-22d6ecce385a") self.assertFalse(case.closed) self.assertEqual("d5ce3a980b5b69e793445ec0e3b2138e", case.user_id) self.assertEqual(datetime(2011, 12, 27), case.modified_on) self.assertEqual("cc_bihar_pregnancy", case.type) self.assertEqual("TEST", case.name) self.assertEqual(2, len(case.actions))
def test_archived_form_gets_removed_from_case_xform_ids(self): initial_amounts = [(p._id, float(100)) for p in self.products] instance_id = self.submit_xml_form( balance_submission(initial_amounts), timestamp=datetime.utcnow() + timedelta(-30) ) case = CommCareCase.get(self.sp.case_id) self.assertIn(instance_id, case.xform_ids) form = XFormInstance.get(instance_id) form.archive() case = CommCareCase.get(self.sp.case_id) self.assertNotIn(instance_id, case.xform_ids)
def testCantPwnCase(self): form = post_xform_to_couch(ALICE_XML) form.domain = ALICE_DOMAIN (case,) = process_cases(form) case_id = case.case_id form = post_xform_to_couch(EVE_XML) form.domain = EVE_DOMAIN with self.assertRaises(IllegalCaseId): process_cases(form) self.assertFalse(hasattr(CommCareCase.get(case_id), 'plan_to_buy_gun')) form = post_xform_to_couch(ALICE_UPDATE_XML) form.domain = ALICE_DOMAIN process_cases(form) self.assertEqual(CommCareCase.get(case_id).plan_to_buy_gun, 'no')
def testForceSave(self): original = CommCareCase() original.save() conflict = CommCareCase.get(original._id) original.foo = 'bar' conflict.foo = 'not bar' original.save() try: conflict.save() self.fail('conflicting save should fail hard!') except ResourceConflict: pass conflict.force_save() self.assertEqual('not bar', CommCareCase.get(original._id).foo)
class LivraisonFluff(fluff.IndicatorDocument): document_class = XFormInstance document_filter = FormPropertyFilter(xmlns=LIVRAISON_XMLNSES[0]) domains = INTRAHEALTH_DOMAINS group_by = ('domain', ) deleted_types = IH_DELETED_TYPES month = flat_field(lambda f: get_month(f, 'mois_visite')) duree_moyenne_livraison = report_calcs.DureeMoyenneLivraison() region_id = flat_field(lambda f: get_location_id_by_type(form=f, type=u'r\xe9gion')) district_id = flat_field(lambda f: CommCareCase.get(f.form['case']['@case_id']).location_id) district_name = flat_field(lambda f: CommCareCase.get(f.form['case']['@case_id']).name)
def process_indicators(self, doc_dict, domain, namespaces): case_type = doc_dict.get('type') if not case_type: return case_indicators = [] for namespace in namespaces: case_indicators.extend(CaseIndicatorDefinition.get_all(namespace, domain, case_type=case_type)) if case_indicators: case_doc = CommCareCase.get(doc_dict['_id']) case_doc.update_indicators_in_bulk(case_indicators, logger=pillow_logging) xform_ids = doc_dict.get('xform_ids', []) for namespace in namespaces: for xform_id in xform_ids: try: xform_doc = XFormInstance.get(xform_id) if not xform_doc.xmlns: continue related_xform_indicators = CaseDataInFormIndicatorDefinition.get_all(namespace, domain, xmlns=xform_doc.xmlns) xform_doc.update_indicators_in_bulk(related_xform_indicators, logger=pillow_logging) except ResourceNotFound: pillow_logging.error("[INDICATOR %(namespace)s %(domain)s] Tried to form indicator %(xform_id)s " "from case %(case_id)s and failed." % { 'namespace': namespace, 'domain': domain, 'xform_id': xform_id, 'case_id': doc_dict['_id'], })
def form_context(request, domain, app_id, module_id, form_id): app = Application.get(app_id) form_url = "%s%s" % (get_url_base(), reverse('download_xform', args=[domain, app_id, module_id, form_id])) case_id = request.GET.get('case_id') try: form = app.get_module(module_id).get_form(form_id).name.values()[0] except (FormNotFoundException, ModuleNotFoundException): raise Http404() # make the name for the session we will use with the case and form session_name = u'{app} > {form}'.format( app=app.name, form=form, ) if case_id: session_name = u'{0} - {1}'.format(session_name, CommCareCase.get(case_id).name) delegation = request.GET.get('task-list') == 'true' offline = request.GET.get('offline') == 'true' session_helper = SessionDataHelper(domain, request.couch_user, case_id, delegation=delegation, offline=offline) return json_response(session_helper.get_full_context( {'form_url': form_url,}, {'session_name': session_name, 'app_id': app._id} ))
def get_cases(request, domain): if request.couch_user.is_commcare_user(): user_id = request.couch_user.get_id else: user_id = request.REQUEST.get("user_id", "") if not user_id and not request.couch_user.is_web_user(): return HttpResponseBadRequest("Must specify user_id!") ids_only = string_to_boolean(request.REQUEST.get("ids_only", "false")) case_id = request.REQUEST.get("case_id", "") footprint = string_to_boolean(request.REQUEST.get("footprint", "false")) include_children = string_to_boolean(request.REQUEST.get("include_children", "false")) if case_id and not footprint and not include_children: # short circuit everything else and just return the case # NOTE: this allows any user in the domain to access any case given # they know its ID, which is slightly different from the previous # behavior (can only access things you own + footprint). If we want to # change this contract we would need to update this to check the # owned case list + footprint case = CommCareCase.get(case_id) assert case.domain == domain cases = [CaseAPIResult(id=case_id, couch_doc=case, id_only=ids_only)] else: filters = get_filters_from_request(request) status = api_closed_to_status(request.REQUEST.get('closed', 'false')) case_type = filters.get('properties/case_type', None) cases = get_filtered_cases(domain, status=status, case_type=case_type, user_id=user_id, filters=filters, footprint=footprint, ids_only=ids_only, strip_history=True, include_children=include_children) return json_response(cases)
def visit_completion_counter(case): mother_counter = 0 child_counter = 0 case_obj = CommCareCase.get(case['_id']) baby_case = [c for c in case_obj.get_subcases().all() if c.type == 'baby'] for i in range(1, 8): if "pp_%s_done" % i in case: val = case["pp_%s_done" % i] try: if val.lower() == 'yes': mother_counter += 1 elif int(float(val)) == 1: mother_counter += 1 except ValueError: pass if baby_case and "bb_pp_%s_done" % i in baby_case[0]: val = baby_case[0]["bb_pp_%s_done" % i] try: if val.lower() == 'yes': child_counter += 1 elif int(float(val)) == 1: child_counter += 1 except ValueError: pass return mother_counter if mother_counter > child_counter else child_counter
def testBasicRebuild(self): user_id = 'test-basic-rebuild-user' now = datetime.utcnow() case_id = _post_util(create=True, user_id=user_id, date_modified=now) _post_util(case_id=case_id, p1='p1-1', p2='p2-1', user_id=user_id, date_modified=now) _post_util(case_id=case_id, p2='p2-2', p3='p3-2', user_id=user_id, date_modified=now) # check initial state case = CommCareCase.get(case_id) self.assertEqual(case.p1, 'p1-1') # original self.assertEqual(case.p2, 'p2-2') # updated self.assertEqual(case.p3, 'p3-2') # new self.assertEqual(3, len(case.actions)) # create + 2 updates a1 = case.actions[1] self.assertEqual(a1.updated_unknown_properties['p1'], 'p1-1') self.assertEqual(a1.updated_unknown_properties['p2'], 'p2-1') a2 = case.actions[2] self.assertEqual(a2.updated_unknown_properties['p2'], 'p2-2') self.assertEqual(a2.updated_unknown_properties['p3'], 'p3-2') # rebuild by flipping the actions case.actions = [case.actions[0], a2, a1] case.xform_ids = [case.xform_ids[0], case.xform_ids[2], case.xform_ids[1]] ActionsUpdateStrategy(case).soft_rebuild_case() self.assertEqual(case.p1, 'p1-1') # original self.assertEqual(case.p2, 'p2-1') # updated (back!) self.assertEqual(case.p3, 'p3-2') # new
def obj_get(self, request, **kwargs): case = CommCareCase.get(kwargs['pk']) # stupid "security" if case.domain == kwargs['domain'] and case.doc_type == 'CommCareCase': return case else: raise ObjectDoesNotExist()
def _get_case(session): session = XFormsSession.get(session.get_id) self.assertTrue(session.submission_id) instance = XFormInstance.get(session.submission_id) case_id = instance.xpath("form/case/@case_id") self.assertTrue(case_id) return CommCareCase.get(case_id)
def case_details(request, domain, case_id): timezone = util.get_timezone(request.couch_user.user_id, domain) try: case = CommCareCase.get(case_id) report_name = 'Details for Case "%s"' % case.name except ResourceNotFound: messages.info(request, "Sorry, we couldn't find that case. If you think this is a mistake plase report an issue.") return HttpResponseRedirect(inspect.SubmitHistory.get_url(domain)) form_lookups = dict((form.get_id, "%s: %s" % (form.received_on.date(), xmlns_to_name(domain, form.xmlns, get_app_id(form)))) \ for form in case.get_forms()) return render_to_response(request, "reports/reportdata/case_details.html", { "domain": domain, "case_id": case_id, "form_lookups": form_lookups, "slug":inspect.CaseListReport.slug, "report": dict( name=report_name, slug=inspect.CaseListReport.slug, is_async=False, ), "layout_flush_content": True, "timezone": timezone })
def get_session_data(domain, couch_user, case_id=None, version=APP_V2, device_id=CLOUDCARE_DEVICE_ID): """ Get session data used by touchforms. """ # expected properties: .raw_username, .get_id if version == APP_V2: session_data = {'device_id': device_id, 'app_version': '2.0', 'username': couch_user.raw_username, 'user_id': couch_user.get_id, "domain": domain } if case_id: session_data["case_id"] = case_id else: assert version == APP_V1 # assume V1 / preloader structure session_data = {"meta": {"UserID": couch_user.get_id, "UserName": couch_user.raw_username}, "property": {"deviceID": CLOUDCARE_DEVICE_ID}} # check for a case id and update preloader appropriately if case_id: case = CommCareCase.get(case_id) session_data["case"] = case.get_preloader_dict() return session_data
def testActionEquality(self): case_id = _post_util(create=True) _post_util(case_id=case_id, p1='p1', p2='p2') case = CommCareCase.get(case_id) self.assertEqual(2, len(case.actions)) # create + update self.assertTrue(case.actions[0] != case.actions[1]) self.assertTrue(case.actions[1] == case.actions[1]) orig = case.actions[1] copy = CommCareCaseAction.wrap(orig._doc.copy()) self.assertTrue(copy != case.actions[0]) self.assertTrue(copy == orig) copy.server_date = copy.server_date + timedelta(seconds=1) self.assertTrue(copy != orig) copy.server_date = orig.server_date self.assertTrue(copy == orig) copy.updated_unknown_properties['p1'] = 'not-p1' self.assertTrue(copy != orig) copy.updated_unknown_properties['p1'] = 'p1' self.assertTrue(copy == orig) copy.updated_unknown_properties['pnew'] = '' self.assertTrue(copy != orig)