82 lines
2.5 KiB
ReStructuredText
82 lines
2.5 KiB
ReStructuredText
|
|
||
|
========================
|
||
|
Adding a Custom Report
|
||
|
========================
|
||
|
|
||
|
We'll start with a simple report which shows all departments and the number of
|
||
|
products for each.
|
||
|
|
||
|
Each type of report has a "key" which uniquely identifies it. For this example
|
||
|
we'll use ``poser_dept_prod_counts`` for the key. Note that it's a good idea
|
||
|
to always use an app-specific prefix (e.g. ``poser_``) in the key.
|
||
|
|
||
|
Typically you will create a new Python module which is named according to the
|
||
|
key. Here we'll create ``~/src/poser/poser/reports/dept_prod_counts.py``, and
|
||
|
in it we'll define the report::
|
||
|
|
||
|
from sqlalchemy import orm
|
||
|
|
||
|
from rattail.reporting import ExcelReport
|
||
|
|
||
|
|
||
|
class DepartmentProductCounts(ExcelReport):
|
||
|
"""
|
||
|
Shows all departments and the number of products for each.
|
||
|
"""
|
||
|
type_key = 'poser_dept_prod_counts'
|
||
|
name = "Department Product Counts"
|
||
|
output_fields = [
|
||
|
'department_number',
|
||
|
'department_name',
|
||
|
'product_count',
|
||
|
]
|
||
|
|
||
|
def make_data(self, session, params, progress=None, **kwargs):
|
||
|
model = self.model
|
||
|
|
||
|
# fetch all departments, with product lists pre-loaded
|
||
|
departments = session.query(model.Department)\
|
||
|
.order_by(model.Department.number)\
|
||
|
.options(orm.joinedload(model.Department.products))\
|
||
|
.all()
|
||
|
rows = []
|
||
|
|
||
|
def add_row(department, i):
|
||
|
rows.append({
|
||
|
'department_number': department.number,
|
||
|
'department_name': department.name,
|
||
|
'product_count': len(department.products),
|
||
|
})
|
||
|
|
||
|
self.progress_loop(add_row, departments, progress,
|
||
|
message="Fetching data for report")
|
||
|
return rows
|
||
|
|
||
|
Then you must register your new report type, to make it available to the app.
|
||
|
This is done within your project's ``setup.py`` file, for instance::
|
||
|
|
||
|
setup(
|
||
|
name = "Poser",
|
||
|
|
||
|
# ...
|
||
|
|
||
|
entry_points = {
|
||
|
|
||
|
'rattail.reports': [
|
||
|
'poser_dept_prod_counts = poser.reports.dept_prod_counts:DepartmentProductCounts',
|
||
|
],
|
||
|
},
|
||
|
)
|
||
|
|
||
|
Once you've added that you must re-install the app to your virtual environment,
|
||
|
for instance:
|
||
|
|
||
|
.. code-block:: sh
|
||
|
|
||
|
cd /srv/envs/poser
|
||
|
source bin/activate
|
||
|
pip install -e ~/src/poser
|
||
|
|
||
|
At this point the report should be available for running within the app. See
|
||
|
:doc:`generate` for more info.
|