Skip to content

Commit da57d62

Browse files
committed
Merge branch 'release/v1.1.0'
2 parents 4f2b949 + aa8af31 commit da57d62

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+1750
-1019
lines changed

.pre-commit-config.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,10 @@ repos:
1111
rev: 23.3.0
1212
hooks:
1313
- id: black
14-
language_version: python3.9
14+
language_version: python3.9
15+
16+
- repo: https://github.com/astral-sh/ruff-pre-commit
17+
# Ruff version.
18+
rev: v0.0.287
19+
hooks:
20+
- id: ruff

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## [1.1.0] -
6+
- Breaking: changed ``report_title_context_key`` default value to `report_title`
7+
- Breaking: Renamed simple_report.html to report.html
8+
- Breaking: Renamed ``SlickReportField`` to ``ComputationField``. SlickReportField will continue to work till next release.
9+
- Revised and renamed js files
10+
- Add dashboard capabilities.
11+
- Added auto_load option to ReportView
12+
- Unified report loading to use the report loader
13+
- Fix issue with group_by_custom_queryset with time series
14+
- Fix issue with No group by report
15+
- Fix issue with traversing fields not showing up on ListViewReport
16+
- Fix issue with date filter not being respected in ListViewReport
17+
518
## [1.0.2] - 2023-08-31
619
- Add a demo project for exploration and also containing all documentation code for proofing.
720
- Revise and Enhancing Tutorial , Group by and Time series documentation.

README.rst

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,18 @@ Use the package manager `pip <https://pip.pypa.io/en/stable/>`_ to install djang
4343
Usage
4444
-----
4545

46-
So you have a model that contains data, let's call it `MySalesItems`
46+
So we have a model `SalesTransaction` which contains typical data about a sale.
47+
We can extract different kinds of information for that model.
4748

48-
You can simply use a code like this
49+
Let's start by a "Group by" report. This will generate a report how much quantity and value was each product sold within a certain time.
4950

5051
.. code-block:: python
5152
52-
# in your urls.py
53-
path("path-to-report", TotalProductSales.as_view())
54-
5553
5654
# in views.py
5755
from django.db.models import Sum
5856
from slick_reporting.views import ReportView, Chart
59-
from slick_reporting.fields import SlickReportField
57+
from slick_reporting.fields import ComputationField
6058
from .models import MySalesItems
6159
6260
@@ -66,8 +64,8 @@ You can simply use a code like this
6664
group_by = "product"
6765
columns = [
6866
"name",
69-
SlickReportField.create(Sum, "quantity", verbose_name="Total quantity sold", is_summable=False),
70-
SlickReportField.create(Sum, "value", name="sum__value", verbose_name="Total Value sold $"),
67+
ComputationField.create(Sum, "quantity", verbose_name="Total quantity sold", is_summable=False),
68+
ComputationField.create(Sum, "value", name="sum__value", verbose_name="Total Value sold $"),
7169
]
7270
7371
chart_settings = [
@@ -85,7 +83,12 @@ You can simply use a code like this
8583
),
8684
]
8785
88-
To get something this
86+
# then, in urls.py
87+
path("total-sales-report", TotalProductSales.as_view())
88+
89+
90+
91+
With this code, you will get something like this:
8992

9093
.. image:: https://i.ibb.co/SvxTM23/Selection-294.png
9194
:target: https://i.ibb.co/SvxTM23/Selection-294.png
@@ -95,29 +98,31 @@ To get something this
9598
Time Series
9699
-----------
97100

101+
A Time series report is a report that is generated for a periods of time.
102+
The period can be daily, weekly, monthly, yearly or custom. Calculations will be performed for each period in the time series.
103+
104+
Example: How much was sold in value for each product monthly within a date period ?
98105

99106
.. code-block:: python
100107
101108
# in views.py
102109
from slick_reporting.views import ReportView
103-
from slick_reporting.fields import SlickReportField
104-
from .models import MySalesItems
110+
from slick_reporting.fields import ComputationField
111+
from .models import SalesTransaction
105112
106113
107114
class MonthlyProductSales(ReportView):
108-
report_model = MySalesItems
109-
date_field = "date_placed"
115+
report_model = SalesTransaction
116+
date_field = "date"
110117
group_by = "product"
111118
columns = ["name", "sku"]
112119
113-
# Settings for creating time series report
114-
time_series_pattern = (
115-
"monthly" # or "yearly" , "weekly" , "daily" , others and custom patterns
116-
)
120+
time_series_pattern = "monthly"
121+
# or "yearly" , "weekly" , "daily" , others and custom patterns
117122
time_series_columns = [
118-
SlickReportField.create(
123+
ComputationField.create(
119124
Sum, "value", verbose_name=_("Sales Value"), name="value"
120-
)
125+
) # what will be calculated for each month
121126
]
122127
123128
chart_settings = [
@@ -128,21 +133,29 @@ Time Series
128133
title_source=["name"],
129134
plot_total=True,
130135
),
136+
Chart("Total Sales [Area chart]",
137+
Chart.AREA,
138+
data_source=["value"],
139+
title_source=["name"],
140+
plot_total=False,
141+
)
131142
]
132143
133144
134-
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/report_view/_static/timeseries.png?raw=true
145+
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/topics/_static/timeseries.png?raw=true
135146
:alt: Time Series Report
136147
:align: center
137148

138149
Cross Tab
139150
---------
151+
Use crosstab reports, also known as matrix reports, to show the relationships between three or more query items.
152+
Crosstab reports show data in rows and columns with information summarized at the intersection points.
140153

141154
.. code-block:: python
142155
143156
# in views.py
144157
from slick_reporting.views import ReportView
145-
from slick_reporting.fields import SlickReportField
158+
from slick_reporting.fields import ComputationField
146159
from .models import MySalesItems
147160
148161
@@ -151,7 +164,7 @@ Cross Tab
151164
crosstab_field = "client"
152165
crosstab_ids = [1, 2, 3]
153166
crosstab_columns = [
154-
SlickReportField.create(Sum, "value", verbose_name=_("Value for")),
167+
ComputationField.create(Sum, "value", verbose_name=_("Value for")),
155168
]
156169
crosstab_compute_remainder = True
157170
@@ -160,11 +173,11 @@ Cross Tab
160173
# You can customize where the crosstab columns are displayed in relation to the other columns
161174
"__crosstab__",
162175
# This is the same as the Same as the calculation in the crosstab, but this one will be on the whole set. IE total value
163-
SlickReportField.create(Sum, "value", verbose_name=_("Total Value")),
176+
ComputationField.create(Sum, "value", verbose_name=_("Total Value")),
164177
]
165178
166179
167-
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/report_view/_static/crosstab.png?raw=true
180+
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/topics/_static/crosstab.png?raw=true
168181
:alt: Homepage
169182
:align: center
170183

@@ -207,9 +220,13 @@ You can also use locally
207220
.. code-block:: console
208221
209222
# clone the repo
210-
# create a virtual environment, activate it, then
223+
git clone https://github.com/ra-systems/django-slick-reporting.git
224+
# create a virtual environment and activate it
225+
python -m venv /path/to/new/virtual/environment
226+
source /path/to/new/virtual/environment/bin/activate
227+
211228
cd django-slick-reporting/demo_proj
212-
pip install requirements.txt
229+
pip install -r requirements.txt
213230
python manage.py migrate
214231
python manage.py create_entries
215232
python manage.py runserver

demo_proj/demo_app/admin.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
from django.contrib import admin
21

32
# Register your models here.

demo_proj/demo_app/helpers.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from django.urls import path
2+
3+
from . import reports
4+
5+
TUTORIAL = [
6+
("product-sales", reports.ProductSales),
7+
("total-product-sales", reports.TotalProductSales),
8+
("total-product-sales-by-country", reports.TotalProductSalesByCountry),
9+
("monthly-product-sales", reports.MonthlyProductSales),
10+
("product-sales-per-client-crosstab", reports.ProductSalesPerClientCrosstab),
11+
("product-sales-per-country-crosstab", reports.ProductSalesPerCountryCrosstab),
12+
("last-10-sales", reports.LastTenSales),
13+
("total-product-sales-with-custom-form", reports.TotalProductSalesWithCustomForm),
14+
15+
]
16+
17+
GROUP_BY = [
18+
("group-by-report", reports.GroupByReport),
19+
("group-by-traversing-field", reports.GroupByTraversingFieldReport),
20+
("group-by-custom-queryset", reports.GroupByCustomQueryset),
21+
("no-group-by", reports.NoGroupByReport),
22+
]
23+
24+
TIME_SERIES = [
25+
("time-series-report", reports.TimeSeriesReport),
26+
("time-series-with-selector", reports.TimeSeriesReportWithSelector),
27+
("time-series-with-custom-dates", reports.TimeSeriesReportWithCustomDates),
28+
("time-series-with-custom-dates-and-title", reports.TimeSeriesReportWithCustomDatesAndCustomTitle),
29+
("time-series-without-group-by", reports.TimeSeriesWithoutGroupBy),
30+
('time-series-with-group-by-custom-queryset', reports.TimeSeriesReportWithCustomGroupByQueryset),
31+
]
32+
33+
CROSSTAB = [
34+
("crosstab-report", reports.CrosstabReport),
35+
("crosstab-report-with-ids", reports.CrosstabWithIds),
36+
("crosstab-report-traversing-field", reports.CrosstabWithTraversingField),
37+
("crosstab-report-custom-filter", reports.CrosstabWithIdsCustomFilter),
38+
("crosstab-report-custom-verbose-name", reports.CrossTabReportWithCustomVerboseName),
39+
("crosstab-report-custom-verbose-name-2", reports.CrossTabReportWithCustomVerboseNameCustomFilter),
40+
("crosstab-report-with-time-series", reports.CrossTabWithTimeSeries),
41+
42+
]
43+
44+
45+
def get_urls_patterns():
46+
urls = []
47+
for name, report in TUTORIAL + GROUP_BY + TIME_SERIES + CROSSTAB:
48+
urls.append(path(f"{name}/", report.as_view(), name=name))
49+
return urls
50+
51+

demo_proj/demo_app/management/commands/create_entries.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ class Command(BaseCommand):
2121

2222
def handle(self, *args, **options):
2323
# create clients
24-
models_list = [
25-
Client,
26-
Product,
27-
]
2824
client_countries = [
2925
"US",
3026
"DE",
@@ -48,7 +44,7 @@ def handle(self, *args, **options):
4844
for i in range(10):
4945
User.objects.create_user(username=f"user {i}", password="password")
5046

51-
users_id = list(User.objects.values_list("id", flat=True))
47+
list(User.objects.values_list("id", flat=True))
5248
for i in range(1, 4):
5349
ProductCategory.objects.create(name=f"Product Category {i}")
5450

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Generated by Django 4.2.4 on 2023-08-30 08:38
2+
3+
from django.db import migrations, models
4+
import uuid
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('demo_app', '0003_product_category'),
11+
]
12+
13+
operations = [
14+
migrations.AddField(
15+
model_name='client',
16+
name='country',
17+
field=models.CharField(default='US', max_length=255, verbose_name='Country'),
18+
),
19+
migrations.AddField(
20+
model_name='product',
21+
name='sku',
22+
field=models.CharField(default=uuid.uuid4, max_length=255, verbose_name='SKU'),
23+
),
24+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.2.4 on 2023-08-30 11:24
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('demo_app', '0004_client_country_product_sku'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='product',
15+
name='size',
16+
field=models.CharField(default='Medium', max_length=100, verbose_name='Product Category'),
17+
),
18+
]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# Generated by Django 4.2.4 on 2023-08-30 17:57
2+
3+
from django.db import migrations, models
4+
import django.db.models.deletion
5+
6+
7+
class Migration(migrations.Migration):
8+
9+
dependencies = [
10+
('demo_app', '0005_product_size'),
11+
]
12+
13+
operations = [
14+
migrations.CreateModel(
15+
name='ProductCategory',
16+
fields=[
17+
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
18+
('name', models.CharField(max_length=100, verbose_name='Product Category Name')),
19+
],
20+
),
21+
migrations.RemoveField(
22+
model_name='product',
23+
name='category',
24+
),
25+
migrations.AlterField(
26+
model_name='product',
27+
name='size',
28+
field=models.CharField(default='Medium', max_length=100, verbose_name='Size'),
29+
),
30+
migrations.AddField(
31+
model_name='product',
32+
name='product_category',
33+
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='demo_app.productcategory'),
34+
),
35+
]

0 commit comments

Comments
 (0)