parent
							
								
									e3b662fb67
								
							
						
					
					
						commit
						2ed0a47f15
					
				
					 3 changed files with 119 additions and 4 deletions
				
			
		|  | @ -29,3 +29,22 @@ class UserIdForm(forms.Form): | ||||||
|         label="User ID", |         label="User ID", | ||||||
|         required=False, |         required=False, | ||||||
|     ) |     ) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | def model_fields_form_factory(model): | ||||||
|  |     ''' Creates a form for specifying fields from a model to display. ''' | ||||||
|  | 
 | ||||||
|  |     fields = model._meta.get_fields() | ||||||
|  | 
 | ||||||
|  |     choices = [] | ||||||
|  |     for field in fields: | ||||||
|  |         if hasattr(field, "verbose_name"): | ||||||
|  |             choices.append((field.name, field.verbose_name)) | ||||||
|  | 
 | ||||||
|  |     class ModelFieldsForm(forms.Form): | ||||||
|  |         fields = forms.MultipleChoiceField( | ||||||
|  |             choices=choices, | ||||||
|  |             required=False, | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |     return ModelFieldsForm | ||||||
|  |  | ||||||
|  | @ -364,6 +364,12 @@ def credit_notes(request, form): | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | class AttendeeListReport(ListReport): | ||||||
|  | 
 | ||||||
|  |     def get_link(self, argument): | ||||||
|  |         return reverse(self._link_view) + "?user=%d" % int(argument) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| @report_view("Attendee", form_type=forms.UserIdForm) | @report_view("Attendee", form_type=forms.UserIdForm) | ||||||
| def attendee(request, form, user_id=None): | def attendee(request, form, user_id=None): | ||||||
|     ''' Returns a list of all manifested attendees if no attendee is specified, |     ''' Returns a list of all manifested attendees if no attendee is specified, | ||||||
|  | @ -484,9 +490,98 @@ def attendee_list(request): | ||||||
|     # Sort by whether they've registered, then ID. |     # Sort by whether they've registered, then ID. | ||||||
|     data.sort(key=lambda a: (-a[3], a[0])) |     data.sort(key=lambda a: (-a[3], a[0])) | ||||||
| 
 | 
 | ||||||
|     class Report(ListReport): |     return AttendeeListReport("Attendees", headings, data, link_view=attendee) | ||||||
| 
 | 
 | ||||||
|         def get_link(self, argument): |  | ||||||
|             return reverse(self._link_view) + "?user=%d" % int(argument) |  | ||||||
| 
 | 
 | ||||||
|     return Report("Attendees", headings, data, link_view=attendee) | ProfileForm = forms.model_fields_form_factory(AttendeeProfile) | ||||||
|  | class ProductCategoryProfileForm(forms.ProductAndCategoryForm, ProfileForm): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @report_view( | ||||||
|  |     "Attendees By Product/Category", | ||||||
|  |     form_type=ProductCategoryProfileForm, | ||||||
|  | ) | ||||||
|  | def attendee_data(request, form, user_id=None): | ||||||
|  |     ''' Lists attendees for a given product/category selection along with | ||||||
|  |     profile data.''' | ||||||
|  | 
 | ||||||
|  |     status_display = { | ||||||
|  |         commerce.Cart.STATUS_ACTIVE: "Unpaid", | ||||||
|  |         commerce.Cart.STATUS_PAID: "Paid", | ||||||
|  |         commerce.Cart.STATUS_RELEASED: "Refunded", | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     output = [] | ||||||
|  | 
 | ||||||
|  |     products = form.cleaned_data["product"] | ||||||
|  |     categories = form.cleaned_data["category"] | ||||||
|  |     fields = form.cleaned_data["fields"] | ||||||
|  |     name_field = AttendeeProfile.name_field() | ||||||
|  | 
 | ||||||
|  |     items = commerce.ProductItem.objects.filter( | ||||||
|  |         Q(product__in=products) | Q(product__category__in=categories), | ||||||
|  |     ).exclude( | ||||||
|  |         cart__status=commerce.Cart.STATUS_RELEASED | ||||||
|  |     ).select_related( | ||||||
|  |         "cart", "product" | ||||||
|  |     ).order_by("cart__status") | ||||||
|  | 
 | ||||||
|  |     # Get all of the relevant attendee profiles in one hit. | ||||||
|  |     profiles = AttendeeProfile.objects.filter( | ||||||
|  |         attendee__user__cart__productitem__in=items | ||||||
|  |     ).select_related("attendee__user") | ||||||
|  |     by_user = {} | ||||||
|  |     for profile in profiles: | ||||||
|  |         by_user[profile.attendee.user] = profile | ||||||
|  | 
 | ||||||
|  |     for field in fields: | ||||||
|  |         field_verbose = AttendeeProfile._meta.get_field(field).verbose_name | ||||||
|  | 
 | ||||||
|  |         cart = "attendee__user__cart" | ||||||
|  |         cart_status = cart + "__status" | ||||||
|  |         product = cart + "__productitem__product" | ||||||
|  |         product_name = product + "__name" | ||||||
|  |         category_name = product + "__category__name" | ||||||
|  | 
 | ||||||
|  |         p = profiles.order_by(product, field).values( | ||||||
|  |             cart_status, product, product_name, category_name, field | ||||||
|  |         ).annotate(count=Count("id")) | ||||||
|  |         output.append(ListReport( | ||||||
|  |             "Grouped by %s" % field_verbose, | ||||||
|  |             ["Product", "Status", field_verbose, "count"], | ||||||
|  |             [ | ||||||
|  |                 ( | ||||||
|  |                     "%s - %s" % (i[category_name], i[product_name]), | ||||||
|  |                     status_display[i[cart_status]], | ||||||
|  |                     i[field], | ||||||
|  |                     i["count"] or 0, | ||||||
|  |                 ) | ||||||
|  |                 for i in p | ||||||
|  |             ], | ||||||
|  |         )) | ||||||
|  | 
 | ||||||
|  |     # DO the report for individual attendees | ||||||
|  | 
 | ||||||
|  |     field_names = [ | ||||||
|  |         AttendeeProfile._meta.get_field(field).verbose_name for field in fields | ||||||
|  |     ] | ||||||
|  | 
 | ||||||
|  |     headings = ["User ID", "Name", "Product", "Item Status"] + field_names | ||||||
|  |     data = [] | ||||||
|  |     for item in items: | ||||||
|  |         profile = by_user[item.cart.user] | ||||||
|  |         line = [ | ||||||
|  |             item.cart.user.id, | ||||||
|  |             getattr(profile, name_field), | ||||||
|  |             item.product, | ||||||
|  |             status_display[item.cart.status], | ||||||
|  |         ] + [ | ||||||
|  |             getattr(profile, field) for field in fields | ||||||
|  |         ] | ||||||
|  |         data.append(line) | ||||||
|  | 
 | ||||||
|  |     output.append(AttendeeListReport( | ||||||
|  |         "Attendees by item with profile data", headings, data, link_view=attendee | ||||||
|  |     )) | ||||||
|  |     return output | ||||||
|  |  | ||||||
|  | @ -43,6 +43,7 @@ public = [ | ||||||
| reports = [ | reports = [ | ||||||
|     url(r"^$", rv.reports_list, name="reports_list"), |     url(r"^$", rv.reports_list, name="reports_list"), | ||||||
|     url(r"^attendee/?$", rv.attendee, name="attendee"), |     url(r"^attendee/?$", rv.attendee, name="attendee"), | ||||||
|  |     url(r"^attendee_data/?$", rv.attendee_data, name="attendee_data"), | ||||||
|     url(r"^attendee/([0-9]*)$", rv.attendee, name="attendee"), |     url(r"^attendee/([0-9]*)$", rv.attendee, name="attendee"), | ||||||
|     url(r"^credit_notes/?$", rv.credit_notes, name="credit_notes"), |     url(r"^credit_notes/?$", rv.credit_notes, name="credit_notes"), | ||||||
|     url(r"^discount_status/?$", rv.discount_status, name="discount_status"), |     url(r"^discount_status/?$", rv.discount_status, name="discount_status"), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Christopher Neugebauer
						Christopher Neugebauer