Refactors core reporting bits into a reporting package
This commit is contained in:
		
							parent
							
								
									fb022bbc7b
								
							
						
					
					
						commit
						86d1ab7160
					
				
					 3 changed files with 93 additions and 85 deletions
				
			
		
							
								
								
									
										0
									
								
								registrasion/reporting/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								registrasion/reporting/__init__.py
									
										
									
									
									
										Normal file
									
								
							
							
								
								
									
										89
									
								
								registrasion/reporting/reports.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								registrasion/reporting/reports.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | ||||||
|  | from collections import namedtuple | ||||||
|  | 
 | ||||||
|  | from django.contrib.auth.decorators import user_passes_test | ||||||
|  | from django.core.urlresolvers import reverse | ||||||
|  | from django.db import models | ||||||
|  | from django.db.models import F, Q | ||||||
|  | from django.db.models import Sum | ||||||
|  | from django.db.models import Case, When, Value | ||||||
|  | from django.http import Http404 | ||||||
|  | from django.shortcuts import render | ||||||
|  | from functools import wraps | ||||||
|  | 
 | ||||||
|  | from registrasion import forms | ||||||
|  | from registrasion import views | ||||||
|  | from registrasion.models import commerce | ||||||
|  | from registrasion.models import inventory | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | ''' A list of report views objects that can be used to load a list of | ||||||
|  | reports. ''' | ||||||
|  | _all_report_views = [] | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | class Report(object): | ||||||
|  | 
 | ||||||
|  |     def __init__(self, title, headings, data): | ||||||
|  |         self._headings = headings | ||||||
|  |         self._data = data | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def title(self): | ||||||
|  |         ''' Returns the title for this report. ''' | ||||||
|  |         return self._title | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def headings(self): | ||||||
|  |         ''' Returns the headings for the table. ''' | ||||||
|  |         return self._headings | ||||||
|  | 
 | ||||||
|  |     @property | ||||||
|  |     def data(self): | ||||||
|  |         ''' Returns the data rows for the table. ''' | ||||||
|  |         return self._data | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def report_view(title, form_type): | ||||||
|  |     ''' Decorator that converts a report view function into something that | ||||||
|  |     displays a Report. | ||||||
|  | 
 | ||||||
|  |     Arguments: | ||||||
|  |         title (str): | ||||||
|  |             The title of the report. | ||||||
|  |         form_type: | ||||||
|  |             A form class that can make this report display things. | ||||||
|  | 
 | ||||||
|  |     ''' | ||||||
|  | 
 | ||||||
|  |     def _report(view): | ||||||
|  | 
 | ||||||
|  |         @wraps(view) | ||||||
|  |         @user_passes_test(views._staff_only) | ||||||
|  |         def inner_view(request, *a, **k): | ||||||
|  | 
 | ||||||
|  |             form = form_type(request.GET) | ||||||
|  |             if form.is_valid() and form.has_changed(): | ||||||
|  |                 report = view(request, form, *a, **k) | ||||||
|  |             else: | ||||||
|  |                 report = None | ||||||
|  | 
 | ||||||
|  |             ctx = { | ||||||
|  |                 "title": title, | ||||||
|  |                 "form": form, | ||||||
|  |                 "report": report, | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return render(request, "registrasion/report.html", ctx) | ||||||
|  | 
 | ||||||
|  |         # Add this report to the list of reports -- makes this reversable. | ||||||
|  |         _all_report_views.append(inner_view) | ||||||
|  | 
 | ||||||
|  |         # Return the callable | ||||||
|  |         return inner_view | ||||||
|  |     return _report | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def get_all_reports(): | ||||||
|  |     ''' Returns all the views that have been registered with @report ''' | ||||||
|  | 
 | ||||||
|  |     return list(_all_report_views) | ||||||
|  | @ -16,87 +16,8 @@ from functools import wraps | ||||||
| from models import commerce | from models import commerce | ||||||
| from models import inventory | from models import inventory | ||||||
| 
 | 
 | ||||||
| 
 | from reporting.reports import Report | ||||||
| ''' | from reporting.reports import report_view | ||||||
| 
 |  | ||||||
| All reports must be viewable by staff only (permissions?) |  | ||||||
| 
 |  | ||||||
| Reports can have: |  | ||||||
| 
 |  | ||||||
| A form |  | ||||||
|  * Reports are all *gettable* - you can save a URL and get back to the same |  | ||||||
|  report |  | ||||||
|  * Fetching a report *cannot* break the underlying data. |  | ||||||
| A table |  | ||||||
|  * Headings |  | ||||||
|  * Data lines |  | ||||||
|  * Formats are pluggable |  | ||||||
| 
 |  | ||||||
| ''' |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| class Report(object): |  | ||||||
| 
 |  | ||||||
|     def __init__(self, title, headings, data): |  | ||||||
|         self._headings = headings |  | ||||||
|         self._data = data |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def title(self): |  | ||||||
|         ''' Returns the title for this report. ''' |  | ||||||
|         return self._title |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def headings(self): |  | ||||||
|         ''' Returns the headings for the table. ''' |  | ||||||
|         return self._headings |  | ||||||
| 
 |  | ||||||
|     @property |  | ||||||
|     def data(self): |  | ||||||
|         ''' Returns the data rows for the table. ''' |  | ||||||
|         return self._data |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| ''' A list of report views objects that can be used to load a list of |  | ||||||
| reports. ''' |  | ||||||
| _all_report_views = [] |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| def report(title, form_type): |  | ||||||
|     ''' Decorator that converts a report view function into something that |  | ||||||
|     displays a Report. |  | ||||||
| 
 |  | ||||||
|     Arguments: |  | ||||||
|         form_type: A form class that can make this report display things. |  | ||||||
| 
 |  | ||||||
|     ''' |  | ||||||
| 
 |  | ||||||
|     def _report(view): |  | ||||||
| 
 |  | ||||||
|         @wraps(view) |  | ||||||
|         @user_passes_test(views._staff_only) |  | ||||||
|         def inner_view(request, *a, **k): |  | ||||||
| 
 |  | ||||||
|             form = form_type(request.GET) |  | ||||||
|             if form.is_valid() and form.has_changed(): |  | ||||||
|                 report = view(request, form, *a, **k) |  | ||||||
|             else: |  | ||||||
|                 report = None |  | ||||||
| 
 |  | ||||||
|             ctx = { |  | ||||||
|                 "title": title, |  | ||||||
|                 "form": form, |  | ||||||
|                 "report": report, |  | ||||||
|             } |  | ||||||
| 
 |  | ||||||
|             return render(request, "registrasion/report.html", ctx) |  | ||||||
| 
 |  | ||||||
|         # Add this report to the list of reports -- makes this reversable. |  | ||||||
|         _all_report_views.append(inner_view) |  | ||||||
| 
 |  | ||||||
|         # Return the callable |  | ||||||
|         return inner_view |  | ||||||
|     return _report |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @user_passes_test(views._staff_only) | @user_passes_test(views._staff_only) | ||||||
|  | @ -118,15 +39,13 @@ def reports_list(request): | ||||||
|         "reports" : reports, |         "reports" : reports, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     print reports |  | ||||||
| 
 |  | ||||||
|     return render(request, "registrasion/reports_list.html", ctx) |     return render(request, "registrasion/reports_list.html", ctx) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| # Report functions | # Report functions | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @report("Paid items", forms.ProductAndCategoryForm) | @report_view("Paid items", forms.ProductAndCategoryForm) | ||||||
| def items_sold(request, form): | def items_sold(request, form): | ||||||
|     ''' Summarises the items sold and discounts granted for a given set of |     ''' Summarises the items sold and discounts granted for a given set of | ||||||
|     products, or products from categories. ''' |     products, or products from categories. ''' | ||||||
|  | @ -172,7 +91,7 @@ def items_sold(request, form): | ||||||
|     return Report("Paid items", headings, data) |     return Report("Paid items", headings, data) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @report("Inventory", forms.ProductAndCategoryForm) | @report_view("Inventory", forms.ProductAndCategoryForm) | ||||||
| def inventory(request, form): | def inventory(request, form): | ||||||
|     ''' Summarises the inventory status of the given items, grouping by |     ''' Summarises the inventory status of the given items, grouping by | ||||||
|     invoice status. ''' |     invoice status. ''' | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Christopher Neugebauer
						Christopher Neugebauer