예제 #1
0
class TestCheckActionOrder(SimpleTestCase):
    def test_already_sorted(self):
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 1, 1, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 2, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 3, 0, 0, 0)),
        ])
        self.assertTrue(CouchCaseUpdateStrategy(case).check_action_order())
예제 #2
0
def get_stock_actions(xform):
    if is_device_report(xform):
        return _empty_actions()

    stock_report_helpers = list(unpack_commtrack(xform))
    transaction_helpers = [
        transaction_helper
        for stock_report_helper in stock_report_helpers
        for transaction_helper in stock_report_helper.transactions
    ]
    if not transaction_helpers:
        return _empty_actions()

    # list of cases that had stock reports in the form
    case_ids = list(set(transaction_helper.case_id
                        for transaction_helper in transaction_helpers))

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']
    case_action_intents = []

    for case_id in case_ids:
        if is_deprecation(xform):
            case_action_intents.append(CaseActionIntent(
                case_id=case_id, form_id=xform.orig_id, is_deprecation=True, action=None
            ))
        else:
            case_action = CommCareCaseAction.from_parsed_action(
                submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
            )
            case_action_intents.append(CaseActionIntent(
                case_id=case_id, form_id=xform._id, is_deprecation=False, action=case_action
            ))

    return StockFormActions(stock_report_helpers, case_action_intents)
예제 #3
0
    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)
예제 #4
0
def _rebuild_action():
    now = datetime.datetime.utcnow()
    return CommCareCaseAction(
        action_type=const.CASE_ACTION_REBUILD,
        date=now,
        server_date=now,
    )
예제 #5
0
def _make_action(server_date, phone_date=EMPTY_DATE, action_type=const.CASE_ACTION_UPDATE, user_id='someuserid', form_id=None):
    if phone_date == EMPTY_DATE:
        phone_date = server_date
    form_id = form_id or uuid.uuid4().hex
    return CommCareCaseAction(
        action_type=action_type, server_date=server_date, date=phone_date, user_id=user_id, xform_id=form_id
    )
예제 #6
0
    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)
예제 #7
0
def process_stock(xform, case_db=None):
    """
    process the commtrack xml constructs in an incoming submission
    """
    case_db = case_db or CaseDbCache()
    assert isinstance(case_db, CaseDbCache)
    if is_device_report(xform):
        return []

    domain = xform.domain

    config = CommtrackConfig.for_domain(domain)

    # these are the raw stock report objects from the xml
    stock_reports = list(unpack_commtrack(xform, config))
    # flattened transaction list spanning all stock reports in the form
    transactions = [t for r in stock_reports for t in r.transactions]
    # omitted: normalize_transactions (used for bulk requisitions?)

    if not transactions:
        return []

    # transactions grouped by case/product id
    grouped_tx = map_reduce(lambda tx: [((tx.case_id, tx.product_id),)],
                            lambda v: sorted(v, key=lambda tx: tx.timestamp),
                            data=transactions,
                            include_docs=True)

    case_ids = list(set(k[0] for k in grouped_tx))
    # list of cases that had stock reports in the form
    # there is no need to wrap them by case type
    relevant_cases = [case_db.get(case_id) for case_id in case_ids]

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']

    # touch every case for proper ota restore logic syncing to be preserved
    for case in relevant_cases:
        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        # hack: clear the sync log id so this modification always counts
        # since consumption data could change server-side
        case_action.sync_log_id = ''
        case.actions.append(case_action)
        case_db.mark_changed(case)

    # also purge the sync token cache for the same reason
    if relevant_cases and xform.get_sync_token():
        xform.get_sync_token().invalidate_cached_payloads()

    # create the django models
    for report in stock_reports:
        report.create_models(domain)

    # TODO make this a signal
    from corehq.apps.commtrack.signals import send_notifications, raise_events
    send_notifications(xform, relevant_cases)
    raise_events(xform, relevant_cases)
    return relevant_cases
예제 #8
0
    def _send_case_to_es(self,
                         domain=None,
                         owner_id=None,
                         user_id=None,
                         case_type=None,
                         opened_on=None,
                         closed_on=None):

        actions = [
            CommCareCaseAction(
                action_type=CASE_ACTION_CREATE,
                date=opened_on,
            )
        ]

        case = CommCareCase(
            _id=uuid.uuid4().hex,
            domain=domain or self.domain,
            owner_id=owner_id or self.owner_id,
            user_id=user_id or self.user_id,
            type=case_type or self.case_type,
            opened_on=opened_on or datetime.now(),
            opened_by=user_id or self.user_id,
            modified_on=datetime.now(),
            closed_on=closed_on,
            closed_by=user_id or self.user_id,
            actions=actions,
        )
        send_to_elasticsearch('cases', case.to_json())
        self.es.indices.refresh(CASE_INDEX_INFO.index)
        return case
    def test_update_dependent_case_owner_still_present(self):
        sync_log = SimplifiedSyncLog(
            domain="domain",
            case_ids_on_phone={'c1', 'd1'},
            dependent_case_ids_on_phone={'d1'},
            index_tree=IndexTree(indices={'c1': {
                'd1-id': 'd1'
            }}),
            user_id="user",
            owner_ids_on_phone={'user1'})

        dependent_case_state = CaseState(case_id="d1", indices=[])
        xform_id = uuid.uuid4().hex
        xform = XFormInstance(_id=xform_id)
        form_actions = [
            CommCareCaseAction(action_type=CASE_ACTION_UPDATE,
                               updated_known_properties={'owner_id': 'user2'})
        ]
        with patch.object(CommCareCase,
                          'get_actions_for_form',
                          return_value=form_actions):
            parent_case = CommCareCase(_id='d1')
            # before this test was added, the following call raised a ValueError on legacy logs.
            sync_log.update_phone_lists(xform, [parent_case])
            self.assertIn(dependent_case_state,
                          sync_log.test_only_get_dependent_cases_on_phone())
예제 #10
0
    def allocated_to(self):
        if self.status == "Closed":
            close_action = [CommCareCaseAction.wrap(a) for a in self.case['actions'] if a['action_type'] ==
                const.CASE_ACTION_CLOSE][0]

            CATI_FOLLOW_UP_FORMS = (
                "http://openrosa.org/formdesigner/A5B08D8F-139D-46C6-9FDF-B1AD176EAE1F",
            )
            if close_action.xform.xmlns in CATI_FOLLOW_UP_FORMS:
                return 'CATI'
            else:
                return 'Field'

        else:
            follow_up_type = self.case.get('follow_up_type', '')
            house_number = self.case.get('phone_house_number', '')
            husband_number = self.case.get('phone_husband_number', '')
            mother_number = self.case.get('phone_mother_number', '')
            asha_number = self.case.get('phone_asha_number', '')

            if follow_up_type != 'field_follow_up' and (house_number or
                   husband_number or mother_number or asha_number):
                return 'CATI'
            else:
                return 'Field'
예제 #11
0
    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[2]
        copy = CommCareCaseAction.wrap(deepcopy(orig._doc))
        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)
예제 #12
0
    def allocated_to(self):
        if self.status == "Closed":
            close_action = [
                CommCareCaseAction.wrap(a) for a in self.case['actions']
                if a['action_type'] == const.CASE_ACTION_CLOSE
            ][0]

            CATI_FOLLOW_UP_FORMS = (
                "http://openrosa.org/formdesigner/A5B08D8F-139D-46C6-9FDF-B1AD176EAE1F",
            )
            if close_action.xform.xmlns in CATI_FOLLOW_UP_FORMS:
                return 'CATI'
            else:
                return 'Field'

        else:
            follow_up_type = self.case.get('follow_up_type', '')
            house_number = self.case.get('phone_house_number', '')
            husband_number = self.case.get('phone_husband_number', '')
            mother_number = self.case.get('phone_mother_number', '')
            asha_number = self.case.get('phone_asha_number', '')

            if follow_up_type != 'field_follow_up' and (house_number
                                                        or husband_number
                                                        or mother_number
                                                        or asha_number):
                return 'CATI'
            else:
                return 'Field'
예제 #13
0
 def test_update_dependent_case_owner_still_present(self):
     dependent_case_state = CaseState(case_id="d1", indices=[])
     sync_log = SyncLog(domain="domain",
                        user_id="user",
                        cases_on_phone=[
                            CaseState(case_id="c1",
                                      indices=[
                                          CommCareCaseIndex(
                                              identifier="d1-id",
                                              referenced_id="d1")
                                      ])
                        ],
                        dependent_cases_on_phone=[dependent_case_state],
                        owner_ids_on_phone=['user1'])
     xform_id = uuid.uuid4().hex
     xform = XFormInstance(_id=xform_id)
     form_actions = [
         CommCareCaseAction(action_type=CASE_ACTION_UPDATE,
                            updated_known_properties={'owner_id': 'user2'})
     ]
     with patch.object(CommCareCase,
                       'get_actions_for_form',
                       return_value=form_actions):
         parent_case = CommCareCase(_id='d1')
         # before this test was added, the following call raised a ValueError on legacy logs.
         for log in [
                 sync_log,
                 SimplifiedSyncLog.from_other_format(sync_log)
         ]:
             log.update_phone_lists(xform, [parent_case])
             self.assertIn(dependent_case_state,
                           log.test_only_get_dependent_cases_on_phone())
예제 #14
0
 def test_update_dependent_case(self):
     sync_log = SyncLog(
         cases_on_phone=[
             CaseState(
                 case_id='bran',
                 indices=[
                     CommCareCaseIndex(identifier='legs',
                                       referenced_id='hodor')
                 ],
             ),
         ],
         dependent_cases_on_phone=[CaseState(case_id='hodor')],
         user_id="someuser")
     xform_id = uuid.uuid4().hex
     xform = XFormInstance(_id=xform_id)
     form_actions = [CommCareCaseAction(action_type=CASE_ACTION_UPDATE, )]
     with patch.object(CommCareCase,
                       'get_actions_for_form',
                       return_value=form_actions):
         parent_case = CommCareCase(_id='hodor')
         # before this test was added, the following call raised a SyncLogAssertionError on legacy logs.
         # this test just ensures it doesn't still do that.
         for log in [
                 sync_log,
                 SimplifiedSyncLog.from_other_format(sync_log)
         ]:
             log.update_phone_lists(xform, [parent_case])
예제 #15
0
def get_stock_actions(xform):
    if is_device_report(xform):
        return [], []

    stock_report_helpers = list(unpack_commtrack(xform))
    transaction_helpers = [
        transaction_helper
        for stock_report_helper in stock_report_helpers
        for transaction_helper in stock_report_helper.transactions
    ]
    if not transaction_helpers:
        return [], []

    # list of cases that had stock reports in the form
    case_ids = list(set(transaction_helper.case_id
                        for transaction_helper in transaction_helpers))

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']
    case_actions = []
    for case_id in case_ids:
        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        case_actions.append((case_id, case_action))

    return stock_report_helpers, case_actions
예제 #16
0
 def get_couch_action(self):
     assert self.action_type == CASE_ACTION_COMMTRACK
     return CommCareCaseAction.from_parsed_action(
         date=self.form.received_on,
         user_id=self.form.metadata.userID,
         xformdoc=self.form,
         action=AbstractAction(self.action_type),
     )
예제 #17
0
 def get_couch_action(self):
     assert self.action_type == CASE_ACTION_COMMTRACK
     return CommCareCaseAction.from_parsed_action(
         date=self.form.received_on,
         user_id=self.form.metadata.userID,
         xformdoc=self.form,
         action=AbstractAction(self.action_type),
     )
예제 #18
0
def process_stock(xform, case_db=None):
    """
    process the commtrack xml constructs in an incoming submission
    """
    case_db = case_db or CaseDbCache()
    assert isinstance(case_db, CaseDbCache)
    if is_device_report(xform):
        return StockProcessingResult(xform)

    stock_report_helpers = list(unpack_commtrack(xform))
    transaction_helpers = [
        transaction_helper
        for stock_report_helper in stock_report_helpers
        for transaction_helper in stock_report_helper.transactions
    ]

    # omitted: normalize_transactions (used for bulk requisitions?)

    if not transaction_helpers:
        return StockProcessingResult(xform)

    # validate product ids
    if any(transaction_helper.product_id in ('', None)
            for transaction_helper in transaction_helpers):
        raise MissingProductId(
            _('Product IDs must be set for all ledger updates!'))

    # list of cases that had stock reports in the form
    # there is no need to wrap them by case type
    case_ids = list(set(transaction_helper.case_id
                        for transaction_helper in transaction_helpers))
    relevant_cases = [case_db.get(case_id) for case_id in case_ids]

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']

    # touch every case for proper ota restore logic syncing to be preserved
    for case_id, case in zip(case_ids, relevant_cases):
        if case is None:
            raise IllegalCaseId(
                _('Ledger transaction references invalid Case ID "{}"')
                .format(case_id))

        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        # hack: clear the sync log id so this modification always counts
        # since consumption data could change server-side
        case_action.sync_log_id = ''
        case.actions.append(case_action)
        case_db.mark_changed(case)

    return StockProcessingResult(
        xform=xform,
        relevant_cases=relevant_cases,
        stock_report_helpers=stock_report_helpers,
    )
예제 #19
0
def process_stock(xform):
    """
    process the commtrack xml constructs in an incoming submission
    """
    if is_device_report(xform):
        return

    domain = xform.domain

    config = CommtrackConfig.for_domain(domain)

    # these are the raw stock report objects from the xml
    stock_reports = list(unpack_commtrack(xform, config))
    # flattened transaction list spanning all stock reports in the form
    transactions = [t for r in stock_reports for t in r.transactions]
    # omitted: normalize_transactions (used for bulk requisitions?)

    if not transactions:
        return

    # transactions grouped by case/product id
    grouped_tx = map_reduce(lambda tx: [((tx.case_id, tx.product_id),)],
                            lambda v: sorted(v, key=lambda tx: tx.timestamp),
                            data=transactions,
                            include_docs=True)

    # list of cases that had stock reports in the form, properly wrapped by case type
    try:
        relevant_cases = [wrap_commtrack_case(result['doc']) for result in
                          CommCareCase.get_db().view('_all_docs',
                                                     keys=list(set(k[0] for k in grouped_tx)),
                                                     include_docs=True)]
    except KeyError:
        raise Exception("Cannot find case matching supplied entity id")

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']

    # touch every case for proper ota restore logic syncing to be preserved
    for case in relevant_cases:
        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        # hack: clear the sync log id so this modification always counts
        # since consumption data could change server-side
        case_action.sync_log_id = ''
        case.actions.append(case_action)
        case.save()

    # create the django models
    for report in stock_reports:
        report.create_models()

    # TODO make this a signal
    from corehq.apps.commtrack.signals import send_notifications, raise_events
    send_notifications(xform, relevant_cases)
    raise_events(xform, relevant_cases)
예제 #20
0
 def creating_user(self):
     creator_id = None
     for action in self.case['actions']:
         if action['action_type'] == 'create':
             action_doc = CommCareCaseAction.wrap(action)
             creator_id = action_doc.get_user_id()
             break
     if not creator_id:
         return None
     return self._user_meta(creator_id)
예제 #21
0
 def creating_user(self):
     creator_id = None
     for action in self.case['actions']:
         if action['action_type'] == 'create':
             action_doc = CommCareCaseAction.wrap(action)
             creator_id = action_doc.get_user_id()
             break
     if not creator_id:
         return _("No data")
     return self._get_username(creator_id)
예제 #22
0
def _make_action(server_date,
                 phone_date=EMPTY_DATE,
                 action_type=const.CASE_ACTION_UPDATE,
                 user_id='someuserid'):
    if phone_date == EMPTY_DATE:
        phone_date = server_date
    return CommCareCaseAction(action_type=action_type,
                              server_date=server_date,
                              date=phone_date,
                              user_id=user_id)
예제 #23
0
 def get_case_actions(self, xformdoc):
     """
     Gets case actions from this object. These are the actual objects that get stored
     in the CommCareCase model (as opposed to the parser's representation of those)
     """
     return [
         CommCareCaseAction.from_parsed_action(
             self.guess_modified_on(), self.user_id, xformdoc, action
         )
         for action in self.actions
     ]
예제 #24
0
 def get_case_actions(self, xformdoc):
     """
     Gets case actions from this object. These are the actual objects that get stored
     in the CommCareCase model (as opposed to the parser's representation of those)
     """
     return [
         CommCareCaseAction.from_parsed_action(self.guess_modified_on(),
                                               self.user_id, xformdoc,
                                               action)
         for action in self.actions
     ]
예제 #25
0
def process_stock(xform, case_db=None):
    """
    process the commtrack xml constructs in an incoming submission
    """
    case_db = case_db or CaseDbCache()
    assert isinstance(case_db, CaseDbCache)
    if is_device_report(xform):
        return StockProcessingResult(xform)

    # these are the raw stock report objects from the xml
    stock_reports = list(unpack_commtrack(xform))
    # flattened transaction list spanning all stock reports in the form
    transactions = [t for r in stock_reports for t in r.transactions]
    # omitted: normalize_transactions (used for bulk requisitions?)

    if not transactions:
        return StockProcessingResult(xform)

    # validate product ids
    is_empty = lambda product_id: product_id is None or product_id == ''
    if any([is_empty(tx.product_id) for tx in transactions]):
        raise MissingProductId(
            _('Product IDs must be set for all ledger updates!'))
    # transactions grouped by case/product id
    grouped_tx = map_reduce(lambda tx: [((tx.case_id, tx.product_id),)],
                            lambda v: sorted(v, key=lambda tx: tx.timestamp),
                            data=transactions,
                            include_docs=True)

    case_ids = list(set(k[0] for k in grouped_tx))
    # list of cases that had stock reports in the form
    # there is no need to wrap them by case type
    relevant_cases = [case_db.get(case_id) for case_id in case_ids]

    user_id = xform.form['meta']['userID']
    submit_time = xform['received_on']

    # touch every case for proper ota restore logic syncing to be preserved
    for case in relevant_cases:
        case_action = CommCareCaseAction.from_parsed_action(
            submit_time, user_id, xform, AbstractAction(CASE_ACTION_COMMTRACK)
        )
        # hack: clear the sync log id so this modification always counts
        # since consumption data could change server-side
        case_action.sync_log_id = ''
        case.actions.append(case_action)
        case_db.mark_changed(case)

    return StockProcessingResult(
        xform=xform,
        relevant_cases=relevant_cases,
        stock_report_helpers=stock_reports,
    )
예제 #26
0
파일: cases.py 프로젝트: ye-man/commcare-hq
    def _creating_user(self):
        try:
            creator_id = self.raw_data['opened_by']
        except KeyError:
            creator_id = None
            if 'actions' in self.raw_data:
                for action in self.raw_data['actions']:
                    if action['action_type'] == 'create':
                        action_doc = CommCareCaseAction.wrap(action)
                        creator_id = action_doc.get_user_id()
                        break

        if not creator_id:
            return None
        return self._user_meta(creator_id)
예제 #27
0
    def creating_user(self):
        try:
            creator_id = self.case['opened_by']
        except KeyError:
            creator_id = None
            if 'actions' in self.case:
                for action in self.case['actions']:
                    if action['action_type'] == 'create':
                        action_doc = CommCareCaseAction.wrap(action)
                        creator_id = action_doc.get_user_id()
                        break

        if not creator_id:
            return None
        return self._user_meta(creator_id)
예제 #28
0
def prepare_case_json(planning_db):
    case_ids = planning_db.get_all_case_ids(valid_only=False)
    for case_json in iter_docs(CommCareCase.get_db(), case_ids):
        case = CommCareCase.wrap(case_json)
        if case.doc_type != "CommCareCase":
            assert case.doc_type == "CommCareCase-Deleted"
            continue

        # to normalize for any new fields added
        case_json = deepcopy(case.to_json())
        actions = [CommCareCaseAction.wrap(action) for action in planning_db.get_actions_by_case(case.case_id)]
        rebuild_case_from_actions(case, actions)
        planning_db.update_case_json(case.case_id, case.to_json())
        planning_db.add_diffs("case", case.case_id, json_diff(case_json, case.to_json()))

    return planning_db
 def test_update_dependent_case(self):
     sync_log = SimplifiedSyncLog(
         case_ids_on_phone={'bran', 'hodor'},
         dependent_case_ids_on_phone={'hodor'},
         index_tree=IndexTree(indices={'bran': {
             'legs': 'hodor'
         }}),
         user_id="someuser")
     xform_id = uuid.uuid4().hex
     xform = XFormInstance(_id=xform_id)
     form_actions = [CommCareCaseAction(action_type=CASE_ACTION_UPDATE, )]
     with patch.object(CommCareCase,
                       'get_actions_for_form',
                       return_value=form_actions):
         parent_case = CommCareCase(_id='hodor')
         # before this test was added, the following call raised a SyncLogAssertionError on legacy logs.
         # this test just ensures it doesn't still do that.
         sync_log.update_phone_lists(xform, [parent_case])
예제 #30
0
    def _copy_unprocessed_case(self, change):
        couch_case = CommCareCase.wrap(change.get_document())
        log.debug('Processing doc: {}({})'.format(couch_case['doc_type'], change.id))
        try:
            first_action = couch_case.actions[0]
        except IndexError:
            first_action = CommCareCaseAction()

        sql_case = CommCareCaseSQL(
            case_id=couch_case.case_id,
            domain=self.domain,
            type=couch_case.type or '',
            name=couch_case.name,
            owner_id=couch_case.owner_id or couch_case.user_id or '',
            opened_on=couch_case.opened_on or first_action.date,
            opened_by=couch_case.opened_by or first_action.user_id,
            modified_on=couch_case.modified_on,
            modified_by=couch_case.modified_by or couch_case.user_id or '',
            server_modified_on=couch_case.server_modified_on,
            closed=couch_case.closed,
            closed_on=couch_case.closed_on,
            closed_by=couch_case.closed_by,
            deleted=True,
            deletion_id=couch_case.deletion_id,
            deleted_on=couch_case.deletion_date,
            external_id=couch_case.external_id,
            case_json=couch_case.dynamic_case_properties()
        )
        _migrate_case_actions(couch_case, sql_case)
        _migrate_case_indices(couch_case, sql_case)
        _migrate_case_attachments(couch_case, sql_case)
        try:
            CaseAccessorSQL.save_case(sql_case)
        except IntegrityError:
            # case re-created by form processing so just mark the case as deleted
            CaseAccessorSQL.soft_delete_cases(
                self.domain,
                [sql_case.case_id],
                sql_case.deleted_on,
                sql_case.deletion_id
            )

        self.processed_docs += 1
        self._log_unprocessed_cases_processed_count(throttled=True)
예제 #31
0
    def _copy_unprocessed_cases(self):
        doc_types = ['CommCareCase-Deleted']
        changes = _get_case_iterator(self.domain,
                                     doc_types=doc_types).iter_all_changes()
        for change in self._with_progress(doc_types, changes):
            couch_case = CommCareCase.wrap(change.get_document())
            self.log_debug('Processing doc: {}({})'.format(
                couch_case['doc_type'], change.id))
            try:
                first_action = couch_case.actions[0]
            except IndexError:
                first_action = CommCareCaseAction()

            sql_case = CommCareCaseSQL(
                case_id=couch_case.case_id,
                domain=self.domain,
                type=couch_case.type or '',
                name=couch_case.name,
                owner_id=couch_case.owner_id or couch_case.user_id or '',
                opened_on=couch_case.opened_on or first_action.date,
                opened_by=couch_case.opened_by or first_action.user_id,
                modified_on=couch_case.modified_on,
                modified_by=couch_case.modified_by or couch_case.user_id or '',
                server_modified_on=couch_case.server_modified_on,
                closed=couch_case.closed,
                closed_on=couch_case.closed_on,
                closed_by=couch_case.closed_by,
                deleted=True,
                deletion_id=couch_case.deletion_id,
                deleted_on=couch_case.deletion_date,
                external_id=couch_case.external_id,
                case_json=couch_case.dynamic_case_properties())
            _migrate_case_actions(couch_case, sql_case)
            _migrate_case_indices(couch_case, sql_case)
            _migrate_case_attachments(couch_case, sql_case)
            try:
                CaseAccessorSQL.save_case(sql_case)
            except IntegrityError as e:
                self.log_error("Unable to migrate case:\n{}\n{}".format(
                    couch_case.case_id, e))
예제 #32
0
    def _copy_unprocessed_case(self, doc):
        couch_case = CommCareCase.wrap(doc)
        log.debug('Processing doc: %(doc_type)s(%(_id)s)', doc)
        try:
            first_action = couch_case.actions[0]
        except IndexError:
            first_action = CommCareCaseAction()

        opened_on = couch_case.opened_on or first_action.date
        sql_case = CommCareCaseSQL(
            case_id=couch_case.case_id,
            domain=self.domain,
            type=couch_case.type or '',
            name=couch_case.name,
            owner_id=couch_case.owner_id or couch_case.user_id or '',
            opened_on=opened_on,
            opened_by=couch_case.opened_by or first_action.user_id,
            modified_on=couch_case.modified_on or opened_on,
            modified_by=couch_case.modified_by or couch_case.user_id or '',
            server_modified_on=couch_case.server_modified_on,
            closed=couch_case.closed,
            closed_on=couch_case.closed_on,
            closed_by=couch_case.closed_by,
            deleted=True,
            deletion_id=couch_case.deletion_id,
            deleted_on=couch_case.deletion_date,
            external_id=couch_case.external_id,
            case_json=couch_case.dynamic_case_properties())
        _migrate_case_actions(couch_case, sql_case)
        _migrate_case_indices(couch_case, sql_case)
        _migrate_case_attachments(couch_case, sql_case)
        try:
            CaseAccessorSQL.save_case(sql_case)
        except IntegrityError:
            # case re-created by form processing so just mark the case as deleted
            CaseAccessorSQL.soft_delete_cases(self.domain, [sql_case.case_id],
                                              sql_case.deleted_on,
                                              sql_case.deletion_id)
        finally:
            self.case_diff_queue.enqueue(couch_case.case_id)
예제 #33
0
            rebuild_case_from_forms(REBUILD_TEST_DOMAIN, child_case_id, RebuildWithReason(reason='test'))


class TestCheckActionOrder(SimpleTestCase):

    def test_already_sorted(self):
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 1, 1, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 2, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 3, 0, 0, 0)),
        ])
        self.assertTrue(CouchCaseUpdateStrategy(case).check_action_order())

    def test_out_of_order(self):
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 1, 1, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 3, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 2, 0, 0, 0)),
        ])
        self.assertFalse(CouchCaseUpdateStrategy(case).check_action_order())

    def test_sorted_with_none(self):
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 1, 1, 0, 0, 0)),
            CommCareCaseAction(server_date=None),
            CommCareCaseAction(server_date=datetime(2001, 1, 2, 0, 0, 0)),
            CommCareCaseAction(server_date=datetime(2001, 1, 3, 0, 0, 0)),
        ])
        self.assertTrue(CouchCaseUpdateStrategy(case).check_action_order())

    def test_out_of_order_with_none(self):
예제 #34
0
 def test_couch_action_not_equals(self):
     orig = CommCareCaseAction()
     copy = CommCareCaseAction.wrap(deepcopy(orig._doc))
     self.assertTrue(orig == copy)
     self.assertFalse(orig != copy)
예제 #35
0
 def _action(self, datetime_):
     return CommCareCaseAction(server_date=datetime_, date=datetime_, action_type='update')
예제 #36
0
class TestCheckActionOrder(TestCase):
    def test(self):
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 01, 01, 00, 00, 00)),
            CommCareCaseAction(server_date=datetime(2001, 01, 02, 00, 00, 00)),
            CommCareCaseAction(server_date=datetime(2001, 01, 03, 00, 00, 00)),
        ])
        self.assertTrue(case.check_action_order())
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 01, 01, 00, 00, 00)),
            CommCareCaseAction(server_date=datetime(2001, 01, 03, 00, 00, 00)),
            CommCareCaseAction(server_date=datetime(2001, 01, 02, 00, 00, 00)),
        ])
        self.assertFalse(case.check_action_order())
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 01, 01, 00, 00, 00)),
            CommCareCaseAction(server_date=None),
            CommCareCaseAction(server_date=datetime(2001, 01, 02, 00, 00, 00)),
            CommCareCaseAction(server_date=datetime(2001, 01, 03, 00, 00, 00)),
        ])
        self.assertTrue(case.check_action_order())
        case = CommCareCase(actions=[
            CommCareCaseAction(server_date=datetime(2001, 01, 01, 00, 00, 00)),
            CommCareCaseAction(server_date=datetime(2001, 01, 03, 00, 00, 00)),
            CommCareCaseAction(server_date=None),
            CommCareCaseAction(server_date=datetime(2001, 01, 02, 00, 00, 00)),
        ])
        self.assertFalse(case.check_action_order())
예제 #37
0
 def test_couch_action_not_equals(self):
     orig = CommCareCaseAction()
     copy = CommCareCaseAction.wrap(deepcopy(orig._doc))
     self.assertTrue(orig == copy)
     self.assertFalse(orig != copy)
예제 #38
0
        ])
    return prepare_case_json(planning_db)


def prepare_case_json(planning_db):
    case_ids = planning_db.get_all_case_ids(valid_only=False)
    for case_json in iter_docs(CommCareCase.get_db(), case_ids):
        case = CommCareCase.wrap(case_json)
        if case.doc_type != 'CommCareCase':
            assert case.doc_type == 'CommCareCase-Deleted'
            continue

        # to normalize for any new fields added
        case_json = deepcopy(case.to_json())
        actions = [
            CommCareCaseAction.wrap(action)
            for action in planning_db.get_actions_by_case(case.case_id)
        ]
        rebuild_case_from_actions(case, actions)
        planning_db.update_case_json(case.case_id, case.to_json())
        planning_db.add_diffs('case', case.case_id,
                              json_diff(case_json, case.to_json()))

    return planning_db


def is_datetime_string(string):
    if not isinstance(string, str):
        return False
    try:
        iso_string_to_datetime(string, strict=True)