예제 #1
0
    def test_ledger_pillow(self):
        factory = CaseFactory(domain=self.domain)
        case = factory.create_case()

        consumer = get_test_kafka_consumer(topics.LEDGER)
        # have to get the seq id before the change is processed
        kafka_seq = get_topic_offset(topics.LEDGER)

        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        submit_case_blocks(
            [get_single_balance_block(case.case_id, self.product_id, 100)],
            self.domain)

        ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id)
        # confirm change made it to kafka
        message = consumer.next()
        change_meta = change_meta_from_kafka_message(message.value)
        if should_use_sql_backend(self.domain):
            self.assertEqual(ref.as_id(), change_meta.document_id)
        else:
            from corehq.apps.commtrack.models import StockState
            state = StockState.objects.all()
            self.assertEqual(1, len(state))
            self.assertEqual(state[0].pk, change_meta.document_id)  #
        self.assertEqual(self.domain, change_meta.domain)

        # send to elasticsearch
        self.pillow.process_changes(since=kafka_seq, forever=False)
        self.elasticsearch.indices.refresh(LEDGER_INDEX_INFO.index)

        # confirm change made it to elasticserach
        self._assert_ledger_in_es(ref)
class TestCasePropertyChanged(TestCase):
    def setUp(self):
        self.domain = "isildur"
        self.factory = CaseFactory(self.domain)
        self.case = self.factory.create_case(owner_id='owner',
                                             case_name="Aragorn",
                                             update={"sword": "Narsil"})
        self.other_case = self.factory.create_case()

    def tearDown(self):
        delete_all_xforms()
        delete_all_cases()

    @run_with_all_backends
    def test_date_case_property_changed(self):
        updated_on = datetime(2015, 5, 3, 12, 11)
        # submit 2 updates
        self.factory.create_or_update_case(
            CaseStructure(self.case.case_id,
                          attrs={
                              "update": {
                                  'abc': "updated"
                              },
                              "date_modified": updated_on
                          }), )
예제 #3
0
 def test_create_overrides(self):
     factory = CaseFactory()
     case = factory.create_case(owner_id='somebody',
                                update={'custom_prop': 'custom_value'})
     self.assertEqual('somebody', case.owner_id)
     self.assertEqual('custom_value',
                      case.dynamic_case_properties()['custom_prop'])
예제 #4
0
 def test_simple_delete(self):
     factory = CaseFactory()
     case = factory.create_case()
     [case] = factory.create_or_update_case(
         CaseStructure(case_id=case._id, attrs={'update': {
             'foo': 'bar'
         }}))
예제 #5
0
 def setUpClass(cls):
     super(TestDemoUser, cls).setUpClass()
     delete_all_users()
     cls.domain = 'main-domain'
     cls.project = create_domain(cls.domain)
     cls.user = CommCareUser.create(cls.domain, '*****@*****.**', 'secret', None, None)
     factory = CaseFactory()
     factory.create_case(owner_id=cls.user._id, update={'custom_prop': 'custom_value'})
예제 #6
0
 def setUpClass(cls):
     super(TestDemoUser, cls).setUpClass()
     delete_all_users()
     cls.domain = 'main-domain'
     cls.project = create_domain(cls.domain)
     cls.user = CommCareUser.create(cls.domain, '*****@*****.**', 'secret')
     factory = CaseFactory()
     factory.create_case(owner_id=cls.user._id, update={'custom_prop': 'custom_value'})
예제 #7
0
 def handle(self, domain, count, **options):
     factory = CaseFactory(domain=domain)
     date_string = datetime.now().isoformat()
     for i in range(count):
         factory.create_case(
             case_name='mock-data-{}-{}'.format(date_string, i))
     print('successfully created {} cases in domain {} with timestamp {}'.
           format(count, domain, date_string))
예제 #8
0
 def test_form_extras_default(self):
     domain = uuid.uuid4().hex
     # have to enable loose sync token validation for the domain or create actual SyncLog documents.
     # this is the easier path.
     token_id = uuid.uuid4().hex
     factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id})
     case = factory.create_case()
     form = FormAccessors(domain).get_form(case.xform_ids[0])
     self.assertEqual(token_id, form.last_sync_token)
class AutomaticCaseUpdateTest(TestCase):
    def setUp(self):
        self.domain = 'auto-update-test'
        self.case_db = CaseAccessors(self.domain)
        self.factory = CaseFactory(self.domain)
        self.rule = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule',
            case_type='test-case-type',
            active=True,
            server_modified_boundary=30,
        )
        self.rule.save()
        self.rule.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
        ]
        self.rule.automaticupdateaction_set = [
            AutomaticUpdateAction(
                action=AutomaticUpdateAction.ACTION_UPDATE,
                property_name='update_flag',
                property_value='Y',
            ),
            AutomaticUpdateAction(action=AutomaticUpdateAction.ACTION_CLOSE, ),
        ]

        self.rule2 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-2',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=30,
        )
        self.rule2.save()
        self.rule2.automaticupdateaction_set = [
            AutomaticUpdateAction(action=AutomaticUpdateAction.ACTION_CLOSE, ),
        ]

        self.rule3 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-3',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=50,
        )
        self.rule3.save()
        self.rule3.automaticupdateaction_set = [
            AutomaticUpdateAction(action=AutomaticUpdateAction.ACTION_CLOSE, ),
        ]

        with drop_connected_signals(case_post_save):
            case = self.factory.create_case(case_type='test-case-type')
        self.case_id = case.case_id
예제 #10
0
 def test_form_extras_default(self):
     domain = uuid.uuid4().hex
     # have to enable loose sync token validation for the domain or create actual SyncLog documents.
     # this is the easier path.
     LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain')
     token_id = uuid.uuid4().hex
     factory = CaseFactory(domain=domain,
                           form_extras={'last_sync_token': token_id})
     case = factory.create_case()
     form = XFormInstance.get(case.xform_ids[0])
     self.assertEqual(token_id, form.last_sync_token)
예제 #11
0
    def test_ledger_pillow_sql(self):
        factory = CaseFactory(domain=self.domain)
        case = factory.create_case()

        consumer = get_test_kafka_consumer(topics.LEDGER)
        # have to get the seq id before the change is processed
        kafka_seq = get_topic_offset(topics.LEDGER)

        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        submit_case_blocks([
            get_single_balance_block(case.case_id, self.product_id, 100)],
            self.domain
        )

        ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id)
        # confirm change made it to kafka
        message = consumer.next()
        change_meta = change_meta_from_kafka_message(message.value)
        if should_use_sql_backend(self.domain):
            self.assertEqual(ref.as_id(), change_meta.document_id)
        else:
            from corehq.apps.commtrack.models import StockState
            state = StockState.objects.all()
            self.assertEqual(1, len(state))
            self.assertEqual(state[0].pk, change_meta.document_id)  #
        self.assertEqual(self.domain, change_meta.domain)

        # send to elasticsearch
        self.pillow.process_changes(since=kafka_seq, forever=False)
        self.elasticsearch.indices.refresh(LEDGER_INDEX_INFO.index)

        # confirm change made it to elasticserach
        results = self.elasticsearch.search(
            LEDGER_INDEX_INFO.index,
            LEDGER_INDEX_INFO.type, body={
                "query": {
                    "bool": {
                        "must": [{
                            "match_all": {}
                        }]
                    }
                }
            }
        )
        self.assertEqual(1, results['hits']['total'])
        ledger_doc = results['hits']['hits'][0]['_source']
        self.assertEqual(self.domain, ledger_doc['domain'])
        self.assertEqual(ref.case_id, ledger_doc['case_id'])
        self.assertEqual(ref.section_id, ledger_doc['section_id'])
        self.assertEqual(ref.entry_id, ledger_doc['entry_id'])
예제 #12
0
    def test_ledger_pillow(self):
        factory = CaseFactory(domain=self.domain)
        case = factory.create_case()

        consumer = get_test_kafka_consumer(topics.LEDGER)
        # have to get the seq id before the change is processed
        kafka_seq = get_topic_offset(topics.LEDGER)

        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        submit_case_blocks([
            get_single_balance_block(case.case_id, self.product_id, 100)],
            self.domain
        )

        ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id)
        # confirm change made it to kafka
        message = consumer.next()
        change_meta = change_meta_from_kafka_message(message.value)
        if should_use_sql_backend(self.domain):
            self.assertEqual(ref.as_id(), change_meta.document_id)
        else:
            from corehq.apps.commtrack.models import StockState
            state = StockState.objects.all()
            self.assertEqual(1, len(state))
            self.assertEqual(state[0].pk, change_meta.document_id)  #
        self.assertEqual(self.domain, change_meta.domain)

        # send to elasticsearch
        self.pillow.process_changes(since=kafka_seq, forever=False)
        self.elasticsearch.indices.refresh(LEDGER_INDEX_INFO.index)

        # confirm change made it to elasticserach
        self._assert_ledger_in_es(ref)
예제 #13
0
    def test_simple_delete(self):
        factory = CaseFactory()
        case = factory.create_case()
        [case] = factory.create_or_update_case(
            CaseStructure(case_id=case.case_id, attrs={'update': {'foo': 'bar'}})
        )
        self.assertIsNotNone(self.casedb.get_case(case.case_id))
        self.assertEqual(2, len(case.xform_ids))
        for form_id in case.xform_ids:
            self.assertIsNotNone(self.formdb.get_form(form_id))

        with capture_kafka_changes_context(topics.FORM_SQL, topics.CASE_SQL) as change_context:
            safe_hard_delete(case)

        if should_use_sql_backend(case.domain):
            self.assertEqual(3, len(change_context.changes))
            expected_ids = {case.case_id} | set(case.xform_ids)
            self.assertEqual(expected_ids, {change.id for change in change_context.changes})
            for change in change_context.changes:
                self.assertTrue(change.deleted)

        with self.assertRaises(CaseNotFound):
            self.casedb.get_case(case.case_id)

        for form_id in case.xform_ids:
            with self.assertRaises(XFormNotFound):
                self.formdb.get_form(form_id)
예제 #14
0
    def test_ledger_reindexer(self):
        factory = CaseFactory(domain=self.domain)
        case = factory.create_case()

        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        submit_case_blocks([
            get_single_balance_block(case.case_id, self.product_id, 100)],
            self.domain
        )

        ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id)

        index_id = 'ledger-v2' if settings.TESTS_SHOULD_USE_SQL_BACKEND else 'ledger-v1'
        call_command('ptop_reindexer_v2', index_id, cleanup=True, noinput=True, reset=True)

        self._assert_ledger_in_es(ref)
예제 #15
0
    def test_ledger_reindexer(self):
        factory = CaseFactory(domain=self.domain)
        case = factory.create_case()

        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        submit_case_blocks(
            [get_single_balance_block(case.case_id, self.product_id, 100)],
            self.domain)

        ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id)

        use_sql = should_use_sql_backend(self.domain)
        index_id = 'ledger-v2' if use_sql else 'ledger-v1'
        options = {'reset': True} if use_sql else {}
        reindex_and_clean(index_id, **options)

        self._assert_ledger_in_es(ref)
예제 #16
0
class TestGetSubcasesExpression(TestCase):

    def setUp(self):
        super(TestGetSubcasesExpression, self).setUp()
        self.domain = uuid.uuid4().hex
        self.factory = CaseFactory(domain=self.domain)
        self.expression = ExpressionFactory.from_spec({
            "type": "get_subcases",
            "case_id_expression": {
                "type": "property_name",
                "property_name": "_id"
            },
        })
        self.context = EvaluationContext({"domain": self.domain})

    def tearDown(self):
        delete_all_xforms()
        delete_all_cases()
        super(TestGetSubcasesExpression, self).tearDown()

    @run_with_all_backends
    def test_no_subcases(self):
        case = self.factory.create_case()
        subcases = self.expression(case.to_json(), self.context)
        self.assertEqual(len(subcases), 0)

    @run_with_all_backends
    def test_single_child(self):
        parent_id = uuid.uuid4().hex
        child_id = uuid.uuid4().hex
        [child, parent] = self.factory.create_or_update_case(CaseStructure(
            case_id=child_id,
            indices=[
                CaseIndex(CaseStructure(case_id=parent_id, attrs={'create': True}))
            ]
        ))
        subcases = self.expression(parent.to_json(), self.context)
        self.assertEqual(len(subcases), 1)
        self.assertEqual(child.case_id, subcases[0]['_id'])

    @run_with_all_backends
    def test_single_extension(self):
        host_id = uuid.uuid4().hex
        extension_id = uuid.uuid4().hex
        [extension, host] = self.factory.create_or_update_case(CaseStructure(
            case_id=extension_id,
            indices=[
                CaseIndex(
                    CaseStructure(case_id=host_id, attrs={'create': True}),
                    relationship=CASE_INDEX_EXTENSION
                )
            ]
        ))
        subcases = self.expression(host.to_json(), self.context)
        self.assertEqual(len(subcases), 1)
        self.assertEqual(extension.case_id, subcases[0]['_id'])
예제 #17
0
 def test_no_walk_related(self):
     factory = CaseFactory()
     parent = factory.create_case()
     child_updates = factory.create_or_update_case(
         CaseStructure(attrs={'create': True}, walk_related=False, relationships=[
             CaseRelationship(CaseStructure(case_id=parent._id))
         ]),
     )
     self.assertEqual(1, len(child_updates))
     self.assertEqual(parent._id, child_updates[0].indices[0].referenced_id)
예제 #18
0
 def test_no_walk_related(self):
     factory = CaseFactory()
     parent = factory.create_case()
     child_updates = factory.create_or_update_case(
         CaseStructure(attrs={'create': True}, walk_related=False, indices=[
             CaseIndex(CaseStructure(case_id=parent.case_id))
         ]),
     )
     self.assertEqual(1, len(child_updates))
     self.assertEqual(parent.case_id, child_updates[0].indices[0].referenced_id)
예제 #19
0
 def test_form_extras_default(self):
     domain = uuid.uuid4().hex
     # have to enable loose sync token validation for the domain or create actual SyncLog documents.
     # this is the easier path.
     LOOSE_SYNC_TOKEN_VALIDATION.set(domain, True, namespace='domain')
     token_id = uuid.uuid4().hex
     factory = CaseFactory(domain=domain, form_extras={'last_sync_token': token_id})
     case = factory.create_case()
     form = XFormInstance.get(case.xform_ids[0])
     self.assertEqual(token_id, form.last_sync_token)
    def setUp(self):
        # can't do this in setUpClass until Django 1.9 since @override_settings
        # doesn't apply to classmethods
        from corehq.apps.commtrack.tests import get_single_balance_block
        factory = CaseFactory(domain=self.domain)
        self.case = factory.create_case()
        submit_case_blocks([
            get_single_balance_block(self.case.case_id, self.product._id, 10)
        ], self.domain)

        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(self.case.case_id)
        self.assertEqual(1, len(ledger_values))
예제 #21
0
 def test_simple_delete(self):
     factory = CaseFactory()
     case = factory.create_case()
     [case] = factory.create_or_update_case(CaseStructure(case_id=case._id, attrs={'update': {'foo': 'bar'}}))
     self.assertTrue(CommCareCase.get_db().doc_exist(case._id))
     self.assertEqual(2, len(case.xform_ids))
     for form_id in case.xform_ids:
         self.assertTrue(XFormInstance.get_db().doc_exist(form_id))
     safe_hard_delete(case)
     self.assertFalse(CommCareCase.get_db().doc_exist(case._id))
     for form_id in case.xform_ids:
         self.assertFalse(XFormInstance.get_db().doc_exist(form_id))
예제 #22
0
class TestDateCasePropertyChanged(TestCase):
    def setUp(self):
        self.factory = CaseFactory('domain')
        self.case = self.factory.create_case()
        self.other_case = self.factory.create_case()

    def tearDown(self):
        delete_all_xforms()
        delete_all_cases()

    def test_date_case_property_changed(self):
        updated_on = datetime(2015, 5, 3, 12, 11)
        # submit 2 updates
        self.factory.create_or_update_case(
            CaseStructure(self.case.case_id,
                          attrs={
                              "update": {
                                  'abc': "updated"
                              },
                              "date_modified": updated_on
                          }), )
예제 #23
0
class TestCaseHistory(TestCase):
    def setUp(self):
        self.domain = "isildur"
        self.factory = CaseFactory(self.domain)
        self.case = self.factory.create_case(owner_id='owner', case_name="Aragorn", update={"prop_1": "val1"})
        self.other_case = self.factory.create_case()

    def tearDown(self):
        delete_all_xforms()
        delete_all_cases()

    @run_with_all_backends
    def test_case_history(self):
        self.factory.create_or_update_case(
            CaseStructure(
                self.case.case_id,
                attrs={
                    "update": {
                        'prop_1': "val1",
                        'prop_2': "val1",
                        'prop_3': "val1",
                    },
                }),
        )
        self.factory.create_or_update_case(
            CaseStructure(
                self.case.case_id,
                attrs={
                    "update": {
                        'prop_1': "val2",
                        'prop_2': "val2",
                        'prop_4': "val",
                    },
                }),
        )
        case = CaseAccessors(self.domain).get_case(self.case.case_id)
        history = get_case_history(case)
        self.assertEqual(history[0]['prop_1'], "val1")
        self.assertEqual(history[1]['prop_2'], "val1")
        self.assertEqual(history[2]['prop_2'], "val2")
예제 #24
0
    def test_ledger_pillow_sql(self):
        factory = CaseFactory(domain=self.domain)
        case = factory.create_case()

        consumer = get_test_kafka_consumer(topics.LEDGER)
        # have to get the seq id before the change is processed
        kafka_seq = consumer.offsets()['fetch'][(topics.LEDGER, 0)]

        from corehq.apps.commtrack.tests import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        submit_case_blocks([
            get_single_balance_block(case.case_id, self.product_id, 100)],
            self.domain
        )

        ref = UniqueLedgerReference(case.case_id, 'stock', self.product_id)
        # confirm change made it to kafka
        message = consumer.next()
        change_meta = change_meta_from_kafka_message(message.value)
        if should_use_sql_backend(self.domain):
            self.assertEqual(ref.as_id(), change_meta.document_id)
        else:
            from corehq.apps.commtrack.models import StockState
            state = StockState.objects.all()
            self.assertEqual(1, len(state))
            self.assertEqual(state[0].pk, change_meta.document_id)  #
        self.assertEqual(self.domain, change_meta.domain)

        # send to elasticsearch
        self.pillow.process_changes(since=kafka_seq, forever=False)
        self.elasticsearch.indices.refresh(LEDGER_INDEX_INFO.index)

        # confirm change made it to elasticserach
        results = self.elasticsearch.search(
            LEDGER_INDEX_INFO.index,
            LEDGER_INDEX_INFO.type, body={
                "query": {
                    "bool": {
                        "must": [{
                            "match_all": {}
                        }]
                    }
                }
            }
        )
        self.assertEqual(1, results['hits']['total'])
        ledger_doc = results['hits']['hits'][0]['_source']
        self.assertEqual(self.domain, ledger_doc['domain'])
        self.assertEqual(ref.case_id, ledger_doc['case_id'])
        self.assertEqual(ref.section_id, ledger_doc['section_id'])
        self.assertEqual(ref.entry_id, ledger_doc['entry_id'])
예제 #25
0
    def test_case_fields(self):

        expected_fields = [
            {"help_text": "", "key": "properties__level", "label": "Level", "type": "unicode"},
            {"help_text": "", "key": "properties__mood", "label": "Mood", "type": "unicode"},
            {"help_text": "", "key": "properties__move_type", "label": "Move type", "type": "unicode"},
            {"help_text": "", "key": "properties__name", "label": "Name", "type": "unicode"},
            {"help_text": "", "key": "properties__opened_on", "label": "Opened on", "type": "unicode"},
            {"help_text": "", "key": "properties__owner_id", "label": "Owner id", "type": "unicode"},
            {"help_text": "", "key": "properties__prop1", "label": "Prop1", "type": "unicode"},
            {"help_text": "", "key": "properties__type", "label": "Type", "type": "unicode"},
            {"help_text": "", "key": "date_closed", "label": "Date closed", "type": "unicode"},
            {"help_text": "", "key": "xform_ids", "label": "XForm IDs", "type": "unicode"},
            {"help_text": "", "key": "properties__date_opened", "label": "Date opened", "type": "unicode"},
            {"help_text": "", "key": "properties__external_id", "label": "External ID", "type": "unicode"},
            {"help_text": "", "key": "properties__case_name", "label": "Case name", "type": "unicode"},
            {"help_text": "", "key": "properties__case_type", "label": "Case type", "type": "unicode"},
            {"help_text": "", "key": "user_id", "label": "User ID", "type": "unicode"},
            {"help_text": "", "key": "date_modified", "label": "Date modified", "type": "unicode"},
            {"help_text": "", "key": "case_id", "label": "Case ID", "type": "unicode"},
            {"help_text": "", "key": "properties__owner_id", "label": "Owner ID", "type": "unicode"},
            {"help_text": "", "key": "resource_uri", "label": "Resource URI", "type": "unicode"}
        ]

        request = Client().get(self.test_url).wsgi_request
        bundle = Resource().build_bundle(data={}, request=request)

        factory = CaseFactory(domain="joto")
        factory.create_case(
            case_type='teddiursa',
            owner_id='owner1',
            case_name='dre',
            update={'prop1': 'blah', 'move_type': 'scratch', 'mood': 'happy', 'level': '100'}
        )

        actual_fields = ZapierCustomFieldCaseResource().obj_get_list(bundle)
        for i in range(len(actual_fields)):
            self.assertEqual(expected_fields[i], actual_fields[i].get_content())
예제 #26
0
    def setUp(self):
        super(LedgerAccessorErrorTests, self).setUp()

        # can't do this in setUpClass until Django 1.9 since @override_settings
        # doesn't apply to classmethods
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        factory = CaseFactory(domain=self.domain)
        self.case = factory.create_case()
        submit_case_blocks([
            get_single_balance_block(self.case.case_id, self.product._id, 10)
        ], self.domain)

        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case.case_id)
        self.assertEqual(1, len(ledger_values))
예제 #27
0
class TestCaseHistory(TestCase):
    def setUp(self):
        self.domain = "isildur"
        self.factory = CaseFactory(self.domain)
        self.case = self.factory.create_case(owner_id='owner',
                                             case_name="Aragorn",
                                             update={"prop_1": "val1"})
        self.other_case = self.factory.create_case()

    def tearDown(self):
        delete_all_xforms()
        delete_all_cases()

    @run_with_all_backends
    def test_case_history(self):
        self.factory.create_or_update_case(
            CaseStructure(self.case.case_id,
                          attrs={
                              "update": {
                                  'prop_1': "val1",
                                  'prop_2': "val1",
                                  'prop_3': "val1",
                              },
                          }), )
예제 #28
0
    def test_delete_with_related(self):
        factory = CaseFactory()
        parent = factory.create_case()
        [child] = factory.create_or_update_case(
            CaseStructure(attrs={'create': True}, walk_related=False, relationships=[
                CaseRelationship(CaseStructure(case_id=parent._id))
            ]),
        )
        # deleting the parent should not be allowed because the child still references it
        with self.assertRaises(CommCareCaseError):
            safe_hard_delete(parent)

        # deleting the child is ok
        safe_hard_delete(child)
        self.assertTrue(CommCareCase.get_db().doc_exist(parent._id))
        self.assertFalse(CommCareCase.get_db().doc_exist(child._id))
예제 #29
0
    def test_simple_delete(self):
        factory = CaseFactory()
        case = factory.create_case()
        [case] = factory.create_or_update_case(CaseStructure(case_id=case._id, attrs={'update': {'foo': 'bar'}}))
        self.assertIsNotNone(FormProcessorInterface.get_case(case.id))
        self.assertEqual(2, len(case.xform_ids))
        for form_id in case.xform_ids:
            self.assertIsNotNone(FormProcessorInterface.get_xform(form_id))
        FormProcessorInterface.hard_delete_case(case)

        with self.assertRaises(CaseNotFound):
            FormProcessorInterface.get_case(case.id)

        for form_id in case.xform_ids:
            with self.assertRaises(XFormNotFound):
                FormProcessorInterface.get_xform(form_id)
예제 #30
0
    def test_delete_with_related(self):
        factory = CaseFactory()
        parent = factory.create_case()
        [child] = factory.create_or_update_case(
            CaseStructure(attrs={'create': True}, walk_related=False, indices=[
                CaseIndex(CaseStructure(case_id=parent._id))
            ]),
        )
        # deleting the parent should not be allowed because the child still references it
        with self.assertRaises(CommCareCaseError):
            FormProcessorInterface.hard_delete_case(parent)

        # deleting the child is ok
        FormProcessorInterface.hard_delete_case(child)
        self.assertIsNotNone(FormProcessorInterface.get_case(parent.id))
        with self.assertRaises(CaseNotFound):
            FormProcessorInterface.get_case(child.id)
예제 #31
0
    def test_delete_with_related(self):
        factory = CaseFactory()
        parent = factory.create_case()
        [child] = factory.create_or_update_case(
            CaseStructure(
                attrs={'create': True},
                walk_related=False,
                indices=[CaseIndex(CaseStructure(case_id=parent.case_id))]), )
        # deleting the parent should not be allowed because the child still references it
        with self.assertRaises(CommCareCaseError):
            safe_hard_delete(parent)

        # deleting the child is ok
        safe_hard_delete(child)
        self.assertIsNotNone(self.casedb.get_case(parent.case_id))
        with self.assertRaises(CaseNotFound):
            self.casedb.get_case(child.case_id)
예제 #32
0
    def test_delete_with_related(self):
        factory = CaseFactory()
        parent = factory.create_case()
        [child] = factory.create_or_update_case(
            CaseStructure(attrs={'create': True},
                          walk_related=False,
                          relationships=[
                              CaseRelationship(
                                  CaseStructure(case_id=parent._id))
                          ]), )
        # deleting the parent should not be allowed because the child still references it
        with self.assertRaises(CommCareCaseError):
            safe_hard_delete(parent)

        # deleting the child is ok
        safe_hard_delete(child)
        self.assertTrue(CommCareCase.get_db().doc_exist(parent._id))
        self.assertFalse(CommCareCase.get_db().doc_exist(child._id))
예제 #33
0
    def create_docs(cls, domain, count):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.hqcase.utils import submit_case_blocks
        from corehq.apps.commtrack.helpers import make_product
        from corehq.form_processor.parsers.ledgers.helpers import UniqueLedgerReference

        cls.product = make_product(cls.domain, 'A Product', 'prodcode_a')

        factory = CaseFactory(cls.domain)
        case_ids = [factory.create_case().case_id for i in range(count)]

        for case_id in case_ids:
            submit_case_blocks([
                get_single_balance_block(case_id, cls.product._id, 10)
            ], domain)

        return [
            UniqueLedgerReference(case_id, 'stock', cls.product._id).as_id()
            for case_id in case_ids
        ]
예제 #34
0
    def post(self, request, *args, **kwargs):
        domain = request.GET.get('domain')
        case_type = request.GET.get('case_type')
        owner_id = request.GET.get('owner_id')
        properties = json.loads(request.body)
        case_name = properties.pop('case_name')
        user_name = request.GET.get('user')

        if not case_type or not owner_id or not domain or not case_name:
            return HttpResponseForbidden('Please fill in all required fields')

        couch_user = CommCareUser.get_by_username(user_name, domain)
        if not couch_user.is_member_of(domain):
            return HttpResponseForbidden(
                "This user does not have access to this domain.")

        factory = CaseFactory(domain=domain)
        new_case = factory.create_case(case_type=case_type,
                                       owner_id=owner_id,
                                       case_name=case_name,
                                       update=properties)

        return HttpResponse("Created case with id {case_id}".format(
            case_id=str(new_case.case_id)))
예제 #35
0
파일: views.py 프로젝트: dimagi/commcare-hq
    def post(self, request, *args, **kwargs):
        domain = request.GET.get('domain')
        case_type = request.GET.get('case_type')
        owner_id = request.GET.get('owner_id')
        properties = json.loads(request.body)
        case_name = properties.pop('case_name')
        user_name = request.GET.get('user')

        if not case_type or not owner_id or not domain or not case_name:
            return HttpResponseBadRequest('Please fill in all required fields')

        couch_user = CommCareUser.get_by_username(user_name)
        if not couch_user.is_member_of(domain):
            return HttpResponseForbidden("This user does not have access to this domain.")

        factory = CaseFactory(domain=domain)
        new_case = factory.create_case(
            case_type=case_type,
            owner_id=owner_id,
            case_name=case_name,
            update=properties
        )

        return HttpResponse("Created case with id {case_id}".format(case_id=str(new_case.case_id)))
예제 #36
0
 def test_create_overrides(self):
     factory = CaseFactory()
     case = factory.create_case(owner_id='somebody', update={'custom_prop': 'custom_value'})
     self.assertEqual('somebody', case.owner_id)
     self.assertEqual('custom_value', case.custom_prop)
예제 #37
0
 def test_simple_create(self):
     factory = CaseFactory()
     case = factory.create_case()
     self.assertIsNotNone(CaseAccessors().get_case(case.case_id))
예제 #38
0
 def create_docs(cls, domain, count):
     factory = CaseFactory(cls.domain)
     return [factory.create_case().case_id for i in range(count)]
class AutomaticCaseUpdateTest(TestCase):
    def setUp(self):
        self.domain = 'auto-update-test'
        self.case_db = CaseAccessors(self.domain)
        self.factory = CaseFactory(self.domain)
        self.rule = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule',
            case_type='test-case-type',
            active=True,
            server_modified_boundary=30,
        )
        self.rule.save()
        self.rule.automaticupdaterulecriteria_set = [
            AutomaticUpdateRuleCriteria(
                property_name='last_visit_date',
                property_value='30',
                match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
            ),
        ]
        self.rule.automaticupdateaction_set = [
            AutomaticUpdateAction(
                action=AutomaticUpdateAction.ACTION_UPDATE,
                property_name='update_flag',
                property_value='Y',
            ),
            AutomaticUpdateAction(
                action=AutomaticUpdateAction.ACTION_CLOSE,
            ),
        ]

        self.rule2 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-2',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=30,
        )
        self.rule2.save()
        self.rule2.automaticupdateaction_set = [
            AutomaticUpdateAction(
                action=AutomaticUpdateAction.ACTION_CLOSE,
            ),
        ]

        self.rule3 = AutomaticUpdateRule(
            domain=self.domain,
            name='test-rule-3',
            case_type='test-case-type-2',
            active=True,
            server_modified_boundary=50,
        )
        self.rule3.save()
        self.rule3.automaticupdateaction_set = [
            AutomaticUpdateAction(
                action=AutomaticUpdateAction.ACTION_CLOSE,
            ),
        ]

        with drop_connected_signals(case_post_save):
            case = self.factory.create_case(case_type='test-case-type')
        self.case_id = case.case_id

    def tearDown(self):
        AutomaticUpdateRuleCriteria.objects.all().delete()
        AutomaticUpdateAction.objects.all().delete()
        AutomaticUpdateRule.objects.all().delete()
        FormProcessorTestUtils.delete_all_cases(self.domain)

    def _get_case_ids(self, *args, **kwargs):
        return [self.case_id]

    def _get_case(self):
        return self.case_db.get_case(self.case_id)

    def _assert_case_revision(self, rev_number, last_modified, expect_modified=False):
        if should_use_sql_backend(self.domain):
            self.assertEqual(
                expect_modified,
                CaseAccessorSQL.case_modified_since(self.case_id, last_modified)
            )
        else:
            doc = self._get_case()
            self.assertTrue(doc['_rev'].startswith('%s-' % rev_number))

    @run_with_all_backends
    def test_rule(self):
        now = datetime(2015, 10, 22, 0, 0)
        with patch('corehq.apps.data_interfaces.models.AutomaticUpdateRule.get_case_ids', new=self._get_case_ids):
            # No update: both dates are 27 days away
            last_modified = datetime(2015, 9, 25, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 25))
            self._assert_case_revision(2, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(2, last_modified)

            # No update: server_modified_on is 32 days away but last_visit_date is 27 days away
            last_modified = datetime(2015, 9, 20, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 25))
            self._assert_case_revision(3, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(3, last_modified)

            # No update: last_visit_date is 32 days away but server_modified_on is 27 days away
            last_modified = datetime(2015, 9, 25, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(4, last_modified)
            run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(4, last_modified)

            # Perform update: both dates are 32 days away
            last_modified = datetime(2015, 9, 20, 12, 0)
            _update_case(self.domain, self.case_id, last_modified, date(2015, 9, 20))
            self._assert_case_revision(5, last_modified)
            with drop_connected_signals(case_post_save):
                run_case_update_rules_for_domain(self.domain, now=now)
            self._assert_case_revision(6, last_modified, True)

            case = self._get_case()
            self.assertEqual(case.get_case_property('update_flag'), 'Y')
            self.assertEqual(case.closed, True)

    @run_with_all_backends
    def test_match_days_since(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='last_visit_date',
                    property_value='30',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
                ),
            ]
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-30')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-03')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-02')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_equal(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='value1',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
            ]
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'x')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'value1')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_not_equal(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property2',
                    property_value='value2',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                ),
            ]
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'value2')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    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.
        """
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='2016-02-24',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
            ]

            set_case_property_directly(case, 'property1', '2016-02-24')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', '2016-02-25')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_date_case_properties_for_inequality(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='2016-02-24',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                ),
            ]

            set_case_property_directly(case, 'property1', '2016-02-24')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', '2016-02-25')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_match_has_value(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:
            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='property3',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
                ),
            ]
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', '')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    @run_with_all_backends
    def test_and_criteria(self):
        with _with_case(self.domain, 'test-case-type-2', datetime(2015, 1, 1)) as case:

            self.rule2.automaticupdaterulecriteria_set = [
                AutomaticUpdateRuleCriteria(
                    property_name='last_visit_date',
                    property_value='30',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_DAYS_SINCE,
                ),
                AutomaticUpdateRuleCriteria(
                    property_name='property1',
                    property_value='value1',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_EQUAL,
                ),
                AutomaticUpdateRuleCriteria(
                    property_name='property2',
                    property_value='value2',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_NOT_EQUAL,
                ),
                AutomaticUpdateRuleCriteria(
                    property_name='property3',
                    match_type=AutomaticUpdateRuleCriteria.MATCH_HAS_VALUE,
                ),
            ]

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            set_case_property_directly(case, 'property1', 'value1')
            set_case_property_directly(case, 'property2', 'x')
            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-12-30')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'last_visit_date', '2015-11-01')
            set_case_property_directly(case, 'property1', 'x')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property1', 'value1')
            set_case_property_directly(case, 'property2', 'value2')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property2', 'x')
            set_case_property_directly(case, 'property3', '')
            self.assertFalse(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

            set_case_property_directly(case, 'property3', 'x')
            self.assertTrue(self.rule2.rule_matches_case(case, datetime(2016, 1, 1)))

    def test_get_rules_from_domain(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        expected_case_types = ['test-case-type', 'test-case-type-2']
        actual_case_types = rules_by_case_type.keys()
        self.assertEqual(set(expected_case_types), set(actual_case_types))

        expected_rule_ids = [self.rule.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

        expected_rule_ids = [self.rule2.pk, self.rule3.pk]
        actual_rule_ids = [rule.pk for rule in rules_by_case_type['test-case-type-2']]
        self.assertEqual(set(expected_rule_ids), set(actual_rule_ids))

    def test_boundary_date(self):
        rules = AutomaticUpdateRule.by_domain(self.domain)
        rules_by_case_type = AutomaticUpdateRule.organize_rules_by_case_type(rules)

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))

        boundary_date = AutomaticUpdateRule.get_boundary_date(
            rules_by_case_type['test-case-type-2'], datetime(2016, 1, 1))
        self.assertEqual(boundary_date, datetime(2015, 12, 2))
예제 #40
0
class LedgerTests(TestCase):

    @classmethod
    def setUpClass(cls):
        super(LedgerTests, cls).setUpClass()
        cls.product_a = make_product(DOMAIN, 'A Product', 'prodcode_a')
        cls.product_b = make_product(DOMAIN, 'B Product', 'prodcode_b')
        cls.product_c = make_product(DOMAIN, 'C Product', 'prodcode_c')

    @classmethod
    def tearDownClass(cls):
        cls.product_a.delete()
        cls.product_b.delete()
        cls.product_c.delete()
        FormProcessorTestUtils.delete_all_cases_forms_ledgers(DOMAIN)
        super(LedgerTests, cls).tearDownClass()

    def setUp(self):
        super(LedgerTests, self).setUp()
        self.interface = FormProcessorInterface(domain=DOMAIN)
        self.factory = CaseFactory(domain=DOMAIN)
        self.case = self.factory.create_case()

    def _submit_ledgers(self, ledger_blocks):
        return submit_case_blocks(ledger_blocks, DOMAIN)[0].form_id

    def _set_balance(self, balance):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        self._submit_ledgers([
            get_single_balance_block(self.case.case_id, self.product_a._id, balance)
        ])

    def _transfer_in(self, amount):
        from corehq.apps.commtrack.tests.util import get_single_transfer_block
        self._submit_ledgers([
            get_single_transfer_block(None, self.case.case_id, self.product_a._id, amount)
        ])

    def _transfer_out(self, amount):
        from corehq.apps.commtrack.tests.util import get_single_transfer_block
        self._submit_ledgers([
            get_single_transfer_block(self.case.case_id, None, self.product_a._id, amount)
        ])

    def test_balance_submission(self):
        orignal_form_count = len(self.interface.get_case_forms(self.case.case_id))
        self._set_balance(100)
        self._assert_ledger_state(100)
        # make sure the form is part of the case's history
        self.assertEqual(orignal_form_count + 1, len(self.interface.get_case_forms(self.case.case_id)))
        self._assert_transactions([
            self._expected_val(100, 100)
        ])

    def test_balance_submission_multiple(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        balances = {
            self.product_a._id: 100,
            self.product_b._id: 50,
            self.product_c._id: 25,
        }
        self._submit_ledgers([
            get_single_balance_block(self.case.case_id, prod_id, balance)
            for prod_id, balance in balances.items()
        ])
예제 #41
0
class OwnerCleanlinessTest(DeprecatedBaseSyncTest):

    def setUp(self):
        super(OwnerCleanlinessTest, self).setUp()
        self.owner_id = uuid.uuid4().hex
        self.synclog_id = uuid.uuid4().hex
        self.domain = uuid.uuid4().hex
        self.factory = CaseFactory(
            domain=self.domain,
            case_defaults={
                'create': True,
                'owner_id': self.owner_id,
                'user_id': self.owner_id,
            }
        )
        self.assert_owner_clean()  # this first call creates the OwnershipCleanliness doc
        self.sample_case = self.factory.create_case()
        self.child, self.parent = self.factory.create_or_update_case(
            CaseStructure(
                indices=[
                    CaseIndex(),
                ]
            )
        )
        self.extension, self.host = self.factory.create_or_update_case(
            CaseStructure(
                attrs={'owner_id': UNOWNED_EXTENSION_OWNER_ID},
                indices=[
                    CaseIndex(
                        relationship=CASE_INDEX_EXTENSION
                    ),
                ]
            )
        )
        self.assert_owner_clean()  # this is an actual assertion

    def _verify_set_cleanliness_flags(self, owner_id=None):
        """
        Can be run at the end of any relevant test to check the current state of the
        OwnershipCleanliness object and verify that rebuilding it from scratch produces
        the same result
        """
        if owner_id is None:
            owner_id = self.owner_id
        owner_cleanliness = self._owner_cleanliness_for_id(owner_id)
        is_clean = owner_cleanliness.is_clean
        hint = owner_cleanliness.hint
        owner_cleanliness.delete()
        set_cleanliness_flags(self.domain, owner_id, force_full=True)
        new_cleanliness = OwnershipCleanlinessFlag.objects.get(owner_id=owner_id)
        self.assertEqual(is_clean, new_cleanliness.is_clean)
        self.assertEqual(hint, new_cleanliness.hint)
        if hint:
            self.assertTrue(hint_still_valid(self.domain, hint))

    @property
    def owner_cleanliness(self):
        return self._owner_cleanliness_for_id(self.owner_id)

    def _owner_cleanliness_for_id(self, owner_id):
        return OwnershipCleanlinessFlag.objects.get_or_create(
            owner_id=owner_id,
            domain=self.domain,
            defaults={'is_clean': True}
        )[0]

    def assert_owner_clean(self):
        self.assertTrue(self.owner_cleanliness.is_clean)

    def assert_owner_dirty(self):
        self.assertFalse(self.owner_cleanliness.is_clean)

    def assert_owner_temporarily_dirty(self):
        """
        Changing any case's owner makes the previous owner ID temporarily dirty, to allow
        syncs to happen, but the should become clean on a rebuild.

        This checks that workflow and rebuilds the cleanliness flag.
        """
        self.assertFalse(self.owner_cleanliness.is_clean)
        set_cleanliness_flags(self.domain, self.owner_id, force_full=True)
        self.assertTrue(self.owner_cleanliness.is_clean)

    def _set_owner(self, case_id, owner_id):
        case = self.factory.create_or_update_case(
            CaseStructure(case_id=case_id, attrs={'create': False, 'owner_id': owner_id})
        )[0]
        self.assertEqual(owner_id, case.owner_id)
예제 #42
0
class TestLedgerDocumentStore(TestCase):

    @classmethod
    def setUpClass(cls):
        super(TestLedgerDocumentStore, cls).setUpClass()
        cls.product_a = make_product(DOMAIN, 'A Product', uuid.uuid4().hex)

    @classmethod
    def tearDownClass(cls):
        cls.product_a.delete()
        FormProcessorTestUtils.delete_all_cases_forms_ledgers(DOMAIN)
        with override_settings(TESTS_SHOULD_USE_SQL_BACKEND=True):
            FormProcessorTestUtils.delete_all_cases_forms_ledgers(DOMAIN)
        super(TestLedgerDocumentStore, cls).tearDownClass()

    def setUp(self):
        super(TestLedgerDocumentStore, self).setUp()
        self.interface = FormProcessorInterface(domain=DOMAIN)
        self.factory = CaseFactory(domain=DOMAIN)
        self.case = self.factory.create_case()

    def test_get_document(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        block = get_single_balance_block(self.case.case_id, self.product_a._id, 100)
        submit_case_blocks(block, DOMAIN)

        from corehq.apps.commtrack.models import StockState
        stock_states = StockState.include_archived.all()
        self.assertEquals(1, len(stock_states))
        state = stock_states[0]
        store = LedgerV1DocumentStore(DOMAIN)
        doc = store.get_document(state.id)
        self.assertEquals(int(doc['_id']), state.id)
        self.assertEquals(doc['case_id'], state.case_id)

    def test_get_document_archived(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        from corehq.apps.commtrack.models import StockState
        from corehq.apps.products.models import SQLProduct

        block = get_single_balance_block(self.case.case_id, self.product_a._id, 100)
        submit_case_blocks(block, DOMAIN)

        stock_states = StockState.include_archived.all()
        self.assertEquals(1, len(stock_states))

        def toggle_product_archive():
            sql_product = SQLProduct.objects.get(code=self.product_a.code)
            sql_product.is_archived = not sql_product.is_archived
            sql_product.save()

        toggle_product_archive()
        self.addCleanup(toggle_product_archive)

        self.assertTrue(SQLProduct.objects.get(code=self.product_a.code).is_archived)

        state = stock_states[0]
        store = LedgerV1DocumentStore(DOMAIN)
        doc = store.get_document(state.id)
        self.assertEquals(int(doc['_id']), state.id)
        self.assertEquals(doc['case_id'], state.case_id)
예제 #43
0
class OwnerCleanlinessTest(SyncBaseTest):

    def setUp(self):
        super(OwnerCleanlinessTest, self).setUp()
        # ensure that randomization is on
        OWNERSHIP_CLEANLINESS.randomness = 1
        self.owner_id = uuid.uuid4().hex
        self.synclog_id = uuid.uuid4().hex
        self.domain = uuid.uuid4().hex
        self.factory = CaseFactory(
            domain=self.domain,
            case_defaults={
                'create': True,
                'owner_id': self.owner_id,
                'user_id': self.owner_id,
            }
        )
        self.assert_owner_clean()  # this first call creates the OwnershipCleanliness doc
        self.sample_case = self.factory.create_case()
        self.child, self.parent = self.factory.create_or_update_case(
            CaseStructure(
                relationships=[
                    CaseRelationship(),
                ]
            )
        )
        self.assert_owner_clean()  # this is an actual assertion

    def _verify_set_cleanliness_flags(self):
        """
        Can be run at the end of any relevant test to check the current state of the
        OwnershipCleanliness object and verify that rebuilding it from scratch produces
        the same result
        """
        is_clean = self.owner_cleanliness.is_clean
        hint = self.owner_cleanliness.hint
        self.owner_cleanliness.delete()
        set_cleanliness_flags(self.domain, self.owner_id, force_full=True)
        new_cleanliness = OwnershipCleanlinessFlag.objects.get(owner_id=self.owner_id)
        self.assertEqual(is_clean, new_cleanliness.is_clean)
        self.assertEqual(hint, new_cleanliness.hint)
        if hint:
            self.assertTrue(hint_still_valid(self.domain, self.owner_id, hint))

    @property
    def owner_cleanliness(self):
        return OwnershipCleanlinessFlag.objects.get_or_create(
            owner_id=self.owner_id,
            domain=self.domain,
            defaults={'is_clean': True}
        )[0]

    def assert_owner_clean(self):
        return self.assertTrue(self.owner_cleanliness.is_clean)

    def assert_owner_dirty(self):
        return self.assertFalse(self.owner_cleanliness.is_clean)

    def _set_owner(self, case_id, owner_id):
        case = self.factory.create_or_update_case(
            CaseStructure(case_id=case_id, attrs={'create': False, 'owner_id': owner_id})
        )[0]
        self.assertEqual(owner_id, case.owner_id)

    def test_add_normal_case_stays_clean(self):
        # change the owner ID of a normal case, should remain clean
        self.factory.create_case()
        self.assert_owner_clean()
        self._verify_set_cleanliness_flags()

    def test_change_owner_stays_clean(self):
        # change the owner ID of a normal case, should remain clean
        new_owner = uuid.uuid4().hex
        self._set_owner(self.sample_case._id, new_owner)
        self.assert_owner_clean()
        self._verify_set_cleanliness_flags()

    def test_change_owner_child_case_stays_clean(self):
        # change the owner ID of a child case, should remain clean
        new_owner = uuid.uuid4().hex
        self._set_owner(self.child._id, new_owner)
        self.assert_owner_clean()
        self._verify_set_cleanliness_flags()

    def test_add_clean_parent_stays_clean(self):
        # add a parent with the same owner, should remain clean
        self.factory.create_or_update_case(CaseStructure(relationships=[CaseRelationship()]))
        self.assert_owner_clean()
        self._verify_set_cleanliness_flags()

    def test_create_dirty_makes_dirty(self):
        # create a case and a parent case with a different owner at the same time
        # make sure the owner becomes dirty.
        new_owner = uuid.uuid4().hex
        [child, parent] = self.factory.create_or_update_case(
            CaseStructure(
                relationships=[
                    CaseRelationship(CaseStructure(attrs={'owner_id': new_owner}))
                ]
            )
        )
        self.assert_owner_dirty()
        self.assertEqual(child._id, self.owner_cleanliness.hint)
        self._verify_set_cleanliness_flags()

    def test_add_dirty_parent_makes_dirty(self):
        # add parent with a different owner and make sure the owner becomes dirty
        new_owner = uuid.uuid4().hex
        [child, parent] = self.factory.create_or_update_case(
            CaseStructure(
                case_id=self.sample_case._id,
                relationships=[
                    CaseRelationship(CaseStructure(attrs={'owner_id': new_owner}))
                ]
            )
        )
        self.assert_owner_dirty()
        self.assertEqual(child._id, self.owner_cleanliness.hint)
        self._verify_set_cleanliness_flags()

    def test_change_parent_owner_makes_dirty(self):
        # change the owner id of a parent case and make sure the owner becomes dirty
        new_owner = uuid.uuid4().hex
        self._set_owner(self.parent._id, new_owner)
        self.assert_owner_dirty()
        self.assertEqual(self.child._id, self.owner_cleanliness.hint)
        self._verify_set_cleanliness_flags()

    def test_toggle(self):
        # make sure the flag gets removed
        OWNERSHIP_CLEANLINESS.randomness = 0
        # and any test that normally expects a flag to be set to fail
        with self.assertRaises(AssertionError):
            self.test_create_dirty_makes_dirty()

    def test_set_flag_clean_no_data(self):
        unused_owner_id = uuid.uuid4().hex
        set_cleanliness_flags(self.domain, unused_owner_id)
        self.assertTrue(OwnershipCleanlinessFlag.objects.get(owner_id=unused_owner_id).is_clean)

    def test_hint_invalidation(self):
        self.test_change_parent_owner_makes_dirty()
        self._set_owner(self.parent._id, self.owner_id)
        # after the submission the dirtiness flag should still be set
        # since it isn't invalidated right away
        self.assert_owner_dirty()
        # explicitly make sure the hint is no longer valid
        self.assertFalse(hint_still_valid(self.domain, self.owner_id, self.owner_cleanliness.hint))
        # reset the cleanliness flag and ensure it worked
        set_cleanliness_flags(self.domain, self.owner_id)
        self.assert_owner_clean()
        self.assertEqual(None, self.owner_cleanliness.hint)

    def test_cross_domain_on_submission(self):
        # create a form that makes a dirty owner with the same ID but in a different domain
        # make sure the original owner stays clean
        new_domain = uuid.uuid4().hex
        # initialize the new cleanliness flag
        OwnershipCleanlinessFlag.objects.create(domain=new_domain, owner_id=self.owner_id, is_clean=True)
        self.factory.domain = new_domain
        self.factory.create_or_update_case(
            CaseStructure(
                relationships=[
                    CaseRelationship(CaseStructure(attrs={'owner_id': uuid.uuid4().hex}))
                ]
            )
        )
        self.assert_owner_clean()
        self.assertEqual(
            False,
            OwnershipCleanlinessFlag.objects.get(owner_id=self.owner_id, domain=new_domain).is_clean,
        )

    def test_cross_domain_both_clean(self):
        new_domain = uuid.uuid4().hex
        self.factory.domain = new_domain
        self.factory.create_or_update_case(
            CaseStructure(
                relationships=[
                    CaseRelationship(),
                ]
            )
        )
        # two clean ownership models in different domains should report clean
        self.assertTrue(get_cleanliness_flag_from_scratch(self.domain, self.owner_id).is_clean)
        self.assertTrue(get_cleanliness_flag_from_scratch(new_domain, self.owner_id).is_clean)

    def test_cross_domain_dirty(self):
        new_domain = uuid.uuid4().hex
        new_owner = uuid.uuid4().hex
        self.factory.domain = new_domain
        self.factory.create_or_update_case(
            CaseStructure(
                relationships=[
                    CaseRelationship(CaseStructure(attrs={'owner_id': new_owner})),
                ]
            )
        )
        # original domain should stay clean but the new one should be dirty
        self.assertTrue(get_cleanliness_flag_from_scratch(self.domain, self.owner_id).is_clean)
        self.assertFalse(get_cleanliness_flag_from_scratch(new_domain, self.owner_id).is_clean)

    @override_settings(TESTS_SHOULD_TRACK_CLEANLINESS=False)
    def test_autocreate_flag_off(self):
        new_owner = uuid.uuid4().hex
        self.factory.create_or_update_case(
            CaseStructure(case_id=uuid.uuid4().hex, attrs={'create': True, 'owner_id': new_owner})
        )[0]
        self.assertFalse(OwnershipCleanlinessFlag.objects.filter(domain=self.domain, owner_id=new_owner).exists())

    @override_settings(TESTS_SHOULD_TRACK_CLEANLINESS=True)
    def test_autocreate_flag_on(self):
        new_owner = uuid.uuid4().hex
        self.factory.create_or_update_case(
            CaseStructure(case_id=uuid.uuid4().hex, attrs={'create': True, 'owner_id': new_owner})
        )[0]
        flag = OwnershipCleanlinessFlag.objects.get(domain=self.domain, owner_id=new_owner)
        self.assertEqual(True, flag.is_clean)
예제 #44
0
 def test_create_overrides(self):
     factory = CaseFactory()
     case = factory.create_case(owner_id="somebody", update={"custom_prop": "custom_value"})
     self.assertEqual("somebody", case.owner_id)
     self.assertEqual("custom_value", case.dynamic_case_properties()["custom_prop"])
예제 #45
0
 def test_simple_create(self):
     factory = CaseFactory()
     case = factory.create_case()
     self.assertTrue(CommCareCase.get_db().doc_exist(case._id))
예제 #46
0
 def test_simple_create(self):
     factory = CaseFactory()
     case = factory.create_case()
     self.assertIsNotNone(CaseAccessors().get_case(case.case_id))
예제 #47
0
 def test_factory_defaults(self):
     owner_id = uuid.uuid4().hex
     factory = CaseFactory(case_defaults={'owner_id': owner_id})
     case = factory.create_case()
     self.assertEqual(owner_id, case.owner_id)
예제 #48
0
 def test_override_defaults(self):
     owner_id = uuid.uuid4().hex
     factory = CaseFactory(case_defaults={'owner_id': owner_id})
     case = factory.create_case(owner_id='notthedefault')
     self.assertEqual('notthedefault', case.owner_id)
예제 #49
0
 def test_override_defaults(self):
     owner_id = uuid.uuid4().hex
     factory = CaseFactory(case_defaults={"owner_id": owner_id})
     case = factory.create_case(owner_id="notthedefault")
     self.assertEqual("notthedefault", case.owner_id)
예제 #50
0
class ImporterTest(TestCase):

    def setUp(self):
        super(ImporterTest, self).setUp()
        self.domain_obj = create_domain("importer-test")
        self.domain = self.domain_obj.name
        self.default_case_type = 'importer-test-casetype'

        self.couch_user = WebUser.create(None, "test", "foobar")
        self.couch_user.add_domain_membership(self.domain, is_admin=True)
        self.couch_user.save()

        self.accessor = CaseAccessors(self.domain)

        self.factory = CaseFactory(domain=self.domain, case_defaults={
            'case_type': self.default_case_type,
        })
        delete_all_cases()

    def tearDown(self):
        self.couch_user.delete()
        self.domain_obj.delete()
        super(ImporterTest, self).tearDown()

    def _config(self, col_names, search_column=None, case_type=None,
                search_field='case_id', create_new_cases=True):
        return ImporterConfig(
            couch_user_id=self.couch_user._id,
            case_type=case_type or self.default_case_type,
            excel_fields=col_names,
            case_fields=[''] * len(col_names),
            custom_fields=col_names,
            search_column=search_column or col_names[0],
            search_field=search_field,
            create_new_cases=create_new_cases,
        )

    @run_with_all_backends
    @patch('corehq.apps.case_importer.tasks.bulk_import_async.update_state')
    def testImportNone(self, update_state):
        res = bulk_import_async.delay(self._config(['anything']), self.domain, None)
        self.assertIsInstance(res.result, Ignore)
        update_state.assert_called_with(
            state=states.FAILURE,
            meta={'errors': 'Sorry, your session has expired. Please start over and try again.'})
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    @run_with_all_backends
    def testImportBasic(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(5, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['num_chunks'])
        case_ids = self.accessor.get_case_ids_in_domain()
        cases = list(self.accessor.get_cases(case_ids))
        self.assertEqual(5, len(cases))
        properties_seen = set()
        for case in cases:
            self.assertEqual(self.couch_user._id, case.user_id)
            self.assertEqual(self.couch_user._id, case.owner_id)
            self.assertEqual(self.default_case_type, case.type)
            for prop in ['age', 'sex', 'location']:
                self.assertTrue(prop in case.get_case_property(prop))
                self.assertFalse(case.get_case_property(prop) in properties_seen)
                properties_seen.add(case.get_case_property(prop))

    @run_with_all_backends
    def testImportNamedColumns(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
        )
        res = do_import(file, config, self.domain)

        self.assertEqual(4, res['created_count'])
        self.assertEqual(4, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testImportTrailingWhitespace(self):
        cols = ['case_id', 'age', 'sex\xa0', 'location']
        config = self._config(cols)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex\xa0', 'location'],
            ['case_id-0', 'age-0', 'sex\xa0-0', 'location-0'],
        )
        res = do_import(file, config, self.domain)

        self.assertEqual(1, res['created_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        case = self.accessor.get_case(case_ids[0])
        self.assertTrue(bool(case.get_case_property('sex')))  # make sure the value also got properly set

    @run_with_all_backends
    def testCaseIdMatching(self):
        # bootstrap a stub case
        [case] = self.factory.create_or_update_case(CaseStructure(attrs={
            'create': True,
            'update': {'importer_test_prop': 'foo'},
        }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        [case] = self.accessor.get_cases(case_ids)
        for prop in ['age', 'sex', 'location']:
            self.assertTrue(prop in case.get_case_property(prop))

        # shouldn't touch existing properties
        self.assertEqual('foo', case.get_case_property('importer_test_prop'))

    @run_with_all_backends
    def testCaseLookupTypeCheck(self):
        [case] = self.factory.create_or_update_case(CaseStructure(attrs={
            'create': True,
            'case_type': 'nonmatch-type',
        }))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        # because the type is wrong these shouldn't match
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(4, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testCaseLookupDomainCheck(self):
        self.factory.domain = 'wrong-domain'
        [case] = self.factory.create_or_update_case(CaseStructure(attrs={
            'create': True,
        }))
        self.assertEqual(0, len(self.accessor.get_case_ids_in_domain()))
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [case.case_id, 'age-0', 'sex-0', 'location-0'],
            [case.case_id, 'age-1', 'sex-1', 'location-1'],
            [case.case_id, 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)

        # because the domain is wrong these shouldn't match
        self.assertEqual(3, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(3, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def testExternalIdMatching(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'
        [case] = self.factory.create_or_update_case(CaseStructure(
            attrs={
                'create': True,
                'external_id': external_id,
            }
        ))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = make_worksheet_wrapper(
            ['external_id', 'age', 'sex', 'location'],
            ['importer-test-external-id', 'age-0', 'sex-0', 'location-0'],
            ['importer-test-external-id', 'age-1', 'sex-1', 'location-1'],
            ['importer-test-external-id', 'age-2', 'sex-2', 'location-2'],
        )
        res = do_import(file, config, self.domain)
        self.assertEqual(0, res['created_count'])
        self.assertEqual(3, res['match_count'])
        self.assertFalse(res['errors'])

        # shouldn't create any more cases, just the one
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

    @run_with_all_backends
    def test_external_id_matching_on_create_with_custom_column_name(self):
        headers = ['id_column', 'age', 'sex', 'location']
        external_id = 'external-id-test'
        config = self._config(headers[1:], search_column='id_column', search_field='external_id')
        file = make_worksheet_wrapper(
            ['id_column', 'age', 'sex', 'location'],
            ['external-id-test', 'age-0', 'sex-0', 'location-0'],
            ['external-id-test', 'age-1', 'sex-1', 'location-1'],
        )

        res = do_import(file, config, self.domain)
        self.assertFalse(res['errors'])
        self.assertEqual(1, res['created_count'])
        self.assertEqual(1, res['match_count'])
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        case = self.accessor.get_case(case_ids[0])
        self.assertEqual(external_id, case.external_id)

    def testNoCreateNew(self):
        config = self._config(['case_id', 'age', 'sex', 'location'], create_new_cases=False)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain)

        # no matching and no create new set - should do nothing
        self.assertEqual(0, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    def testBlankRows(self):
        # don't create new cases for rows left blank
        config = self._config(['case_id', 'age', 'sex', 'location'], create_new_cases=True)
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            [None, None, None, None],
            ['', '', '', ''],
        )
        res = do_import(file, config, self.domain)

        # no matching and no create new set - should do nothing
        self.assertEqual(0, res['created_count'])
        self.assertEqual(0, res['match_count'])
        self.assertEqual(0, len(get_case_ids_in_domain(self.domain)))

    def testBasicChunking(self):
        config = self._config(['case_id', 'age', 'sex', 'location'])
        file = make_worksheet_wrapper(
            ['case_id', 'age', 'sex', 'location'],
            ['case_id-0', 'age-0', 'sex-0', 'location-0'],
            ['case_id-1', 'age-1', 'sex-1', 'location-1'],
            ['case_id-2', 'age-2', 'sex-2', 'location-2'],
            ['case_id-3', 'age-3', 'sex-3', 'location-3'],
            ['case_id-4', 'age-4', 'sex-4', 'location-4'],
        )
        res = do_import(file, config, self.domain, chunksize=2)
        # 5 cases in chunks of 2 = 3 chunks
        self.assertEqual(3, res['num_chunks'])
        self.assertEqual(5, res['created_count'])
        self.assertEqual(5, len(get_case_ids_in_domain(self.domain)))

    @run_with_all_backends
    def testExternalIdChunking(self):
        # bootstrap a stub case
        external_id = 'importer-test-external-id'

        headers = ['external_id', 'age', 'sex', 'location']
        config = self._config(headers, search_field='external_id')
        file = make_worksheet_wrapper(
            ['external_id', 'age', 'sex', 'location'],
            ['importer-test-external-id', 'age-0', 'sex-0', 'location-0'],
            ['importer-test-external-id', 'age-1', 'sex-1', 'location-1'],
            ['importer-test-external-id', 'age-2', 'sex-2', 'location-2'],
        )

        # the first one should create the case, and the remaining two should update it
        res = do_import(file, config, self.domain)
        self.assertEqual(1, res['created_count'])
        self.assertEqual(2, res['match_count'])
        self.assertFalse(res['errors'])
        self.assertEqual(2, res['num_chunks']) # the lookup causes an extra chunk

        # should just create the one case
        case_ids = self.accessor.get_case_ids_in_domain()
        self.assertEqual(1, len(case_ids))
        [case] = self.accessor.get_cases(case_ids)
        self.assertEqual(external_id, case.external_id)
        for prop in ['age', 'sex', 'location']:
            self.assertTrue(prop in case.get_case_property(prop))

    @run_with_all_backends
    def testParentCase(self):
        headers = ['parent_id', 'name', 'case_id']
        config = self._config(headers, create_new_cases=True, search_column='case_id')
        rows = 3
        [parent_case] = self.factory.create_or_update_case(CaseStructure(attrs={'create': True}))
        self.assertEqual(1, len(self.accessor.get_case_ids_in_domain()))

        file = make_worksheet_wrapper(
            ['parent_id', 'name', 'case_id'],
            [parent_case.case_id, 'name-0', 'case_id-0'],
            [parent_case.case_id, 'name-1', 'case_id-1'],
            [parent_case.case_id, 'name-2', 'case_id-2'],
        )
        file_missing = make_worksheet_wrapper(
            ['parent_id', 'name', 'case_id'],
            ['parent_id-0', 'name-0', 'case_id-0'],
            ['parent_id-1', 'name-1', 'case_id-1'],
            ['parent_id-2', 'name-2', 'case_id-2'],
        )

        # Should successfully match on `rows` cases
        res = do_import(file, config, self.domain)
        self.assertEqual(rows, res['created_count'])

        # Should be unable to find parent case on `rows` cases
        res = do_import(file_missing, config, self.domain)
        error_column_name = 'parent_id'
        self.assertEqual(rows,
                         len(res['errors'][ImportErrors.InvalidParentId][error_column_name]['rows']),
                         "All cases should have missing parent")

    def import_mock_file(self, rows):
        config = self._config(rows[0])
        xls_file = make_worksheet_wrapper(*rows)
        return do_import(xls_file, config, self.domain)

    @run_with_all_backends
    def testLocationOwner(self):
        # This is actually testing several different things, but I figure it's
        # worth it, as each of these tests takes a non-trivial amount of time.
        non_case_sharing = LocationType.objects.create(
            domain=self.domain, name='lt1', shares_cases=False
        )
        case_sharing = LocationType.objects.create(
            domain=self.domain, name='lt2', shares_cases=True
        )
        location = make_loc('loc-1', 'Loc 1', self.domain, case_sharing.code)
        make_loc('loc-2', 'Loc 2', self.domain, case_sharing.code)
        duplicate_loc = make_loc('loc-3', 'Loc 2', self.domain, case_sharing.code)
        improper_loc = make_loc('loc-4', 'Loc 4', self.domain, non_case_sharing.code)

        res = self.import_mock_file([
            ['case_id', 'name', 'owner_id', 'owner_name'],
            ['', 'location-owner-id', location.group_id, ''],
            ['', 'location-owner-code', '', location.site_code],
            ['', 'location-owner-name', '', location.name],
            ['', 'duplicate-location-name', '', duplicate_loc.name],
            ['', 'non-case-owning-name', '', improper_loc.name],
        ])
        case_ids = self.accessor.get_case_ids_in_domain()
        cases = {c.name: c for c in list(self.accessor.get_cases(case_ids))}

        self.assertEqual(cases['location-owner-id'].owner_id, location.group_id)
        self.assertEqual(cases['location-owner-code'].owner_id, location.group_id)
        self.assertEqual(cases['location-owner-name'].owner_id, location.group_id)

        error_message = ImportErrors.DuplicateLocationName
        error_column_name = None
        self.assertIn(error_message, res['errors'])
        self.assertEqual(res['errors'][error_message][error_column_name]['rows'], [5])

        error_message = ImportErrors.InvalidOwnerId
        self.assertIn(error_message, res['errors'])
        error_column_name = 'owner_id'
        self.assertEqual(res['errors'][error_message][error_column_name]['rows'], [6])

    @run_with_all_backends
    def test_opened_on(self):
        case = self.factory.create_case()
        new_date = '2015-04-30T14:41:53.000000Z'
        with flag_enabled('BULK_UPLOAD_DATE_OPENED'):
            self.import_mock_file([
                ['case_id', 'date_opened'],
                [case.case_id, new_date]
            ])
        case = CaseAccessors(self.domain).get_case(case.case_id)
        self.assertEqual(case.opened_on, PhoneTime(parse_datetime(new_date)).done())

    @run_with_all_backends
    def test_columns_and_rows_align(self):
        case_owner = CommCareUser.create(self.domain, 'username', 'pw')
        res = self.import_mock_file([
            ['case_id', 'name', '', 'favorite_color', 'owner_id'],
            ['', 'Jeff', '', 'blue', case_owner._id],
            ['', 'Caroline', '', 'yellow', case_owner._id],
        ])
        self.assertEqual(res['errors'], {})

        case_ids = self.accessor.get_case_ids_in_domain()
        cases = {c.name: c for c in list(self.accessor.get_cases(case_ids))}
        self.assertEqual(cases['Jeff'].owner_id, case_owner._id)
        self.assertEqual(cases['Jeff'].get_case_property('favorite_color'), 'blue')
        self.assertEqual(cases['Caroline'].owner_id, case_owner._id)
        self.assertEqual(cases['Caroline'].get_case_property('favorite_color'), 'yellow')
예제 #51
0
 def test_domain(self):
     domain = uuid.uuid4().hex
     factory = CaseFactory(domain=domain)
     case = factory.create_case()
     self.assertEqual(domain, case.domain)
예제 #52
0
 def test_factory_defaults(self):
     owner_id = uuid.uuid4().hex
     factory = CaseFactory(case_defaults={'owner_id': owner_id})
     case = factory.create_case()
     self.assertEqual(owner_id, case.owner_id)
예제 #53
0
class LedgerDBAccessorTest(TestCase):
    @classmethod
    def setUpClass(cls):
        super(LedgerDBAccessorTest, cls).setUpClass()
        cls.domain = uuid.uuid4().hex
        with override_settings(TESTS_SHOULD_USE_SQL_BACKEND=True):
            FormProcessorTestUtils.delete_all_cases_forms_ledgers(cls.domain)
        cls.product_a = make_product(cls.domain, 'A Product', 'prodcode_a')
        cls.product_b = make_product(cls.domain, 'B Product', 'prodcode_b')
        cls.product_c = make_product(cls.domain, 'C Product', 'prodcode_c')

    @classmethod
    def tearDownClass(cls):
        cls.product_a.delete()
        cls.product_b.delete()
        cls.product_c.delete()

        with override_settings(TESTS_SHOULD_USE_SQL_BACKEND=True):
            FormProcessorTestUtils.delete_all_cases_forms_ledgers(cls.domain)
        super(LedgerDBAccessorTest, cls).tearDownClass()

    def setUp(self):
        super(LedgerDBAccessorTest, self).setUp()
        self.factory = CaseFactory(domain=self.domain)
        self.case_one = self.factory.create_case()
        self.case_two = self.factory.create_case()

    def tearDown(self):
        FormProcessorTestUtils.delete_all_ledgers(self.domain)
        super(LedgerDBAccessorTest, self).tearDown()

    def _submit_ledgers(self, ledger_blocks):
        return submit_case_blocks(ledger_blocks, self.domain)[0].form_id

    def _set_balance(self, balance, case_id, product_id):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        return self._submit_ledgers(
            [get_single_balance_block(case_id, product_id, balance)])

    def test_delete_ledger_transactions_for_form(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block

        self._set_balance(100, self.case_one.case_id, self.product_a._id)

        case_ids = [self.case_one.case_id, self.case_two.case_id]
        form_id = self._submit_ledgers([
            get_single_balance_block(case_id, product_id, 10)
            for case_id in case_ids
            for product_id in [self.product_a._id, self.product_b._id]
        ])
        deleted = LedgerAccessorSQL.delete_ledger_transactions_for_form(
            case_ids, form_id)
        self.assertEqual(4, deleted)
        self.assertEqual(
            1,
            len(
                LedgerAccessorSQL.get_ledger_transactions_for_case(
                    self.case_one.case_id)))
        self.assertEqual(
            0,
            len(
                LedgerAccessorSQL.get_ledger_transactions_for_case(
                    self.case_two.case_id)))

    def test_delete_ledger_values_case_section_entry(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        form_id = self._submit_ledgers([
            get_single_balance_block(self.case_one.case_id, product_id, 10)
            for product_id in [self.product_a._id, self.product_b._id]
        ])
        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(2, len(ledger_values))

        LedgerAccessorSQL.delete_ledger_transactions_for_form(
            [self.case_one.case_id], form_id)
        deleted = LedgerAccessorSQL.delete_ledger_values(
            self.case_one.case_id, 'stock', self.product_a._id)
        self.assertEqual(1, deleted)

        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(1, len(ledger_values))
        self.assertEqual(self.product_b._id, ledger_values[0].product_id)

    def test_delete_ledger_values_case_section(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        form_id = self._submit_ledgers([
            get_single_balance_block(self.case_one.case_id, product_id, 10)
            for product_id in [self.product_a._id, self.product_b._id]
        ])
        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(2, len(ledger_values))

        LedgerAccessorSQL.delete_ledger_transactions_for_form(
            [self.case_one.case_id], form_id)
        deleted = LedgerAccessorSQL.delete_ledger_values(
            self.case_one.case_id, 'stock')
        self.assertEqual(2, deleted)

        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(0, len(ledger_values))

    def test_delete_ledger_values_case_section_1(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        form_id = self._submit_ledgers([
            get_single_balance_block(self.case_one.case_id,
                                     self.product_a._id,
                                     10,
                                     section_id=section_id)
            for section_id in ['stock', 'consumption']
        ])
        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(2, len(ledger_values))

        LedgerAccessorSQL.delete_ledger_transactions_for_form(
            [self.case_one.case_id], form_id)
        deleted = LedgerAccessorSQL.delete_ledger_values(
            self.case_one.case_id, 'stock')
        self.assertEqual(1, deleted)

        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(1, len(ledger_values))
        self.assertEqual('consumption', ledger_values[0].section_id)

    def test_delete_ledger_values_case(self):
        from corehq.apps.commtrack.tests.util import get_single_balance_block
        form_id = self._submit_ledgers([
            get_single_balance_block(self.case_one.case_id,
                                     product_id,
                                     10,
                                     section_id=section_id)
            for product_id in [self.product_a._id, self.product_b._id]
            for section_id in ['stock', 'consumption']
        ])
        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(4, len(ledger_values))

        LedgerAccessorSQL.delete_ledger_transactions_for_form(
            [self.case_one.case_id], form_id)
        deleted = LedgerAccessorSQL.delete_ledger_values(self.case_one.case_id)
        self.assertEqual(4, deleted)

        ledger_values = LedgerAccessorSQL.get_ledger_values_for_case(
            self.case_one.case_id)
        self.assertEqual(0, len(ledger_values))
예제 #54
0
 def test_override_defaults(self):
     owner_id = uuid.uuid4().hex
     factory = CaseFactory(case_defaults={'owner_id': owner_id})
     case = factory.create_case(owner_id='notthedefault')
     self.assertEqual('notthedefault', case.owner_id)
예제 #55
0
 def test_domain(self):
     domain = uuid.uuid4().hex
     factory = CaseFactory(domain=domain)
     case = factory.create_case()
     self.assertEqual(domain, case.domain)
예제 #56
0
class LedgerTests(TestCase):

    @classmethod
    def setUpClass(cls):
        FormProcessorTestUtils.delete_all_cases(DOMAIN)
        FormProcessorTestUtils.delete_all_xforms(DOMAIN)
        cls.product = make_product(DOMAIN, 'A Product', 'prodcode')

    def setUp(self):
        self.interface = FormProcessorInterface(domain=DOMAIN)
        self.factory = CaseFactory(domain=DOMAIN)
        self.case = self.factory.create_case()

    def _submit_ledgers(self, ledger_block, quantity):
        return submit_case_blocks(
            ledger_block.format(case_id=self.case.case_id, product_id=self.product._id, quantity=quantity),
            DOMAIN
        )

    def _set_balance(self, balance):
        self._submit_ledgers(BALANCE_BLOCK, balance)

    @run_with_all_backends
    def test_balance_submission(self):
        orignal_form_count = len(self.interface.get_case_forms(self.case.case_id))
        self._submit_ledgers(BALANCE_BLOCK, 100)
        self._assert_ledger_state(100)
        # make sure the form is part of the case's history
        self.assertEqual(orignal_form_count + 1, len(self.interface.get_case_forms(self.case.case_id)))

    @run_with_all_backends
    def test_balance_submission_with_prior_balance(self):
        self._set_balance(100)
        self._assert_ledger_state(100)
        self._set_balance(50)
        self._assert_ledger_state(50)
        self._set_balance(150)
        self._assert_ledger_state(150)

    @run_with_all_backends
    def test_transfer_submission(self):
        orignal_form_count = len(self.interface.get_case_forms(self.case.case_id))
        self._submit_ledgers(TRANSFER_BLOCK, 100)
        self._assert_ledger_state(100)
        # make sure the form is part of the case's history
        self.assertEqual(orignal_form_count + 1, len(self.interface.get_case_forms(self.case.case_id)))

    @run_with_all_backends
    def test_transfer_submission_with_prior_balance(self):
        self._set_balance(100)
        self._submit_ledgers(TRANSFER_BLOCK, 100)
        self._assert_ledger_state(200)

    def _assert_ledger_state(self, expected_balance):
        ledgers = self.interface.ledger_processor.get_ledgers_for_case(self.case.case_id)
        self.assertEqual(1, len(ledgers))
        ledger = ledgers[0]
        self.assertEqual(self.case.case_id, ledger.case_id)
        self.assertEqual(self.product._id, ledger.entry_id)
        self.assertEqual('stock', ledger.section_id)
        self.assertEqual(expected_balance, ledger.balance)