Example #1
0
    def test_sync_from_remote(self):
        # no existing contact with same identity
        remote = TembaContact.create(uuid="C-002", name="Frank", blocked=False)
        self.assertEqual(sync_from_remote(self.unicef, self.syncer, remote), SyncOutcome.created)

        Contact.objects.get(org=self.unicef, uuid="C-002", name="Frank", backend=self.rapidpro_backend, is_active=True)
        self.assertIsNone(Contact.objects.filter(org=self.unicef, uuid="C-002", name="Frank",
                                                 backend=self.floip_backend, is_active=True).first())

        remote = TembaContact.create(uuid="CF-002", name="Frank", blocked=False)
        self.assertEqual(sync_from_remote(self.unicef, self.syncer2, remote), SyncOutcome.created)
        Contact.objects.get(org=self.unicef, uuid="CF-002", name="Frank", backend=self.floip_backend, is_active=True)

        # no significant change
        remote = TembaContact.create(uuid="C-002", name="Frank", blocked=False)
        self.assertEqual(sync_from_remote(self.unicef, self.syncer, remote), SyncOutcome.ignored)

        Contact.objects.get(org=self.unicef, uuid="C-002", name="Frank", backend=self.rapidpro_backend, is_active=True)

        # significant change (name)
        remote = TembaContact.create(uuid="C-002", name="Franky", blocked=False)
        self.assertEqual(sync_from_remote(self.unicef, self.syncer, remote), SyncOutcome.updated)

        Contact.objects.get(org=self.unicef, uuid="C-002", name="Franky", backend=self.rapidpro_backend, is_active=True)

        # change to something we don't want locally
        remote = TembaContact.create(uuid="C-002", name="Franky", blocked=True)
        self.assertEqual(sync_from_remote(self.unicef, self.syncer, remote), SyncOutcome.deleted)

        Contact.objects.get(org=self.unicef, uuid="C-002", name="Franky", backend=self.rapidpro_backend,
                            is_active=False)
Example #2
0
    def test_local_kwargs(self):
        remote = TembaContact.create(uuid="C-002", name="Frank", blocked=False)
        kwargs = self.syncer.local_kwargs(self.unicef, remote)
        self.assertEqual(kwargs, {'org': self.unicef, 'uuid': "C-002", 'name': "Frank",
                                  'backend': self.rapidpro_backend})

        remote = TembaContact.create(uuid="CF-002", name="Frank", blocked=False)
        kwargs = self.syncer2.local_kwargs(self.unicef, remote)
        self.assertEqual(kwargs, {'org': self.unicef, 'uuid': "CF-002", 'name': "Frank",
                                  'backend': self.floip_backend})

        remote = TembaContact.create(uuid="C-002", name="Frank", blocked=True)
        self.assertIsNone(self.syncer.local_kwargs(self.unicef, remote))

        remote = TembaContact.create(uuid="CF-002", name="Frank", blocked=True)
        self.assertIsNone(self.syncer2.local_kwargs(self.unicef, remote))
def make_contact(phone_number='5551234567', groups=None):
    if groups is None:
        groups = []
    return Contact.create(urns=[f'tel:+1{phone_number}'],
                          groups=groups,
                          modified_on=make_aware(datetime(2018, 1, 2, 3, 4,
                                                          5)))
Example #4
0
    def test_local_kwargs(self):
        kwargs = self.syncer.local_kwargs(
            self.unicef,
            TembaContact.create(
                uuid="C-001",
                name="Bob McFlow",
                language="eng",
                urns=["twitter:bobflow"],
                groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                fields={"age": "34"},
                stopped=False,
                blocked=False,
            ),
        )

        self.assertEqual(
            kwargs,
            {
                "org": self.unicef,
                "uuid": "C-001",
                "name": "Bob McFlow",
                "language": "eng",
                "is_blocked": False,
                "is_stopped": False,
                "is_stub": False,
                "fields": {"age": "34"},
                "__data__groups": [("G-001", "Customers")],
            },
        )
Example #5
0
def make_contact(phone_number='5551234567', groups=None, uuid="blarg"):
    if groups is None:
        groups = []
    return Contact.create(uuid=uuid,
                          urns=[make_phone_number_urn(phone_number)],
                          groups=groups,
                          modified_on=make_aware(datetime(2018, 1, 2, 3, 4,
                                                          5)))
Example #6
0
 def test_wont_add_contact_to_group_if_they_have_blocked_or_stopped_us(
         self):
     contact = Contact.create(groups=["FAKE ARG GROUP"],
                              fields={"fake_field": "blah"},
                              blocked=True)
     client, _ = make_client_mocks("get_contacts", contact)
     mock_query(client, "get_groups", "FAKE BOOP GROUP")
     campaign = FollowupCampaign("Boop Group", "date_of_boop")
     with freeze_time("2018-01-02"):
         campaign.add_contact(client, "Narf Jones", "5551234567", "en")
     client.update_contact.assert_not_called()
Example #7
0
 def get_contacts(self, uuids=None, urns=None, groups=None, after=None, before=None, pager=None):
     return [
         TembaContact.create(
             uuid="000-001",
             name="Ann",
             urns=["tel:1234"],
             groups=["000-002"],
             fields=dict(state="Lagos", lga="Oyo", gender="Female", born="1990"),
             language="eng",
             modified_on=timezone.now(),
         )
     ]
Example #8
0
    def test_sync_local_to_set(self):
        Contact.objects.all().delete()  # start with no contacts...

        remote_set = [
            TembaContact.create(uuid="C-001", name="Anne", blocked=False),
            TembaContact.create(uuid="C-002", name="Bob", blocked=False),
            TembaContact.create(uuid="C-003", name="Colin", blocked=False),
            TembaContact.create(uuid="C-004", name="Donald", blocked=True)
        ]

        self.assertEqual(sync_local_to_set(self.unicef, self.syncer, remote_set), (3, 0, 0, 1))
        self.assertEqual(Contact.objects.count(), 3)

        remote_set = [
            # first contact removed
            TembaContact.create(uuid="C-002", name="Bob", blocked=False),    # no change
            TembaContact.create(uuid="C-003", name="Colm", blocked=False),   # changed name
            TembaContact.create(uuid="C-005", name="Edward", blocked=False)  # new contact
        ]

        self.assertEqual(sync_local_to_set(self.unicef, self.syncer, remote_set), (1, 1, 1, 1))

        self.assertEqual(Contact.objects.count(), 4)
        Contact.objects.get(org=self.unicef, uuid="C-001", name="Anne", is_active=False)
        Contact.objects.get(org=self.unicef, uuid="C-002", name="Bob", is_active=True)
        Contact.objects.get(org=self.unicef, uuid="C-003", name="Colm", is_active=True)
        Contact.objects.get(org=self.unicef, uuid="C-005", name="Edward", is_active=True)

        remote_set = [
            # first contact removed
            TembaContact.create(uuid="CF-002", name="Bob", blocked=False),    # no change
            TembaContact.create(uuid="CF-003", name="Colm", blocked=False),   # changed name
            TembaContact.create(uuid="CF-005", name="Edward", blocked=False)  # new contact
        ]
        self.assertEqual(sync_local_to_set(self.unicef, self.syncer2, remote_set), (3, 0, 0, 0))
        self.assertEqual(Contact.objects.count(), 7)
        Contact.objects.get(org=self.unicef, uuid="CF-002", name="Bob", backend=self.floip_backend, is_active=True)
        Contact.objects.get(org=self.unicef, uuid="CF-003", name="Colm", backend=self.floip_backend, is_active=True)
        Contact.objects.get(org=self.unicef, uuid="CF-005", name="Edward", backend=self.floip_backend, is_active=True)
 def test_add_contact_works(self):
     contact = Contact.create(groups=["FAKE ARG GROUP"],
                              fields={'fake_field': 'blah'})
     client, _ = make_client_mocks('get_contacts', contact)
     mock_query(client, 'get_groups', "FAKE BOOP GROUP")
     campaign = FollowupCampaign('Boop Group', 'date_of_boop')
     with freeze_time('2018-01-02'):
         campaign.add_contact(client, "Narf Jones", "5551234567")
     client.update_contact.assert_called_once_with(
         contact,
         groups=["FAKE ARG GROUP", "FAKE BOOP GROUP"],
         fields={
             'fake_field': 'blah',
             'date_of_boop': '2018-01-02T00:00:00.000000Z'
         })
Example #10
0
 def test_add_contact_works(self):
     contact = Contact.create(groups=["FAKE ARG GROUP"],
                              fields={"fake_field": "blah"})
     client, _ = make_client_mocks("get_contacts", contact)
     mock_query(client, "get_groups", "FAKE BOOP GROUP")
     campaign = FollowupCampaign("Boop Group", "date_of_boop")
     with freeze_time("2018-01-02"):
         campaign.add_contact(client, "Narf Jones", "5551234567", "en")
     client.update_contact.assert_called_once_with(
         contact,
         groups=["FAKE ARG GROUP", "FAKE BOOP GROUP"],
         fields={
             "fake_field": "blah",
             "date_of_boop": "2018-01-02T00:00:00.000000Z"
         },
     )
Example #11
0
    def test_local_kwargs(self):
        kwargs = self.syncer.local_kwargs(self.unicef, TembaContact.create(
                uuid="C-001",
                name="Bob McFlow",
                language="eng",
                urns=["twitter:bobflow"],
                groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                fields={'age': "34"},
                failed=False,
                blocked=False
        ))

        self.assertEqual(kwargs, {
            'org': self.unicef,
            'uuid': "C-001",
            'name': "Bob McFlow",
            'language': "eng",
            'is_stub': False,
            'fields': {'age': "34"},
            '__data__groups': [("G-001", "Customers")],
        })
Example #12
0
 def get_contacts(self,
                  uuids=None,
                  urns=None,
                  groups=None,
                  after=None,
                  before=None,
                  pager=None):
     return [
         TembaContact.create(
             uuid="000-001",
             name="Ann",
             urns=["tel:1234"],
             groups=["000-002"],
             fields=dict(state="Lagos",
                         lga="Oyo",
                         gender="Female",
                         born="1990"),
             language="eng",
             modified_on=timezone.now(),
         )
     ]
Example #13
0
    def test_local_kwargs(self):
        kwargs = self.syncer.local_kwargs(self.unicef, TembaContact.create(
                uuid="C-001",
                name="Bob McFlow",
                language="eng",
                urns=["twitter:bobflow"],
                groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                fields={'age': "34"},
                stopped=False,
                blocked=False
        ))

        self.assertEqual(kwargs, {
            'org': self.unicef,
            'uuid': "C-001",
            'name': "Bob McFlow",
            'language': "eng",
            'is_blocked': False,
            'is_stopped': False,
            'is_stub': False,
            'fields': {'age': "34"},
            '__data__groups': [("G-001", "Customers")],
        })
Example #14
0
    def test_pull_contacts(self, mock_get_contacts):

        Contact.objects.all().delete()

        # empty fetches
        mock_get_contacts.side_effect = [
            # first call to get active contacts
            MockClientQuery([]),

            # second call to get deleted contacts
            MockClientQuery([])
        ]

        with self.assertNumQueries(0):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 0, 0, 0))

        # fecthed contact not in configured group get ignored
        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlow", language="eng", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                        fields={'age': "34"}, failed=False, blocked=False
                    ),
                    TembaContact.create(
                        uuid="C-002", name="Jim McMsg", language="fre", urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={'age': "67"}, failed=False, blocked=False
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003", name="Ann McPoll", language="eng", urns=["tel:+250783835664"],
                        groups=[],
                        fields={'age': "35"}, failed=True, blocked=False
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(4):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 0, 0, 3))

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlow", language="eng", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "34"}, failed=False, blocked=False
                    ),
                    TembaContact.create(
                        uuid="C-002", name="Jim McMsg", language="fre", urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={'age': "67"}, failed=False, blocked=False
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003", name="Ann McPoll", language="eng", urns=["tel:+250783835664"],
                        groups=[],
                        fields={'age': "35"}, failed=True, blocked=False
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(8):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (1, 0, 0, 2))

        Contact.objects.all().delete()

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlow", language="eng", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "34"}, failed=False, blocked=False
                    ),
                    TembaContact.create(
                        uuid="C-002", name="Jim McMsg", language="fre", urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "67"}, failed=False, blocked=False
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003", name="Ann McPoll", language="eng", urns=["tel:+250783835664"],
                        groups=[],
                        fields={'age': "35"}, failed=True, blocked=False
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(9):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (2, 0, 0, 1))

        Contact.objects.all().delete()

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            # all included in the reporters
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlow", language="eng", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "34"}, failed=False, blocked=False
                    ),
                    TembaContact.create(
                        uuid="C-002", name="Jim McMsg", language="fre", urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "67"}, failed=False, blocked=False
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003", name="Ann McPoll", language="eng", urns=["tel:+250783835664"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "35"}, failed=True, blocked=False
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(10):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (3, 0, 0, 0))

        contact_jan = Contact.objects.filter(uuid='C-001').first()
        self.assertFalse(contact_jan.born)
        self.assertFalse(contact_jan.state)

        mock_get_contacts.side_effect = [
            # first call to get active contacts
            MockClientQuery(
                [
                    TembaContact.create(uuid='C-001', name="Jan", urns=['tel:123'],
                                        groups=[ObjectRef.create(uuid='G-001', name='ureporters'),
                                                ObjectRef.create(uuid='G-007', name='Actors')],
                                        fields={'registration_date': '2014-01-02T03:04:05.000000Z', 'state':'Lagos',
                                                'lga': 'Oyo', 'occupation': 'Student', 'born': '1990',
                                                'gender': 'Male'},
                                        language='eng'),
                    TembaContact.create(
                        uuid="C-002", name="Jim McMsg", language="fre", urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={'age': "67", "born": "1992"}, failed=False, blocked=False
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(8):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 2, 0, 0))

        contact_jan = Contact.objects.filter(uuid='C-001').first()

        self.assertTrue(contact_jan.born)
        self.assertEqual(contact_jan.born, 1990)
        self.assertTrue(contact_jan.state)
        self.assertEqual(contact_jan.state, 'R-LAGOS')

        self.assertTrue(Contact.objects.filter(uuid='C-002', is_active=True))

        mock_get_contacts.side_effect = [
            # first call to get active contacts
            MockClientQuery([]
            ),
            # second call to get deleted contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-002", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(2):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 0, 1, 0))

        self.assertFalse(Contact.objects.filter(uuid='C-002', is_active=True))
Example #15
0
    def test_local_kwargs(self):

        temba_contact = TembaContact.create(uuid='C-006', name="Jan", urns=['tel:123'],
                                            groups=[ObjectRef.create(uuid='G-001', name='Musicians'),
                                                    ObjectRef.create(uuid='G-007', name='Actors')],
                                            fields={'registration_date': None, 'state': None,
                                                    'lga': None, 'occupation': None, 'born': None,
                                                    'gender': None},
                                            language='eng')

        self.assertIsNone(self.syncer.local_kwargs(self.nigeria, temba_contact))

        temba_contact = TembaContact.create(uuid='C-006', name="Jan", urns=['tel:123'],
                                            groups=[ObjectRef.create(uuid='G-001', name='ureporters'),
                                                    ObjectRef.create(uuid='G-007', name='Actors')],
                                            fields={'registration_date': None, 'state': None,
                                                    'lga': None, 'occupation': None, 'born': None,
                                                    'gender': None},
                                            language='eng')

        self.assertEqual(self.syncer.local_kwargs(self.nigeria, temba_contact),
                         {'org': self.nigeria,
                          'uuid': 'C-006',
                          'gender': '',
                          'born': 0,
                          'occupation': '',
                          'registered_on': None,
                          'state': '',
                          'district': ''})

        temba_contact = TembaContact.create(uuid='C-007', name="Jan", urns=['tel:123'],
                                            groups=[ObjectRef.create(uuid='G-001', name='ureporters'),
                                                    ObjectRef.create(uuid='G-007', name='Actors')],
                                            fields={'registration_date': '2014-01-02T03:04:05.000000Z',
                                                    'state': 'Kigali', 'lga': 'Oyo', 'occupation': 'Student',
                                                    'born': '1990', 'gender': 'Male'},
                                            language='eng')

        self.assertEqual(self.syncer.local_kwargs(self.nigeria, temba_contact),
                         {'org': self.nigeria,
                          'uuid': 'C-007',
                          'gender': 'M',
                          'born': 1990,
                          'occupation': 'Student',
                          'registered_on': json_date_to_datetime('2014-01-02T03:04:05.000'),
                          'state': '',
                          'district': ''})

        temba_contact = TembaContact.create(uuid='C-008', name="Jan", urns=['tel:123'],
                                            groups=[ObjectRef.create(uuid='G-001', name='ureporters'),
                                                    ObjectRef.create(uuid='G-007', name='Actors')],
                                            fields={'registration_date': '2014-01-02T03:04:05.000000Z', 'state':'Lagos',
                                                    'lga': 'Oyo', 'occupation': 'Student', 'born': '1990',
                                                    'gender': 'Male'},
                                            language='eng')

        self.assertEqual(self.syncer.local_kwargs(self.nigeria, temba_contact),
                         {'org': self.nigeria,
                          'uuid': 'C-008',
                          'gender': 'M',
                          'born': 1990,
                          'occupation': 'Student',
                          'registered_on': json_date_to_datetime('2014-01-02T03:04:05.000'),
                          'state': 'R-LAGOS',
                          'district': 'R-OYO'})

        temba_contact = TembaContact.create(uuid='C-008', name="Jan", urns=['tel:123'],
                                            groups=[ObjectRef.create(uuid='G-001', name='ureporters'),
                                                    ObjectRef.create(uuid='G-007', name='Actors')],
                                            fields={'registration_date': '2014-01-02T03:04:05.000000Z', 'state':'Lagos',
                                                    'lga': 'Oyo', 'occupation': 'Student', 'born': '-1',
                                                    'gender': 'Male'},
                                            language='eng')

        self.assertEqual(self.syncer.local_kwargs(self.nigeria, temba_contact),
                         {'org': self.nigeria,
                          'uuid': 'C-008',
                          'gender': 'M',
                          'born': 0,
                          'occupation': 'Student',
                          'registered_on': json_date_to_datetime('2014-01-02T03:04:05.000'),
                          'state': 'R-LAGOS',
                          'district': 'R-OYO'})

        temba_contact = TembaContact.create(uuid='C-008', name="Jan", urns=['tel:123'],
                                            groups=[ObjectRef.create(uuid='G-001', name='ureporters'),
                                                    ObjectRef.create(uuid='G-007', name='Actors')],
                                            fields={'registration_date': '2014-01-02T03:04:05.000000Z', 'state':'Lagos',
                                                    'lga': 'Oyo', 'occupation': 'Student', 'born': '2147483648',
                                                    'gender': 'Male'},
                                            language='eng')

        self.assertEqual(self.syncer.local_kwargs(self.nigeria, temba_contact),
                         {'org': self.nigeria,
                          'uuid': 'C-008',
                          'gender': 'M',
                          'born': 0,
                          'occupation': 'Student',
                          'registered_on': json_date_to_datetime('2014-01-02T03:04:05.000'),
                          'state': 'R-LAGOS',
                          'district': 'R-OYO'})
Example #16
0
 def get_contacts(self, uuids=None, urns=None, groups=None, after=None, before=None, pager=None):
     return [TembaContact.create(
             uuid='000-001', name="Ann", urns=['tel:1234'], groups=['000-002'],
             fields=dict(state="Lagos", lga="Oyo", gender='Female', born="1990"),
             language='eng', modified_on=timezone.now())]
Example #17
0
    def test_update_required(self):
        # create stub contact
        local = Contact.get_or_create(self.unicef, "C-001", "Ann")

        # a stub contact should always be updated
        self.assertTrue(
            self.syncer.update_required(
                local,
                TembaContact.create(
                    uuid="000-001",
                    name="Ann",
                    urns=["tel:1234"],
                    groups=[],
                    fields={},
                    language=None,
                    blocked=False,
                    stopped=False,
                    modified_on=now(),
                ),
                {},
            )
        )

        local.groups.add(self.reporters)
        local.language = "eng"
        local.is_stub = False
        local.fields = {"chat_name": "ann"}
        local.save()

        # no differences (besides null field value which is ignored)
        self.assertFalse(
            self.syncer.update_required(
                local,
                TembaContact.create(
                    uuid="000-001",
                    name="Ann",
                    urns=["tel:1234"],
                    groups=[ObjectRef.create(uuid="G-003", name="Reporters")],
                    fields={"chat_name": "ann", "age": None},
                    language="eng",
                    blocked=False,
                    stopped=False,
                    modified_on=now(),
                ),
                {},
            )
        )

        # name change
        self.assertTrue(
            self.syncer.update_required(
                local,
                TembaContact.create(
                    uuid="000-001",
                    name="Annie",
                    urns=["tel:1234"],
                    groups=[ObjectRef.create(uuid="G-003", name="Reporters")],
                    fields={"chat_name": "ann"},
                    language="eng",
                    blocked=False,
                    stopped=False,
                    modified_on=now(),
                ),
                {},
            )
        )

        # group change
        self.assertTrue(
            self.syncer.update_required(
                local,
                TembaContact.create(
                    uuid="000-001",
                    name="Ann",
                    urns=["tel:1234"],
                    groups=[ObjectRef.create(uuid="G-002", name="Females")],
                    fields={"chat_name": "ann"},
                    language="eng",
                    blocked=False,
                    stopped=False,
                    modified_on=now(),
                ),
                {},
            )
        )

        # field value change
        self.assertTrue(
            self.syncer.update_required(
                local,
                TembaContact.create(
                    uuid="000-001",
                    name="Ann",
                    urns=["tel:1234"],
                    groups=[ObjectRef.create(uuid="G-003", name="Reporters")],
                    fields={"chat_name": "ann8111"},
                    language="eng",
                    blocked=False,
                    stopped=False,
                    modified_on=now(),
                ),
                {},
            )
        )

        # new field
        self.assertTrue(
            self.syncer.update_required(
                local,
                TembaContact.create(
                    uuid="000-001",
                    name="Ann",
                    urns=["tel:1234"],
                    groups=[ObjectRef.create(uuid="G-003", name="Reporters")],
                    fields={"chat_name": "ann", "age": "35"},
                    language="eng",
                    blocked=False,
                    stopped=False,
                    modified_on=now(),
                ),
                {},
            )
        )
Example #18
0
    def test_pull_contacts(self, mock_get_contacts):
        # start with nothing...
        Group.objects.all().delete()
        Field.objects.all().delete()
        Contact.objects.all().delete()

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlow",
                        language="eng",
                        urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                        fields={"age": "34"},
                        stopped=False,
                        blocked=False,
                    ),
                    TembaContact.create(
                        uuid="C-002",
                        name="Jim McMsg",
                        language="fre",
                        urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={"age": "67"},
                        stopped=False,
                        blocked=False,
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003",
                        name="Ann McPoll",
                        language="eng",
                        urns=["tel:+250783835664"],
                        groups=[],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ],
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(16):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (3, 0, 0, 0))

        bob = Contact.objects.get(uuid="C-001")
        jim = Contact.objects.get(uuid="C-002")
        ann = Contact.objects.get(uuid="C-003")

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {bob, jim, ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), set())

        # stub contact groups will have been created too
        customers = Group.objects.get(org=self.unicef, uuid="G-001", name="Customers", is_active=False)
        spammers = Group.objects.get(org=self.unicef, uuid="G-002", name="Spammers", is_active=False)

        self.assertEqual(bob.name, "Bob McFlow")
        self.assertEqual(bob.language, "eng")
        self.assertEqual(set(bob.groups.all()), {customers})
        self.assertEqual(bob.get_fields(), {"age": "34"})

        mock_get_contacts.side_effect = [
            # first call to get active contacts will just one updated contact
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlough",
                        language="fre",
                        urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
            # second call to get deleted contacts returns Jim
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-002",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(13):
            self.assertEqual(self.backend.pull_contacts(self.unicef, None, None), (0, 1, 1, 0))

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {bob, ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), {jim})

        self.assertEqual(jim.groups.count(), 0)  # de-activated contacts are removed from groups

        bob.refresh_from_db()
        self.assertEqual(bob.name, "Bob McFlough")
        self.assertEqual(bob.language, "fre")
        self.assertEqual(set(bob.groups.all()), {spammers})
        self.assertEqual(bob.get_fields(), {"age": "35"})

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return a contact with only a change to URNs.. which we don't track
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlough",
                        language="fre",
                        urns=["twitter:bobflow22"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
            MockClientQuery([]),
        ]

        with self.assertNumQueries(3):
            self.assertEqual(self.backend.pull_contacts(self.unicef, None, None), (0, 0, 0, 1))

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {bob, ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), {jim})
Example #19
0
    def test_contact_sync(self, mock_get_groups, mock_get_fields, mock_get_contacts):
        # start with no groups or fields
        Group.objects.all().delete()
        Field.objects.all().delete()

        fetch_size = 250
        num_fetches = 4
        num_groups = 50
        num_fields = 50
        names = ["Ann", "Bob", "Cat"]
        field_values = ["12345", None]
        groups_in = 5

        # setup get_fields
        fields = [
            TembaField.create(key="field_%d" % f, label="Field #%d" % f, value_type="text")
            for f in range(0, num_fields)
        ]
        mock_get_fields.return_value = MockClientQuery(fields)

        # sync fields
        start = time.time()
        self.assertEqual((num_fields, 0, 0, 0), self.backend.pull_fields(self.unicef))

        print("Initial field sync: %f secs" % (time.time() - start))

        # setup get_groups
        groups = [
            TembaGroup.create(uuid="G0000000-0000-0000-0000-00000000%04d" % g, name="Group #%d" % g, count=0)
            for g in range(0, num_groups)
        ]
        mock_get_groups.return_value = MockClientQuery(groups)

        # sync groups
        start = time.time()
        self.assertEqual((num_groups, 0, 0, 0), self.backend.pull_groups(self.unicef))

        print("Initial group sync: %f secs" % (time.time() - start))

        # setup get_contacts to return multiple fetches of contacts
        active_fetches = []
        for b in range(0, num_fetches):
            batch = []
            for c in range(0, fetch_size):
                num = b * fetch_size + c
                batch.append(
                    TembaContact.create(
                        uuid="C0000000-0000-0000-0000-00000000%04d" % num,
                        name=names[num % len(names)],
                        language="eng",
                        urns=["tel:+26096415%04d" % num],
                        groups=[
                            ObjectRef.create(uuid="G0000000-0000-0000-0000-00000000%04d" % g, name="Group #%d" % g)
                            for g in range(0, groups_in)
                        ],
                        fields={
                            "custom_field_%d" % f: field_values[f % len(field_values)] for f in range(0, num_fields)
                        },
                        stopped=False,
                        blocked=False,
                    )
                )
            active_fetches.append(batch)

        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]  # no deleted contacts

        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)

        print("Initial contact sync: %f secs" % (time.time() - start))

        self.assertEqual((num_created, num_updated, num_deleted), (num_fetches * fetch_size, 0, 0))

        # slowest_queries = sorted(connection.queries, key=lambda q: q['time'], reverse=True)[:10]

        # for q in slowest_queries:
        #    print "%s -- %s" % (q['time'], q['sql'])

        # simulate a subsequent sync with no changes
        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]
        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)
        self.assertEqual((num_created, num_updated, num_deleted), (0, 0, 0))

        print("Contact sync with no changes: %f secs" % (time.time() - start))

        # simulate an update of 1 field value
        for batch in active_fetches:
            for c in batch:
                c.fields["custom_field_1"] = "UPDATED"

        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]
        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)
        self.assertEqual((num_created, num_updated, num_deleted), (0, num_fetches * fetch_size, 0))

        print("Contact sync with 1 field value changes: %f secs" % (time.time() - start))

        # simulate an update of 10 field values
        for batch in active_fetches:
            for c in batch:
                for f in (10, 11, 12, 13, 14, 15, 16, 17, 18, 19):
                    c.fields["custom_field_%d" % f] = "UPDATED"

        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]
        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)
        self.assertEqual((num_created, num_updated, num_deleted), (0, num_fetches * fetch_size, 0))

        print("Contact sync with 10 field value changes: %f secs" % (time.time() - start))
Example #20
0
    def test_update_required(self):
        # create stub contact
        local = Contact.get_or_create(self.unicef, 'C-001', "Ann")

        # a stub contact should always be updated
        self.assertTrue(self.syncer.update_required(local, TembaContact.create(
            uuid='000-001',
            name="Ann",
            urns=['tel:1234'],
            groups=[],
            fields={},
            language=None,
            modified_on=now()
        ), {}))

        local.groups.add(self.reporters)
        local.language = "eng"
        local.is_stub = False
        local.fields = {'chat_name': "ann"}
        local.save()

        # no differences (besides null field value which is ignored)
        self.assertFalse(self.syncer.update_required(local, TembaContact.create(
            uuid='000-001',
            name="Ann",
            urns=['tel:1234'],
            groups=[ObjectRef.create(uuid='G-003', name="Reporters")],
            fields={'chat_name': "ann", 'age': None},
            language='eng',
            modified_on=now()
        ), {}))

        # name change
        self.assertTrue(self.syncer.update_required(local, TembaContact.create(
            uuid='000-001',
            name="Annie",
            urns=['tel:1234'],
            groups=[ObjectRef.create(uuid='G-003', name="Reporters")],
            fields={'chat_name': "ann"},
            language='eng',
            modified_on=now()
        ), {}))

        # group change
        self.assertTrue(self.syncer.update_required(local, TembaContact.create(
            uuid='000-001',
            name="Ann",
            urns=['tel:1234'],
            groups=[ObjectRef.create(uuid='G-002', name="Females")],
            fields={'chat_name': "ann"},
            language='eng', modified_on=now()
        ), {}))

        # field value change
        self.assertTrue(self.syncer.update_required(local, TembaContact.create(
            uuid='000-001',
            name="Ann",
            urns=['tel:1234'],
            groups=[ObjectRef.create(uuid='G-003', name="Reporters")],
            fields={'chat_name': "ann8111"},
            language='eng', modified_on=now()
        ), {}))

        # new field
        self.assertTrue(self.syncer.update_required(local, TembaContact.create(
            uuid='000-001',
            name="Ann",
            urns=['tel:1234'],
            groups=[ObjectRef.create(uuid='G-003', name="Reporters")],
            fields={'chat_name': "ann", 'age': "35"},
            language='eng', modified_on=now()
        ), {}))
Example #21
0
    def test_local_kwargs(self):
        temba_contact = TembaContact.create(
            uuid="C-006",
            name="Jan",
            urns=["tel:123"],
            groups=[ObjectRef.create(uuid="G-001", name="ureporters"), ObjectRef.create(uuid="G-007", name="Actors")],
            fields={
                "registration_date": None,
                "state": None,
                "lga": None,
                "occupation": None,
                "born": None,
                "gender": None,
            },
            language="eng",
        )

        self.assertEqual(
            self.syncer.local_kwargs(self.nigeria, temba_contact),
            {
                "backend": self.floip_backend,
                "org": self.nigeria,
                "uuid": "C-006",
                "gender": "",
                "born": 0,
                "occupation": "",
                "registered_on": None,
                "state": "",
                "district": "",
                "ward": "",
            },
        )

        temba_contact = TembaContact.create(
            uuid="C-007",
            name="Jan",
            urns=["tel:123"],
            groups=[ObjectRef.create(uuid="G-001", name="ureporters"), ObjectRef.create(uuid="G-007", name="Actors")],
            fields={
                "registration_date": "2014-01-02T03:04:05.000000Z",
                "state": "Kigali",
                "lga": "Oyo",
                "occupation": "Student",
                "born": "1990",
                "gender": "Male",
            },
            language="eng",
        )

        self.assertEqual(
            self.syncer.local_kwargs(self.nigeria, temba_contact),
            {
                "backend": self.floip_backend,
                "org": self.nigeria,
                "uuid": "C-007",
                "gender": "M",
                "born": 1990,
                "occupation": "Student",
                "registered_on": json_date_to_datetime("2014-01-02T03:04:05.000"),
                "state": "",
                "district": "",
                "ward": "",
            },
        )

        temba_contact = TembaContact.create(
            uuid="C-008",
            name="Jan",
            urns=["tel:123"],
            groups=[ObjectRef.create(uuid="G-001", name="ureporters"), ObjectRef.create(uuid="G-007", name="Actors")],
            fields={
                "registration_date": "2014-01-02T03:04:05.000000Z",
                "state": "Lagos",
                "lga": "Oyo",
                "ward": "Ikeja",
                "occupation": "Student",
                "born": "1990",
                "gender": "Male",
            },
            language="eng",
        )

        self.assertEqual(
            self.syncer.local_kwargs(self.nigeria, temba_contact),
            {
                "backend": self.floip_backend,
                "org": self.nigeria,
                "uuid": "C-008",
                "gender": "M",
                "born": 1990,
                "occupation": "Student",
                "registered_on": json_date_to_datetime("2014-01-02T03:04:05.000"),
                "state": "R-LAGOS",
                "district": "R-OYO",
                "ward": "R-IKEJA",
            },
        )

        temba_contact = TembaContact.create(
            uuid="C-008",
            name="Jan",
            urns=["tel:123"],
            groups=[ObjectRef.create(uuid="G-001", name="ureporters"), ObjectRef.create(uuid="G-007", name="Actors")],
            fields={
                "registration_date": "2014-01-02T03:04:05.000000Z",
                "state": "Lagos",
                "lga": "Oyo",
                "occupation": "Student",
                "born": "-1",
                "gender": "Male",
            },
            language="eng",
        )

        self.assertEqual(
            self.syncer.local_kwargs(self.nigeria, temba_contact),
            {
                "backend": self.floip_backend,
                "org": self.nigeria,
                "uuid": "C-008",
                "gender": "M",
                "born": 0,
                "occupation": "Student",
                "registered_on": json_date_to_datetime("2014-01-02T03:04:05.000"),
                "state": "R-LAGOS",
                "district": "R-OYO",
                "ward": "",
            },
        )

        temba_contact = TembaContact.create(
            uuid="C-008",
            name="Jan",
            urns=["tel:123"],
            groups=[ObjectRef.create(uuid="G-001", name="ureporters"), ObjectRef.create(uuid="G-007", name="Actors")],
            fields={
                "registration_date": "2014-01-02T03:04:05.000000Z",
                "state": "Lagos",
                "lga": "Oyo",
                "occupation": "Student",
                "born": "2147483648",
                "gender": "Male",
            },
            language="eng",
        )

        self.assertEqual(
            self.syncer.local_kwargs(self.nigeria, temba_contact),
            {
                "backend": self.floip_backend,
                "org": self.nigeria,
                "uuid": "C-008",
                "gender": "M",
                "born": 0,
                "occupation": "Student",
                "registered_on": json_date_to_datetime("2014-01-02T03:04:05.000"),
                "state": "R-LAGOS",
                "district": "R-OYO",
                "ward": "",
            },
        )
Example #22
0
    def test_pull_contacts(self, mock_get_contacts):

        Contact.objects.all().delete()

        # empty fetches
        mock_get_contacts.side_effect = [
            # first call to get active contacts
            MockClientQuery([]),
            # second call to get deleted contacts
            MockClientQuery([]),
        ]

        with self.assertNumQueries(0):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 0, 0, 0))

        # fecthed contact not in configured group get ignored
        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlow",
                        language="eng",
                        urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                        fields={"age": "34"},
                        stopped=False,
                        blocked=False,
                    ),
                    TembaContact.create(
                        uuid="C-002",
                        name="Jim McMsg",
                        language="fre",
                        urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={"age": "67"},
                        stopped=False,
                        blocked=False,
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003",
                        name="Ann McPoll",
                        language="eng",
                        urns=["tel:+250783835664"],
                        groups=[],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ],
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(10):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (3, 0, 0, 0))

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlow",
                        language="eng",
                        urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "34"},
                        stopped=False,
                        blocked=False,
                    ),
                    TembaContact.create(
                        uuid="C-002",
                        name="Jim McMsg",
                        language="fre",
                        urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={"age": "67"},
                        stopped=False,
                        blocked=False,
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003",
                        name="Ann McPoll",
                        language="eng",
                        urns=["tel:+250783835664"],
                        groups=[],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ],
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(10):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 0, 0, 3))

        Contact.objects.all().delete()

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlow",
                        language="eng",
                        urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "34"},
                        stopped=False,
                        blocked=False,
                    ),
                    TembaContact.create(
                        uuid="C-002",
                        name="Jim McMsg",
                        language="fre",
                        urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "67"},
                        stopped=False,
                        blocked=False,
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003",
                        name="Ann McPoll",
                        language="eng",
                        urns=["tel:+250783835664"],
                        groups=[],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ],
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(10):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (3, 0, 0, 0))

        Contact.objects.all().delete()

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            # all included in the reporters
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Bob McFlow",
                        language="eng",
                        urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "34"},
                        stopped=False,
                        blocked=False,
                    ),
                    TembaContact.create(
                        uuid="C-002",
                        name="Jim McMsg",
                        language="fre",
                        urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "67"},
                        stopped=False,
                        blocked=False,
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003",
                        name="Ann McPoll",
                        language="eng",
                        urns=["tel:+250783835664"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "35"},
                        stopped=True,
                        blocked=False,
                    )
                ],
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(10):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (3, 0, 0, 0))

        contact_jan = Contact.objects.filter(uuid="C-001").first()
        self.assertFalse(contact_jan.born)
        self.assertFalse(contact_jan.state)

        mock_get_contacts.side_effect = [
            # first call to get active contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001",
                        name="Jan",
                        urns=["tel:123"],
                        groups=[
                            ObjectRef.create(uuid="G-001", name="ureporters"),
                            ObjectRef.create(uuid="G-007", name="Actors"),
                        ],
                        fields={
                            "registration_date": "2014-01-02T03:04:05.000000Z",
                            "state": "Nigeria > Lagos",
                            "lga": "Nigeria > Lagos > Oyo",
                            "occupation": "Student",
                            "born": "1990",
                            "gender": "Male",
                        },
                        language="eng",
                    ),
                    TembaContact.create(
                        uuid="C-002",
                        name="Jim McMsg",
                        language="fre",
                        urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-001", name="ureporters")],
                        fields={"age": "67", "born": "1992"},
                        stopped=False,
                        blocked=False,
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(10):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 2, 0, 0))

        contact_jan = Contact.objects.filter(uuid="C-001").first()

        self.assertTrue(contact_jan.born)
        self.assertEqual(contact_jan.born, 1990)
        self.assertTrue(contact_jan.state)
        self.assertEqual(contact_jan.state, "R-LAGOS")

        self.assertTrue(Contact.objects.filter(uuid="C-002", is_active=True))

        mock_get_contacts.side_effect = [
            # first call to get active contacts
            MockClientQuery([]),
            # second call to get deleted contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-002",
                        name=None,
                        language=None,
                        urns=[],
                        groups=[],
                        fields=None,
                        stopped=True,
                        blocked=False,
                    )
                ]
            ),
        ]

        with self.assertNumQueries(3):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.nigeria, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (0, 0, 1, 0))

        self.assertFalse(Contact.objects.filter(uuid="C-002", is_active=True))
Example #23
0
    def test_contact_sync(self, mock_get_groups, mock_get_fields, mock_get_contacts):
        # start with no groups or fields
        Group.objects.all().delete()
        Field.objects.all().delete()

        fetch_size = 250
        num_fetches = 4
        num_groups = 50
        num_fields = 50
        names = ["Ann", "Bob", "Cat"]
        field_values = ["12345", None]
        groups_in = 5

        # setup get_fields
        fields = [TembaField.create(key='field_%d' % f, label='Field #%d' % f, value_type='text')
                  for f in range(0, num_fields)]
        mock_get_fields.return_value = MockClientQuery(fields)

        # sync fields
        start = time.time()
        self.assertEqual((num_fields, 0, 0, 0), self.backend.pull_fields(self.unicef))

        print "Initial field sync: %f secs" % (time.time() - start)

        # setup get_groups
        groups = [TembaGroup.create(uuid="G0000000-0000-0000-0000-00000000%04d" % g, name="Group #%d" % g, count=0)
                  for g in range(0, num_groups)]
        mock_get_groups.return_value = MockClientQuery(groups)

        # sync groups
        start = time.time()
        self.assertEqual((num_groups, 0, 0, 0), self.backend.pull_groups(self.unicef))

        print "Initial group sync: %f secs" % (time.time() - start)

        # setup get_contacts to return multiple fetches of contacts
        active_fetches = []
        for b in range(0, num_fetches):
            batch = []
            for c in range(0, fetch_size):
                num = b * fetch_size + c
                batch.append(TembaContact.create(
                    uuid="C0000000-0000-0000-0000-00000000%04d" % num,
                    name=names[num % len(names)],
                    language="eng",
                    urns=["tel:+26096415%04d" % num],
                    groups=[
                        ObjectRef.create(uuid="G0000000-0000-0000-0000-00000000%04d" % g, name="Group #%d" % g)
                        for g in range(0, groups_in)
                    ],
                    fields={'custom_field_%d' % f: field_values[f % len(field_values)] for f in range(0, num_fields)},
                    failed=False,
                    blocked=False
                ))
            active_fetches.append(batch)

        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]  # no deleted contacts

        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)

        print "Initial contact sync: %f secs" % (time.time() - start)

        self.assertEqual((num_created, num_updated, num_deleted), (num_fetches * fetch_size, 0, 0))

        # slowest_queries = sorted(connection.queries, key=lambda q: q['time'], reverse=True)[:10]

        # for q in slowest_queries:
        #    print "%s -- %s" % (q['time'], q['sql'])

        # simulate a subsequent sync with no changes
        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]
        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)
        self.assertEqual((num_created, num_updated, num_deleted), (0, 0, 0))

        print "Contact sync with no changes: %f secs" % (time.time() - start)

        # simulate an update of 1 field value
        for batch in active_fetches:
            for c in batch:
                c.fields['custom_field_1'] = "UPDATED"

        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]
        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)
        self.assertEqual((num_created, num_updated, num_deleted), (0, num_fetches * fetch_size, 0))

        print "Contact sync with 1 field value changes: %f secs" % (time.time() - start)

        # simulate an update of 10 field values
        for batch in active_fetches:
            for c in batch:
                for f in (10, 11, 12, 13, 14, 15, 16, 17, 18, 19):
                    c.fields['custom_field_%d' % f] = "UPDATED"

        mock_get_contacts.side_effect = [MockClientQuery(*active_fetches), MockClientQuery([])]
        start = time.time()
        num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)
        self.assertEqual((num_created, num_updated, num_deleted), (0, num_fetches * fetch_size, 0))

        print "Contact sync with 10 field value changes: %f secs" % (time.time() - start)
Example #24
0
    def test_pull_contacts(self, mock_get_contacts):
        # start with nothing...
        Group.objects.all().delete()
        Field.objects.all().delete()
        Contact.objects.all().delete()

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return two fetches of 2 and 1 contacts
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlow", language="eng", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-001", name="Customers")],
                        fields={'age': "34"}, failed=False, blocked=False
                    ),
                    TembaContact.create(
                        uuid="C-002", name="Jim McMsg", language="fre", urns=["tel:+250783835665"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={'age': "67"}, failed=False, blocked=False
                    ),
                ],
                [
                    TembaContact.create(
                        uuid="C-003", name="Ann McPoll", language="eng", urns=["tel:+250783835664"],
                        groups=[],
                        fields={'age': "35"}, failed=True, blocked=False
                    ),
                ]
            ),
            # second call to get deleted contacts returns a contact we don't have
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-004", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(15):
            num_created, num_updated, num_deleted, num_ignored = self.backend.pull_contacts(self.unicef, None, None)

        self.assertEqual((num_created, num_updated, num_deleted, num_ignored), (3, 0, 0, 0))

        bob = Contact.objects.get(uuid="C-001")
        jim = Contact.objects.get(uuid="C-002")
        ann = Contact.objects.get(uuid="C-003")

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {bob, jim, ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), set())

        # stub contact groups will have been created too
        customers = Group.objects.get(org=self.unicef, uuid="G-001", name="Customers", is_active=False)
        spammers = Group.objects.get(org=self.unicef, uuid="G-002", name="Spammers", is_active=False)

        self.assertEqual(bob.name, "Bob McFlow")
        self.assertEqual(bob.language, "eng")
        self.assertEqual(set(bob.groups.all()), {customers})
        self.assertEqual(bob.get_fields(), {'age': "34"})

        mock_get_contacts.side_effect = [
            # first call to get active contacts will just one updated contact
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlough", language="fre", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={'age': "35"}, failed=True, blocked=False
                    )
                ]
            ),
            # second call to get deleted contacts returns Jim
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-002", name=None, language=None, urns=[], groups=[],
                        fields=None, failed=True, blocked=False
                    ),
                ]
            )
        ]

        with self.assertNumQueries(12):
            self.assertEqual(self.backend.pull_contacts(self.unicef, None, None), (0, 1, 1, 0))

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {bob, ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), {jim})

        self.assertEqual(jim.groups.count(), 0)  # de-activated contacts are removed from groups

        bob.refresh_from_db()
        self.assertEqual(bob.name, "Bob McFlough")
        self.assertEqual(bob.language, "fre")
        self.assertEqual(set(bob.groups.all()), {spammers})
        self.assertEqual(bob.get_fields(), {'age': "35"})

        mock_get_contacts.side_effect = [
            # first call to get active contacts will return a contact with only a change to URNs.. which we don't track
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlough", language="fre", urns=["twitter:bobflow22"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={'age': "35"}, failed=True, blocked=False
                    )
                ]
            ),
            MockClientQuery([])
        ]

        with self.assertNumQueries(2):
            self.assertEqual(self.backend.pull_contacts(self.unicef, None, None), (0, 0, 0, 1))

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {bob, ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), {jim})

        mock_get_contacts.side_effect = [
            # first call to get active contacts will show one contact is now blocked
            MockClientQuery(
                [
                    TembaContact.create(
                        uuid="C-001", name="Bob McFlough", language="fre", urns=["twitter:bobflow"],
                        groups=[ObjectRef.create(uuid="G-002", name="Spammers")],
                        fields={'age': 35}, failed=True, blocked=True
                    )
                ]
            ),
            MockClientQuery([])
        ]

        with self.assertNumQueries(5):
            self.assertEqual(self.backend.pull_contacts(self.unicef, None, None), (0, 0, 1, 0))  # blocked = deleted

        self.assertEqual(set(Contact.objects.filter(is_active=True)), {ann})
        self.assertEqual(set(Contact.objects.filter(is_active=False)), {bob, jim})
Example #25
0
    def test_sync_local_to_changes(self):
        Contact.objects.all().delete()  # start with no contacts...

        fetches = MockClientQuery([
            TembaContact.create(uuid="C-001", name="Anne", blocked=False),
            TembaContact.create(uuid="C-002", name="Bob", blocked=False),
            TembaContact.create(uuid="C-003", name="Colin", blocked=False),
            TembaContact.create(uuid="C-004", name="Donald", blocked=True)
        ])
        deleted_fetches = MockClientQuery([])  # no deleted contacts this time

        self.assertEqual(sync_local_to_changes(self.unicef, self.syncer, fetches, deleted_fetches), (3, 0, 0, 1))

        fetches = MockClientQuery([
            TembaContact.create(uuid="C-005", name="Edward", blocked=False),  # new contact
            TembaContact.create(uuid="C-006", name="Frank", blocked=False),   # new contact
        ])
        deleted_fetches = MockClientQuery([
            TembaContact.create(uuid="C-001", name=None, blocked=None),       # deleted
        ])

        self.assertEqual(sync_local_to_changes(self.unicef, self.syncer, fetches, deleted_fetches), (2, 0, 1, 0))

        fetches = MockClientQuery([
            TembaContact.create(uuid="C-002", name="Bob", blocked=True),   # blocked so locally invalid
            TembaContact.create(uuid="C-003", name="Colm", blocked=False),  # changed name
        ])
        deleted_fetches = MockClientQuery([])

        self.assertEqual(sync_local_to_changes(self.unicef, self.syncer, fetches, deleted_fetches), (0, 1, 1, 0))

        fetches = MockClientQuery([
            TembaContact.create(uuid="CF-001", name="Anne", blocked=False),
            TembaContact.create(uuid="CF-002", name="Bob", blocked=False),
            TembaContact.create(uuid="CF-003", name="Colin", blocked=False),
            TembaContact.create(uuid="CF-004", name="Donald", blocked=True)
        ])
        deleted_fetches = MockClientQuery([])  # no deleted contacts this time

        self.assertEqual(sync_local_to_changes(self.unicef, self.syncer2, fetches, deleted_fetches), (3, 0, 0, 1))

        fetches = MockClientQuery([
            TembaContact.create(uuid="CF-005", name="Edward", blocked=False),  # new contact
            TembaContact.create(uuid="CF-006", name="Frank", blocked=False),   # new contact
        ])
        deleted_fetches = MockClientQuery([
            TembaContact.create(uuid="CF-001", name=None, blocked=None),       # deleted
        ])

        self.assertEqual(sync_local_to_changes(self.unicef, self.syncer2, fetches, deleted_fetches), (2, 0, 1, 0))

        fetches = MockClientQuery([
            TembaContact.create(uuid="CF-002", name="Bob", blocked=True),   # blocked so locally invalid
            TembaContact.create(uuid="CF-003", name="Colm", blocked=False),  # changed name
        ])
        deleted_fetches = MockClientQuery([])

        self.assertEqual(sync_local_to_changes(self.unicef, self.syncer2, fetches, deleted_fetches), (0, 1, 1, 0))