<s> from collections import namedtuple , OrderedDict <EOL> from itertools import chain <EOL> import json <EOL> from urllib import urlencode <EOL> import uuid <EOL> from django import forms <EOL> from django . core . urlresolvers import reverse <EOL> from django . forms import Widget <EOL> from django . forms . util import flatatt <EOL> from django . template . loader import render_to_string <EOL> from django . utils . html import format_html <EOL> from django . utils . safestring import mark_safe <EOL> from django . utils . translation import ugettext as _ , ugettext_noop , ugettext_lazy <EOL> from crispy_forms import layout as crispy <EOL> from crispy_forms . bootstrap import StrictButton <EOL> from crispy_forms . helper import FormHelper <EOL> from corehq . apps . style import crispy as hqcrispy <EOL> from corehq . apps . app_manager . fields import ApplicationDataSourceUIHelper <EOL> from corehq . apps . app_manager . models import ( <EOL> Application , <EOL> Form , <EOL> ) <EOL> from corehq . apps . app_manager . util import get_case_properties <EOL> from corehq . apps . app_manager . xform import XForm <EOL> from corehq . apps . style . crispy import FieldWithHelpBubble <EOL> from corehq . apps . userreports import tasks <EOL> from corehq . apps . userreports . app_manager import _clean_table_name <EOL> from corehq . apps . userreports . models import ( <EOL> DataSourceBuildInformation , <EOL> DataSourceConfiguration , <EOL> DataSourceMeta , <EOL> ReportConfiguration , <EOL> ReportMeta , <EOL> ) <EOL> from corehq . apps . userreports . reports . builder import ( <EOL> DEFAULT_CASE_PROPERTY_DATATYPES , <EOL> FORM_METADATA_PROPERTIES , <EOL> make_case_data_source_filter , <EOL> make_case_property_indicator , <EOL> make_form_data_source_filter , <EOL> make_form_meta_block_indicator , <EOL> make_form_question_indicator , <EOL> make_owner_name_indicator , <EOL> get_filter_format_from_question_type , <EOL> make_user_name_indicator ) <EOL> from corehq . apps . userreports . exceptions import BadBuilderConfigError <EOL> from corehq . apps . userreports . sql import get_column_name <EOL> from corehq . apps . userreports . ui . fields import JsonField <EOL> from dimagi . utils . decorators . memoized import memoized <EOL> from corehq . toggles import UNLIMITED_REPORT_BUILDER_REPORTS <EOL> class FilterField ( JsonField ) : <EOL> """<STR_LIT>""" <EOL> def validate ( self , value ) : <EOL> super ( FilterField , self ) . validate ( value ) <EOL> for filter_conf in value : <EOL> if filter_conf . get ( '<STR_LIT>' , None ) not in [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] : <EOL> raise forms . ValidationError ( "<STR_LIT>" ) <EOL> class Select2 ( Widget ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , attrs = None , choices = ( ) ) : <EOL> super ( Select2 , self ) . __init__ ( attrs ) <EOL> self . choices = list ( choices ) <EOL> def render ( self , name , value , attrs = None , choices = ( ) ) : <EOL> value = '<STR_LIT>' if value is None else value <EOL> final_attrs = self . build_attrs ( attrs , name = name ) <EOL> return format_html ( <EOL> '<STR_LIT>' , <EOL> flatatt ( final_attrs ) , <EOL> json . dumps ( self . _choices_for_binding ( choices ) ) , <EOL> '<STR_LIT>' . format ( json . dumps ( value ) ) if value else "<STR_LIT>" <EOL> ) <EOL> def _choices_for_binding ( self , choices ) : <EOL> return [ { '<STR_LIT:id>' : id , '<STR_LIT:text>' : text } for id , text in chain ( self . choices , choices ) ] <EOL> class QuestionSelect ( Widget ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , attrs = None , choices = ( ) ) : <EOL> super ( QuestionSelect , self ) . __init__ ( attrs ) <EOL> self . choices = list ( choices ) <EOL> def render ( self , name , value , attrs = None , choices = ( ) ) : <EOL> value = '<STR_LIT>' if value is None else value <EOL> final_attrs = self . build_attrs ( attrs , name = name ) <EOL> return format_html ( <EOL> """<STR_LIT>""" , <EOL> flatatt ( final_attrs ) , <EOL> mark_safe ( self . render_options ( choices ) ) , <EOL> value <EOL> ) <EOL> def render_options ( self , choices ) : <EOL> def escape ( literal ) : <EOL> return literal . replace ( '<STR_LIT:&>' , '<STR_LIT>' ) . replace ( "<STR_LIT:'>" , "<STR_LIT>" ) <EOL> return json . dumps ( <EOL> [ { '<STR_LIT:value>' : escape ( v ) , '<STR_LIT:label>' : escape ( l ) } for v , l in chain ( self . choices , choices ) ] <EOL> ) <EOL> class DataSourceProperty ( namedtuple ( "<STR_LIT>" , [ "<STR_LIT:type>" , "<STR_LIT:id>" , "<STR_LIT:text>" , "<STR_LIT>" , "<STR_LIT:source>" ] ) ) : <EOL> """<STR_LIT>""" <EOL> class DataSourceBuilder ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , domain , app , source_type , source_id ) : <EOL> assert ( source_type in [ '<STR_LIT>' , '<STR_LIT>' ] ) <EOL> self . domain = domain <EOL> self . app = app <EOL> self . source_type = source_type <EOL> self . source_id = source_id <EOL> if self . source_type == '<STR_LIT>' : <EOL> self . source_form = Form . get_form ( self . source_id ) <EOL> self . source_xform = XForm ( self . source_form . source ) <EOL> if self . source_type == '<STR_LIT>' : <EOL> prop_map = get_case_properties ( <EOL> self . app , [ self . source_id ] , defaults = DEFAULT_CASE_PROPERTY_DATATYPES . keys ( ) <EOL> ) <EOL> self . case_properties = sorted ( set ( prop_map [ self . source_id ] ) | { '<STR_LIT>' } ) <EOL> @ property <EOL> @ memoized <EOL> def source_doc_type ( self ) : <EOL> if self . source_type == "<STR_LIT>" : <EOL> return "<STR_LIT>" <EOL> if self . source_type == "<STR_LIT>" : <EOL> return "<STR_LIT>" <EOL> @ property <EOL> @ memoized <EOL> def filter ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . source_type == "<STR_LIT>" : <EOL> return make_case_data_source_filter ( self . source_id ) <EOL> if self . source_type == "<STR_LIT>" : <EOL> return make_form_data_source_filter ( self . source_xform . data_node . tag_xmlns ) <EOL> def indicators ( self , number_columns = None ) : <EOL> """<STR_LIT>""" <EOL> ret = [ ] <EOL> for prop in self . data_source_properties . values ( ) : <EOL> if prop . type == '<STR_LIT>' : <EOL> ret . append ( make_form_meta_block_indicator ( <EOL> prop . source , prop . column_id <EOL> ) ) <EOL> elif prop . type == "<STR_LIT>" : <EOL> ret . append ( make_form_question_indicator ( <EOL> prop . source , prop . column_id <EOL> ) ) <EOL> elif prop . type == '<STR_LIT>' and prop . source == '<STR_LIT>' : <EOL> ret . append ( make_owner_name_indicator ( prop . column_id ) ) <EOL> elif prop . type == '<STR_LIT>' and prop . source == '<STR_LIT>' : <EOL> ret . append ( make_user_name_indicator ( prop . column_id ) ) <EOL> elif prop . type == '<STR_LIT>' : <EOL> indicator = make_case_property_indicator ( <EOL> prop . source , prop . column_id <EOL> ) <EOL> if number_columns : <EOL> if indicator [ '<STR_LIT>' ] in number_columns : <EOL> indicator [ '<STR_LIT>' ] = '<STR_LIT>' <EOL> ret . append ( indicator ) <EOL> ret . append ( { <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT:type>" : "<STR_LIT:count>" , <EOL> "<STR_LIT>" : "<STR_LIT:count>" <EOL> } ) <EOL> return ret <EOL> @ property <EOL> @ memoized <EOL> def data_source_properties ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . source_type == '<STR_LIT>' : <EOL> return self . _get_data_source_properties_from_case ( self . case_properties ) <EOL> if self . source_type == '<STR_LIT>' : <EOL> return self . _get_data_source_properties_from_form ( self . source_form , self . source_xform ) <EOL> @ classmethod <EOL> def _get_data_source_properties_from_case ( cls , case_properties ) : <EOL> property_map = { <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> } <EOL> properties = OrderedDict ( ) <EOL> for property in case_properties : <EOL> properties [ property ] = DataSourceProperty ( <EOL> type = '<STR_LIT>' , <EOL> id = property , <EOL> column_id = get_column_name ( property ) , <EOL> text = property_map . get ( property , property . replace ( '<STR_LIT:_>' , '<STR_LIT:U+0020>' ) ) , <EOL> source = property <EOL> ) <EOL> properties [ '<STR_LIT>' ] = cls . _get_owner_name_pseudo_property ( ) <EOL> properties [ '<STR_LIT>' ] = cls . _get_user_name_pseudo_property ( ) <EOL> return properties <EOL> @ staticmethod <EOL> def _get_owner_name_pseudo_property ( ) : <EOL> return DataSourceProperty ( <EOL> type = '<STR_LIT>' , <EOL> id = '<STR_LIT>' , <EOL> column_id = get_column_name ( '<STR_LIT>' ) , <EOL> text = _ ( '<STR_LIT>' ) , <EOL> source = '<STR_LIT>' <EOL> ) <EOL> @ staticmethod <EOL> def _get_user_name_pseudo_property ( ) : <EOL> return DataSourceProperty ( <EOL> type = '<STR_LIT>' , <EOL> id = '<STR_LIT>' , <EOL> column_id = get_column_name ( '<STR_LIT>' ) , <EOL> text = _ ( '<STR_LIT>' ) , <EOL> source = '<STR_LIT>' , <EOL> ) <EOL> @ staticmethod <EOL> def _get_data_source_properties_from_form ( form , form_xml ) : <EOL> property_map = { <EOL> '<STR_LIT:username>' : _ ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' : _ ( '<STR_LIT>' ) , <EOL> } <EOL> properties = OrderedDict ( ) <EOL> questions = form_xml . get_questions ( [ ] ) <EOL> for prop in FORM_METADATA_PROPERTIES : <EOL> properties [ prop [ <NUM_LIT:0> ] ] = DataSourceProperty ( <EOL> type = "<STR_LIT>" , <EOL> id = prop [ <NUM_LIT:0> ] , <EOL> column_id = get_column_name ( prop [ <NUM_LIT:0> ] . strip ( "<STR_LIT:/>" ) ) , <EOL> text = property_map . get ( prop [ <NUM_LIT:0> ] , prop [ <NUM_LIT:0> ] ) , <EOL> source = prop , <EOL> ) <EOL> for question in questions : <EOL> properties [ question [ '<STR_LIT:value>' ] ] = DataSourceProperty ( <EOL> type = "<STR_LIT>" , <EOL> id = question [ '<STR_LIT:value>' ] , <EOL> column_id = get_column_name ( question [ '<STR_LIT:value>' ] . strip ( "<STR_LIT:/>" ) ) , <EOL> text = question [ '<STR_LIT:label>' ] , <EOL> source = question , <EOL> ) <EOL> if form . get_app ( ) . auto_gps_capture : <EOL> properties [ '<STR_LIT:location>' ] = DataSourceProperty ( <EOL> type = "<STR_LIT>" , <EOL> id = '<STR_LIT:location>' , <EOL> column_id = get_column_name ( '<STR_LIT:location>' ) , <EOL> text = '<STR_LIT:location>' , <EOL> source = ( [ '<STR_LIT:location>' , '<STR_LIT>' ] , '<STR_LIT>' ) , <EOL> ) <EOL> return properties <EOL> @ property <EOL> @ memoized <EOL> def data_source_name ( self ) : <EOL> if self . source_type == '<STR_LIT>' : <EOL> return u"<STR_LIT>" . format ( self . source_form . default_name ( ) , self . app . version ) <EOL> if self . source_type == '<STR_LIT>' : <EOL> return u"<STR_LIT>" . format ( self . source_id , self . app . version ) <EOL> def get_existing_match ( self ) : <EOL> return DataSourceConfiguration . view ( <EOL> '<STR_LIT>' , <EOL> key = [ <EOL> self . domain , <EOL> self . source_doc_type , <EOL> self . source_id , <EOL> self . app . _id , <EOL> self . app . version <EOL> ] , <EOL> include_docs = True , <EOL> reduce = False <EOL> ) . one ( ) <EOL> def _legend ( title , subtext ) : <EOL> """<STR_LIT>""" <EOL> return '<STR_LIT>' . format ( <EOL> title = title , subtext = subtext <EOL> ) <EOL> class DataSourceForm ( forms . Form ) : <EOL> report_name = forms . CharField ( ) <EOL> chart_type = forms . ChoiceField ( <EOL> choices = [ <EOL> ( '<STR_LIT:bar>' , _ ( '<STR_LIT>' ) ) , <EOL> ( '<STR_LIT>' , _ ( "<STR_LIT>" ) ) , <EOL> ] , <EOL> ) <EOL> def __init__ ( self , domain , report_type , * args , ** kwargs ) : <EOL> super ( DataSourceForm , self ) . __init__ ( * args , ** kwargs ) <EOL> self . domain = domain <EOL> self . report_type = report_type <EOL> self . app_source_helper = ApplicationDataSourceUIHelper ( ) <EOL> self . app_source_helper . source_type_field . label = _ ( '<STR_LIT>' ) <EOL> self . app_source_helper . source_type_field . choices = [ ( "<STR_LIT>" , _ ( "<STR_LIT>" ) ) , ( "<STR_LIT>" , _ ( "<STR_LIT>" ) ) ] <EOL> self . app_source_helper . source_field . label = '<STR_LIT>' <EOL> self . app_source_helper . bootstrap ( self . domain ) <EOL> report_source_fields = self . app_source_helper . get_fields ( ) <EOL> report_source_help_texts = { <EOL> "<STR_LIT>" : _ ( "<STR_LIT>" ) , <EOL> "<STR_LIT>" : _ ( "<STR_LIT>" ) , <EOL> "<STR_LIT:source>" : _ ( "<STR_LIT>" ) , <EOL> } <EOL> self . fields . update ( report_source_fields ) <EOL> self . fields [ '<STR_LIT>' ] . required = self . report_type == "<STR_LIT>" <EOL> self . helper = FormHelper ( ) <EOL> self . helper . form_class = "<STR_LIT>" <EOL> self . helper . form_id = "<STR_LIT>" <EOL> self . helper . label_class = '<STR_LIT>' <EOL> self . helper . field_class = '<STR_LIT>' <EOL> chart_type_crispy_field = None <EOL> if self . report_type == '<STR_LIT>' : <EOL> chart_type_crispy_field = FieldWithHelpBubble ( '<STR_LIT>' , help_bubble_text = _ ( "<STR_LIT>" ) ) <EOL> report_source_crispy_fields = [ ] <EOL> for k in report_source_fields . keys ( ) : <EOL> if k in report_source_help_texts : <EOL> report_source_crispy_fields . append ( FieldWithHelpBubble ( <EOL> k , help_bubble_text = report_source_help_texts [ k ] <EOL> ) ) <EOL> else : <EOL> report_source_crispy_fields . append ( k ) <EOL> top_fields = [ <EOL> FieldWithHelpBubble ( <EOL> '<STR_LIT>' , <EOL> help_bubble_text = _ ( '<STR_LIT>' ) ) <EOL> ] <EOL> if chart_type_crispy_field : <EOL> top_fields . append ( chart_type_crispy_field ) <EOL> self . helper . layout = crispy . Layout ( <EOL> crispy . Fieldset ( <EOL> _ ( '<STR_LIT>' . format ( self . report_type . capitalize ( ) ) ) , <EOL> * top_fields <EOL> ) , <EOL> crispy . Fieldset ( <EOL> _ ( '<STR_LIT>' ) , * report_source_crispy_fields <EOL> ) , <EOL> hqcrispy . FormActions ( <EOL> StrictButton ( <EOL> _ ( '<STR_LIT>' ) , <EOL> type = "<STR_LIT>" , <EOL> css_class = "<STR_LIT>" , <EOL> ) <EOL> ) , <EOL> ) <EOL> @ property <EOL> def sources_map ( self ) : <EOL> return self . app_source_helper . all_sources <EOL> def get_selected_source ( self ) : <EOL> return self . app_source_helper . get_app_source ( self . cleaned_data ) <EOL> def clean ( self ) : <EOL> """<STR_LIT>""" <EOL> cleaned_data = super ( DataSourceForm , self ) . clean ( ) <EOL> existing_reports = ReportConfiguration . by_domain ( self . domain ) <EOL> builder_reports = filter ( lambda report : report . report_meta . created_by_builder , existing_reports ) <EOL> if len ( builder_reports ) >= <NUM_LIT:5> and not UNLIMITED_REPORT_BUILDER_REPORTS . enabled ( self . domain ) : <EOL> raise forms . ValidationError ( _ ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) ) <EOL> return cleaned_data <EOL> _shared_properties = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] <EOL> FilterViewModel = namedtuple ( "<STR_LIT>" , _shared_properties + [ '<STR_LIT>' ] ) <EOL> ColumnViewModel = namedtuple ( "<STR_LIT>" , _shared_properties + [ '<STR_LIT>' ] ) <EOL> class ConfigureNewReportBase ( forms . Form ) : <EOL> filters = FilterField ( required = False ) <EOL> button_text = ugettext_noop ( '<STR_LIT>' ) <EOL> def __init__ ( self , report_name , app_id , source_type , report_source_id , existing_report = None , * args , ** kwargs ) : <EOL> """<STR_LIT>""" <EOL> super ( ConfigureNewReportBase , self ) . __init__ ( * args , ** kwargs ) <EOL> self . existing_report = existing_report <EOL> if self . existing_report : <EOL> self . _bootstrap ( self . existing_report ) <EOL> self . button_text = _ ( '<STR_LIT>' ) <EOL> else : <EOL> self . report_name = report_name <EOL> assert source_type in [ '<STR_LIT>' , '<STR_LIT>' ] <EOL> self . source_type = source_type <EOL> self . report_source_id = report_source_id <EOL> self . app = Application . get ( app_id ) <EOL> self . domain = self . app . domain <EOL> self . ds_builder = DataSourceBuilder ( <EOL> self . domain , self . app , self . source_type , self . report_source_id <EOL> ) <EOL> self . data_source_properties = self . ds_builder . data_source_properties <EOL> self . _properties_by_column = { <EOL> p . column_id : p for p in self . data_source_properties . values ( ) <EOL> } <EOL> self . helper = FormHelper ( ) <EOL> self . helper . form_class = "<STR_LIT>" <EOL> self . helper . label_class = '<STR_LIT>' <EOL> self . helper . field_class = '<STR_LIT>' <EOL> self . helper . attrs [ '<STR_LIT>' ] = "<STR_LIT>" <EOL> self . helper . form_id = "<STR_LIT>" <EOL> buttons = [ <EOL> StrictButton ( <EOL> _ ( self . button_text ) , <EOL> css_class = "<STR_LIT>" , <EOL> type = "<STR_LIT>" , <EOL> ) <EOL> ] <EOL> if not self . existing_report : <EOL> buttons . insert ( <EOL> <NUM_LIT:0> , <EOL> crispy . HTML ( <EOL> '<STR_LIT>' . format ( <EOL> reverse ( <EOL> '<STR_LIT>' , <EOL> args = ( self . domain , self . report_type ) , <EOL> ) , <EOL> _ ( '<STR_LIT>' ) <EOL> ) <EOL> ) , <EOL> ) <EOL> else : <EOL> buttons . insert ( <EOL> <NUM_LIT:0> , <EOL> crispy . HTML ( <EOL> '<STR_LIT>' . format ( <EOL> reverse ( <EOL> '<STR_LIT>' , <EOL> args = ( self . domain , self . existing_report . _id ) , <EOL> ) + "<STR_LIT>" . format ( urlencode ( <EOL> { '<STR_LIT>' : reverse ( '<STR_LIT>' , args = [ self . domain ] ) } <EOL> ) ) , <EOL> _ ( '<STR_LIT>' ) <EOL> ) <EOL> ) <EOL> ) <EOL> self . helper . layout = crispy . Layout ( <EOL> self . container_fieldset , <EOL> hqcrispy . FormActions ( crispy . ButtonHolder ( * buttons ) ) , <EOL> ) <EOL> def _bootstrap ( self , existing_report ) : <EOL> """<STR_LIT>""" <EOL> self . report_name = existing_report . title <EOL> self . source_type = { <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" <EOL> } [ existing_report . config . referenced_doc_type ] <EOL> self . report_source_id = existing_report . config . meta . build . source_id <EOL> app_id = existing_report . config . meta . build . app_id <EOL> if app_id : <EOL> self . app = Application . get ( app_id ) <EOL> else : <EOL> raise BadBuilderConfigError ( _ ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) ) <EOL> @ property <EOL> def column_config_template ( self ) : <EOL> return render_to_string ( '<STR_LIT>' ) <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> """<STR_LIT>""" <EOL> return crispy . Fieldset ( <EOL> "<STR_LIT>" , <EOL> self . filter_fieldset <EOL> ) <EOL> @ property <EOL> def filter_fieldset ( self ) : <EOL> """<STR_LIT>""" <EOL> return crispy . Fieldset ( <EOL> _legend ( <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( "<STR_LIT>" ) <EOL> ) , <EOL> crispy . Div ( <EOL> crispy . HTML ( self . column_config_template ) , id = "<STR_LIT>" , data_bind = '<STR_LIT>' <EOL> ) , <EOL> crispy . Hidden ( '<STR_LIT>' , None , data_bind = "<STR_LIT>" ) <EOL> ) <EOL> def _build_data_source ( self ) : <EOL> data_source_config = DataSourceConfiguration ( <EOL> domain = self . domain , <EOL> display_name = self . ds_builder . data_source_name , <EOL> referenced_doc_type = self . ds_builder . source_doc_type , <EOL> table_id = _clean_table_name ( self . domain , str ( uuid . uuid4 ( ) . hex ) ) , <EOL> configured_filter = self . ds_builder . filter , <EOL> configured_indicators = self . ds_builder . indicators ( self . _number_columns ) , <EOL> meta = DataSourceMeta ( build = DataSourceBuildInformation ( <EOL> source_id = self . report_source_id , <EOL> app_id = self . app . _id , <EOL> app_version = self . app . version , <EOL> ) ) <EOL> ) <EOL> data_source_config . validate ( ) <EOL> data_source_config . save ( ) <EOL> tasks . rebuild_indicators . delay ( data_source_config . _id ) <EOL> return data_source_config . _id <EOL> def update_report ( self ) : <EOL> matching_data_source = self . ds_builder . get_existing_match ( ) <EOL> if matching_data_source : <EOL> reactivated = False <EOL> if matching_data_source . _id != self . existing_report . config_id : <EOL> data_source = DataSourceConfiguration . get ( self . existing_report . config_id ) <EOL> if data_source . get_report_count ( ) <= <NUM_LIT:1> : <EOL> data_source . deactivate ( ) <EOL> self . existing_report . config_id = matching_data_source . _id <EOL> elif matching_data_source . is_deactivated : <EOL> matching_data_source . is_deactivated = False <EOL> reactivated = True <EOL> changed = False <EOL> indicators = self . ds_builder . indicators ( self . _number_columns ) <EOL> if matching_data_source . configured_indicators != indicators : <EOL> matching_data_source . configured_indicators = indicators <EOL> changed = True <EOL> if changed or reactivated : <EOL> matching_data_source . save ( ) <EOL> tasks . rebuild_indicators . delay ( matching_data_source . _id ) <EOL> else : <EOL> old_data_source = DataSourceConfiguration . get ( self . existing_report . config_id ) <EOL> if old_data_source . get_report_count ( ) <= <NUM_LIT:1> : <EOL> old_data_source . deactivate ( ) <EOL> data_source_config_id = self . _build_data_source ( ) <EOL> self . existing_report . config_id = data_source_config_id <EOL> self . existing_report . aggregation_columns = self . _report_aggregation_cols <EOL> self . existing_report . columns = self . _report_columns <EOL> self . existing_report . filters = self . _report_filters <EOL> self . existing_report . configured_charts = self . _report_charts <EOL> self . existing_report . validate ( ) <EOL> self . existing_report . save ( ) <EOL> return self . existing_report <EOL> def create_report ( self ) : <EOL> """<STR_LIT>""" <EOL> matching_data_source = self . ds_builder . get_existing_match ( ) <EOL> if matching_data_source : <EOL> data_source_config_id = matching_data_source . _id <EOL> reactivated = False <EOL> if matching_data_source . is_deactivated : <EOL> matching_data_source . is_deactivated = False <EOL> reactivated = True <EOL> changed = False <EOL> indicators = self . ds_builder . indicators ( self . _number_columns ) <EOL> if matching_data_source . configured_indicators != indicators : <EOL> matching_data_source . configured_indicators = indicators <EOL> changed = True <EOL> if changed or reactivated : <EOL> matching_data_source . save ( ) <EOL> tasks . rebuild_indicators . delay ( matching_data_source . _id ) <EOL> else : <EOL> data_source_config_id = self . _build_data_source ( ) <EOL> report = ReportConfiguration ( <EOL> domain = self . domain , <EOL> config_id = data_source_config_id , <EOL> title = self . report_name , <EOL> aggregation_columns = self . _report_aggregation_cols , <EOL> columns = self . _report_columns , <EOL> filters = self . _report_filters , <EOL> configured_charts = self . _report_charts , <EOL> report_meta = ReportMeta ( <EOL> created_by_builder = True , <EOL> builder_report_type = self . report_type <EOL> ) <EOL> ) <EOL> report . validate ( ) <EOL> report . save ( ) <EOL> return report <EOL> @ property <EOL> @ memoized <EOL> def initial_filters ( self ) : <EOL> if self . existing_report : <EOL> return [ self . _get_view_model ( f ) for f in self . existing_report . filters ] <EOL> if self . source_type == '<STR_LIT>' : <EOL> return self . _default_case_report_filters <EOL> else : <EOL> return self . _default_form_report_filters <EOL> @ property <EOL> @ memoized <EOL> def _default_case_report_filters ( self ) : <EOL> return [ <EOL> FilterViewModel ( <EOL> exists_in_current_version = True , <EOL> property = '<STR_LIT>' , <EOL> data_source_field = None , <EOL> display_text = _ ( '<STR_LIT>' ) , <EOL> format = '<STR_LIT>' , <EOL> ) , <EOL> FilterViewModel ( <EOL> exists_in_current_version = True , <EOL> property = '<STR_LIT>' , <EOL> data_source_field = None , <EOL> display_text = _ ( '<STR_LIT>' ) , <EOL> format = '<STR_LIT>' , <EOL> ) , <EOL> ] <EOL> @ property <EOL> @ memoized <EOL> def _default_form_report_filters ( self ) : <EOL> return [ <EOL> FilterViewModel ( <EOL> exists_in_current_version = True , <EOL> property = '<STR_LIT>' , <EOL> data_source_field = None , <EOL> display_text = '<STR_LIT>' , <EOL> format = '<STR_LIT>' , <EOL> ) , <EOL> ] <EOL> def _get_view_model ( self , filter ) : <EOL> """<STR_LIT>""" <EOL> filter_type_map = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT:date>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> } <EOL> exists = self . _column_exists ( filter [ '<STR_LIT>' ] ) <EOL> return FilterViewModel ( <EOL> exists_in_current_version = exists , <EOL> display_text = filter [ '<STR_LIT>' ] , <EOL> format = filter_type_map [ filter [ '<STR_LIT:type>' ] ] , <EOL> property = self . _get_property_from_column ( filter [ '<STR_LIT>' ] ) if exists else None , <EOL> data_source_field = filter [ '<STR_LIT>' ] if not exists else None <EOL> ) <EOL> def _get_property_from_column ( self , col ) : <EOL> column = self . _properties_by_column . get ( col ) <EOL> if column : <EOL> return column . id <EOL> def _column_exists ( self , column_id ) : <EOL> """<STR_LIT>""" <EOL> return column_id in self . _properties_by_column <EOL> @ property <EOL> def _report_aggregation_cols ( self ) : <EOL> return [ '<STR_LIT>' ] <EOL> @ property <EOL> def _report_columns ( self ) : <EOL> return [ ] <EOL> @ property <EOL> @ memoized <EOL> def _number_columns ( self ) : <EOL> return [ col [ "<STR_LIT>" ] for col in self . _report_columns if col . get ( "<STR_LIT>" , None ) in [ "<STR_LIT>" , "<STR_LIT>" ] ] <EOL> @ property <EOL> def _report_filters ( self ) : <EOL> """<STR_LIT>""" <EOL> filter_type_map = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT:date>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> } <EOL> def _make_report_filter ( conf , index ) : <EOL> property = self . data_source_properties [ conf [ "<STR_LIT>" ] ] <EOL> col_id = property . column_id <EOL> selected_filter_type = conf [ '<STR_LIT>' ] <EOL> if not selected_filter_type or self . source_type == '<STR_LIT>' : <EOL> if property . type == '<STR_LIT>' : <EOL> filter_format = get_filter_format_from_question_type ( <EOL> property . source [ '<STR_LIT:type>' ] <EOL> ) <EOL> else : <EOL> assert property . type == '<STR_LIT>' <EOL> filter_format = get_filter_format_from_question_type ( <EOL> property . source [ <NUM_LIT:1> ] <EOL> ) <EOL> else : <EOL> filter_format = filter_type_map [ selected_filter_type ] <EOL> ret = { <EOL> "<STR_LIT>" : col_id , <EOL> "<STR_LIT>" : "<STR_LIT>" . format ( col_id , index ) , <EOL> "<STR_LIT>" : conf [ "<STR_LIT>" ] , <EOL> "<STR_LIT:type>" : filter_format <EOL> } <EOL> if conf [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> ret . update ( { '<STR_LIT>' : True } ) <EOL> return ret <EOL> filter_configs = self . cleaned_data [ '<STR_LIT>' ] <EOL> filters = [ _make_report_filter ( f , i ) for i , f in enumerate ( filter_configs ) ] <EOL> if self . source_type == '<STR_LIT>' : <EOL> self . _convert_closed_filter_to_choice_list ( filters ) <EOL> return filters <EOL> @ classmethod <EOL> def _convert_closed_filter_to_choice_list ( cls , filters ) : <EOL> for f in filters : <EOL> if f [ '<STR_LIT>' ] == get_column_name ( '<STR_LIT>' ) and f [ '<STR_LIT:type>' ] == '<STR_LIT>' : <EOL> f [ '<STR_LIT:type>' ] = '<STR_LIT>' <EOL> f [ '<STR_LIT>' ] = [ <EOL> { '<STR_LIT:value>' : '<STR_LIT:True>' } , <EOL> { '<STR_LIT:value>' : '<STR_LIT:False>' } <EOL> ] <EOL> @ property <EOL> def _report_charts ( self ) : <EOL> return [ ] <EOL> class ConfigureBarChartReportForm ( ConfigureNewReportBase ) : <EOL> group_by = forms . ChoiceField ( label = _ ( "<STR_LIT>" ) ) <EOL> report_type = '<STR_LIT>' <EOL> def __init__ ( self , report_name , app_id , source_type , report_source_id , existing_report = None , * args , ** kwargs ) : <EOL> super ( ConfigureBarChartReportForm , self ) . __init__ ( <EOL> report_name , app_id , source_type , report_source_id , existing_report , * args , ** kwargs <EOL> ) <EOL> if self . source_type == "<STR_LIT>" : <EOL> self . fields [ '<STR_LIT>' ] . widget = QuestionSelect ( attrs = { '<STR_LIT:class>' : '<STR_LIT>' } ) <EOL> else : <EOL> self . fields [ '<STR_LIT>' ] . widget = Select2 ( attrs = { '<STR_LIT:class>' : '<STR_LIT>' } ) <EOL> self . fields [ '<STR_LIT>' ] . choices = self . _group_by_choices <EOL> if self . existing_report : <EOL> existing_agg_cols = existing_report . aggregation_columns <EOL> assert len ( existing_agg_cols ) < <NUM_LIT:2> <EOL> if existing_agg_cols : <EOL> self . fields [ '<STR_LIT>' ] . initial = self . _get_property_from_column ( existing_agg_cols [ <NUM_LIT:0> ] ) <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> return crispy . Fieldset ( <EOL> _ ( '<STR_LIT>' ) , <EOL> FieldWithHelpBubble ( <EOL> '<STR_LIT>' , <EOL> help_bubble_text = _ ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) , <EOL> placeholder = _ ( "<STR_LIT>" ) , <EOL> ) , <EOL> self . filter_fieldset <EOL> ) <EOL> @ property <EOL> def aggregation_field ( self ) : <EOL> return self . cleaned_data [ "<STR_LIT>" ] <EOL> @ property <EOL> def _report_aggregation_cols ( self ) : <EOL> return [ <EOL> self . data_source_properties [ self . aggregation_field ] . column_id <EOL> ] <EOL> @ property <EOL> def _report_charts ( self ) : <EOL> agg_col = self . data_source_properties [ self . aggregation_field ] . column_id <EOL> return [ { <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : agg_col , <EOL> "<STR_LIT>" : [ "<STR_LIT:count>" ] , <EOL> } ] <EOL> @ property <EOL> def _report_columns ( self ) : <EOL> agg_col_id = self . data_source_properties [ self . aggregation_field ] . column_id <EOL> agg_disp = self . data_source_properties [ self . aggregation_field ] . text <EOL> return [ <EOL> { <EOL> "<STR_LIT>" : "<STR_LIT:default>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : agg_col_id , <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : agg_disp <EOL> } , <EOL> { <EOL> "<STR_LIT>" : "<STR_LIT:default>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT:count>" , <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : "<STR_LIT>" <EOL> } <EOL> ] <EOL> @ property <EOL> def _group_by_choices ( self ) : <EOL> return [ ( p . id , p . text ) for p in self . data_source_properties . values ( ) ] <EOL> class ConfigurePieChartReportForm ( ConfigureBarChartReportForm ) : <EOL> group_by = forms . ChoiceField ( label = _ ( "<STR_LIT>" ) ) <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> return crispy . Fieldset ( <EOL> _ ( '<STR_LIT>' ) , <EOL> FieldWithHelpBubble ( <EOL> '<STR_LIT>' , <EOL> help_bubble_text = _ ( <EOL> "<STR_LIT>" <EOL> "<STR_LIT>" <EOL> ) , <EOL> placeholder = _ ( <EOL> "<STR_LIT>" <EOL> ) , <EOL> ) , <EOL> self . filter_fieldset <EOL> ) <EOL> @ property <EOL> def _report_charts ( self ) : <EOL> agg = self . data_source_properties [ self . aggregation_field ] . column_id <EOL> return [ { <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : agg , <EOL> "<STR_LIT>" : "<STR_LIT:count>" , <EOL> } ] <EOL> class ConfigureListReportForm ( ConfigureNewReportBase ) : <EOL> report_type = '<STR_LIT:list>' <EOL> columns = JsonField ( <EOL> expected_type = list , <EOL> null_values = ( [ ] , ) , <EOL> required = True , <EOL> widget = forms . HiddenInput , <EOL> error_messages = { "<STR_LIT>" : ugettext_lazy ( "<STR_LIT>" ) } , <EOL> ) <EOL> column_legend_fine_print = ugettext_noop ( "<STR_LIT>" ) <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> source_name = '<STR_LIT>' <EOL> if self . source_type == '<STR_LIT>' : <EOL> source_name = self . report_source_id <EOL> if self . source_type == '<STR_LIT>' : <EOL> source_name = Form . get_form ( self . report_source_id ) . default_name ( ) <EOL> return crispy . Fieldset ( <EOL> '<STR_LIT>' , <EOL> crispy . Fieldset ( <EOL> _legend ( <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( '<STR_LIT>' ) . format ( <EOL> name = source_name , source = self . source_type <EOL> ) <EOL> ) <EOL> ) , <EOL> self . column_fieldset , <EOL> self . filter_fieldset <EOL> ) <EOL> @ property <EOL> def column_fieldset ( self ) : <EOL> return crispy . Fieldset ( <EOL> _legend ( _ ( "<STR_LIT>" ) , _ ( self . column_legend_fine_print ) ) , <EOL> crispy . Div ( <EOL> crispy . HTML ( self . column_config_template ) , id = "<STR_LIT>" , data_bind = '<STR_LIT>' <EOL> ) , <EOL> hqcrispy . HiddenFieldWithErrors ( '<STR_LIT>' , None , data_bind = "<STR_LIT>" ) , <EOL> ) <EOL> @ property <EOL> @ memoized <EOL> def initial_columns ( self ) : <EOL> if self . existing_report : <EOL> reverse_agg_map = { <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' <EOL> } <EOL> cols = [ ] <EOL> for c in self . existing_report . columns : <EOL> exists = self . _column_exists ( c [ '<STR_LIT>' ] ) <EOL> cols . append ( <EOL> ColumnViewModel ( <EOL> display_text = c [ '<STR_LIT>' ] , <EOL> exists_in_current_version = exists , <EOL> property = self . _get_property_from_column ( c [ '<STR_LIT>' ] ) if exists else None , <EOL> data_source_field = c [ '<STR_LIT>' ] if not exists else None , <EOL> calculation = reverse_agg_map . get ( c . get ( '<STR_LIT>' ) , _ ( '<STR_LIT>' ) ) <EOL> ) <EOL> ) <EOL> return cols <EOL> return [ ColumnViewModel ( <EOL> display_text = '<STR_LIT>' , <EOL> exists_in_current_version = True , <EOL> property = None , <EOL> data_source_field = None , <EOL> calculation = _ ( '<STR_LIT>' ) <EOL> ) ] <EOL> @ property <EOL> def _report_columns ( self ) : <EOL> def _make_column ( conf , index ) : <EOL> return { <EOL> "<STR_LIT>" : "<STR_LIT:default>" , <EOL> "<STR_LIT>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : self . data_source_properties [ conf [ '<STR_LIT>' ] ] . column_id , <EOL> "<STR_LIT>" : "<STR_LIT>" . format ( index ) , <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : conf [ '<STR_LIT>' ] <EOL> } <EOL> return [ _make_column ( conf , i ) for i , conf in enumerate ( self . cleaned_data [ '<STR_LIT>' ] ) ] <EOL> @ property <EOL> def _report_aggregation_cols ( self ) : <EOL> return [ '<STR_LIT>' ] <EOL> class ConfigureTableReportForm ( ConfigureListReportForm , ConfigureBarChartReportForm ) : <EOL> report_type = '<STR_LIT>' <EOL> column_legend_fine_print = ugettext_noop ( '<STR_LIT>' ) <EOL> group_by = forms . ChoiceField ( label = _ ( "<STR_LIT>" ) ) <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> return crispy . Fieldset ( <EOL> "<STR_LIT>" , <EOL> self . column_fieldset , <EOL> crispy . Fieldset ( <EOL> _legend ( <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> ) , <EOL> '<STR_LIT>' , <EOL> ) , <EOL> self . filter_fieldset <EOL> ) <EOL> @ property <EOL> def _report_charts ( self ) : <EOL> return [ ] <EOL> @ property <EOL> def _report_columns ( self ) : <EOL> agg_field_id = self . data_source_properties [ self . aggregation_field ] . column_id <EOL> agg_field_text = self . data_source_properties [ self . aggregation_field ] . text <EOL> def _make_column ( conf , index ) : <EOL> aggregation_map = { '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> '<STR_LIT>' : '<STR_LIT>' } <EOL> return { <EOL> "<STR_LIT>" : "<STR_LIT:default>" , <EOL> "<STR_LIT>" : aggregation_map [ conf [ '<STR_LIT>' ] ] , <EOL> "<STR_LIT>" : self . data_source_properties [ conf [ '<STR_LIT>' ] ] . column_id , <EOL> "<STR_LIT>" : "<STR_LIT>" . format ( index ) , <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> "<STR_LIT>" : conf [ '<STR_LIT>' ] , <EOL> "<STR_LIT>" : { '<STR_LIT:type>' : '<STR_LIT>' , '<STR_LIT>' : '<STR_LIT>' } <EOL> } <EOL> columns = [ _make_column ( conf , i ) for i , conf in enumerate ( self . cleaned_data [ '<STR_LIT>' ] ) ] <EOL> displaying_agg_column = bool ( [ c for c in columns if c [ '<STR_LIT>' ] == agg_field_id ] ) <EOL> if not displaying_agg_column : <EOL> columns = [ { <EOL> '<STR_LIT>' : '<STR_LIT:default>' , <EOL> '<STR_LIT>' : '<STR_LIT>' , <EOL> "<STR_LIT:type>" : "<STR_LIT>" , <EOL> '<STR_LIT>' : agg_field_id , <EOL> '<STR_LIT>' : agg_field_text <EOL> } ] + columns <EOL> for c in columns : <EOL> if c [ '<STR_LIT>' ] != agg_field_id and c [ '<STR_LIT>' ] == '<STR_LIT>' : <EOL> c [ '<STR_LIT>' ] = "<STR_LIT>" <EOL> return columns <EOL> @ property <EOL> @ memoized <EOL> def initial_columns ( self ) : <EOL> columns = super ( ConfigureTableReportForm , self ) . initial_columns <EOL> if self . existing_report : <EOL> agg_properties = [ <EOL> self . _get_property_from_column ( c ) <EOL> for c in self . existing_report . aggregation_columns <EOL> ] <EOL> return [ c for c in columns if c . property not in agg_properties ] <EOL> return columns <EOL> @ property <EOL> @ memoized <EOL> def _report_aggregation_cols ( self ) : <EOL> return [ <EOL> self . data_source_properties [ self . aggregation_field ] . column_id <EOL> ] <EOL> class ConfigureWorkerReportForm ( ConfigureTableReportForm ) : <EOL> report_type = '<STR_LIT>' <EOL> column_legend_fine_print = ugettext_noop ( '<STR_LIT>' ) <EOL> def __init__ ( self , * args , ** kwargs ) : <EOL> super ( ConfigureWorkerReportForm , self ) . __init__ ( * args , ** kwargs ) <EOL> self . fields . pop ( '<STR_LIT>' ) <EOL> @ property <EOL> def aggregation_field ( self ) : <EOL> if self . source_type == "<STR_LIT>" : <EOL> return "<STR_LIT:username>" <EOL> if self . source_type == "<STR_LIT>" : <EOL> return "<STR_LIT>" <EOL> @ property <EOL> @ memoized <EOL> def _default_case_report_filters ( self ) : <EOL> return [ <EOL> FilterViewModel ( <EOL> exists_in_current_version = True , <EOL> property = '<STR_LIT>' , <EOL> data_source_field = None , <EOL> display_text = '<STR_LIT>' , <EOL> format = '<STR_LIT>' , <EOL> ) , <EOL> FilterViewModel ( <EOL> exists_in_current_version = True , <EOL> property = '<STR_LIT>' , <EOL> data_source_field = None , <EOL> display_text = '<STR_LIT>' , <EOL> format = '<STR_LIT>' , <EOL> ) , <EOL> ] <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> return crispy . Fieldset ( <EOL> '<STR_LIT>' , <EOL> crispy . Fieldset ( <EOL> _legend ( <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> ) <EOL> ) , <EOL> self . column_fieldset , <EOL> self . filter_fieldset <EOL> ) <EOL> class ConfigureMapReportForm ( ConfigureListReportForm ) : <EOL> report_type = '<STR_LIT>' <EOL> location = forms . ChoiceField ( label = "<STR_LIT>" ) <EOL> def __init__ ( self , report_name , app_id , source_type , report_source_id , existing_report = None , * args , ** kwargs ) : <EOL> super ( ConfigureMapReportForm , self ) . __init__ ( <EOL> report_name , app_id , source_type , report_source_id , existing_report , * args , ** kwargs <EOL> ) <EOL> if self . source_type == "<STR_LIT>" : <EOL> self . fields [ '<STR_LIT:location>' ] . widget = QuestionSelect ( attrs = { '<STR_LIT:class>' : '<STR_LIT>' } ) <EOL> else : <EOL> self . fields [ '<STR_LIT:location>' ] . widget = Select2 ( attrs = { '<STR_LIT:class>' : '<STR_LIT>' } ) <EOL> self . fields [ '<STR_LIT:location>' ] . choices = self . _location_choices <EOL> if self . existing_report and existing_report . location_column_id : <EOL> existing_loc_col = existing_report . location_column_id <EOL> self . fields [ '<STR_LIT:location>' ] . initial = self . _get_property_from_column ( existing_loc_col ) <EOL> @ property <EOL> def _location_choices ( self ) : <EOL> return [ ( p . id , p . text ) for p in self . data_source_properties . values ( ) ] <EOL> @ property <EOL> def container_fieldset ( self ) : <EOL> return crispy . Fieldset ( <EOL> "<STR_LIT>" , <EOL> self . column_fieldset , <EOL> crispy . Fieldset ( <EOL> _legend ( <EOL> _ ( "<STR_LIT>" ) , <EOL> _ ( '<STR_LIT>' ) , <EOL> ) , <EOL> '<STR_LIT:location>' , <EOL> ) , <EOL> self . filter_fieldset <EOL> ) <EOL> @ property <EOL> @ memoized <EOL> def initial_columns ( self ) : <EOL> columns = super ( ConfigureMapReportForm , self ) . initial_columns <EOL> if self . existing_report and self . existing_report . location_column_id : <EOL> col_id = self . existing_report . location_column_id <EOL> location_property = self . _get_property_from_column ( col_id ) <EOL> return [ c for c in columns if c . property != location_property ] <EOL> return columns <EOL> @ property <EOL> def location_field ( self ) : <EOL> return self . cleaned_data [ "<STR_LIT:location>" ] <EOL> @ property <EOL> def _report_columns ( self ) : <EOL> loc_field_id = self . data_source_properties [ self . location_field ] . column_id <EOL> loc_field_text = self . data_source_properties [ self . location_field ] . text <EOL> columns = super ( ConfigureMapReportForm , self ) . _report_columns <EOL> displaying_loc_column = bool ( [ c for c in columns if c [ '<STR_LIT>' ] == loc_field_id ] ) <EOL> if not displaying_loc_column : <EOL> columns = columns + [ { <EOL> "<STR_LIT>" : loc_field_id , <EOL> "<STR_LIT:type>" : "<STR_LIT:location>" , <EOL> '<STR_LIT>' : loc_field_id , <EOL> '<STR_LIT>' : loc_field_text <EOL> } ] <EOL> return columns </s>
