def test_query_no_search(self): self.assertEqual( self.choice_provider.query(ChoiceQueryContext('', 2, page=0)), [Choice('1', 'One'), Choice('2', 'Two')]) self.assertEqual( self.choice_provider.query(ChoiceQueryContext('', 2, page=1)), [Choice('3', 'Three')])
def test_get_choices_for_values(self): self.assertEqual( set( self.choice_provider.get_choices_for_values(['2', '4', '6'], None)), {Choice('2', 'Two'), Choice('4', '4'), Choice('6', '6')})
def test_multiple_selections(self): self.filter_spec["datatype"] = "string" filter = ReportFilterFactory.from_spec(self.filter_spec) test_strings = (u'apple', u'apple{s}banana'.format(s=CHOICE_DELIMITER), u'apple{s}banana{s}carrot'.format(s=CHOICE_DELIMITER)) choices = [ Choice('apple', 'apple'), Choice('banana', 'banana'), Choice('carrot', 'carrot') ] for i, s in enumerate(test_strings): self.assertListEqual(choices[0:i + 1], filter.value(dynoslug=s))
def _build_choice_list_filter(spec, report): wrapped = ChoiceListFilterSpec.wrap(spec) choices = [ Choice(fc.value if fc.value is not None else NONE_CHOICE, fc.get_display()) for fc in wrapped.choices ] if wrapped.show_all: choices.insert(0, Choice(SHOW_ALL_CHOICE, _('Show all'))) return ChoiceListFilter( name=wrapped.slug, datatype=wrapped.datatype, label=wrapped.display, choices=choices, )
def test_multiple_selections(self): self.filter_spec["datatype"] = "string" filter = ReportFilterFactory.from_spec(self.filter_spec) test_cases = ( ['apple'], ['apple', 'banana'], ['apple', 'banana', 'carrot'], ) choices = [ Choice('apple', 'apple'), Choice('banana', 'banana'), Choice('carrot', 'carrot') ] for i, s in enumerate(test_cases): self.assertListEqual(choices[0:i + 1], filter.value(dynoslug=s))
def query(self, query_context): default = None limit = query_context.limit offset = query_context.offset query = query_context.query user = query_context.user choices = [] if offset == 0: choices.append(default) limit -= 1 else: offset -= 1 for choice_provider in self.choice_providers: default = choice_provider.default_value(user) if limit <= 0: break query_context = ChoiceQueryContext(query=query, limit=limit, offset=offset, user=user) new_choices = choice_provider.query(query_context) choices.extend(new_choices) if len(new_choices): limit -= len(new_choices) offset = 0 else: offset -= choice_provider.query_count(query, user=user) if choices[0] is None: if not default: default = [Choice(SHOW_ALL_CHOICE, "[{}]".format(ugettext('Show All')))] choices[0] = default[0] return choices
def get_choices_for_values(self, values, user): choices = set(self.get_choices_for_known_values(values, user)) used_values = {value for value, _ in choices} for value in values: if value not in used_values: choices.add(Choice(value, str(value) if value is not None else '')) used_values.add(value) return choices
def query(self, query_context): try: return [ Choice(value, value) for value in self.get_values_for_query(query_context) ] except ColumnNotFoundError: return []
def default_value(self, user): """Return only the locations this user can access """ location = user.get_sql_location(self.domain) if location: return self._locations_to_choices([location]) # If the user isn't assigned to a location, they have access to all locations return [Choice(SHOW_ALL_CHOICE, "[{}]".format(ugettext('Show All')))]
def get_choices_for_known_values(self, values, user): _map = { 'cory': 'Cory Zue', 'ctsims': 'Clayton Sims', 'daniel': 'Daniel Roberts' } return [ Choice(value, _map.get(value, value)) for value in values ]
def test_query_no_registry_access(self): self.assertEqual([Choice(value='A', display='A')], self.choice_provider.query( ChoiceQueryContext( query='A', offset=0, user=self.web_user_no_registry_access))) self.assertEqual([Choice(value='A', display='A')], self.choice_provider.query( ChoiceQueryContext( query='', offset=0, user=self.web_user_no_registry_access))) self.assertEqual([Choice(value='A', display='A')], self.choice_provider.query( ChoiceQueryContext( query='D', offset=0, user=self.web_user_no_registry_access)))
def test_ancestor_location_type_filter(self): ucr_filter = AncestorLocationTypeFilter( ancestor_location_type_name='state') ui_filter = self._get_dynamic_choice_list_ui_filter() ancestor_state_value = ucr_filter.get_filter_value( self.nate, ui_filter) self.assertEqual(ancestor_state_value, [ Choice(value=self.massachusetts.location_id, display=self.massachusetts.location_id) ])
def get_choices_for_known_values(self, values): selected_locations = SQLLocation.active_objects.filter( location_id__in=values) if self.include_descendants: selected_locations = SQLLocation.objects.get_queryset_descendants( selected_locations, include_self=True) return [ Choice(loc.location_id, loc.display_name) for loc in selected_locations ]
def query(self, query_context): # todo: consider making this an extensions framework similar to custom expressions # todo: does this need fancier permission restrictions and what not? # see e.g. locations.views.child_locations_for_select2 locations = self._locations_query(query_context.query).order_by('name') return [ Choice(loc.location_id, loc.display_name) for loc in locations[query_context.offset:query_context.offset + query_context.limit] ]
def query(self, query_context): try: default = self.default_value(query_context.user) if not default: default = [Choice(SHOW_ALL_CHOICE, "[{}]".format(ugettext('Show All')))] choices = [ self._make_choice_from_value(value) for value in self.get_values_for_query(query_context) ] return default + self._deduplicate_and_sort_choices(choices) except ColumnNotFoundError: return []
def test_domain_with_some_grants(self): user = self.make_web_user_with_registry_role('*****@*****.**', self.domain_b, has_registry_access=True) config = RegistryDataSourceConfiguration( domain="B", table_id='foo', referenced_doc_type='CommCareCase', registry_slug=self.registry.slug, ) config.save() report = RegistryReportConfiguration(domain="B", config_id=config._id) self.choice_provider = DomainChoiceProvider(report, None) self.assertEqual( [Choice(value='B', display='B'), Choice( value='C', display='C', )], self.choice_provider.query( ChoiceQueryContext(query='', offset=0, user=user))) config.delete()
def _locations_to_choices(self, locations): cached_path_display = {} def display(loc): if self.show_full_path: if loc.parent_id in cached_path_display: path_display = '{}/{}'.format(cached_path_display[loc.parent_id], loc.name) else: path_display = loc.get_path_display() cached_path_display[loc.id] = path_display return path_display else: return loc.display_name return [Choice(loc.location_id, display(loc)) for loc in locations]
def ucr_report(self): spec = StaticReportConfiguration.by_id('static-%s-adherence' % self.domain) report = ReportFactory.from_spec( spec, include_prefilters=True ) filter_values = get_filter_values(spec.ui_filters, self.request_params, self.request.couch_user) locations_id = [ Choice(value=location_id, display='') for location_id in self.report_config.locations_id if location_id ] if locations_id: filter_values['village'] = locations_id report.set_filter_values(filter_values) return report
def test_filter_by_case_sharing_group_id(self): result = _filter_by_case_sharing_group_id(self.sheel, None) self.assertEqual( result, [Choice(value=self.somerville.location_id, display=None)])
def get_choices_from_es_query(group_es): return [ Choice(group_id, name) for group_id, name in group_es.values_list('_id', 'name') ]
def get_choices_from_es_query(user_es): return [ Choice(user_id, raw_username(username)) for user_id, username in user_es.values_list('_id', 'username') ]
def custom_data(self, selected_location, domain): data = {} for config in self.sources['data_source']: filters = {} if selected_location: key = selected_location.location_type.name.lower() + '_id' filters = { key: [ Choice(value=selected_location.location_id, display=selected_location.name) ] } if 'date_filter_field' in config: filters.update( {config['date_filter_field']: self.config['date_span']}) if 'filter' in config: for fil in config['filter']: if 'type' in fil: now = datetime.now() start_date = now if 'start' not in fil else now - timedelta( days=fil['start']) end_date = now if 'end' not in fil else now - timedelta( days=fil['end']) datespan = DateSpan(start_date, end_date) filters.update({fil['column']: datespan}) else: filters.update({ fil['column']: { 'operator': fil['operator'], 'operand': fil['value'] } }) report_data = ICDSData(domain, filters, config['id']).data() for column in config['columns']: column_agg_func = column['agg_fun'] column_name = column['column_name'] column_data = 0 if column_agg_func == 'sum': column_data = sum( [x.get(column_name, 0) for x in report_data]) elif column_agg_func == 'count': column_data = len(report_data) elif column_agg_func == 'count_if': value = column['condition']['value'] op = column['condition']['operator'] def check_condition(v): if isinstance(v, basestring): fil_v = str(value) elif isinstance(v, int): fil_v = int(value) else: fil_v = value if op == "in": return OPERATORS[op](fil_v, v) else: return OPERATORS[op](v, fil_v) column_data = len([ val for val in report_data if check_condition(val[column_name]) ]) elif column_agg_func == 'avg': values = [x.get(column_name, 0) for x in report_data] column_data = sum(values) / (len(values) or 1) column_display = column_name if 'column_in_report' not in column else column[ 'column_in_report'] data.update({ column_display: data.get(column_display, 0) + column_data }) return data
def _custom_data(self, selected_location, domain): data = {} for config in self.sources['data_source']: filters = {} if selected_location: key = selected_location.location_type.name.lower() + '_id' filters = { key: [Choice(value=selected_location.location_id, display=selected_location.name)] } if 'date_filter_field' in config: filters.update({config['date_filter_field']: self.config['date_span']}) if 'filter' in config: for fil in config['filter']: if 'type' in fil: now = datetime.now() start_date = now if 'start' not in fil else now - timedelta(days=fil['start']) end_date = now if 'end' not in fil else now - timedelta(days=fil['end']) datespan = DateSpan(start_date, end_date) filters.update({fil['column']: datespan}) else: filters.update({ fil['column']: { 'operator': fil['operator'], 'operand': fil['value'] } }) timer = TimingContext() with timer: report_data = ICDSData(domain, filters, config['id']).data() if selected_location: loc_type = selected_location.location_type.name else: loc_type = None datadog_histogram( "commcare.icds.block_reports.ucr_querytime", timer.duration, tags="config:{}, location_type:{}, report_slug:{}".format( config['id'], loc_type, self.slug ) ) for column in config['columns']: column_agg_func = column['agg_fun'] column_name = column['column_name'] column_data = 0 if column_agg_func == 'sum': column_data = sum([x.get(column_name, 0) or 0 for x in report_data]) elif column_agg_func == 'count': column_data = len(report_data) elif column_agg_func == 'count_if': value = column['condition']['value'] op = column['condition']['operator'] def check_condition(v): if isinstance(v, six.string_types): soft_assert_type_text(v) fil_v = str(value) elif isinstance(v, int): fil_v = int(value) else: fil_v = value if op == "in": return OPERATORS[op](fil_v, v) else: return OPERATORS[op](v, fil_v) column_data = len([val for val in report_data if check_condition(val[column_name])]) elif column_agg_func == 'avg': values = [x.get(column_name, 0) for x in report_data] column_data = sum(values) / (len(values) or 1) column_display = column_name if 'column_in_report' not in column else column['column_in_report'] data.update({ column_display: data.get(column_display, 0) + column_data }) return data
def _make_choice_from_value(self, value): if value is None or value == '': return Choice(NONE_CHOICE, '[Blank]') return Choice(value, value)
def setUpClass(cls): cls.choice_provider = StaticChoiceProvider( [Choice('1', 'One'), Choice('2', 'Two'), Choice('3', 'Three')])
def test_filter_by_username(self): result = _filter_by_username(self.sheel, None) self.assertEqual(result, Choice(value='sheel', display=None))
def test_filter_by_user_id(self): result = _filter_by_user_id(self.sheel, None) self.assertEqual(result, Choice(value=self.sheel._id, display=None))
def charts(self): case_finding_sql_data = self.case_finding_sql_data[0] sputum_conversion_report = ReportFactory.from_spec( StaticReportConfiguration.by_id('static-%s-sputum_conversion' % self.domain), include_prefilters=True) filter_values = {'date': self.datespan} locations_id = [ Choice(value=location_id, display='') for location_id in self.report_config.locations_id if location_id ] if locations_id: filter_values['village'] = locations_id if self.report_config.is_migrated is not None: filter_values['is_migrated'] = Choice( value=self.report_config.is_migrated, display='') sputum_conversion_report.set_filter_values(filter_values) sputum_conversion_data = sputum_conversion_report.get_data()[0] charts_sql_data = self.charts_sql_data[0] treatment_outcome_sql_data = self.treatment_outcome_sql_data[0] default_value = {'sort_key': 0} chart = PieChart(title=_('Cases by Gender'), key='gender', values=[]) chart.data = [{ 'label': _('Male'), 'value': case_finding_sql_data.get('male_total', default_value)['sort_key'] }, { 'label': _('Female'), 'value': case_finding_sql_data.get('female_total', default_value)['sort_key'] }, { 'label': _('Transgender'), 'value': case_finding_sql_data.get('transgender_total', default_value)['sort_key'] }] chart2 = MultiBarChart(_('Cases By Type'), x_axis=Axis(''), y_axis=Axis('')) chart2.stacked = False chart2.showLegend = False positive_smear = case_finding_sql_data.get('new_positive_tb_pulmonary', default_value)['sort_key'] negative_smear = case_finding_sql_data.get('new_negative_tb_pulmonary', default_value)['sort_key'] positive_extra_pulmonary = case_finding_sql_data.get( 'new_positive_tb_extrapulmonary', default_value)['sort_key'] relapse_cases = case_finding_sql_data.get('recurrent_positive_tb', default_value)['sort_key'] failure_cases = case_finding_sql_data.get('failure_positive_tb', default_value)['sort_key'] lfu_cases = case_finding_sql_data.get('lfu_positive_tb', default_value)['sort_key'] others_cases = case_finding_sql_data.get('others_positive_tb', default_value)['sort_key'] chart2.add_dataset(_('New'), [{ 'x': 'Smear +ve', 'y': positive_smear }, { 'x': 'Smear -ve', 'y': negative_smear }, { 'x': 'EP', 'y': positive_extra_pulmonary }]) chart2.add_dataset(_('Retreatment'), [{ 'x': 'Relapse', 'y': relapse_cases }, { 'x': 'Failure', 'y': failure_cases }, { 'x': 'Treatment After Default', 'y': lfu_cases }, { 'x': 'Others', 'y': others_cases }]) chart3 = MultiBarChart('Sputum Conversion By Patient Type', Axis(''), Axis('')) chart3.stacked = True chart3.add_dataset('Positive', [ { 'x': _('New Sputum +ve (2 month IP)'), 'y': sputum_conversion_data.get( 'new_sputum_positive_patient_2months_ip', 0) }, { 'x': _('New Sputum +ve (3 month IP)'), 'y': sputum_conversion_data.get( 'new_sputum_positive_patient_3months_ip', 0) }, { 'x': _('Cat II (3 month IP)'), 'y': sputum_conversion_data.get('positive_endofip_patients_cat2', 0) }, ]) chart3.add_dataset(_('Negative'), [ { 'x': _('New Sputum +ve (2 month IP)'), 'y': sputum_conversion_data.get( 'new_sputum_negative_patient_2months_ip', 0) }, { 'x': _('New Sputum +ve (3 month IP)'), 'y': sputum_conversion_data.get( 'new_sputum_negative_patient_3months_ip', 0) }, { 'x': _('Cat II (3 month IP)'), 'y': sputum_conversion_data.get('negative_endofip_patients_cat2', 0) }, ]) chart3.add_dataset('NA', [ { 'x': _('New Sputum +ve (2 month IP)'), 'y': sputum_conversion_data.get('new_sputum_na_patient_2months_ip', 0) }, { 'x': _('New Sputum +ve (3 month IP)'), 'y': sputum_conversion_data.get('new_sputum_na_patient_3months_ip', 0) }, { 'x': _('Cat II (3 month IP)'), 'y': sputum_conversion_data.get('na_endofip_patients_cat2', 0) }, ]) chart4 = PieChart(title=_('Total number of patients by category'), key='', values=[]) chart4.data = [{ 'label': _('Cat1'), 'value': charts_sql_data.get('cat1_patients', default_value)['sort_key'] }, { 'label': _('Cat2'), 'value': charts_sql_data.get('cat2_patients', default_value)['sort_key'] }] chart5 = MultiBarChart('Outcome By Type', Axis(''), Axis('')) chart5.stacked = True chart5.add_dataset(_('Cured'), [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_cured', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get('recurrent_patients_cured', default_value)['sort_key'] }]) chart5.add_dataset('Treatment Complete', [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_treatment_complete', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get( 'recurrent_patients_treatment_complete', default_value)['sort_key'] }]) chart5.add_dataset('Died', [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_died', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get('recurrent_patients_died', default_value)['sort_key'] }]) chart5.add_dataset(_('Failure'), [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_treatment_failure', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get( 'recurrent_patients_treatment_failure', default_value)['sort_key'] }]) chart5.add_dataset(_('Loss to Follow-up'), [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_loss_to_follow_up', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get( 'recurrent_patients_loss_to_follow_up', default_value)['sort_key'] }]) chart5.add_dataset(_('Regimen Changed'), [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_regimen_changed', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get( 'recurrent_patients_regimen_changed', default_value)['sort_key'] }]) chart5.add_dataset('Not Evaluated', [{ 'x': _('New'), 'y': treatment_outcome_sql_data.get('new_patients_not_evaluated', default_value)['sort_key'] }, { 'x': _('Retreatment'), 'y': treatment_outcome_sql_data.get('recurrent_patients_not_evaluated', default_value)['sort_key'] }]) return [chart, chart2, chart3, chart4, chart5]
def setUpClass(cls): super(StaticChoiceProviderTest, cls).setUpClass() cls.choice_provider = StaticChoiceProvider( [Choice('1', 'One'), Choice('2', 'Two'), Choice('3', 'Three')])
def _locations_to_choices(self, locations): def display(loc): return loc.get_path_display( ) if self.show_full_path else loc.display_name return [Choice(loc.location_id, display(loc)) for loc in locations]