More docs! w/ some emphasis on "reports" section
This commit is contained in:
parent
2072e41e19
commit
da9823324d
38 changed files with 358 additions and 71 deletions
6
docs/data/reports/autoemail.rst
Normal file
6
docs/data/reports/autoemail.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
====================
|
||||
Auto-Emailed Reports
|
||||
====================
|
||||
|
||||
TODO
|
81
docs/data/reports/custom.rst
Normal file
81
docs/data/reports/custom.rst
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
========================
|
||||
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.
|
6
docs/data/reports/generate.rst
Normal file
6
docs/data/reports/generate.rst
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
===================
|
||||
Generating a Report
|
||||
===================
|
||||
|
||||
TODO
|
19
docs/data/reports/handler.rst
Normal file
19
docs/data/reports/handler.rst
Normal file
|
@ -0,0 +1,19 @@
|
|||
|
||||
==============
|
||||
Report Handler
|
||||
==============
|
||||
|
||||
Each app will have exactly one "report handler" which is reponsible for the
|
||||
overall logic of running and emailing reports etc. It also determines which
|
||||
report types are available to be ran.
|
||||
|
||||
Rattail provides a default report handler so unless you have custom
|
||||
requirements, you will not need to define your own report handler. See the
|
||||
:class:`~rattail:rattail.reporting.handlers.ReportHandler` class for more
|
||||
details.
|
||||
|
||||
Programmatically you can access your report handler like so::
|
||||
|
||||
# assuming you already have config
|
||||
app = config.get_app()
|
||||
handler = app.get_report_handler()
|
13
docs/data/reports/index.rst
Normal file
13
docs/data/reports/index.rst
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
Reports
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
overview
|
||||
handler
|
||||
generate
|
||||
autoemail
|
||||
custom
|
28
docs/data/reports/overview.rst
Normal file
28
docs/data/reports/overview.rst
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
==========
|
||||
Overview
|
||||
==========
|
||||
|
||||
A report is conceptually just what you think it is, probably. But there are a
|
||||
few related concepts which we'll try to briefly outline here.
|
||||
|
||||
* report type
|
||||
* report handler
|
||||
* report output
|
||||
|
||||
First a "report type" refers to the logic for running a specific type of
|
||||
report. For example, "Daily Sales" or "Slow Movers" might be report types.
|
||||
This defines what sort of data is included on the report, how it is displayed
|
||||
etc. See :doc:`custom` for how to create a new report type.
|
||||
|
||||
Next, a "report handler" is responsible for overall logic used to orchestrate
|
||||
the running of all reports for the app. See :doc:`handler` for more on that.
|
||||
|
||||
Finally "report output" refers to the result of running a report. Generally
|
||||
speaking whenever a report runs, the details are saved to the DB for
|
||||
convenience and historical record. See :doc:`generate` for more on that.
|
||||
|
||||
It's perhaps worth noting, that in Rattail-speak "an email is not a report" and
|
||||
vice versa. Meaning, a report is a *generated document* and if sent via email,
|
||||
it will be an attachment as opposed to being part of the message body. See
|
||||
also :doc:`autoemail`.
|
Loading…
Add table
Add a link
Reference in a new issue