From 928b5715fe7aba9c19d1c970620249368d449c3f Mon Sep 17 00:00:00 2001 From: Ramez Date: Sat, 27 Aug 2022 22:02:35 +0200 Subject: [PATCH 1/9] Added option to customize aspects of the column by adding it as a tuple like ('field_name', dict(verbose_name=_('My Enhanced Verbose_name')) --- slick_reporting/fields.py | 1 + slick_reporting/generator.py | 32 ++++++++++++++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/slick_reporting/fields.py b/slick_reporting/fields.py index 038d369..3d59dce 100644 --- a/slick_reporting/fields.py +++ b/slick_reporting/fields.py @@ -408,6 +408,7 @@ class BalanceQTYReportField(SlickReportField): verbose_name = _('Cumulative QTY') calculation_field = 'quantity' requires = ['__fb_quan__'] + is_summable = False def final_calculation(self, debit, credit, dep_dict): # Use `get` so it fails loud if its not there diff --git a/slick_reporting/generator.py b/slick_reporting/generator.py index 72af8d6..2540013 100644 --- a/slick_reporting/generator.py +++ b/slick_reporting/generator.py @@ -2,10 +2,9 @@ import datetime import logging -from inspect import isclass - from django.core.exceptions import ImproperlyConfigured, FieldDoesNotExist from django.db.models import Q, ForeignKey +from inspect import isclass from .app_settings import SLICK_REPORTING_DEFAULT_CHARTS_ENGINE from .fields import SlickReportField @@ -57,6 +56,11 @@ class ReportGenerator(object): Example: columns = ['product_id', '__time_series__', 'col_b'] Same is true with __crosstab__ + + You can customize aspects of the column by adding it as a tuple like this + ('field_name', dict(verbose_name=_('My Enhanced Verbose_name')) + + """ time_series_pattern = '' @@ -249,7 +253,8 @@ def __init__(self, report_model=None, main_queryset=None, start_date=None, end_d concrete_fields = [f.name for f in self.group_by_field.related_model._meta.concrete_fields] # add database columns that are not already in concrete_fields final_fields = concrete_fields + list(set(self.get_database_columns()) - set(concrete_fields)) - self.main_queryset = self.group_by_field.related_model.objects.filter(pk__in=ids).values(*final_fields) + self.main_queryset = self.group_by_field.related_model.objects.filter(pk__in=ids).values( + *final_fields) else: self.main_queryset = self.main_queryset.distinct().values(self.group_by_field_attname) else: @@ -411,7 +416,10 @@ def check_columns(cls, columns, group_by, report_model, ): """ group_by_model = None if group_by: - group_by_field = [x for x in report_model._meta.get_fields() if x.name == group_by.split('__')[0]][0] + try: + group_by_field = [x for x in report_model._meta.get_fields() if x.name == group_by.split('__')[0]][0] + except IndexError: + raise ImproperlyConfigured(f"Could not find {group_by} in {report_model}") if group_by_field.is_relation: group_by_model = group_by_field.related_model else: @@ -419,15 +427,19 @@ def check_columns(cls, columns, group_by, report_model, ): parsed_columns = [] for col in columns: + options = {} + if type(col) is tuple: + col, options = col + if col in ['__time_series__', '__crosstab__']: # These are placeholder not real computation field continue magic_field_class = None - attr = None + attribute_field = None if type(col) is str: - attr = getattr(cls, col, None) + attribute_field = getattr(cls, col, None) elif issubclass(col, SlickReportField): magic_field_class = col @@ -436,12 +448,12 @@ def check_columns(cls, columns, group_by, report_model, ): except KeyError: magic_field_class = None - if attr: + if attribute_field: # todo Add testing here col_data = {'name': col, - 'verbose_name': getattr(attr, 'verbose_name', col), + 'verbose_name': getattr(attribute_field, 'verbose_name', col), # 'type': 'method', - 'ref': attr, + 'ref': attribute_field, 'type': 'text' } elif magic_field_class: @@ -473,6 +485,7 @@ def check_columns(cls, columns, group_by, report_model, ): 'ref': field, 'type': field.get_internal_type() } + col_data.update(options) parsed_columns.append(col_data) return parsed_columns @@ -704,4 +717,3 @@ def get_chart_settings(self, chart_settings=None, default_chart_title=None): x['engine_name'] = x.get('engine_name', SLICK_REPORTING_DEFAULT_CHARTS_ENGINE) output.append(x) return output - From a503247f77859119540016d739162935b0b64aed Mon Sep 17 00:00:00 2001 From: Ramez Date: Sun, 4 Sep 2022 10:59:57 +0200 Subject: [PATCH 2/9] Fix a bug with ra_highcharts displayChart todo: check chart_settings --- slick_reporting/static/slick_reporting/ra.highchart.js | 4 ++-- slick_reporting/views.py | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/slick_reporting/static/slick_reporting/ra.highchart.js b/slick_reporting/static/slick_reporting/ra.highchart.js index 6e848f7..5e10eb4 100644 --- a/slick_reporting/static/slick_reporting/ra.highchart.js +++ b/slick_reporting/static/slick_reporting/ra.highchart.js @@ -441,7 +441,7 @@ function displayChart(data, $elem, chart_id) { chart_id = chart_id || $elem.attr('data-report-default-chart') || ''; let chart = $elem; - let chartObject = getObjFromArray(data.chart_settings, 'id', chart_id, true); + // let chartObject = getObjFromArray(data.chart_settings, 'id', chart_id, true); try { let existing_chart = _chart_cache[data.report_slug]; @@ -452,7 +452,7 @@ console.error(e) } - chartObject = $.slick_reporting.highcharts.createChartObject(data, chartObject); + chartObject = $.slick_reporting.highcharts.createChartObject(data, chart_id); _chart_cache[data.report_slug] = chart.highcharts(chartObject); } diff --git a/slick_reporting/views.py b/slick_reporting/views.py index 93a8813..50fc7f8 100644 --- a/slick_reporting/views.py +++ b/slick_reporting/views.py @@ -236,3 +236,8 @@ def __init_subclass__(cls) -> None: cls.report_generator_class.check_columns(cls.columns, cls.group_by, cls.get_report_model()) super().__init_subclass__() + + @staticmethod + def check_chart_settings(chart_settings=None): + #todo check on chart settings + return From dc83eaf69fefca71eda04369865dbf16ecfb2114 Mon Sep 17 00:00:00 2001 From: Ramez Date: Tue, 6 Sep 2022 21:22:41 +0200 Subject: [PATCH 3/9] Changed get_initial to get_form_initial Added initial to report_form_factory WIP: added required to report form factory --- .travis.yml | 1 + CHANGELOG.md | 4 ++++ requirements.txt | 5 +++++ slick_reporting/form_factory.py | 18 +++++++++++++----- .../static/slick_reporting/ra.highchart.js | 6 +++--- slick_reporting/views.py | 8 ++++++-- tests/models.py | 2 +- 7 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 requirements.txt diff --git a/.travis.yml b/.travis.yml index 51475fa..46c67e5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,6 +10,7 @@ env: - DJANGO=django==3.1.8 - DJANGO=django==3.2 - DJANGO=django==4.0 + - DJANGO=django==4.1 matrix: exclude: diff --git a/CHANGELOG.md b/CHANGELOG.md index 77b1317..739e8f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ All notable changes to this project will be documented in this file. +## [0.6.4] +- Fix highchart cache to target the specific chart +- Added initial and required to report_form_factory + ## [0.6.3] - Change the deprecated in Django 4 `request.is_ajax` . diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..257d3e4 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +django>=2.2 +python-dateutil>=2.8.1 +pytz +simplejson +django-crispy-forms \ No newline at end of file diff --git a/slick_reporting/form_factory.py b/slick_reporting/form_factory.py index 3eee679..3dbc66e 100644 --- a/slick_reporting/form_factory.py +++ b/slick_reporting/form_factory.py @@ -97,7 +97,7 @@ def _default_foreign_key_widget(f_field): def report_form_factory(model, crosstab_model=None, display_compute_reminder=True, fkeys_filter_func=None, - foreign_key_widget_func=None, excluded_fields=None): + foreign_key_widget_func=None, excluded_fields=None, initial=None, required=None): """ Create a Report Form based on the report_model passed by 1. adding a start_date and end_date fields @@ -110,12 +110,16 @@ def report_form_factory(model, crosstab_model=None, display_compute_reminder=Tru :param fkeys_filter_func: a receives an OrderedDict of Foreign Keys names and their model field instances found on the model, return the OrderedDict that would be used :param foreign_key_widget_func: receives a Field class return the used widget like this {'form_class': forms.ModelMultipleChoiceField, 'required': False, } :param excluded_fields: a list of fields to be excluded from the report form + :param initial a dict for fields initial + :param required a list of fields that should be marked as required :return: """ foreign_key_widget_func = foreign_key_widget_func or _default_foreign_key_widget fkeys_filter_func = fkeys_filter_func or (lambda x: x) # gather foreign keys + initial = initial or {} + required = required or [] fkeys_map = get_foreign_keys(model) excluded_fields = excluded_fields or [] for excluded in excluded_fields: @@ -127,17 +131,21 @@ def report_form_factory(model, crosstab_model=None, display_compute_reminder=Tru fields = OrderedDict() fields['start_date'] = forms.DateTimeField(required=False, label=_('From date'), - initial=app_settings.SLICK_REPORTING_DEFAULT_START_DATE, + initial=initial.get('start_date', + app_settings.SLICK_REPORTING_DEFAULT_START_DATE), widget=forms.DateTimeInput(attrs={'autocomplete': "off"})) fields['end_date'] = forms.DateTimeField(required=False, label=_('To date'), - initial=app_settings.SLICK_REPORTING_DEFAULT_END_DATE, + initial=initial.get('end_date', + app_settings.SLICK_REPORTING_DEFAULT_END_DATE), widget=forms.DateTimeInput(attrs={'autocomplete': "off"})) for name, f_field in fkeys_map.items(): fkeys_list.append(name) - - fields[name] = f_field.formfield(**foreign_key_widget_func(f_field)) + field_attrs = foreign_key_widget_func(f_field) + if name in required: + field_attrs['required'] = True + fields[name] = f_field.formfield(**field_attrs) if crosstab_model and display_compute_reminder: fields['crosstab_compute_reminder'] = forms.BooleanField(required=False, diff --git a/slick_reporting/static/slick_reporting/ra.highchart.js b/slick_reporting/static/slick_reporting/ra.highchart.js index 5e10eb4..74706ae 100644 --- a/slick_reporting/static/slick_reporting/ra.highchart.js +++ b/slick_reporting/static/slick_reporting/ra.highchart.js @@ -442,9 +442,9 @@ chart_id = chart_id || $elem.attr('data-report-default-chart') || ''; let chart = $elem; // let chartObject = getObjFromArray(data.chart_settings, 'id', chart_id, true); - + let cache_key = data.report_slug + ':' + chart_id try { - let existing_chart = _chart_cache[data.report_slug]; + let existing_chart = _chart_cache[cache_key]; if (typeof (existing_chart) !== 'undefined') { existing_chart.highcharts().destroy() } @@ -453,7 +453,7 @@ } chartObject = $.slick_reporting.highcharts.createChartObject(data, chart_id); - _chart_cache[data.report_slug] = chart.highcharts(chartObject); + _chart_cache[cache_key] = chart.highcharts(chartObject); } diff --git a/slick_reporting/views.py b/slick_reporting/views.py index 50fc7f8..fc07ada 100644 --- a/slick_reporting/views.py +++ b/slick_reporting/views.py @@ -92,7 +92,10 @@ def get_form_class(self): """ return self.form_class or report_form_factory(self.get_report_model(), crosstab_model=self.crosstab_model, display_compute_reminder=self.crosstab_compute_reminder, - excluded_fields=self.excluded_fields) + excluded_fields=self.excluded_fields, + initial=self.get_form_initial(), + # required=self.required_fields + ) def get_form_kwargs(self): """ @@ -209,7 +212,8 @@ def filter_results(self, data, for_print=False): def get_report_slug(cls): return cls.__name__.lower() - def get_initial(self): + @staticmethod + def get_form_initial(): # todo revise why not actually displaying datetime on screen return { 'start_date': SLICK_REPORTING_DEFAULT_START_DATE, diff --git a/tests/models.py b/tests/models.py index 82f5f41..599346e 100644 --- a/tests/models.py +++ b/tests/models.py @@ -188,7 +188,7 @@ class Architect(models.Model): class Initiative(models.Model): - id = models.AutoField(primary_key=True, null=True) + id = models.AutoField(primary_key=True) # cx_pem = models.ForeignKey(ProjectEngineeringManager, on_delete=models.DO_NOTHING, # verbose_name="CX PEM:", null=True, # blank=True) From 22e5d92abef3c1ad57c9ad3ecf1583b877289b3a Mon Sep 17 00:00:00 2001 From: Ramez Date: Tue, 6 Sep 2022 21:29:57 +0200 Subject: [PATCH 4/9] Update travis --- .travis.yml | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 46c67e5..7b124aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,14 @@ language: python python: - - "3.7" - "3.8" - "3.9" + - "3.10" env: - - DJANGO=django==2.2.20 - - DJANGO=django==3.1.8 - - DJANGO=django==3.2 - - DJANGO=django==4.0 - - DJANGO=django==4.1 + - DJANGO=django==3.2.15 + - DJANGO=django==4.0.7 + - DJANGO=django==4.1.1 matrix: exclude: From 7be6c8f3f0dfb3ce4e7a944f2c5b50f9fda00613 Mon Sep 17 00:00:00 2001 From: Ramez Date: Thu, 8 Sep 2022 09:47:18 +0200 Subject: [PATCH 5/9] Added base_q_filters and base_kwargs_filters to SlickReportField to control the base queryset --- CHANGELOG.md | 1 + slick_reporting/fields.py | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 739e8f6..6eeb145 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [0.6.4] - Fix highchart cache to target the specific chart - Added initial and required to report_form_factory +- Added base_q_filters and base_kwargs_filters to SlickReportField to control the base queryset ## [0.6.3] diff --git a/slick_reporting/fields.py b/slick_reporting/fields.py index 3d59dce..d848e10 100644 --- a/slick_reporting/fields.py +++ b/slick_reporting/fields.py @@ -43,6 +43,9 @@ class SlickReportField(object): plus_side_q = None minus_side_q = None + base_kwargs_filters = None + base_q_filters = None + _require_classes = None _debit_and_credit = True @@ -126,6 +129,7 @@ def init_preparation(self, q_filters=None, kwargs_filters=None, **kwargs): self._cache = debit_results, credit_results, dep_values def prepare(self, q_filters=None, kwargs_filters=None, **kwargs): + # super(SlickReportField, self).prepare(q_filters, kwargs_filters, **kwargs) """ This is the first hook where you can customize the calculation away from the Django Query aggregation method This method et called with all available parameters , so you can prepare the results for the whole set and save @@ -163,6 +167,10 @@ def prepare(self, q_filters=None, kwargs_filters=None, **kwargs): def get_queryset(self): queryset = self.report_model.objects + if self.base_q_filters: + queryset = queryset.filter(*self.base_q_filters) + if self.base_kwargs_filters: + queryset = queryset.filter(**self.base_kwargs_filters) return queryset.order_by() def get_annotation_name(self): From 7b70c46cc072c89aa252a8e88b0689d91876f8f8 Mon Sep 17 00:00:00 2001 From: Ramez Ashraf Date: Thu, 8 Sep 2022 15:22:00 +0200 Subject: [PATCH 6/9] * Adds `prevent_group_by` option to SlickReportField Will prevent group by calculation for this specific field, serves when you want to compute overall results. * Support reference to SlickReportField class directly in `requires` instead of its "registered" name. * Adds PercentageToBalance report field --- slick_reporting/fields.py | 27 ++++++++++++++++++++++----- tests/report_generators.py | 12 ++++++++++-- tests/tests.py | 15 +++++++++------ 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/slick_reporting/fields.py b/slick_reporting/fields.py index d848e10..5568c70 100644 --- a/slick_reporting/fields.py +++ b/slick_reporting/fields.py @@ -49,6 +49,9 @@ class SlickReportField(object): _require_classes = None _debit_and_credit = True + prevent_group_by = False + """Will prevent group by calculation for this specific field, serves when you want to compute overall results""" + @classmethod def create(cls, method, field, name=None, verbose_name=None, is_summable=True): """ @@ -89,7 +92,7 @@ def __init__(self, plus_side_q=None, minus_side_q=None, self.requires = self.requires or [] self.group_by = self.group_by or group_by self._cache = None, None, None - self._require_classes = [field_registry.get_field_by_name(x) for x in self.requires] + self._require_classes = self._get_required_classes() if not self.plus_side_q and not self.minus_side_q: self._debit_and_credit = False @@ -97,7 +100,7 @@ def __init__(self, plus_side_q=None, minus_side_q=None, @classmethod def _get_required_classes(cls): requires = cls.requires or [] - return [field_registry.get_field_by_name(x) for x in requires] + return [field_registry.get_field_by_name(x) if type(x) is str else x for x in requires] def apply_q_plus_filter(self, qs): return qs.filter(*self.plus_side_q) @@ -142,6 +145,7 @@ def prepare(self, q_filters=None, kwargs_filters=None, **kwargs): :return: """ queryset = self.get_queryset() + group_by = '' if self.prevent_group_by else self.group_by if q_filters: queryset = queryset.filter(*q_filters) if kwargs_filters: @@ -149,7 +153,7 @@ def prepare(self, q_filters=None, kwargs_filters=None, **kwargs): if self.plus_side_q: queryset = self.apply_q_plus_filter(queryset) - debit_results = self.apply_aggregation(queryset, self.group_by) + debit_results = self.apply_aggregation(queryset, group_by) credit_results = None if self._debit_and_credit: @@ -161,7 +165,7 @@ def prepare(self, q_filters=None, kwargs_filters=None, **kwargs): if self.minus_side_q: queryset = self.apply_q_minus_filter(queryset) - credit_results = self.apply_aggregation(queryset, self.group_by) + credit_results = self.apply_aggregation(queryset, group_by) return debit_results, credit_results @@ -229,7 +233,7 @@ def _resolve_dependencies(self, current_obj): return dep_results def extract_data(self, cached, current_obj): - group_by = self.group_by + group_by = '' if self.prevent_group_by else self.group_by debit_value = 0 credit_value = 0 annotation = self.get_annotation_name() @@ -369,6 +373,19 @@ def final_calculation(self, debit, credit, dep_dict): field_registry.register(BalanceReportField) +class PercentageToBalance(SlickReportField): + requires = [BalanceReportField] + name = 'PercentageToBalance' + verbose_name = _('%') + + prevent_group_by = True + + def final_calculation(self, debit, credit, dep_dict): + obj_balance = dep_dict.get('__balance__') + total = debit - credit + return (obj_balance/total) * 100 + + class CreditReportField(SlickReportField): name = '__credit__' verbose_name = _('Credit') diff --git a/tests/report_generators.py b/tests/report_generators.py index c254656..4318e79 100644 --- a/tests/report_generators.py +++ b/tests/report_generators.py @@ -3,7 +3,7 @@ from django.db.models import Sum from django.utils.translation import gettext_lazy as _ -from slick_reporting.fields import SlickReportField +from slick_reporting.fields import SlickReportField, PercentageToBalance from slick_reporting.generator import ReportGenerator from .models import Client, SimpleSales, Product, SalesWithFlag from .models import OrderLine @@ -82,6 +82,15 @@ class ProductTotalSales(ReportGenerator): columns = ['slug', 'name', '__balance__', '__balance_quantity__'] +class ProductTotalSalesWithPercentage(ReportGenerator): + report_model = SimpleSales + date_field = 'doc_date' + group_by = 'client' + columns = ['slug', 'name', + '__balance__', + '__balance_quantity__', PercentageToBalance] + + class ClientList(ReportGenerator): report_title = _('Our Clients') @@ -94,7 +103,6 @@ class ClientList(ReportGenerator): class ProductClientSales(ReportGenerator): - base_model = Client report_model = SimpleSales report_slug = 'client_sales_of_products' diff --git a/tests/tests.py b/tests/tests.py index c6ce33c..af3028a 100644 --- a/tests/tests.py +++ b/tests/tests.py @@ -2,18 +2,17 @@ from django.contrib.auth import get_user_model from django.db.models import Count -from django.test import SimpleTestCase, TestCase, override_settings +from django.test import TestCase, override_settings from django.urls import reverse from django.utils.timezone import now -from slick_reporting.generator import ReportGenerator from slick_reporting.fields import SlickReportField, BalanceReportField +from slick_reporting.generator import ReportGenerator +from slick_reporting.registry import field_registry from tests.report_generators import ClientTotalBalance, ProductClientSalesMatrix2, GroupByCharField, \ GroupByCharFieldPlusTimeSeries, TimeSeriesWithOutGroupBy -from .models import Client, Contact, Product, SimpleSales, OrderLine, UserJoined, SalesWithFlag, ComplexSales, TaxCode from . import report_generators - -from slick_reporting.registry import field_registry +from .models import Client, Contact, Product, SimpleSales, UserJoined, SalesWithFlag, ComplexSales, TaxCode from .views import SlickReportView User = get_user_model() @@ -123,6 +122,11 @@ def test_product_total_sales(self): data = report.get_report_data() self.assertEqual(data[0]['__balance__'], 1800) + def test_product_total_sales_with_percentage(self): + report = report_generators.ProductTotalSalesWithPercentage() + data = report.get_report_data() + self.assertEqual(data[2]['PercentageToBalance'], 50) + @override_settings(SLICK_REPORTING_DEFAULT_START_DATE=datetime.datetime(2020, 1, 1), SLICK_REPORTING_DEFAULT_END_DATE=datetime.datetime(2021, 1, 1)) def test_product_total_sales_with_changed_dated(self): @@ -288,7 +292,6 @@ def test_crosstab_report_view(self): self.assertEqual(view_report_data['data'], data) def test_crosstab_report_view_clumns_on_fly(self): - from .report_generators import ProductClientSalesMatrix data = ProductClientSalesMatrix2(crosstab_compute_reminder=True, crosstab_ids=[self.client1.pk, self.client2.pk]).get_report_data() From 52770c2e35617a21bcc35990ce3333464cc75bde Mon Sep 17 00:00:00 2001 From: Ramez Ashraf Date: Fri, 9 Sep 2022 22:17:54 +0200 Subject: [PATCH 7/9] New release preparation --- .travis.yml | 1 - CHANGELOG.md | 6 +++++- slick_reporting/fields.py | 1 - slick_reporting/generator.py | 1 - 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7b124aa..2456eaa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,6 @@ language: python python: - "3.8" - "3.9" - - "3.10" env: - DJANGO=django==3.2.15 diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eeb145..cd3e7ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. ## [0.6.4] - Fix highchart cache to target the specific chart - Added initial and required to report_form_factory -- Added base_q_filters and base_kwargs_filters to SlickReportField to control the base queryset +- Added base_q_filters and base_kwargs_filters to SlickReportField to control the base queryset +- Add ability to customize ReportField on the fly +- Adds `prevent_group_by` option to SlickReportField Will prevent group by calculation for this specific field, serves when you want to compute overall results. +- Support reference to SlickReportField class directly in `requires` instead of its "registered" name. +- Adds PercentageToBalance report field ## [0.6.3] diff --git a/slick_reporting/fields.py b/slick_reporting/fields.py index 5568c70..1e86eab 100644 --- a/slick_reporting/fields.py +++ b/slick_reporting/fields.py @@ -132,7 +132,6 @@ def init_preparation(self, q_filters=None, kwargs_filters=None, **kwargs): self._cache = debit_results, credit_results, dep_values def prepare(self, q_filters=None, kwargs_filters=None, **kwargs): - # super(SlickReportField, self).prepare(q_filters, kwargs_filters, **kwargs) """ This is the first hook where you can customize the calculation away from the Django Query aggregation method This method et called with all available parameters , so you can prepare the results for the whole set and save diff --git a/slick_reporting/generator.py b/slick_reporting/generator.py index 2540013..2b597ae 100644 --- a/slick_reporting/generator.py +++ b/slick_reporting/generator.py @@ -449,7 +449,6 @@ def check_columns(cls, columns, group_by, report_model, ): magic_field_class = None if attribute_field: - # todo Add testing here col_data = {'name': col, 'verbose_name': getattr(attribute_field, 'verbose_name', col), # 'type': 'method', From 9f758485d909c4d96b3951fe39e0a794cbddd397 Mon Sep 17 00:00:00 2001 From: Ramez Ashraf Date: Tue, 24 Jan 2023 07:50:02 +0200 Subject: [PATCH 8/9] New release preparation --- docs/source/concept.rst | 4 ++-- tests/views.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/source/concept.rst b/docs/source/concept.rst index 2b1f814..0d8ccb3 100644 --- a/docs/source/concept.rst +++ b/docs/source/concept.rst @@ -3,7 +3,7 @@ Structure ========== -If you haven't, please check https://django-slick-reporting.com for a quick walk-though with live code examples.. +If you haven't yet, please check https://django-slick-reporting.com for a quick walk-though with live code examples.. And now, Let's explore the main components of Django Slick Reporting and what setting you can set on project level. @@ -11,7 +11,7 @@ Components ---------- -1. Result Field: represent a number, a calculation unit, for example: a Sum of a certain field. +1. Report Field: represent a number, a calculation unit, for example: a Sum of a certain field. The report field identifies how the calculation should be done. ResultFields can depend on each other. 2. Generator: Represent a concrete report structure.If it would group by certain field, do a time series or a cross tab, and which columns (Report Field) to be calculated. diff --git a/tests/views.py b/tests/views.py index 327d919..da3c66e 100644 --- a/tests/views.py +++ b/tests/views.py @@ -1,5 +1,5 @@ from slick_reporting.views import SlickReportView -from slick_reporting.fields import SlickReportField +from slick_reporting.fields import SlickReportField, TotalReportField from django.db.models import Sum, Count from .models import SimpleSales, ComplexSales from django.utils.translation import gettext_lazy as _ @@ -23,7 +23,7 @@ class ProductClientSalesMatrix(SlickReportView): columns = ['slug', 'name'] crosstab_model = 'client' - crosstab_columns = ['__total__'] + crosstab_columns = [TotalReportField] chart_settings = [ { @@ -61,7 +61,7 @@ class MonthlyProductSalesWQS(SlickReportView): group_by = 'client' columns = ['slug', 'name'] time_series_pattern = 'monthly' - time_series_columns = ['__total__', '__balance__'] + time_series_columns = [TotalReportField, '__balance__'] class TaxSales(SlickReportView): From b9e925fa70bf17de526406a5b23bb49401afe9ea Mon Sep 17 00:00:00 2001 From: Ramez Ashraf Date: Tue, 24 Jan 2023 07:53:37 +0200 Subject: [PATCH 9/9] Version bump --- docs/requirements.txt | 2 +- docs/source/conf.py | 2 +- slick_reporting/__init__.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/requirements.txt b/docs/requirements.txt index eded4f2..f0ffece 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,4 +1,4 @@ sphinx==4.2.0 sphinx_rtd_theme==1.0.0 readthedocs-sphinx-search==0.1.1 -django-slick-reporting==0.6.3 \ No newline at end of file +django-slick-reporting==0.6.4 \ No newline at end of file diff --git a/docs/source/conf.py b/docs/source/conf.py index 36ae840..f358cdd 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -27,7 +27,7 @@ master_doc = 'index' # The full version, including alpha/beta/rc tags -release = '0.6.3' +release = '0.6.4' # -- General configuration --------------------------------------------------- diff --git a/slick_reporting/__init__.py b/slick_reporting/__init__.py index 928efe3..b012eb3 100644 --- a/slick_reporting/__init__.py +++ b/slick_reporting/__init__.py @@ -1,5 +1,5 @@ default_app_config = 'slick_reporting.apps.ReportAppConfig' -VERSION = (0, 6, 3) +VERSION = (0, 6, 4) -__version__ = '0.6.3' +__version__ = '0.6.4'