Changeset - ea07469634ee
[Not reviewed]
0 2 0
Christopher Neugebauer - 8 years ago 2016-12-06 23:18:48
chrisjrn@gmail.com
Fixes individual attendee view, which had disappeared.
2 files changed with 7 insertions and 2 deletions:
0 comments (0 inline, 0 general)
registrasion/reporting/reports.py
Show inline comments
...
 
@@ -168,145 +168,148 @@ class Links(Report):
 
                (url, link_text)
 

	
 
        '''
 
        self._title = title
 
        self._links = links
 

	
 
    def title(self):
 
        return self._title
 

	
 
    def headings(self):
 
        return []
 

	
 
    def rows(self, content_type):
 
        print self._links
 
        for url, link_text in self._links:
 
            yield [
 
                self._linked_text(content_type, url, link_text)
 
            ]
 

	
 

	
 
def report_view(title, form_type=None):
 
    ''' Decorator that converts a report view function into something that
 
    displays a Report.
 

	
 
    Arguments:
 
        title (str):
 
            The title of the report.
 
        form_type (Optional[forms.Form]):
 
            A form class that can make this report display things. If not
 
            supplied, no form will be displayed.
 

	
 
    '''
 

	
 
    # Create & return view
 
    def _report(view):
 
        report_view = ReportView(view, title, form_type)
 
        report_view = user_passes_test(views._staff_only)(report_view)
 
        report_view = wraps(view)(report_view)
 

	
 
        # Add this report to the list of reports.
 
        _all_report_views.append(report_view)
 

	
 
        return report_view
 

	
 
    return _report
 

	
 

	
 
class ReportView(object):
 

	
 
    def __init__(self, inner_view, title, form_type):
 
        # Consolidate form_type so it has content type and section
 
        self.inner_view = inner_view
 
        self.title = title
 
        self.form_type = form_type
 

	
 
    def __call__(self, request, *a, **k):
 
        data = ReportViewRequestData(self, request, *a, **k)
 
        return self.render(data)
 

	
 
    def get_form(self, request):
 

	
 
        # Create a form instance
 
        if self.form_type is not None:
 
            form = self.form_type(request.GET)
 

	
 
            # Pre-validate it
 
            form.is_valid()
 
        else:
 
            form = None
 

	
 
        return form
 

	
 
    @classmethod
 
    def wrap_reports(cls, reports, content_type):
 
        reports = [
 
            _ReportTemplateWrapper(content_type, report)
 
            for report in reports
 
        ]
 

	
 
        return reports
 

	
 
    def render(self, data):
 
        renderers = {
 
            "text/csv": self._render_as_csv,
 
            "text/html": self._render_as_html,
 
            None: self._render_as_html,
 
        }
 
        render = renderers[data.content_type]
 
        return render(data)
 

	
 
    def _render_as_html(self, data):
 
        ctx = {
 
            "title": self.title,
 
            "form": data.form,
 
            "reports": data.reports,
 
        }
 

	
 
        return render(data.request, "registrasion/report.html", ctx)
 

	
 
    def _render_as_csv(self, data):
 
        report = data.reports[data.section]
 

	
 
        # Create the HttpResponse object with the appropriate CSV header.
 
        response = HttpResponse(content_type='text/csv')
 

	
 
        writer = csv.writer(response)
 
        encode = lambda i: i.encode("utf8") if isinstance(i, unicode) else i
 
        writer.writerow(list(encode(i) for i in report.headings()))
 
        for row in report.rows():
 
            writer.writerow(list(encode(i) for i in row))
 

	
 
        return response
 

	
 

	
 
class ReportViewRequestData(object):
 

	
 
    def __init__(self, report_view, request, *a, **k):
 
        self.report_view = report_view
 
        self.request = request
 

	
 
        # Calculate other data
 
        self.form = report_view.get_form(request)
 

	
 
        # Content type and section come from request.GET
 
        self.content_type = request.GET.get("content_type")
 
        self.section = request.GET.get("section")
 
        self.section = int(self.section) if self.section else None
 

	
 
        if self.content_type is None:
 
            self.content_type = "text/html"
 

	
 
        # Reports come from calling the inner view
 
        reports = report_view.inner_view(request, self.form, *a, **k)
 

	
 
        # Normalise to a list
 
        if isinstance(reports, Report):
 
            reports = [reports]
 

	
 
        # Wrap them in appropriate format
 
        reports = ReportView.wrap_reports(reports, self.content_type)
 

	
 
        self.reports = reports
 

	
 

	
 
def get_all_reports():
 
    ''' Returns all the views that have been registered with @report '''
 

	
 
    return list(_all_report_views)
registrasion/reporting/views.py
Show inline comments
...
 
@@ -283,261 +283,263 @@ def product_status(request, form):
 
def discount_status(request, form):
 
    ''' Summarises the usage of a given discount. '''
 

	
 
    discounts = form.cleaned_data["discount"]
 

	
 
    items = commerce.DiscountItem.objects.filter(
 
        Q(discount__in=discounts),
 
    ).select_related("cart", "product", "product__category")
 

	
 
    items = group_by_cart_status(
 
        items,
 
        ["discount",],
 
        ["discount", "discount__description",],
 
    )
 

	
 
    headings = [
 
        "Discount", "Paid", "Reserved", "Unreserved", "Refunded",
 
    ]
 
    data = []
 

	
 
    for item in items:
 
        data.append([
 
            item["discount__description"],
 
            item["total_paid"],
 
            item["total_reserved"],
 
            item["total_unreserved"],
 
            item["total_refunded"],
 
        ])
 

	
 
    return ListReport("Usage by item", headings, data)
 

	
 

	
 
@report_view("Paid invoices by date", form_type=forms.ProductAndCategoryForm)
 
def paid_invoices_by_date(request, form):
 
    ''' Shows the number of paid invoices containing given products or
 
    categories per day. '''
 

	
 
    products = form.cleaned_data["product"]
 
    categories = form.cleaned_data["category"]
 

	
 
    invoices = commerce.Invoice.objects.filter(
 
        (
 
            Q(lineitem__product__in=products) |
 
            Q(lineitem__product__category__in=categories)
 
        ),
 
        status=commerce.Invoice.STATUS_PAID,
 
    )
 

	
 
    # Invoices with payments will be paid at the time of their latest payment
 
    payments = commerce.PaymentBase.objects.all()
 
    payments = payments.filter(
 
        invoice__in=invoices,
 
    )
 
    payments = payments.order_by("invoice")
 
    invoice_max_time = payments.values("invoice").annotate(
 
        max_time=Max("time")
 
    )
 

	
 
    # Zero-value invoices will have no payments, so they're paid at issue time
 
    zero_value_invoices = invoices.filter(value=0)
 

	
 
    times = itertools.chain(
 
        (line["max_time"] for line in invoice_max_time),
 
        (invoice.issue_time for invoice in zero_value_invoices),
 
    )
 

	
 
    by_date = collections.defaultdict(int)
 
    for time in times:
 
        date = datetime.datetime(
 
            year=time.year, month=time.month, day=time.day
 
        )
 
        by_date[date] += 1
 

	
 
    data = [(date, count) for date, count in sorted(by_date.items())]
 
    data = [(date.strftime("%Y-%m-%d"), count) for date, count in data]
 

	
 
    return ListReport(
 
        "Paid Invoices By Date",
 
        ["date", "count"],
 
        data,
 
    )
 

	
 
@report_view("Credit notes")
 
def credit_notes(request, form):
 
    ''' Shows all of the credit notes in the system. '''
 

	
 
    notes = commerce.CreditNote.objects.all().select_related(
 
        "creditnoterefund",
 
        "creditnoteapplication",
 
        "invoice",
 
        "invoice__user__attendee__attendeeprofilebase",
 
    )
 

	
 
    return QuerysetReport(
 
        "Credit Notes",
 
        ["id", "invoice__user__attendee__attendeeprofilebase__invoice_recipient", "status", "value"],  # NOQA
 
        notes,
 
        headings=["id", "Owner", "Status", "Value"],
 
        link_view=views.credit_note,
 
    )
 

	
 

	
 
@report_view("Invoices")
 
def invoices(request,form):
 
    ''' Shows all of the invoices in the system. '''
 

	
 
    invoices = commerce.Invoice.objects.all().order_by("status")
 

	
 
    return QuerysetReport(
 
        "Invoices",
 
        ["id", "recipient", "value", "get_status_display"],
 
        invoices,
 
        headings=["id", "Recipient", "Value", "Status"],
 
        link_view=views.invoice,
 
    )
 

	
 

	
 
class AttendeeListReport(ListReport):
 

	
 
    def get_link(self, argument):
 
        return reverse(self._link_view) + "?user=%d" % int(argument)
 

	
 

	
 
@report_view("Attendee", form_type=forms.UserIdForm)
 
def attendee(request, form, user_id=None):
 
    ''' Returns a list of all manifested attendees if no attendee is specified,
 
    else displays the attendee manifest. '''
 

	
 
    if user_id is None and form.cleaned_data["user"] is not None:
 
        user_id = form.cleaned_data["user"]
 

	
 
    if user_id is None:
 
        return attendee_list(request)
 

	
 
    if form.cleaned_data["user"] is not None:
 
        user_id = form.cleaned_data["user"]
 
    print user_id
 

	
 
    attendee = people.Attendee.objects.get(user__id=user_id)
 
    name = attendee.attendeeprofilebase.attendee_name()
 

	
 
    reports = []
 

	
 
    profile_data = []
 
    try:
 
        profile = people.AttendeeProfileBase.objects.get_subclass(
 
            attendee=attendee
 
        )
 
        fields = profile._meta.get_fields()
 
    except people.AttendeeProfileBase.DoesNotExist:
 
        fields = []
 

	
 
    exclude = set(["attendeeprofilebase_ptr", "id"])
 
    for field in fields:
 
        if field.name in exclude:
 
            # Not actually important
 
            continue
 
        if not hasattr(field, "verbose_name"):
 
            continue  # Not a publicly visible field
 
        value = getattr(profile, field.name)
 

	
 
        if isinstance(field, models.ManyToManyField):
 
            value = ", ".join(str(i) for i in value.all())
 

	
 
        profile_data.append((field.verbose_name, value))
 

	
 
    cart = CartController.for_user(attendee.user)
 
    reservation = cart.cart.reservation_duration + cart.cart.time_last_updated
 
    profile_data.append(("Current cart reserved until", reservation))
 

	
 
    reports.append(ListReport("Profile", ["", ""], profile_data))
 

	
 
    links = []
 
    links.append((
 
        reverse(views.amend_registration, args=[user_id]),
 
        "Amend current cart",
 
    ))
 
    links.append((
 
        reverse(views.extend_reservation, args=[user_id]),
 
        "Extend reservation",
 
    ))
 

	
 
    reports.append(Links("Actions for " + name, links))
 

	
 
    # Paid and pending  products
 
    ic = ItemController(attendee.user)
 
    reports.append(ListReport(
 
        "Paid Products",
 
        ["Product", "Quantity"],
 
        [(pq.product, pq.quantity) for pq in ic.items_purchased()],
 
    ))
 
    reports.append(ListReport(
 
        "Unpaid Products",
 
        ["Product", "Quantity"],
 
        [(pq.product, pq.quantity) for pq in ic.items_pending()],
 
    ))
 

	
 
    # Invoices
 
    invoices = commerce.Invoice.objects.filter(
 
        user=attendee.user,
 
    )
 
    reports.append(QuerysetReport(
 
        "Invoices",
 
        ["id", "get_status_display", "value"],
 
        invoices,
 
        headings=["Invoice ID", "Status", "Value"],
 
        link_view=views.invoice,
 
    ))
 

	
 
    # Credit Notes
 
    credit_notes = commerce.CreditNote.objects.filter(
 
        invoice__user=attendee.user,
 
    ).select_related("invoice", "creditnoteapplication", "creditnoterefund")
 

	
 
    reports.append(QuerysetReport(
 
        "Credit Notes",
 
        ["id", "status", "value"],
 
        credit_notes,
 
        link_view=views.credit_note,
 
    ))
 

	
 
    # All payments
 
    payments = commerce.PaymentBase.objects.filter(
 
        invoice__user=attendee.user,
 
    ).select_related("invoice")
 

	
 
    reports.append(QuerysetReport(
 
        "Payments",
 
        ["invoice__id", "id", "reference", "amount"],
 
        payments,
 
        link_view=views.invoice,
 
    ))
 

	
 
    return reports
 

	
 

	
 
def attendee_list(request):
 
    ''' Returns a list of all attendees. '''
 

	
 
    attendees = people.Attendee.objects.select_related(
 
        "attendeeprofilebase",
 
        "user",
 
    )
 

	
 
    profiles = AttendeeProfile.objects.filter(
 
        attendee__in=attendees
 
    ).select_related(
 
        "attendee", "attendee__user",
 
    )
 
    profiles_by_attendee = dict((i.attendee, i) for i in profiles)
 

	
 
    attendees = attendees.annotate(
 
        has_registered=Count(
 
            Q(user__invoice__status=commerce.Invoice.STATUS_PAID)
 
        ),
 
    )
 

	
 
    headings = [
 
        "User ID", "Name", "Email", "Has registered",
 
    ]
 

	
 
    data = []
 

	
 
    for a in attendees:
 
        data.append([
0 comments (0 inline, 0 general)