def get_results(self, obj): if self.ruleset: return Value.get_value_summary(ruleset=self.ruleset, segment=self.segment) else: return Value.get_value_summary(contact_field=self.contact_field, segment=self.segment)
def test_field_results(self): (c1, c2, c3, c4) = (self.create_contact("Contact1", '0788111111'), self.create_contact("Contact2", '0788222222'), self.create_contact("Contact3", '0788333333'), self.create_contact("Contact4", '0788444444')) # create a gender field that uses strings gender = ContactField.get_or_create(self.org, 'gender', label="Gender", value_type=TEXT) c1.set_field('gender', "Male") c2.set_field('gender', "Female") c3.set_field('gender', "Female") result = Value.get_value_summary(contact_field=gender)[0] self.assertEquals(2, len(result['categories'])) self.assertEquals(3, result['set']) self.assertEquals(2, result['unset']) # this is two as we have the default contact created by our unit tests self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Female", 2) self.assertResult(result, 1, "Male", 1) # create an born field that uses decimals born = ContactField.get_or_create(self.org, 'born', label="Born", value_type=DECIMAL) c1.set_field('born', 1977) c2.set_field('born', 1990) c3.set_field('born', 1977) result = Value.get_value_summary(contact_field=born)[0] self.assertEquals(2, len(result['categories'])) self.assertEquals(3, result['set']) self.assertEquals(2, result['unset']) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "1977", 2) self.assertResult(result, 1, "1990", 1) # ok, state field! state = ContactField.get_or_create(self.org, 'state', label="State", value_type=STATE) c1.set_field('state', "Kigali City") c2.set_field('state', "Kigali City") result = Value.get_value_summary(contact_field=state)[0] self.assertEquals(1, len(result['categories'])) self.assertEquals(2, result['set']) self.assertEquals(3, result['unset']) self.assertResult(result, 0, "1708283", 2) reg_date = ContactField.get_or_create(self.org, 'reg_date', label="Registration Date", value_type=DATETIME) now = timezone.now() c1.set_field('reg_date', now.replace(hour=9)) c2.set_field('reg_date', now.replace(hour=4)) c3.set_field('reg_date', now - timedelta(days=1)) result = Value.get_value_summary(contact_field=reg_date)[0] self.assertEquals(2, len(result['categories'])) self.assertEquals(3, result['set']) self.assertEquals(2, result['unset']) self.assertResult(result, 0, (now - timedelta(days=1)).replace(hour=0, minute=0, second=0, microsecond=0), 1) self.assertResult(result, 1, now.replace(hour=0, minute=0, second=0, microsecond=0), 2)
def test_open_ended_word_frequencies(self): flow = self.get_flow('random_word') def run_flow(contact, word): self.assertEquals("Thank you", self.send_message(flow, word, contact=contact, restart_participants=True)) (c1, c2, c3, c4, c5, c6) = (self.create_contact("Contact1", '0788111111'), self.create_contact("Contact2", '0788222222'), self.create_contact("Contact3", '0788333333'), self.create_contact("Contact4", '0788444444'), self.create_contact("Contact5", '0788555555'), self.create_contact("Contact6", '0788666666', is_test=True)) run_flow(c1, "1 better place") run_flow(c2, "the great coffee") run_flow(c3, "1 cup of black tea") run_flow(c4, "awesome than this encore") run_flow(c5, "from an awesome place in kigali") run_flow(c6, "awesome coffee") random = RuleSet.objects.get(flow=flow, label="Random") result = Value.get_value_summary(ruleset=random)[0] self.assertEquals(10, len(result['categories'])) self.assertTrue(result['open_ended']) self.assertResult(result, 0, "awesome", 2) self.assertResult(result, 1, "place", 2) self.assertResult(result, 2, "better", 1) self.assertResult(result, 3, "black", 1) self.assertResult(result, 4, "coffee", 1) self.assertResult(result, 5, "cup", 1) self.assertResult(result, 6, "encore", 1) self.assertResult(result, 7, "great", 1) self.assertResult(result, 8, "kigali", 1) self.assertResult(result, 9, "tea", 1) # add French to org languages Language.create(self.org, self.admin, 'French', 'fre') # make sure we cleared the cache Value.invalidate_cache(ruleset=random) # encore is a french stop word and should not be included this time result = Value.get_value_summary(ruleset=random)[0] self.assertEquals(9, len(result['categories'])) self.assertTrue(result['open_ended']) self.assertResult(result, 0, "awesome", 2) self.assertResult(result, 1, "place", 2) self.assertResult(result, 2, "better", 1) self.assertResult(result, 3, "black", 1) self.assertResult(result, 4, "coffee", 1) self.assertResult(result, 5, "cup", 1) self.assertResult(result, 6, "great", 1) self.assertResult(result, 7, "kigali", 1) self.assertResult(result, 8, "tea", 1)
def test_open_ended_word_frequencies(self): flow = self.get_flow('random_word') def run_flow(contact, word): self.assertEquals("Thank you", self.send_message(flow, word, contact=contact, restart_participants=True)) (c1, c2, c3, c4, c5) = (self.create_contact("Contact1", '0788111111'), self.create_contact("Contact2", '0788222222'), self.create_contact("Contact3", '0788333333'), self.create_contact("Contact4", '0788444444'), self.create_contact("Contact4", '0788555555')) run_flow(c1, "1 better place") run_flow(c2, "the great coffee") run_flow(c3, "1 cup of black tea") run_flow(c4, "awesome than this") run_flow(c5, "from an awesome place in kigali") random = RuleSet.objects.get(flow=flow, label="Random") result = Value.get_value_summary(ruleset=random)[0] self.assertEquals(9, len(result['categories'])) self.assertTrue(result['open_ended']) self.assertResult(result, 0, "awesome", 2) self.assertResult(result, 1, "place", 2) self.assertResult(result, 2, "better", 1) self.assertResult(result, 3, "black", 1) self.assertResult(result, 4, "coffee", 1) self.assertResult(result, 5, "cup", 1) self.assertResult(result, 6, "great", 1) self.assertResult(result, 7, "kigali", 1) self.assertResult(result, 8, "tea", 1)
def _create_values(self, contacts, field, callback): """ Creates a field value for each given contact (a lot faster than calling set_field) """ values = [] for contact in contacts: string_value = callback(contact) values.append(Value(contact=contact, org=self.org, contact_field=field, string_value=string_value)) Value.objects.bulk_create(values) return values
def _create_contact_batch(self, batch): """ Bulk creates a batch of contacts from flat representations """ for c in batch: c['object'] = Contact(org=c['org'], name=c['name'], language=c['language'], is_stopped=c['is_stopped'], is_blocked=c['is_blocked'], is_active=c['is_active'], created_by=c['user'], created_on=c['created_on'], modified_by=c['user'], modified_on=c['modified_on']) Contact.objects.bulk_create([c['object'] for c in batch]) # now that contacts have pks, bulk create the actual URN, value and group membership objects batch_urns = [] batch_values = [] batch_memberships = [] for c in batch: org = c['org'] c['urns'] = [] if c['tel']: c['urns'].append(ContactURN(org=org, contact=c['object'], priority=50, scheme=TEL_SCHEME, path=c['tel'], urn=URN.from_tel(c['tel']))) if c['twitter']: c['urns'].append(ContactURN(org=org, contact=c['object'], priority=50, scheme=TWITTER_SCHEME, path=c['twitter'], urn=URN.from_twitter(c['twitter']))) if c['gender']: batch_values.append(Value(org=org, contact=c['object'], contact_field=org.cache['fields']['gender'], string_value=c['gender'])) if c['age']: batch_values.append(Value(org=org, contact=c['object'], contact_field=org.cache['fields']['age'], string_value=str(c['age']), decimal_value=c['age'])) if c['joined']: batch_values.append(Value(org=org, contact=c['object'], contact_field=org.cache['fields']['joined'], string_value=datetime_to_str(c['joined']), datetime_value=c['joined'])) if c['ward']: batch_values.append(Value(org=org, contact=c['object'], contact_field=org.cache['fields']['ward'], string_value=c['ward'].name, location_value=c['ward'])) if c['district']: batch_values.append(Value(org=org, contact=c['object'], contact_field=org.cache['fields']['district'], string_value=c['district'].name, location_value=c['district'])) if c['state']: batch_values.append(Value(org=org, contact=c['object'], contact_field=org.cache['fields']['state'], string_value=c['state'].name, location_value=c['state'])) for g in c['groups']: batch_memberships.append(ContactGroup.contacts.through(contact=c['object'], contactgroup=g)) batch_urns += c['urns'] ContactURN.objects.bulk_create(batch_urns) Value.objects.bulk_create(batch_values) ContactGroup.contacts.through.objects.bulk_create(batch_memberships)
def test_category_results(self): self.setup_color_gender_flow() # create a state field: # assign c1 and c2 to Kigali state = ContactField.get_or_create(self.org, 'state', label="State", value_type=STATE) district = ContactField.get_or_create(self.org, 'district', label="District", value_type=DISTRICT) self.c1.set_field('state', "Kigali City") self.c1.set_field('district', "Kigali") self.c2.set_field('state', "Kigali City") self.c2.set_field('district', "Kigali") self.run_color_gender_flow(self.c1, "red", "male", "16") self.run_color_gender_flow(self.c2, "blue", "female", "19") self.run_color_gender_flow(self.c3, "green", "male", "75") self.run_color_gender_flow(self.c4, "maroon", "female", "50") # create a group of the women ladies = self.create_group("Ladies", [self.c2, self.c4]) # get our rulesets color = RuleSet.objects.get(flow=self.flow, label="Color") gender = RuleSet.objects.get(flow=self.flow, label="Gender") age = RuleSet.objects.get(flow=self.flow, label="Age") # categories should be in the same order as our rules, should have correct counts result = Value.get_value_summary(ruleset=color)[0] self.assertEquals(3, len(result['categories'])) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Red", 2) self.assertResult(result, 1, "Blue", 1) self.assertResult(result, 2, "Green", 1) # check our age category as well result = Value.get_value_summary(ruleset=age)[0] self.assertEquals(3, len(result['categories'])) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Child", 1) self.assertResult(result, 1, "Adult", 2) self.assertResult(result, 2, "Senior", 1) # and our gender categories result = Value.get_value_summary(ruleset=gender)[0] self.assertEquals(2, len(result['categories'])) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Male", 2) self.assertResult(result, 1, "Female", 2) # now filter the results and only get responses by men result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=gender.pk, categories=["Male"])])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 0) self.assertResult(result, 2, "Green", 1) # what about men that are adults? result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=gender.pk, categories=["Male"]), dict(ruleset=age.pk, categories=["Adult"])])[0] self.assertResult(result, 0, "Red", 0) self.assertResult(result, 1, "Blue", 0) self.assertResult(result, 2, "Green", 0) # union of all genders result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=gender.pk, categories=["Male", "Female"]), dict(ruleset=age.pk, categories=["Adult"])])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 1) self.assertResult(result, 2, "Green", 0) # just women adults by group result = Value.get_value_summary(ruleset=color, filters=[dict(groups=[ladies.pk]), dict(ruleset=age.pk, categories="Adult")])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 1) self.assertResult(result, 2, "Green", 0) # remove one of the women from the group ladies.update_contacts([self.c2], False) # get a new summary result = Value.get_value_summary(ruleset=color, filters=[dict(groups=[ladies.pk]), dict(ruleset=age.pk, categories="Adult")])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 0) self.assertResult(result, 2, "Green", 0) # ok, back in she goes ladies.update_contacts([self.c2], True) # do another run for contact 1 run5 = self.run_color_gender_flow(self.c1, "blue", "male", "16") # totals should reflect the new value, not the old result = Value.get_value_summary(ruleset=color)[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 2) self.assertResult(result, 2, "Green", 1) # what if we do a partial run? self.send_message(self.flow, "red", contact=self.c1, restart_participants=True) # should change our male/female breakdown since c1 now no longer has a gender result = Value.get_value_summary(ruleset=gender)[0] self.assertEquals(2, len(result['categories'])) self.assertResult(result, 0, "Male", 1) self.assertResult(result, 1, "Female", 2) # back to a full flow run5 = self.run_color_gender_flow(self.c1, "blue", "male", "16") # ok, now segment by gender result = Value.get_value_summary(ruleset=color, filters=[], segment=dict(ruleset=gender.pk, categories=["Male", "Female"])) male_result = result[0] self.assertResult(male_result, 0, "Red", 0) self.assertResult(male_result, 1, "Blue", 1) self.assertResult(male_result, 2, "Green", 1) female_result = result[1] self.assertResult(female_result, 0, "Red", 1) self.assertResult(female_result, 1, "Blue", 1) self.assertResult(female_result, 2, "Green", 0) # segment by gender again, but use the contact field to do so result = Value.get_value_summary(ruleset=color, filters=[], segment=dict(contact_field="Gender", values=["MALE", "Female"])) male_result = result[0] self.assertResult(male_result, 0, "Red", 0) self.assertResult(male_result, 1, "Blue", 1) self.assertResult(male_result, 2, "Green", 1) female_result = result[1] self.assertResult(female_result, 0, "Red", 1) self.assertResult(female_result, 1, "Blue", 1) self.assertResult(female_result, 2, "Green", 0) # add in a filter at the same time result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=color.pk, categories=["Blue"])], segment=dict(ruleset=gender.pk, categories=["Male", "Female"])) male_result = result[0] self.assertResult(male_result, 0, "Red", 0) self.assertResult(male_result, 1, "Blue", 1) self.assertResult(male_result, 2, "Green", 0) female_result = result[1] self.assertResult(female_result, 0, "Red", 0) self.assertResult(female_result, 1, "Blue", 1) self.assertResult(female_result, 2, "Green", 0) # ok, try segmenting by location instead result = Value.get_value_summary(ruleset=color, segment=dict(location="State")) eastern_result = result[0] self.assertEquals('171591', eastern_result['boundary']) self.assertEquals('Eastern Province', eastern_result['label']) self.assertResult(eastern_result, 0, "Red", 0) self.assertResult(eastern_result, 1, "Blue", 0) self.assertResult(eastern_result, 2, "Green", 0) kigali_result = result[1] self.assertEquals('1708283', kigali_result['boundary']) self.assertEquals('Kigali City', kigali_result['label']) self.assertResult(kigali_result, 0, "Red", 0) self.assertResult(kigali_result, 1, "Blue", 2) self.assertResult(kigali_result, 2, "Green", 0) # updating state location leads to updated data self.c2.set_field('state', "Eastern Province") result = Value.get_value_summary(ruleset=color, segment=dict(location="State")) eastern_result = result[0] self.assertEquals('171591', eastern_result['boundary']) self.assertEquals('Eastern Province', eastern_result['label']) self.assertResult(eastern_result, 0, "Red", 0) self.assertResult(eastern_result, 1, "Blue", 1) self.assertResult(eastern_result, 2, "Green", 0) kigali_result = result[1] self.assertEquals('1708283', kigali_result['boundary']) self.assertEquals('Kigali City', kigali_result['label']) self.assertResult(kigali_result, 0, "Red", 0) self.assertResult(kigali_result, 1, "Blue", 1) self.assertResult(kigali_result, 2, "Green", 0) # segment by district instead result = Value.get_value_summary(ruleset=color, segment=dict(parent="1708283", location="District")) # only on district in kigali self.assertEquals(1, len(result)) kigali_result = result[0] self.assertEquals('60485579', kigali_result['boundary']) self.assertEquals('Kigali', kigali_result['label']) self.assertResult(kigali_result, 0, "Red", 0) self.assertResult(kigali_result, 1, "Blue", 2) self.assertResult(kigali_result, 2, "Green", 0) # do a sanity check on our choropleth view self.login(self.admin) response = self.client.get(reverse('flows.ruleset_choropleth', args=[color.pk]) + "?_format=json&boundary=" + self.org.country.osm_id) # response should be valid json response = json.loads(response.content) # should have breaks self.assertTrue('breaks' in response) # should have two categories, Blue and Others self.assertEquals(2, len(response['categories'])) self.assertEquals("Blue", response['categories'][0]) self.assertEquals("Others", response['categories'][1]) # assert our kigali result kigali_result = response['scores']['1708283'] self.assertEquals(1, kigali_result['score']) self.assertEquals("Kigali City", kigali_result['name']) self.assertEquals("Blue", kigali_result['results'][0]['label']) self.assertEquals("Others", kigali_result['results'][1]['label']) self.assertEquals(1, kigali_result['results'][0]['count']) self.assertEquals(0, kigali_result['results'][1]['count']) self.assertEquals(100, kigali_result['results'][0]['percentage']) self.assertEquals(0, kigali_result['results'][1]['percentage']) with patch('temba.values.models.Value.get_value_summary') as mock: mock.return_value = [] response = self.client.get(reverse('flows.ruleset_choropleth', args=[color.pk]) + "?_format=json&boundary=" + self.org.country.osm_id) # response should be valid json response = json.loads(response.content) # should have two categories, Blue and Others self.assertEquals(2, len(response['categories'])) self.assertEquals("", response['categories'][0]) self.assertEquals("", response['categories'][1]) # all counts and percentage are 0 self.assertEquals(0, response['totals']['count']) self.assertEquals(0, response['totals']['results'][0]['count']) self.assertEquals(0, response['totals']['results'][0]['percentage']) self.assertEquals(0, response['totals']['results'][1]['count']) self.assertEquals(0, response['totals']['results'][1]['percentage']) # and empty string labels self.assertEquals("", response['totals']['results'][0]['label']) self.assertEquals("", response['totals']['results'][1]['label']) # also check our analytics view response = self.client.get(reverse('flows.ruleset_analytics')) # make sure we have only one flow in it flows = json.loads(response.context['flows']) self.assertEquals(1, len(flows)) self.assertEquals(3, len(flows[0]['rules']))
def test_category_results(self): self.setup_color_gender_flow() # create a state field: # assign c1 and c2 to Kigali state = ContactField.get_or_create(self.org, 'state', label="State", value_type=STATE) district = ContactField.get_or_create(self.org, 'district', label="District", value_type=DISTRICT) self.c1.set_field('state', "Kigali City") self.c1.set_field('district', "Kigali") self.c2.set_field('state', "Kigali City") self.c2.set_field('district', "Kigali") self.run_color_gender_flow(self.c1, "red", "male", "16") self.run_color_gender_flow(self.c2, "blue", "female", "19") self.run_color_gender_flow(self.c3, "green", "male", "75") self.run_color_gender_flow(self.c4, "maroon", "female", "50") # create a group of the women ladies = self.create_group("Ladies", [self.c2, self.c4]) # get our rulesets color = RuleSet.objects.get(flow=self.flow, label="Color") gender = RuleSet.objects.get(flow=self.flow, label="Gender") age = RuleSet.objects.get(flow=self.flow, label="Age") # categories should be in the same order as our rules, should have correct counts result = Value.get_value_summary(ruleset=color)[0] self.assertEquals(3, len(result['categories'])) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Red", 2) self.assertResult(result, 1, "Blue", 1) self.assertResult(result, 2, "Green", 1) # check our age category as well result = Value.get_value_summary(ruleset=age)[0] self.assertEquals(3, len(result['categories'])) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Child", 1) self.assertResult(result, 1, "Adult", 2) self.assertResult(result, 2, "Senior", 1) # and our gender categories result = Value.get_value_summary(ruleset=gender)[0] self.assertEquals(2, len(result['categories'])) self.assertFalse(result['open_ended']) self.assertResult(result, 0, "Male", 2) self.assertResult(result, 1, "Female", 2) # now filter the results and only get responses by men result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=gender.pk, categories=["Male"])])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 0) self.assertResult(result, 2, "Green", 1) # what about men that are adults? result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=gender.pk, categories=["Male"]), dict(ruleset=age.pk, categories=["Adult"])])[0] self.assertResult(result, 0, "Red", 0) self.assertResult(result, 1, "Blue", 0) self.assertResult(result, 2, "Green", 0) # union of all genders result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=gender.pk, categories=["Male", "Female"]), dict(ruleset=age.pk, categories=["Adult"])])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 1) self.assertResult(result, 2, "Green", 0) # just women adults by group result = Value.get_value_summary(ruleset=color, filters=[dict(groups=[ladies.pk]), dict(ruleset=age.pk, categories="Adult")])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 1) self.assertResult(result, 2, "Green", 0) # remove one of the women from the group ladies.update_contacts([self.c2], False) # get a new summary result = Value.get_value_summary(ruleset=color, filters=[dict(groups=[ladies.pk]), dict(ruleset=age.pk, categories="Adult")])[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 0) self.assertResult(result, 2, "Green", 0) # ok, back in she goes ladies.update_contacts([self.c2], True) # do another run for contact 1 run5 = self.run_color_gender_flow(self.c1, "blue", "male", "16") # totals should reflect the new value, not the old result = Value.get_value_summary(ruleset=color)[0] self.assertResult(result, 0, "Red", 1) self.assertResult(result, 1, "Blue", 2) self.assertResult(result, 2, "Green", 1) # what if we do a partial run? self.send_message(self.flow, "red", contact=self.c1, restart_participants=True) # should change our male/female breakdown since c1 now no longer has a gender result = Value.get_value_summary(ruleset=gender)[0] self.assertEquals(2, len(result['categories'])) self.assertResult(result, 0, "Male", 1) self.assertResult(result, 1, "Female", 2) # back to a full flow run5 = self.run_color_gender_flow(self.c1, "blue", "male", "16") # ok, now segment by gender result = Value.get_value_summary(ruleset=color, filters=[], segment=dict(ruleset=gender.pk, categories=["Male", "Female"])) male_result = result[0] self.assertResult(male_result, 0, "Red", 0) self.assertResult(male_result, 1, "Blue", 1) self.assertResult(male_result, 2, "Green", 1) female_result = result[1] self.assertResult(female_result, 0, "Red", 1) self.assertResult(female_result, 1, "Blue", 1) self.assertResult(female_result, 2, "Green", 0) # add in a filter at the same time result = Value.get_value_summary(ruleset=color, filters=[dict(ruleset=color.pk, categories=["Blue"])], segment=dict(ruleset=gender.pk, categories=["Male", "Female"])) male_result = result[0] self.assertResult(male_result, 0, "Red", 0) self.assertResult(male_result, 1, "Blue", 1) self.assertResult(male_result, 2, "Green", 0) female_result = result[1] self.assertResult(female_result, 0, "Red", 0) self.assertResult(female_result, 1, "Blue", 1) self.assertResult(female_result, 2, "Green", 0) # ok, try segmenting by location instead result = Value.get_value_summary(ruleset=color, segment=dict(location="State")) eastern_result = result[0] self.assertEquals('171591', eastern_result['boundary']) self.assertEquals('Eastern Province', eastern_result['label']) self.assertResult(eastern_result, 0, "Red", 0) self.assertResult(eastern_result, 1, "Blue", 0) self.assertResult(eastern_result, 2, "Green", 0) kigali_result = result[1] self.assertEquals('1708283', kigali_result['boundary']) self.assertEquals('Kigali City', kigali_result['label']) self.assertResult(kigali_result, 0, "Red", 0) self.assertResult(kigali_result, 1, "Blue", 2) self.assertResult(kigali_result, 2, "Green", 0) # updating state location leads to updated data self.c2.set_field('state', "Eastern Province") result = Value.get_value_summary(ruleset=color, segment=dict(location="State")) eastern_result = result[0] self.assertEquals('171591', eastern_result['boundary']) self.assertEquals('Eastern Province', eastern_result['label']) self.assertResult(eastern_result, 0, "Red", 0) self.assertResult(eastern_result, 1, "Blue", 1) self.assertResult(eastern_result, 2, "Green", 0) kigali_result = result[1] self.assertEquals('1708283', kigali_result['boundary']) self.assertEquals('Kigali City', kigali_result['label']) self.assertResult(kigali_result, 0, "Red", 0) self.assertResult(kigali_result, 1, "Blue", 1) self.assertResult(kigali_result, 2, "Green", 0) # segment by district instead result = Value.get_value_summary(ruleset=color, segment=dict(parent="1708283", location="District")) # only on district in kigali self.assertEquals(1, len(result)) kigali_result = result[0] self.assertEquals('60485579', kigali_result['boundary']) self.assertEquals('Kigali', kigali_result['label']) self.assertResult(kigali_result, 0, "Red", 0) self.assertResult(kigali_result, 1, "Blue", 2) self.assertResult(kigali_result, 2, "Green", 0)
def create_contacts(self, orgs, locations, num_total): batch_size = 5000 num_test_contacts = len(orgs) * len(USERS) group_membership_model = ContactGroup.contacts.through group_counts = defaultdict(int) self._log("Creating %d test contacts...\n" % num_test_contacts) for org in orgs: for user in org.cache['users']: Contact.get_test_contact(user) self._log("Creating %d regular contacts...\n" % (num_total - num_test_contacts)) base_contact_id = self.get_current_id(Contact) + 1 # Disable table triggers to speed up insertion and in the case of contact group m2m, avoid having an unsquashed # count row for every contact with DisableTriggersOn(Contact, ContactURN, Value, group_membership_model): names = [('%s %s' % (c1, c2)).strip() for c2 in CONTACT_NAMES[1] for c1 in CONTACT_NAMES[0]] names = [n if n else None for n in names] batch = 1 for index_batch in chunk_list(range(num_total - num_test_contacts), batch_size): contacts = [] urns = [] values = [] memberships = [] def add_to_group(g): group_counts[g] += 1 memberships.append(group_membership_model(contact_id=c['id'], contactgroup=g)) for c_index in index_batch: # pragma: no cover org = orgs[c_index] if c_index < len(orgs) else self.random_org(orgs) # at least 1 contact per org name = self.random_choice(names) location = self.random_choice(locations) if self.probability(CONTACT_HAS_FIELD_PROB) else None created_on = self.timeline_date(float(num_test_contacts + c_index) / num_total) c = { 'id': base_contact_id + c_index, # database id this contact will have when created 'org': org, 'user': org.cache['users'][0], 'name': name, 'tel': '+2507%08d' % c_index if self.probability(CONTACT_HAS_TEL_PROB) else None, 'twitter': '%s%d' % (name.replace(' ', '_').lower() if name else 'tweep', c_index) if self.probability(CONTACT_HAS_TWITTER_PROB) else None, 'gender': self.random_choice(('M', 'F')) if self.probability(CONTACT_HAS_FIELD_PROB) else None, 'age': self.random.randint(16, 80) if self.probability(CONTACT_HAS_FIELD_PROB) else None, 'joined': self.random_date() if self.probability(CONTACT_HAS_FIELD_PROB) else None, 'ward': location[0] if location else None, 'district': location[1] if location else None, 'state': location[2] if location else None, 'language': self.random_choice(CONTACT_LANGS), 'is_stopped': self.probability(CONTACT_IS_STOPPED_PROB), 'is_blocked': self.probability(CONTACT_IS_BLOCKED_PROB), 'is_active': self.probability(1 - CONTACT_IS_DELETED_PROB), 'created_on': created_on, 'modified_on': self.random_date(created_on, self.db_ends_on), } if c['is_active']: if not c['is_blocked'] and not c['is_stopped']: add_to_group(org.cache['system_groups'][ContactGroup.TYPE_ALL]) if c['is_blocked']: add_to_group(org.cache['system_groups'][ContactGroup.TYPE_BLOCKED]) if c['is_stopped']: add_to_group(org.cache['system_groups'][ContactGroup.TYPE_STOPPED]) contacts.append(Contact(org=org, name=c['name'], language=c['language'], is_stopped=c['is_stopped'], is_blocked=c['is_blocked'], is_active=c['is_active'], created_by=user, created_on=c['created_on'], modified_by=user, modified_on=c['modified_on'])) if c['tel']: urns.append(ContactURN(org=org, contact_id=c['id'], priority=50, scheme=TEL_SCHEME, path=c['tel'], urn=URN.from_tel(c['tel']))) if c['twitter']: urns.append(ContactURN(org=org, contact_id=c['id'], priority=50, scheme=TWITTER_SCHEME, path=c['twitter'], urn=URN.from_twitter(c['twitter']))) if c['gender']: values.append(Value(org=org, contact_id=c['id'], contact_field=org.cache['fields']['gender'], string_value=c['gender'])) if c['age']: values.append(Value(org=org, contact_id=c['id'], contact_field=org.cache['fields']['age'], string_value=str(c['age']), decimal_value=c['age'])) if c['joined']: values.append(Value(org=org, contact_id=c['id'], contact_field=org.cache['fields']['joined'], string_value=datetime_to_str(c['joined']), datetime_value=c['joined'])) if location: values.append(Value(org=org, contact_id=c['id'], contact_field=org.cache['fields']['ward'], string_value=c['ward'].name, location_value=c['ward'])) values.append(Value(org=org, contact_id=c['id'], contact_field=org.cache['fields']['district'], string_value=c['district'].name, location_value=c['district'])) values.append(Value(org=org, contact_id=c['id'], contact_field=org.cache['fields']['state'], string_value=c['state'].name, location_value=c['state'])) # let each group decide if it is taking this contact for g in org.cache['groups']: if g.member(c) if callable(g.member) else self.probability(g.member): add_to_group(g) Contact.objects.bulk_create(contacts) ContactURN.objects.bulk_create(urns) Value.objects.bulk_create(values) group_membership_model.objects.bulk_create(memberships) self._log(" > Created batch %d of %d\n" % (batch, max(num_total // batch_size, 1))) batch += 1 # create group count records manually counts = [] for group, count in group_counts.items(): counts.append(ContactGroupCount(group=group, count=count, is_squashed=True)) ContactGroupCount.objects.bulk_create(counts) # for sanity check that our presumed last contact id matches the last actual contact id assert c['id'] == Contact.objects.order_by('-id').first().id