Ejemplo n.º 1
0
    def get_ajax(self, params):
        try:
            data_source = self.data_source
            if len(data_source.inner_columns
                   ) > 50 and not DISABLE_COLUMN_LIMIT_IN_UCR.enabled(
                       self.domain):
                raise UserReportsError(
                    _("This report has too many columns to be displayed"))
            data_source.set_filter_values(self.filter_values)

            sort_column = params.get('iSortCol_0')
            sort_order = params.get('sSortDir_0', 'ASC')
            echo = int(params.get('sEcho', 1))
            if sort_column and echo != 1:
                data_source.set_order_by([
                    (data_source.top_level_columns[int(sort_column)].column_id,
                     sort_order.upper())
                ])

            datatables_params = DatatablesParams.from_request_dict(params)
            page = list(
                data_source.get_data(start=datatables_params.start,
                                     limit=datatables_params.count))
            total_records = data_source.get_total_records()
            total_row = data_source.get_total_row(
            ) if data_source.has_total_row else None
        except UserReportsError as e:
            if settings.DEBUG:
                raise
            return self.render_json_response({
                'error': e.message,
                'aaData': [],
                'iTotalRecords': 0,
                'iTotalDisplayRecords': 0,
            })
        except TableNotFoundWarning:
            if self.spec.report_meta.created_by_builder:
                msg = _(
                    "The database table backing your report does not exist yet. "
                    "Please wait while the report is populated.")
            else:
                msg = _(
                    "The database table backing your report does not exist yet. "
                    "You must rebuild the data source before viewing the report."
                )
            return self.render_json_response({'warning': msg})

        json_response = {
            'aaData': page,
            "sEcho": params.get('sEcho', 0),
            "iTotalRecords": total_records,
            "iTotalDisplayRecords": total_records,
        }
        if total_row is not None:
            json_response["total_row"] = total_row
        if data_source.data_source.config.backend_id == UCR_LABORATORY_BACKEND:
            compare_ucr_dbs.delay(self.domain, self.report_config_id,
                                  self.filter_values, sort_column, sort_order,
                                  params)
        return self.render_json_response(json_response)
Ejemplo n.º 2
0
    def get_total_row(self):
        def _clean_total_row(aggregations, aggregation_name):
            agg = getattr(aggregations, aggregation_name)
            if hasattr(agg, 'value'):
                return agg.value
            elif hasattr(agg, 'doc_count'):
                return agg.doc_count
            else:
                return ''

        def _get_relevant_column_ids(col):
            col_id_to_expanded_col = get_expanded_columns(self.top_level_columns, self.config)
            return col_id_to_expanded_col.get(col.column_id, [col.column_id])

        aggregations = self._get_total_aggregated_results()

        total_row = []
        for col in self.top_level_columns:
            for col_id in _get_relevant_column_ids(col):
                if not col.calculate_total:
                    total_row.append('')
                    continue
                elif getattr(col, 'aggregation', '') == 'simple':
                    # could have this append '', but doing this for
                    # compatibility with SQL
                    raise UserReportsError(ugettext("You cannot calculate the total of a simple column"))

                total_row.append(_clean_total_row(aggregations, safe_es_column(col_id)))

        if total_row and total_row[0] is '':
            total_row[0] = ugettext('Total')
        return total_row
Ejemplo n.º 3
0
    def get_ajax(self, request):
        try:
            data_source = self.data_source
            if len(data_source.columns) > 50:
                raise UserReportsError(_("This report has too many columns to be displayed"))
            data_source.set_filter_values(self.filter_values)

            sort_column = request.GET.get('iSortCol_0')
            sort_order = request.GET.get('sSortDir_0', 'ASC')
            echo = int(request.GET.get('sEcho', 1))
            if sort_column and echo != 1:
                data_source.set_order_by(
                    [(data_source.column_configs[int(sort_column)].column_id, sort_order.upper())]
                )

            datatables_params = DatatablesParams.from_request_dict(request.GET)
            page = list(data_source.get_data(start=datatables_params.start, limit=datatables_params.count))

            total_records = data_source.get_total_records()
            total_row = data_source.get_total_row() if data_source.has_total_row else None
        except UserReportsError as e:
            if settings.DEBUG:
                raise
            return self.render_json_response({
                'error': e.message,
                'aaData': [],
                'iTotalRecords': 0,
                'iTotalDisplayRecords': 0,
            })
        except TableNotFoundWarning:
            if self.spec.report_meta.created_by_builder:
                msg = _(
                    "The database table backing your report does not exist yet. "
                    "Please wait while the report is populated."
                )
            else:
                msg = _(
                    "The database table backing your report does not exist yet. "
                    "You must rebuild the data source before viewing the report."
                )
            return self.render_json_response({
                'warning': msg
            })

        json_response = {
            'aaData': page,
            "sEcho": self.request_dict.get('sEcho', 0),
            "iTotalRecords": total_records,
            "iTotalDisplayRecords": total_records,
        }
        if total_row is not None:
            json_response["total_row"] = total_row
        return self.render_json_response(json_response)
Ejemplo n.º 4
0
 def _inner(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except (
         ColumnNotFoundException,
         ProgrammingError,
         InvalidQueryColumn,
     ) as e:
         error = translate_programming_error(e)
         if isinstance(error, TableNotFoundWarning):
             raise error
         raise UserReportsError(str(e))
Ejemplo n.º 5
0
 def _inner(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except (
             ColumnNotFoundException,
             ProgrammingError,
             InvalidQueryColumn,
     ) as e:
         if not settings.UNIT_TESTING:
             _soft_assert(False, unicode(e))
         raise UserReportsError(unicode(e))
     except TableNotFoundException:
         raise TableNotFoundWarning
Ejemplo n.º 6
0
 def _inner(*args, **kwargs):
     try:
         return func(*args, **kwargs)
     except (
         ColumnNotFoundException,
         ProgrammingError,
         InvalidQueryColumn,
     ) as e:
         error = translate_programming_error(e)
         if isinstance(error, TableNotFoundWarning):
             raise error
         if not settings.UNIT_TESTING:
             _soft_assert(False, six.text_type(e))
         raise UserReportsError(six.text_type(e))
Ejemplo n.º 7
0
    def get_data(self, slugs=None):
        try:
            ret = super(ConfigurableReportDataSource, self).get_data(slugs)
            for report_column in self.column_configs:
                report_column.format_data(ret)
        except (
                ColumnNotFoundException,
                ProgrammingError,
        ) as e:
            raise UserReportsError(e.message)
        except TableNotFoundException as e:
            raise TableNotFoundWarning
        # TODO: Should sort in the database instead of memory, but not currently supported by sqlagg.
        try:
            # If a sort order is specified, sort by it.
            if self._order_by:
                for col in reversed(self._order_by):
                    sort_column_id, order = col
                    is_descending = order == DESCENDING
                    try:
                        matching_report_column = self._column_configs[
                            sort_column_id]
                    except KeyError:
                        raise SortConfigurationError(
                            'Sort column {} not found in report!'.format(
                                sort_column_id))

                    def get_datatype(report_column):
                        """
                        Given a report column, get the data type by trying to pull it out
                        from the data source config of the db column it points at. Defaults to "string"
                        """
                        try:
                            field = report_column.field
                        except AttributeError:
                            # if the report column doesn't have a field object, default to string.
                            # necessary for percent columns
                            return 'string'

                        matching_indicators = filter(
                            lambda configured_indicator: configured_indicator[
                                'column_id'] == field,
                            self.config.configured_indicators)
                        if not len(matching_indicators) == 1:
                            raise SortConfigurationError(
                                'Number of indicators matching column %(col)s is %(num_matching)d'
                                % {
                                    'col': col[0],
                                    'num_matching': len(matching_indicators),
                                })
                        return matching_indicators[0]['datatype']

                    datatype = get_datatype(matching_report_column)

                    def sort_by(row):
                        value = row.get(sort_column_id, None)
                        return value or get_default_sort_value(datatype)

                    ret.sort(key=sort_by, reverse=is_descending)
                return ret
            # Otherwise sort by the first column
            else:
                return sorted(
                    ret,
                    key=lambda x: x.get(self.column_configs[0].column_id,
                                        next(x.itervalues())))
        except (SortConfigurationError, TypeError):
            # if the data isn't sortable according to the report spec
            # just return the data in the order we got it
            return ret