Ejemplo n.º 1
0
class CaseExpressionRepeaterForm(GenericRepeaterForm):
    configured_filter = JsonField(expected_type=dict,
                                  help_text=help_text.CONFIGURED_FILTER)
    configured_expression = JsonField(expected_type=dict)
    url_template = CharField(
        required=False,
        help_text=
        _("Items to add to the end of the URL. Please see the documentation for more information."
          ))

    def get_ordered_crispy_form_fields(self):
        fields = super().get_ordered_crispy_form_fields()
        return fields + [
            'url_template', 'configured_filter', 'configured_expression'
        ]

    def clean_configured_expression(self):
        try:
            ExpressionFactory.from_spec(
                self.cleaned_data['configured_expression'],
                FactoryContext.empty())
        except BadSpecError as e:
            raise ValidationError(e)

        return self.cleaned_data['configured_expression']

    def clean_configured_filter(self):
        try:
            FilterFactory.from_spec(self.cleaned_data['configured_filter'])
        except BadSpecError as e:
            raise ValidationError(e)

        return self.cleaned_data['configured_filter']
Ejemplo n.º 2
0
class OpenmrsConfigForm(forms.Form):
    case_config = JsonField(expected_type=dict)
    form_configs = JsonField(expected_type=list)

    def __init__(self, *args, **kwargs):
        super(OpenmrsConfigForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', _('Save Changes')))
Ejemplo n.º 3
0
class ConfigurableDataSourceEditForm(DocumentFormBase):

    table_id = forms.CharField(label=_("Table ID"),
                               help_text=help_text.TABLE_ID)
    referenced_doc_type = forms.ChoiceField(choices=DOC_TYPE_CHOICES,
                                            label=_("Source Type"))
    display_name = forms.CharField(label=_("Report Title"),
                                   help_text=help_text.DISPLAY_NAME)
    description = forms.CharField(required=False,
                                  help_text=help_text.DESCRIPTION)
    base_item_expression = JsonField(expected_type=dict,
                                     help_text=help_text.BASE_ITEM_EXPRESSION)
    configured_filter = JsonField(expected_type=dict,
                                  help_text=help_text.CONFIGURED_FILTER)
    configured_indicators = JsonField(
        expected_type=list, help_text=help_text.CONFIGURED_INDICATORS)
    named_filters = JsonField(required=False,
                              expected_type=dict,
                              label=_("Named filters (optional)"),
                              help_text=help_text.NAMED_FILTER)

    def __init__(self, domain, *args, **kwargs):
        self.domain = domain
        super(ConfigurableDataSourceEditForm, self).__init__(*args, **kwargs)

    def clean_table_id(self):
        # todo: validate table_id as [a-z][a-z0-9_]*
        table_id = self.cleaned_data['table_id']
        table_name = get_table_name(self.domain, table_id)
        if len(table_name) > 63:  # max table name length for postgres
            raise ValidationError(
                _('Table id is too long. Your table id and domain name must add up to fewer than 40 characters'
                  ))
        for src in self.instance.by_domain(self.domain):
            if src.table_id == table_id and src.get_id != self.instance.get_id:
                raise ValidationError(
                    _('A data source with this table id already exists. Table'
                      ' ids must be unique'))
        return table_id

    def clean(self):
        cleaned_data = super(ConfigurableDataSourceEditForm, self).clean()
        # only call additional validation if initial validation has passed for all fields
        for field in self.fields:
            if field not in cleaned_data:
                return
        try:
            config = self.populate_instance(self.instance, cleaned_data)
            config.validate()
        except Exception, e:
            if settings.DEBUG:
                raise
            raise ValidationError(
                _(u'Problem with data source spec: {}').format(e))
        return cleaned_data
Ejemplo n.º 4
0
class AdvancedPerformanceMessageEditForm(PerformanceFormMixin, forms.Form):
    recipient_id = forms.CharField()
    schedule = JsonField()
    template = forms.CharField(widget=forms.Textarea)
    template_variables = JsonField(expected_type=list)

    def __init__(self, domain, config, *args, **kwargs):
        self.domain = domain
        self.config = config
        super(AdvancedPerformanceMessageEditForm,
              self).__init__(initial=config.to_json(), *args, **kwargs)

        self.fields['recipient_id'] = GroupField(domain=domain,
                                                 label=_('Recipient Group'))

        self.helper = _get_default_form_helper()
        form_layout = self.fields.keys()
        form_layout.append(
            hqcrispy.FormActions(
                StrictButton(
                    _("Save Changes"),
                    type="submit",
                    css_class="btn btn-primary",
                ), ))
        self.helper.layout = Layout(*form_layout)

    def clean_schedule(self):
        return ScheduleConfiguration.wrap(self.cleaned_data['schedule'])

    def _apply_updates_to_config(self, config, cleaned_data):
        config.recipient_id = cleaned_data['recipient_id']
        config.schedule = cleaned_data['schedule']
        config.template = cleaned_data['template']
        config.template_variables = cleaned_data['template_variables']
        return config

    def clean_template_variables(self):
        template_vars = self.cleaned_data['template_variables']
        if not isinstance(template_vars, list):
            raise forms.ValidationError(
                _('Template variables must be a list!'))
        wrapped_vars = []
        for var in template_vars:
            try:
                wrapped = TemplateVariable.wrap(var)
                wrapped.validate()
                wrapped_vars.append(wrapped)
            except Exception as e:
                raise forms.ValidationError(
                    _(u'Problem wrapping template variable! {}').format(e))
        return wrapped_vars
Ejemplo n.º 5
0
class OpenmrsConfigForm(forms.Form):
    openmrs_provider = forms.CharField(label=_("Provider UUID"),
                                       required=False)
    patient_config = JsonField(expected_type=dict)
    encounters_config = JsonField(expected_type=list)

    def __init__(self, *args, **kwargs):
        super(OpenmrsConfigForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', _('Save Changes')))

    def clean_patient_config(self):

        for key in self.cleaned_data['patient_config']['person_properties']:
            if key not in PERSON_PROPERTIES:
                raise ValidationError(
                    _('person property key "%(key)s" is not valid.'),
                    code='invalid',
                    params={'key': key})

        for key in self.cleaned_data['patient_config'][
                'person_preferred_name']:
            if key not in NAME_PROPERTIES:
                raise ValidationError(
                    _('person preferred name key "%(key)s" is not valid.'),
                    code='invalid',
                    params={'key': key})

        for key in self.cleaned_data['patient_config'][
                'person_preferred_address']:
            if key not in ADDRESS_PROPERTIES:
                raise ValidationError(
                    _('person preferred address key "%(key)s" is not valid.'),
                    code='invalid',
                    params={'key': key})

        for id_ in self.cleaned_data['patient_config']['match_on_ids']:
            if id_ not in self.cleaned_data['patient_config'][
                    'patient_identifiers']:
                raise ValidationError(_(
                    'ID "%(id_)s" used in "match_on_ids" is missing from "patient_identifiers".'
                ),
                                      code='invalid',
                                      params={'id_': id_})

        return self.cleaned_data['patient_config']
Ejemplo n.º 6
0
class ConfigureListReportForm(ConfigureNewReportBase):
    report_type = 'list'
    columns = JsonField(required=True)
    column_legend_fine_print = _(
        "Add columns to your report to display information from cases or form submissions. You may rearrange the order of the columns by dragging the arrows next to the column."
    )

    @property
    def container_fieldset(self):
        return crispy.Fieldset("", self.column_fieldset, self.filter_fieldset)

    @property
    def column_fieldset(self):
        return crispy.Fieldset(
            _legend(_("Columns"), self.column_legend_fine_print),
            crispy.Div(crispy.HTML(self.column_config_template),
                       id="columns-table",
                       data_bind='with: columnsList'),
            crispy.Hidden('columns',
                          None,
                          data_bind="value: columnsList.serializedProperties"))

    @property
    @memoized
    def initial_columns(self):
        if self.existing_report:
            cols = []
            for c in self.existing_report.columns:
                exists = self._column_exists(c['field'])
                cols.append(
                    ColumnViewModel(
                        display_text=c['display'],
                        exists_in_current_version=exists,
                        property=self._get_property_from_column(c['field'])
                        if exists else None,
                        data_source_field=c['field'] if not exists else None,
                    ))
            return cols
        return []

    @property
    def _report_columns(self):
        def _make_column(conf):
            return {
                "format": "default",
                "aggregation": "simple",
                "field":
                self.data_source_properties[conf['property']]['column_id'],
                "type": "field",
                "display": conf['display_text']
            }

        return [_make_column(conf) for conf in self.cleaned_data['columns']]

    @property
    def _report_aggregation_cols(self):
        return ['doc_id']
Ejemplo n.º 7
0
class Dhis2ConfigForm(forms.Form):
    form_configs = JsonField(expected_type=list)

    def __init__(self, *args, **kwargs):
        super(Dhis2ConfigForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', _('Save Changes')))

    def clean_form_configs(self):
        errors = _validate_form_configs(self.cleaned_data['form_configs'])
        if errors:
            raise ValidationError(errors)
        return self.cleaned_data['form_configs']
Ejemplo n.º 8
0
class Dhis2ConfigForm(forms.Form):
    form_configs = JsonField(expected_type=list)

    def __init__(self, *args, **kwargs):
        super(Dhis2ConfigForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', _('Save Changes')))

    def clean_form_configs(self):
        errors = []
        for form_config in self.cleaned_data['form_configs']:
            if form_config.get('xmlns'):
                required_msg = _('The "%(property)s" property is required for '
                                 'form "{}".').format(form_config['xmlns'])
            else:
                required_msg = _('The "%(property)s" property is required.')

            if not form_config.get('program_id'):
                errors.append(
                    ValidationError(
                        '{} {}'.format(
                            required_msg,
                            _('Please specify the DHIS2 Program of the event.')
                        ),
                        params={'property': 'program_id'},
                        code='required_property',
                    ))
            if not form_config.get('event_date'):
                errors.append(
                    ValidationError(
                        '{} {}'.format(
                            required_msg,
                            _('Please provide a FormQuestion, FormQuestionMap or '
                              'ConstantString to determine the date of the event.'
                              )),
                        params={'property': 'event_date'},
                        code='required_property',
                    ))
            if not form_config.get('datavalue_maps'):
                errors.append(
                    ValidationError(
                        '{} {}'.format(
                            required_msg,
                            _('Please map CommCare values to OpenMRS data elements.'
                              )),
                        params={'property': 'datavalue_maps'},
                        code='required_property',
                    ))
        if errors:
            raise ValidationError(errors)
        return self.cleaned_data['form_configs']
Ejemplo n.º 9
0
class ConfigurableReportEditForm(DocumentFormBase):

    config_id = forms.ChoiceField()  # gets overridden on instantiation
    title = forms.CharField()
    visible = forms.ChoiceField(label=_('Visible to:'),
                                choices=VISIBILITY_CHOICES)
    description = forms.CharField(required=False)
    aggregation_columns = JsonField(expected_type=list)
    filters = JsonField(expected_type=list)
    columns = JsonField(expected_type=list)
    configured_charts = JsonField(expected_type=list)
    sort_expression = JsonField(expected_type=list)

    def __init__(self,
                 domain,
                 instance=None,
                 read_only=False,
                 *args,
                 **kwargs):
        super(ConfigurableReportEditForm,
              self).__init__(instance, read_only, *args, **kwargs)
        self.fields['config_id'] = ReportDataSourceField(domain=domain)

    def clean_visible(self):
        return self.cleaned_data['visible'] == 'True'

    def clean(self):
        cleaned_data = super(ConfigurableReportEditForm, self).clean()
        # only call additional validation if initial validation has passed for all fields
        for field in self.fields:
            if field not in cleaned_data:
                return
        try:
            config = self.populate_instance(self.instance, cleaned_data)
            config.validate()
        except Exception, e:
            raise ValidationError(_(u'Problem with report spec: {}').format(e))
        return cleaned_data
Ejemplo n.º 10
0
class OpenmrsConfigForm(forms.Form):
    openmrs_provider = forms.CharField(label=_('Provider UUID'), required=False)
    case_config = JsonField(expected_type=dict)
    form_configs = JsonField(expected_type=list)

    def __init__(self, *args, **kwargs):
        super(OpenmrsConfigForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.add_input(Submit('submit', _('Save Changes')))

    def clean_case_config(self):

        for key in self.cleaned_data['case_config']['person_properties']:
            if key not in PERSON_PROPERTIES:
                raise ValidationError(
                    _('person property key "%(key)s" is not valid.'),
                    code='invalid',
                    params={'key': key}
                )

        for key in self.cleaned_data['case_config']['person_preferred_name']:
            if key not in NAME_PROPERTIES:
                raise ValidationError(
                    _('person preferred name key "%(key)s" is not valid.'),
                    code='invalid',
                    params={'key': key}
                )

        for key in self.cleaned_data['case_config']['person_preferred_address']:
            if key not in ADDRESS_PROPERTIES:
                raise ValidationError(
                    _('person preferred address key "%(key)s" is not valid.'),
                    code='invalid',
                    params={'key': key}
                )

        return self.cleaned_data['case_config']
Ejemplo n.º 11
0
class Dhis2EntityConfigForm(forms.Form):
    """
    Dhis2EntityConfig.case_configs is a list. Dhis2EntityConfigForm has
    one case_config, and is used in a formset.
    """
    case_config = JsonField()

    def clean_case_config(self):
        errors = []
        case_config = self.cleaned_data['case_config']
        if not isinstance(case_config, dict):
            raise ValidationError(_(
                'The "case_type" property is a dictionary, not a "%(data_type)s".'
            ),
                                  params={
                                      'data_type': type(case_config).__name__
                                  })
        if not case_config.get('case_type'):
            errors.append(
                ValidationError(
                    _('The "%(property)s" property is required.'),
                    params={'property': 'case_type'},
                    code='required_property',
                ))
        if 'form_configs' not in case_config:
            errors.append(
                ValidationError(
                    _('The "%(property)s" property is required.'),
                    params={'property': 'form_configs'},
                    code='required_property',
                ))
        elif not isinstance(case_config['form_configs'], list):
            raise ValidationError(_(
                'The "form_configs" property is a dictionary, not a "%(data_type)s".'
            ),
                                  params={
                                      'data_type':
                                      type(
                                          case_config['form_configs']).__name__
                                  })
        else:
            errors.extend(_validate_form_configs(case_config['form_configs']))
        if errors:
            raise ValidationError(errors)
        return self.cleaned_data['case_config']
Ejemplo n.º 12
0
 def __init__(self, request, *args, **kwargs):
     super().__init__(*args, **kwargs)
     self.domain = request.domain
     self.fields['description'] = forms.CharField(required=False)
     self.fields['definition'] = JsonField(initial={
         "type": "property_name",
         "property_name": "name"
     })
     self.helper = HQFormHelper()
     self.helper.layout = crispy.Layout(
         crispy.Fieldset(
             _('Expression'),
             crispy.Field('name'),
             crispy.Field('expression_type'),
             crispy.Field('description'),
             crispy.Field('definition'),
         ))
     self.helper.add_input(crispy.Submit('submit', _('Save')))
     self.helper.render_required_fields = True
Ejemplo n.º 13
0
class ConfigurableReportEditForm(DocumentFormBase):

    config_id = forms.ChoiceField()  # gets overridden on instantiation
    title = forms.CharField()
    visible = forms.ChoiceField(label=_('Visible to:'), choices=VISIBILITY_CHOICES)
    description = forms.CharField(required=False)
    aggregation_columns = JsonField(expected_type=list)
    filters = JsonField(expected_type=list)
    columns = JsonField(expected_type=list)
    configured_charts = JsonField(expected_type=list)
    sort_expression = JsonField(expected_type=list)

    def __init__(self, domain, instance=None, read_only=False, *args, **kwargs):
        super(ConfigurableReportEditForm, self).__init__(instance, read_only, *args, **kwargs)
        self.fields['config_id'] = ReportDataSourceField(domain=domain)

        self.helper = FormHelper()

        self.helper.form_method = 'POST'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_action = '#'

        self.helper.label_class = 'col-sm-3 col-md-2'
        self.helper.field_class = 'col-sm-9 col-md-9'

        self.helper.layout = crispy.Layout(
            crispy.Fieldset(
                _("Report Configuration"),
                'config_id',
                'title',
                'visible',
                'description',
                'aggregation_columns',
                'filters',
                'columns',
                'configured_charts',
                'sort_expression',
            ),
            hqcrispy.FormActions(
                twbscrispy.StrictButton(
                    _("Save Changes"),
                    type="submit",
                    css_class="btn btn-primary",
                ),
            ),
        )

    def clean_visible(self):
        return self.cleaned_data['visible'] == 'True'

    def clean(self):
        cleaned_data = super(ConfigurableReportEditForm, self).clean()
        # only call additional validation if initial validation has passed for all fields
        for field in self.fields:
            if field not in cleaned_data:
                return
        try:
            config = self.populate_instance(self.instance, cleaned_data)
            config.validate()
        except Exception, e:
            raise ValidationError(_(u'Problem with report spec: {}').format(e))
        return cleaned_data
Ejemplo n.º 14
0
class OpenmrsImporterForm(forms.Form):
    server_url = forms.CharField(label=_('OpenMRS URL'), required=True,
                                 help_text=_('e.g. "http://www.example.com/openmrs"'))
    username = forms.CharField(label=_('Username'), required=True)
    password = forms.CharField(label=_('Password'), widget=forms.PasswordInput, required=False)
    location_id = forms.CharField(label=_('Location ID'), required=False,
                                  help_text='If a project space has multiple OpenMRS servers to import from, for '
                                            'which CommCare location is this OpenMRS server authoritative?')
    import_frequency = forms.ChoiceField(label=_('Import Frequency'), choices=IMPORT_FREQUENCY_CHOICES,
                                         help_text=_('How often should cases be imported?'), required=False)
    log_level = forms.TypedChoiceField(label=_('Log Level'), required=False, choices=LOG_LEVEL_CHOICES, coerce=int)

    report_uuid = forms.CharField(label=_('Report UUID'), required=True,
                                  help_text=_('The OpenMRS UUID of the report of patients to be imported'))
    report_params = JsonField(label=_('Report Parameters'), required=False, expected_type=dict)
    case_type = forms.CharField(label=_('Case Type'), required=True)
    owner_id = forms.CharField(label=_owner_id_label, required=False,
                               help_text=_('The ID of the mobile worker or location who will own new cases'))
    location_type_name = forms.CharField(label=_location_type_name_label, required=False,
                                         help_text=_('The Organization Level whose mobile worker will own new '
                                                     'cases'))
    external_id_column = forms.CharField(label=_('External ID Column'), required=True,
                                         help_text=_("The column that contains the OpenMRS UUID of the patient"))
    name_columns = forms.CharField(label=_('Name Columns'), required=True,
                                   help_text=_('Space-separated column(s) to be concatenated to create the case '
                                               'name (e.g. "givenName familyName")'))
    column_map = JsonField(label=_('Map columns to properties'), required=True, expected_type=list,
                           help_text=_('e.g. [{"column": "givenName", "property": "first_name"}, ...]'))

    def clean(self):
        cleaned_data = super(OpenmrsImporterForm, self).clean()
        if bool(cleaned_data.get('owner_id')) == bool(cleaned_data.get('location_type_name')):
            message = _(
                'The owner of imported patient cases is determined using either "{owner_id}" or '
                '"{location_type_name}". Please specify either one or the other.').format(
                owner_id=_owner_id_label, location_type_name=_location_type_name_label)
            self.add_error('owner_id', message)
            self.add_error('location_type_name', message)
        return self.cleaned_data

    def save(self, domain_name):
        try:
            importers = get_openmrs_importers_by_domain(domain_name)
            importer = importers[0] if importers else None  # TODO: Support multiple
            if importer is None:
                importer = OpenmrsImporter(domain=domain_name)
            importer.server_url = self.cleaned_data['server_url']
            importer.username = self.cleaned_data['username']
            if self.cleaned_data['password']:
                # Don't save it if it hasn't been changed.
                importer.password = b64_aes_encrypt(self.cleaned_data['password'])
            importer.location_id = self.cleaned_data['location_id']
            importer.import_frequency = self.cleaned_data['import_frequency']
            importer.log_level = self.cleaned_data['log_level']

            importer.report_uuid = self.cleaned_data['report_uuid']
            importer.report_params = self.cleaned_data['report_params']
            importer.case_type = self.cleaned_data['case_type']
            importer.owner_id = self.cleaned_data['owner_id']
            importer.location_type_name = self.cleaned_data['location_type_name']
            importer.external_id_column = self.cleaned_data['external_id_column']
            importer.name_columns = self.cleaned_data['name_columns']
            importer.column_map = list(map(ColumnMapping.wrap, self.cleaned_data['column_map']))
            importer.save()
            return True
        except Exception as err:
            logging.error('Unable to save OpenMRS Importer: %s' % err)
            return False
Ejemplo n.º 15
0
class OpenmrsImporterForm(forms.Form):
    server_url = forms.CharField(
        label=_('OpenMRS URL'),
        required=True,
        help_text=_('e.g. "http://www.example.com/openmrs"'))
    username = forms.CharField(label=_('Username'), required=True)
    password = forms.CharField(label=_('Password'),
                               widget=forms.PasswordInput,
                               required=False)
    notify_addresses_str = forms.CharField(
        label=_('Addresses to send notifications'),
        required=False,
        help_text=_('A comma-separated list of email addresses to send error '
                    'notifications'))
    location_id = forms.CharField(
        label=_('Location ID'),
        required=False,
        help_text=_(
            'If a project space has multiple OpenMRS servers to import from, '
            'for which CommCare location is this OpenMRS server authoritative?'
        ))
    import_frequency = forms.ChoiceField(
        label=_('Import Frequency'),
        choices=IMPORT_FREQUENCY_CHOICES,
        help_text=_('How often should cases be imported?'),
        required=False)
    log_level = forms.TypedChoiceField(label=_('Log Level'),
                                       required=False,
                                       choices=LOG_LEVEL_CHOICES,
                                       coerce=int)
    timezone = forms.CharField(
        label=_('Timezone'),
        required=False,
        help_text=
        _("Timezone name. If not specified, the domain's timezone will be used."
          ))

    report_uuid = forms.CharField(
        label=_('Report UUID'),
        required=True,
        help_text=_(
            'The OpenMRS UUID of the report of patients to be imported'))
    report_params = JsonField(label=_('Report Parameters'),
                              required=False,
                              expected_type=dict)
    case_type = forms.CharField(label=_('Case Type'), required=True)
    owner_id = forms.CharField(
        label=_owner_id_label,
        required=False,
        help_text=_(
            'The ID of the mobile worker or location who will own new cases'))
    location_type_name = forms.CharField(
        label=_location_type_name_label,
        required=False,
        help_text=_('The Organization Level whose mobile worker will own new '
                    'cases'))
    external_id_column = forms.CharField(
        label=_('External ID Column'),
        required=True,
        help_text=_(
            "The column that contains the OpenMRS UUID of the patient"))
    name_columns = forms.CharField(
        label=_('Name Columns'),
        required=True,
        help_text=_(
            'Space-separated column(s) to be concatenated to create the case '
            'name (e.g. "givenName familyName")'))
    column_map = JsonField(
        label=_('Map columns to properties'),
        required=True,
        expected_type=list,
        help_text=_(
            'e.g. [{"column": "givenName", "property": "first_name"}, ...]'))
Ejemplo n.º 16
0
class ConfigurableDataSourceEditForm(DocumentFormBase):

    _id = forms.CharField(required=False,
                          disabled=True,
                          label=_('Data Source ID'),
                          help_text=help_text.DATA_SOURCE_ID)
    table_id = forms.CharField(label=_("Table ID"),
                               help_text=help_text.TABLE_ID)
    referenced_doc_type = forms.ChoiceField(choices=DOC_TYPE_CHOICES,
                                            label=_("Source Type"))
    display_name = forms.CharField(label=_("Data Source Display Name"),
                                   help_text=help_text.DISPLAY_NAME)
    description = forms.CharField(required=False,
                                  help_text=help_text.DESCRIPTION)
    base_item_expression = JsonField(expected_type=dict,
                                     help_text=help_text.BASE_ITEM_EXPRESSION)
    configured_filter = JsonField(expected_type=dict,
                                  help_text=help_text.CONFIGURED_FILTER)
    configured_indicators = JsonField(
        expected_type=list, help_text=help_text.CONFIGURED_INDICATORS)
    named_expressions = JsonField(required=False,
                                  expected_type=dict,
                                  label=_("Named expressions (optional)"),
                                  help_text=help_text.NAMED_EXPRESSIONS)
    named_filters = JsonField(required=False,
                              expected_type=dict,
                              label=_("Named filters (optional)"),
                              help_text=help_text.NAMED_FILTER)
    asynchronous = forms.BooleanField(
        initial=False,
        required=False,
        label="",
        widget=BootstrapCheckboxInput(inline_label="Asynchronous processing"))

    def __init__(self, domain, data_source_config, read_only, *args, **kwargs):
        self.domain = domain
        super(ConfigurableDataSourceEditForm,
              self).__init__(data_source_config, read_only, *args, **kwargs)

        if toggles.LOCATIONS_IN_UCR.enabled(domain):
            choices = self.fields['referenced_doc_type'].choices
            choices.append(('Location', _('locations')))
            self.fields['referenced_doc_type'].choices = choices
        self.helper = FormHelper()

        self.helper.form_method = 'POST'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_action = '#'

        self.helper.label_class = 'col-sm-3 col-md-2'
        self.helper.field_class = 'col-sm-9 col-md-9'

        fields = [
            'table_id',
            'referenced_doc_type',
            'display_name',
            'description',
            'base_item_expression',
            'configured_filter',
            'configured_indicators',
            'named_expressions',
            'named_filters',
            'asynchronous',
        ]
        if data_source_config.get_id:
            fields.append('_id')

        self.helper.layout = crispy.Layout(
            crispy.Fieldset(_("Edit Data Source"), *fields),
            hqcrispy.FormActions(
                twbscrispy.StrictButton(
                    _("Save Changes"),
                    type="submit",
                    css_class="btn btn-primary",
                ), ),
        )

    def clean_table_id(self):
        # todo: validate table_id as [a-z][a-z0-9_]*
        table_id = self.cleaned_data['table_id']
        table_name = get_table_name(self.domain, table_id)
        if len(table_name) > 63:  # max table name length for postgres
            raise ValidationError(
                _('Table id is too long. Your table id and domain name must add up to fewer than 40 characters'
                  ))
        for src in self.instance.by_domain(self.domain):
            if src.table_id == table_id and src.get_id != self.instance.get_id:
                raise ValidationError(
                    _('A data source with this table id already exists. Table'
                      ' ids must be unique'))
        return table_id

    def clean(self):
        cleaned_data = super(ConfigurableDataSourceEditForm, self).clean()
        # only call additional validation if initial validation has passed for all fields
        for field in self.fields:
            if field not in cleaned_data:
                return
        try:
            config = self.populate_instance(self.instance, cleaned_data)
            config.validate()
        except Exception as e:
            if settings.DEBUG:
                raise
            raise ValidationError(
                _('Problem with data source spec: {}').format(e))
        return cleaned_data

    def save(self, commit=False):
        self.instance.meta.build.finished = False
        self.instance.meta.build.initiated = None
        return super(ConfigurableDataSourceEditForm, self).save(commit)
Ejemplo n.º 17
0
class ConfigurableReportEditForm(DocumentFormBase):

    _id = forms.CharField(required=False,
                          disabled=True,
                          label=_('Report ID'),
                          help_text=help_text.REPORT_ID)
    config_id = forms.ChoiceField()  # gets overridden on instantiation
    title = forms.CharField()
    visible = forms.ChoiceField(label=_('Visible to:'),
                                choices=VISIBILITY_CHOICES)
    description = forms.CharField(required=False)
    aggregation_columns = JsonField(expected_type=list)
    filters = JsonField(expected_type=list)
    columns = JsonField(expected_type=list)
    configured_charts = JsonField(expected_type=list)
    sort_expression = JsonField(expected_type=list)

    def __init__(self,
                 domain,
                 instance=None,
                 read_only=False,
                 *args,
                 **kwargs):
        super(ConfigurableReportEditForm,
              self).__init__(instance, read_only, *args, **kwargs)
        self.fields['config_id'] = ReportDataSourceField(domain=domain)

        self.helper = FormHelper()

        self.helper.form_method = 'POST'
        self.helper.form_class = 'form-horizontal'
        self.helper.form_action = '#'

        self.helper.label_class = 'col-sm-3 col-md-2'
        self.helper.field_class = 'col-sm-9 col-md-9'

        fields = [
            'config_id',
            'title',
            'visible',
            'description',
            'aggregation_columns',
            'filters',
            'columns',
            'configured_charts',
            'sort_expression',
        ]
        if instance.config_id:
            fields.append('_id')

        self.helper.layout = crispy.Layout(
            crispy.Fieldset(_("Report Configuration"), *fields), )
        # Restrict edit for static reports
        if not read_only:
            self.helper.layout.append(
                hqcrispy.FormActions(
                    twbscrispy.StrictButton(
                        _("Save Changes"),
                        type="submit",
                        css_class="btn btn-primary",
                    ), ))

    def clean_visible(self):
        return self.cleaned_data['visible'] == 'True'

    def clean(self):
        cleaned_data = super(ConfigurableReportEditForm, self).clean()
        # only call additional validation if initial validation has passed for all fields
        for field in self.fields:
            if field not in cleaned_data:
                return
        try:
            config = self.populate_instance(self.instance, cleaned_data)
            config.validate()
        except Exception as e:
            raise ValidationError(_('Problem with report spec: {}').format(e))
        return cleaned_data

    def save(self, commit=False):
        self.instance.report_meta.edited_manually = True
        if toggles.AGGREGATE_UCRS.enabled(self.instance.domain):
            # hack - if the ID looks like a guid, assume it is non-aggregate, else aggregate
            try:
                UUID(self.instance.config_id)
                self.instance.data_source_type = DATA_SOURCE_TYPE_STANDARD
            except ValueError:
                self.instance.data_source_type = DATA_SOURCE_TYPE_AGGREGATE
        return super(ConfigurableReportEditForm, self).save(commit)
Ejemplo n.º 18
0
class OpenmrsImporterForm(forms.Form):
    server_url = forms.CharField(label=_('OpenMRS URL'), required=True,
                                 help_text=_('e.g. "http://www.example.com/openmrs"'))
    username = forms.CharField(label=_('Username'), required=True)
    password = forms.CharField(label=_('Password'), widget=forms.PasswordInput, required=False)
    import_frequency = forms.ChoiceField(label=_('Import Frequency'), choices=IMPORT_FREQUENCY_CHOICES,
                                         help_text=_('How often should cases be imported?'), required=False)
    log_level = forms.TypedChoiceField(label=_('Log Level'), required=False, choices=LOG_LEVEL_CHOICES, coerce=int)

    report_uuid = forms.CharField(label=_('Report UUID'), required=True,
                                  help_text=_('The OpenMRS UUID of the report of patients to be imported'))
    report_params = JsonField(label=_('Report Parameters'), required=False, expected_type=dict)
    case_type = forms.CharField(label=_('Case Type'), required=True)
    owner_id = forms.CharField(label=_('Owner ID'), required=False,
                               help_text=_('The ID of the mobile worker or location who will own new cases'))
    location_type_name = forms.CharField(label=_('Organization Level'), required=False,
                                         help_text=_('The Organization Level whose owners will own new cases'))
    external_id_column = forms.CharField(label=_('External ID Column'), required=True,
                                         help_text=_("The column that stores the case's external ID"))
    name_columns = forms.CharField(label=_('Name Columns'), required=True,
                                   help_text=_('Space-separated column(s) to be concatenated to create the case '
                                               'name (e.g. "givenName familyName")'))
    column_map = JsonField(label=_('Map columns to properties'), required=True, expected_type=list,
                           help_text=_('e.g. [{"column": "givenName", "property": "first_name"}, ...]'))

    def __init__(self, *args, **kwargs):
        super(OpenmrsImporterForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_class = 'form-horizontal'
        self.helper.label_class = 'col-sm-3 col-md-2'
        self.helper.field_class = 'col-sm-9 col-md-8 col-lg-6'
        self.helper.layout = crispy.Layout(
            crispy.Fieldset(
                _('Edit OpenMRS Importer'),
                crispy.Field('server_url'),
                crispy.Field('username'),
                crispy.Field('password'),
                crispy.Field('import_frequency'),
                crispy.Field('log_level'),

                crispy.Field('report_uuid'),
                crispy.Field('report_params'),
                crispy.Field('case_type'),
                crispy.Field('owner_id'),
                crispy.Field('location_type_name'),
                crispy.Field('external_id_column'),
                crispy.Field('name_columns'),
                crispy.Field('column_map'),
            ),
            hqcrispy.FormActions(
                StrictButton(
                    _("Update OpenMRS Importer"),
                    type="submit",
                    css_class='btn-primary',
                ),
                StrictButton(
                    _('Import Now'),
                    type='button',
                    id='btn-import-now',
                    css_class='btn-default',
                ),
            ),
        )

    def save(self, domain_name):
        try:
            importers = get_openmrs_importers_by_domain(domain_name)
            importer = importers[0] if importers else None  # TODO: Support multiple
            if importer is None:
                importer = OpenmrsImporter(domain=domain_name)
            importer.server_url = self.cleaned_data['server_url']
            importer.username = self.cleaned_data['username']
            if self.cleaned_data['password']:
                # Don't save it if it hasn't been changed.
                importer.password = b64_aes_encrypt(self.cleaned_data['password'])
            importer.import_frequency = self.cleaned_data['import_frequency']
            importer.log_level = self.cleaned_data['log_level']

            importer.report_uuid = self.cleaned_data['report_uuid']
            importer.report_params = self.cleaned_data['report_params']
            importer.case_type = self.cleaned_data['case_type']
            importer.owner_id = self.cleaned_data['owner_id']
            importer.location_type_name = self.cleaned_data['location_type_name']
            importer.external_id_column = self.cleaned_data['external_id_column']
            importer.name_columns = self.cleaned_data['name_columns']
            importer.column_map = map(ColumnMapping.wrap, self.cleaned_data['column_map'])
            importer.save()
            return True
        except Exception as err:
            logging.error('Unable to save OpenMRS Importer: %s' % err)
            return False