def rebuild_case_from_actions(case, actions): strategy = ActionsUpdateStrategy(case) strategy.reset_case_state() # in addition to resetting the state, also manually clear xform_ids and actions # since we're going to rebuild these from the forms case.xform_ids = [] case.actions = actions # call "rebuild" on the case, which should populate xform_ids # and re-sort actions if necessary strategy.soft_rebuild_case(strict=False)
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 testReconcileActions(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 = ActionsUpdateStrategy(case) original_actions = [deepcopy(a) for a in case.actions] original_form_ids = [id for id in case.xform_ids] self.assertEqual(3, len(original_actions)) self.assertEqual(3, len(original_form_ids)) self._assertListEqual(original_actions, case.actions) # test reordering case.actions = [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(9, 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(4, 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(case_id) self._assertListEqual(original_actions, primary_actions(case)) self._assertListEqual(original_form_ids, case.xform_ids)
def _get_or_update_model(case_update, xform, case_db): """ Gets or updates an existing case, based on a block of data in a submitted form. Doesn't save anything. """ case = case_db.get(case_update.id) if case is None: case = ActionsUpdateStrategy.case_from_case_update(case_update, xform) case_db.set(case['_id'], case) return case else: ActionsUpdateStrategy(case).update_from_case_update(case_update, xform, case_db.get_cached_forms()) return case