======================== 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.