diff --git a/membershipworks/tables.py b/membershipworks/tables.py index 9371dd7..1d8120d 100644 --- a/membershipworks/tables.py +++ b/membershipworks/tables.py @@ -65,6 +65,30 @@ class EventTable(tables.Table): } +class EventRegistrationsTable(tables.Table): + ticket_count = tables.Column(empty_values=()) + name = tables.Column(accessor="Full name") + email = tables.EmailColumn(accessor="Email") + phone = tables.Column(accessor="Phone") + emergency_contact_name = tables.Column(accessor="Emergency Contact Name:") + emergency_contact_phone_number = tables.Column( + accessor="Emergency Contact Phone Number:" + ) + emergency_contact_relation = tables.Column(accessor="Emergency Contact Relation:") + + def render_ticket_count(self, record): + return sum(int(v) for k, v in record.items() if k.startswith("Ticket: ")) + + class Meta: + row_attrs = { + "class": lambda table, record: ( + "" + if table.render_ticket_count(record) > 0 + else "text-decoration-line-through table-danger" + ) + } + + class EventSummaryTable(tables.Table): event_count = tables.Column("Events") canceled_event_count = tables.Column("Canceled Events") diff --git a/membershipworks/templates/membershipworks/event_detail.dj.html b/membershipworks/templates/membershipworks/event_detail.dj.html index b51e546..dab8429 100644 --- a/membershipworks/templates/membershipworks/event_detail.dj.html +++ b/membershipworks/templates/membershipworks/event_detail.dj.html @@ -13,6 +13,10 @@ {% endblock %} {% block content %}
+ {% if event.registrations is not None %} + {% url 'membershipworks:event-registrations' event.pk as registrations_url %} + {% bootstrap_button href=registrations_url content="Show Registrations" %} + {% endif %} {% include "membershipworks/event_invoice.dj.html" %}
diff --git a/membershipworks/templates/membershipworks/event_registrations.dj.html b/membershipworks/templates/membershipworks/event_registrations.dj.html new file mode 100644 index 0000000..7ac5eac --- /dev/null +++ b/membershipworks/templates/membershipworks/event_registrations.dj.html @@ -0,0 +1,29 @@ +{% extends "base.dj.html" %} + +{% load nh3_tags %} +{% load render_table from django_tables2 %} +{% load django_bootstrap5 %} + +{% block title %}Registrations for {{ event.details.ttl|nh3 }}{% endblock %} +{% block admin_link %} + {% url 'admin:membershipworks_eventext_change' event.pk %} +{% endblock %} +{% block breadcrumbs %} + {% include "./components/event_breadcrumbs.dj.html" %} + + +{% endblock %} +{% block content %} +
+
+
+ {% bootstrap_button extra_classes="btn-sm" href=email_link target="_blank" content="Email all attendees" %} +
+
{% include "cmsmanage/components/download_table.dj.html" %}
+
+ {% render_table table %} +

Data last updated {{ event.details_timestamp }}

+
+{% endblock %} diff --git a/membershipworks/urls.py b/membershipworks/urls.py index 2ad8fd4..ec722c7 100644 --- a/membershipworks/urls.py +++ b/membershipworks/urls.py @@ -45,6 +45,11 @@ urlpatterns = [ views.EventDetailView.as_view(), name="event-detail", ), + path( + "event//registrations", + views.EventRegistrationsView.as_view(), + name="event-registrations", + ), path( "event/invoice/.pdf", views.EventInvoicePDFView.as_view(), diff --git a/membershipworks/views.py b/membershipworks/views.py index 0601e58..b7a5422 100644 --- a/membershipworks/views.py +++ b/membershipworks/views.py @@ -1,6 +1,7 @@ import uuid from datetime import datetime from typing import Any +from urllib.parse import quote, urlencode from django.conf import settings from django.contrib import messages @@ -46,6 +47,7 @@ from .invoice_email import make_invoice_emails from .models import EventAttendee, EventExt, EventInvoice, Member from .tables import ( EventAttendeeTable, + EventRegistrationsTable, EventSummaryTable, EventTable, InvoiceTable, @@ -418,6 +420,50 @@ class EventInvoicePDFView(AccessMixin, BaseDetailView): return self.handle_no_permission() +class EventRegistrationsView(ExportMixin, SingleTableMixin, AccessMixin, DetailView): + permission_required = "membershipworks.view_eventext" + model = EventExt + pk_url_kwarg = "eid" + context_object_name = "event" + template_name = "membershipworks/event_registrations.dj.html" + table_class = EventRegistrationsTable + export_formats = ("csv", "xlsx", "ods") + + def render_to_response( + self, context: dict[str, Any], **response_kwargs: Any + ) -> HttpResponse: + if self.request.user.has_perm( + self.permission_required + ) or self.object.user_is_instructor(self.request.user): + return super().render_to_response(context, **response_kwargs) + else: + return self.handle_no_permission() + + def get_context_data(self, **kwargs: Any) -> dict[str, Any]: + context_data = super().get_context_data(**kwargs) + + context_data["email_link"] = "mailto:?" + urlencode( + { + "subject": f"[CMS Event] {self.object.title}", + "bcc": ",".join( + mail.message.sanitize_address( + (reg["Full name"], reg["Email"]), settings.DEFAULT_CHARSET + ) + for reg in self.object.registrations + if any( + int(v) > 0 for k, v in reg.items() if k.startswith("Ticket: ") + ) + ), + }, + quote_via=quote, + ) + + return context_data + + def get_table_data(self): + return self.object.registrations + + class EventAttendeeFilters(django_filters.FilterSet): new_since = django_filters.DateFilter( field_name="event__start", method="filter_new_since"