Skip to content

Commit

Permalink
Merge branch 'release/v1.1.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
RamezIssac committed Sep 7, 2023
2 parents 4f2b949 + aa8af31 commit da57d62
Show file tree
Hide file tree
Showing 57 changed files with 1,750 additions and 1,019 deletions.
8 changes: 7 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ repos:
rev: 23.3.0
hooks:
- id: black
language_version: python3.9
language_version: python3.9

- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.0.287
hooks:
- id: ruff
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

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

## [1.1.0] -
- Breaking: changed ``report_title_context_key`` default value to `report_title`
- Breaking: Renamed simple_report.html to report.html
- Breaking: Renamed ``SlickReportField`` to ``ComputationField``. SlickReportField will continue to work till next release.
- Revised and renamed js files
- Add dashboard capabilities.
- Added auto_load option to ReportView
- Unified report loading to use the report loader
- Fix issue with group_by_custom_queryset with time series
- Fix issue with No group by report
- Fix issue with traversing fields not showing up on ListViewReport
- Fix issue with date filter not being respected in ListViewReport

## [1.0.2] - 2023-08-31
- Add a demo project for exploration and also containing all documentation code for proofing.
- Revise and Enhancing Tutorial , Group by and Time series documentation.
Expand Down
69 changes: 43 additions & 26 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,18 @@ Use the package manager `pip <https://pip.pypa.io/en/stable/>`_ to install djang
Usage
-----

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

You can simply use a code like this
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.

.. code-block:: python
# in your urls.py
path("path-to-report", TotalProductSales.as_view())
# in views.py
from django.db.models import Sum
from slick_reporting.views import ReportView, Chart
from slick_reporting.fields import SlickReportField
from slick_reporting.fields import ComputationField
from .models import MySalesItems
Expand All @@ -66,8 +64,8 @@ You can simply use a code like this
group_by = "product"
columns = [
"name",
SlickReportField.create(Sum, "quantity", verbose_name="Total quantity sold", is_summable=False),
SlickReportField.create(Sum, "value", name="sum__value", verbose_name="Total Value sold $"),
ComputationField.create(Sum, "quantity", verbose_name="Total quantity sold", is_summable=False),
ComputationField.create(Sum, "value", name="sum__value", verbose_name="Total Value sold $"),
]
chart_settings = [
Expand All @@ -85,7 +83,12 @@ You can simply use a code like this
),
]
To get something this
# then, in urls.py
path("total-sales-report", TotalProductSales.as_view())
With this code, you will get something like this:

.. image:: https://i.ibb.co/SvxTM23/Selection-294.png
:target: https://i.ibb.co/SvxTM23/Selection-294.png
Expand All @@ -95,29 +98,31 @@ To get something this
Time Series
-----------

A Time series report is a report that is generated for a periods of time.
The period can be daily, weekly, monthly, yearly or custom. Calculations will be performed for each period in the time series.

Example: How much was sold in value for each product monthly within a date period ?

.. code-block:: python
# in views.py
from slick_reporting.views import ReportView
from slick_reporting.fields import SlickReportField
from .models import MySalesItems
from slick_reporting.fields import ComputationField
from .models import SalesTransaction
class MonthlyProductSales(ReportView):
report_model = MySalesItems
date_field = "date_placed"
report_model = SalesTransaction
date_field = "date"
group_by = "product"
columns = ["name", "sku"]
# Settings for creating time series report
time_series_pattern = (
"monthly" # or "yearly" , "weekly" , "daily" , others and custom patterns
)
time_series_pattern = "monthly"
# or "yearly" , "weekly" , "daily" , others and custom patterns
time_series_columns = [
SlickReportField.create(
ComputationField.create(
Sum, "value", verbose_name=_("Sales Value"), name="value"
)
) # what will be calculated for each month
]
chart_settings = [
Expand All @@ -128,21 +133,29 @@ Time Series
title_source=["name"],
plot_total=True,
),
Chart("Total Sales [Area chart]",
Chart.AREA,
data_source=["value"],
title_source=["name"],
plot_total=False,
)
]
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/report_view/_static/timeseries.png?raw=true
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/topics/_static/timeseries.png?raw=true
:alt: Time Series Report
:align: center

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

.. code-block:: python
# in views.py
from slick_reporting.views import ReportView
from slick_reporting.fields import SlickReportField
from slick_reporting.fields import ComputationField
from .models import MySalesItems
Expand All @@ -151,7 +164,7 @@ Cross Tab
crosstab_field = "client"
crosstab_ids = [1, 2, 3]
crosstab_columns = [
SlickReportField.create(Sum, "value", verbose_name=_("Value for")),
ComputationField.create(Sum, "value", verbose_name=_("Value for")),
]
crosstab_compute_remainder = True
Expand All @@ -160,11 +173,11 @@ Cross Tab
# You can customize where the crosstab columns are displayed in relation to the other columns
"__crosstab__",
# 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
SlickReportField.create(Sum, "value", verbose_name=_("Total Value")),
ComputationField.create(Sum, "value", verbose_name=_("Total Value")),
]
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/report_view/_static/crosstab.png?raw=true
.. image:: https://github.com/ra-systems/django-slick-reporting/blob/develop/docs/source/topics/_static/crosstab.png?raw=true
:alt: Homepage
:align: center

Expand Down Expand Up @@ -207,9 +220,13 @@ You can also use locally
.. code-block:: console
# clone the repo
# create a virtual environment, activate it, then
git clone https://github.com/ra-systems/django-slick-reporting.git
# create a virtual environment and activate it
python -m venv /path/to/new/virtual/environment
source /path/to/new/virtual/environment/bin/activate
cd django-slick-reporting/demo_proj
pip install requirements.txt
pip install -r requirements.txt
python manage.py migrate
python manage.py create_entries
python manage.py runserver
Expand Down
1 change: 0 additions & 1 deletion demo_proj/demo_app/admin.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
from django.contrib import admin

# Register your models here.
51 changes: 51 additions & 0 deletions demo_proj/demo_app/helpers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from django.urls import path

from . import reports

TUTORIAL = [
("product-sales", reports.ProductSales),
("total-product-sales", reports.TotalProductSales),
("total-product-sales-by-country", reports.TotalProductSalesByCountry),
("monthly-product-sales", reports.MonthlyProductSales),
("product-sales-per-client-crosstab", reports.ProductSalesPerClientCrosstab),
("product-sales-per-country-crosstab", reports.ProductSalesPerCountryCrosstab),
("last-10-sales", reports.LastTenSales),
("total-product-sales-with-custom-form", reports.TotalProductSalesWithCustomForm),

]

GROUP_BY = [
("group-by-report", reports.GroupByReport),
("group-by-traversing-field", reports.GroupByTraversingFieldReport),
("group-by-custom-queryset", reports.GroupByCustomQueryset),
("no-group-by", reports.NoGroupByReport),
]

TIME_SERIES = [
("time-series-report", reports.TimeSeriesReport),
("time-series-with-selector", reports.TimeSeriesReportWithSelector),
("time-series-with-custom-dates", reports.TimeSeriesReportWithCustomDates),
("time-series-with-custom-dates-and-title", reports.TimeSeriesReportWithCustomDatesAndCustomTitle),
("time-series-without-group-by", reports.TimeSeriesWithoutGroupBy),
('time-series-with-group-by-custom-queryset', reports.TimeSeriesReportWithCustomGroupByQueryset),
]

CROSSTAB = [
("crosstab-report", reports.CrosstabReport),
("crosstab-report-with-ids", reports.CrosstabWithIds),
("crosstab-report-traversing-field", reports.CrosstabWithTraversingField),
("crosstab-report-custom-filter", reports.CrosstabWithIdsCustomFilter),
("crosstab-report-custom-verbose-name", reports.CrossTabReportWithCustomVerboseName),
("crosstab-report-custom-verbose-name-2", reports.CrossTabReportWithCustomVerboseNameCustomFilter),
("crosstab-report-with-time-series", reports.CrossTabWithTimeSeries),

]


def get_urls_patterns():
urls = []
for name, report in TUTORIAL + GROUP_BY + TIME_SERIES + CROSSTAB:
urls.append(path(f"{name}/", report.as_view(), name=name))
return urls


6 changes: 1 addition & 5 deletions demo_proj/demo_app/management/commands/create_entries.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ class Command(BaseCommand):

def handle(self, *args, **options):
# create clients
models_list = [
Client,
Product,
]
client_countries = [
"US",
"DE",
Expand All @@ -48,7 +44,7 @@ def handle(self, *args, **options):
for i in range(10):
User.objects.create_user(username=f"user {i}", password="password")

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

Expand Down
24 changes: 24 additions & 0 deletions demo_proj/demo_app/migrations/0004_client_country_product_sku.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 4.2.4 on 2023-08-30 08:38

from django.db import migrations, models
import uuid


class Migration(migrations.Migration):

dependencies = [
('demo_app', '0003_product_category'),
]

operations = [
migrations.AddField(
model_name='client',
name='country',
field=models.CharField(default='US', max_length=255, verbose_name='Country'),
),
migrations.AddField(
model_name='product',
name='sku',
field=models.CharField(default=uuid.uuid4, max_length=255, verbose_name='SKU'),
),
]
18 changes: 18 additions & 0 deletions demo_proj/demo_app/migrations/0005_product_size.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 4.2.4 on 2023-08-30 11:24

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('demo_app', '0004_client_country_product_sku'),
]

operations = [
migrations.AddField(
model_name='product',
name='size',
field=models.CharField(default='Medium', max_length=100, verbose_name='Product Category'),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Generated by Django 4.2.4 on 2023-08-30 17:57

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('demo_app', '0005_product_size'),
]

operations = [
migrations.CreateModel(
name='ProductCategory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100, verbose_name='Product Category Name')),
],
),
migrations.RemoveField(
model_name='product',
name='category',
),
migrations.AlterField(
model_name='product',
name='size',
field=models.CharField(default='Medium', max_length=100, verbose_name='Size'),
),
migrations.AddField(
model_name='product',
name='product_category',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='demo_app.productcategory'),
),
]

0 comments on commit da57d62

Please sign in to comment.