membershipworks: Add new event attendee email report
All checks were successful
Ruff / ruff (push) Successful in 20s
All checks were successful
Ruff / ruff (push) Successful in 20s
This commit is contained in:
parent
c3f51df7d4
commit
560225cdb3
@ -16,6 +16,7 @@ class MembershipworksDashboardFragment(dashboard.DashboardFragment):
|
||||
|
||||
if self.request.user.has_perm("membershipworks.view_event"):
|
||||
links["Event Report"] = reverse("membershipworks:event-index-report")
|
||||
links["Event Attendees"] = reverse("membershipworks:event-attendees")
|
||||
|
||||
return {"links": links}
|
||||
|
||||
|
26
membershipworks/migrations/0013_eventattendee.py
Normal file
26
membershipworks/migrations/0013_eventattendee.py
Normal file
@ -0,0 +1,26 @@
|
||||
# Generated by Django 5.0.1 on 2024-02-02 22:07
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
import django_db_views.migration_functions
|
||||
import django_db_views.operations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("membershipworks", "0012_eventattendeestats_eventtickettype"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
django_db_views.operations.ViewRunPython(
|
||||
code=django_db_views.migration_functions.ForwardViewMigration(
|
||||
"SELECT eventext.event_ptr_id as event_id, tkt.uid, tkt.name, tkt.email, tkt.sum\n FROM\n membershipworks_eventext as eventext,\n JSON_TABLE(eventext.details, '$.usr[*]' COLUMNS (\n uid VARCHAR(24) PATH '$.uid',\n name VARCHAR(256) PATH '$.nam',\n email VARCHAR(256) PATH '$.eml',\n sum DOUBLE PATH '$.sum'\n )) as tkt",
|
||||
"membershipworks_eventattendee",
|
||||
engine="django.db.backends.mysql",
|
||||
),
|
||||
reverse_code=django_db_views.migration_functions.BackwardViewMigration(
|
||||
"", "membershipworks_eventattendee", engine="django.db.backends.mysql"
|
||||
),
|
||||
atomic=False,
|
||||
),
|
||||
]
|
@ -688,3 +688,28 @@ class EventAttendeeStats(DBView):
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
|
||||
|
||||
class EventAttendee(DBView):
|
||||
event = models.ForeignKey(
|
||||
EventExt, on_delete=models.CASCADE, related_name="attendees"
|
||||
)
|
||||
uid = models.ForeignKey(Member, on_delete=models.DO_NOTHING)
|
||||
name = models.CharField(max_length=256)
|
||||
email = models.CharField(max_length=256)
|
||||
sum = models.FloatField()
|
||||
|
||||
view_definition = """
|
||||
SELECT eventext.event_ptr_id as event_id, tkt.uid, tkt.name, tkt.email, tkt.sum
|
||||
FROM
|
||||
membershipworks_eventext as eventext,
|
||||
JSON_TABLE(eventext.details, '$.usr[*]' COLUMNS (
|
||||
uid VARCHAR(24) PATH '$.uid',
|
||||
name VARCHAR(256) PATH '$.nam',
|
||||
email VARCHAR(256) PATH '$.eml',
|
||||
sum DOUBLE PATH '$.sum'
|
||||
)) as tkt
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
managed = False
|
||||
|
@ -0,0 +1,27 @@
|
||||
{% extends "base.dj.html" %}
|
||||
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block title %}Event Attendees{% endblock %}
|
||||
{% block admin_link %}
|
||||
{% url 'admin:membershipworks_eventext_changelist' %}
|
||||
{% endblock %}
|
||||
{% block content %}
|
||||
<form method="get" class="container-fluid">
|
||||
<div class="row g-2 align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="form-floating">
|
||||
<input type="date"
|
||||
class="form-control"
|
||||
id="newSince"
|
||||
name="new_since"
|
||||
value="{{ filter.form.new_since.value }}">
|
||||
<label for="newSince">New Since</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-primary col-auto" type="submit">Filter</button>
|
||||
<div class="col-auto">{% include "cmsmanage/components/download_table.dj.html" %}</div>
|
||||
</div>
|
||||
</form>
|
||||
{% render_table table %}
|
||||
{% endblock %}
|
@ -1,6 +1,7 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import (
|
||||
EventAttendeeListView,
|
||||
EventIndexReport,
|
||||
EventInvoiceView,
|
||||
EventMonthReport,
|
||||
@ -42,4 +43,9 @@ urlpatterns = [
|
||||
EventInvoiceView.as_view(),
|
||||
name="event-invoice",
|
||||
),
|
||||
path(
|
||||
"event-attendees",
|
||||
EventAttendeeListView.as_view(),
|
||||
name="event-attendees",
|
||||
),
|
||||
]
|
||||
|
@ -4,24 +4,27 @@ from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import permission_required
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.db.models import Subquery
|
||||
from django.db.models.functions import TruncMonth, TruncYear
|
||||
from django.shortcuts import render
|
||||
from django.template.defaultfilters import floatformat
|
||||
from django.views.generic import DetailView
|
||||
from django.views.generic import DetailView, ListView
|
||||
from django.views.generic.dates import (
|
||||
ArchiveIndexView,
|
||||
MonthArchiveView,
|
||||
YearArchiveView,
|
||||
)
|
||||
|
||||
import django_filters
|
||||
import django_tables2 as tables
|
||||
from dal import autocomplete
|
||||
from django_filters.views import BaseFilterView
|
||||
from django_tables2 import A, SingleTableMixin
|
||||
from django_tables2.export.views import ExportMixin
|
||||
|
||||
from membershipworks.membershipworks_api import MembershipWorks
|
||||
|
||||
from .models import EventExt, Member
|
||||
from .models import EventAttendee, EventExt, Member
|
||||
|
||||
|
||||
class MemberAutocomplete(autocomplete.Select2QuerySetView):
|
||||
@ -329,3 +332,36 @@ class EventInvoiceView(SingleTableMixin, PermissionRequiredMixin, DetailView):
|
||||
|
||||
def get_table_kwargs(self):
|
||||
return {"event": self.object}
|
||||
|
||||
|
||||
class EventAttendeeTable(tables.Table):
|
||||
class Meta:
|
||||
model = EventAttendee
|
||||
fields = ("name", "email")
|
||||
|
||||
|
||||
class EventAttendeeFilters(django_filters.FilterSet):
|
||||
new_since = django_filters.DateFilter(
|
||||
field_name="event__start", method="filter_new_since"
|
||||
)
|
||||
|
||||
def filter_new_since(self, queryset, name, value):
|
||||
return queryset.filter(**{f"{name}__gte": value}).exclude(
|
||||
email__in=Subquery(
|
||||
queryset.filter(**{f"{name}__lt": value}).values("email")
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class EventAttendeeListView(
|
||||
BaseFilterView, ExportMixin, SingleTableMixin, PermissionRequiredMixin, ListView
|
||||
):
|
||||
permission_required = "membershipworks.view_eventext"
|
||||
queryset = EventAttendee.objects.all()
|
||||
table_class = EventAttendeeTable
|
||||
template_name = "membershipworks/eventattendee_list.dj.html"
|
||||
export_formats = ("csv", "xlsx", "ods")
|
||||
filterset_class = EventAttendeeFilters
|
||||
|
||||
def get_table_data(self):
|
||||
return super().get_table_data().values("name", "email").distinct()
|
||||
|
Loading…
Reference in New Issue
Block a user