81 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			81 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.
 | 
