diff --git a/membershipworks/dashboard.py b/membershipworks/dashboard.py index f454acb..2c5e346 100644 --- a/membershipworks/dashboard.py +++ b/membershipworks/dashboard.py @@ -25,6 +25,11 @@ class MembershipworksDashboardFragment(dashboard.LinksCardDashboardFragment): reverse("membershipworks:event-attendees"), permission="membershipworks.view_event", ), + Link( + "Missing Paperwork", + reverse("membershipworks:missing-paperwork-report"), + permission="membershipworks.view_member", + ), ] @property diff --git a/membershipworks/templates/membershipworks/missing_paperwork_report.dj.html b/membershipworks/templates/membershipworks/missing_paperwork_report.dj.html new file mode 100644 index 0000000..d1a9719 --- /dev/null +++ b/membershipworks/templates/membershipworks/missing_paperwork_report.dj.html @@ -0,0 +1,12 @@ +{% extends "base.dj.html" %} + +{% load render_table from django_tables2 %} + +{% block title %}Missing Paperwork Report{% endblock %} +{% block admin_link %} + {% url 'admin:membershipworks_member_changelist' %} +{% endblock %} +{% block content %} + {% include "cmsmanage/components/download_table.dj.html" %} + {% render_table table %} +{% endblock %} diff --git a/membershipworks/urls.py b/membershipworks/urls.py index 0c3f326..8fb9777 100644 --- a/membershipworks/urls.py +++ b/membershipworks/urls.py @@ -1,51 +1,48 @@ from django.urls import path -from .views import ( - EventAttendeeListView, - EventIndexReport, - EventInvoiceView, - EventMonthReport, - EventYearReport, - MemberAutocomplete, - upcoming_events, -) +from . import views app_name = "membershipworks" urlpatterns = [ path( "member-autocomplete/", - MemberAutocomplete.as_view(), + views.MemberAutocomplete.as_view(), name="member-autocomplete", ), path( "upcoming-events/", - upcoming_events, + views.upcoming_events, name="upcoming-events", ), path( "event-report/", - EventIndexReport.as_view(), + views.EventIndexReport.as_view(), name="event-index-report", ), path( "event-report//", - EventYearReport.as_view(), + views.EventYearReport.as_view(), name="event-year-report", ), path( "event-report///", - EventMonthReport.as_view(month_format="%m"), + views.EventMonthReport.as_view(month_format="%m"), name="event-month-report", ), path( "event-invoice/", - EventInvoiceView.as_view(), + views.EventInvoiceView.as_view(), name="event-invoice", ), path( "event-attendees", - EventAttendeeListView.as_view(), + views.EventAttendeeListView.as_view(), name="event-attendees", ), + path( + "missing-paperwork", + views.MissingPaperworkReport.as_view(), + name="missing-paperwork-report", + ), ] diff --git a/membershipworks/views.py b/membershipworks/views.py index deabddb..1e0a42e 100644 --- a/membershipworks/views.py +++ b/membershipworks/views.py @@ -4,7 +4,7 @@ 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 import OuterRef, Q, Subquery from django.db.models.functions import TruncMonth, TruncYear from django.shortcuts import render from django.template.defaultfilters import floatformat @@ -19,6 +19,7 @@ import django_filters import django_tables2 as tables from dal import autocomplete from django_filters.views import BaseFilterView +from django_mysql.models import GroupConcat from django_tables2 import A, SingleTableMixin from django_tables2.export.views import ExportMixin @@ -365,3 +366,53 @@ class EventAttendeeListView( def get_table_data(self): return super().get_table_data().values("name", "email").distinct() + + +class MissingPaperworkTable(tables.Table): + policy_agreement = tables.BooleanColumn() + authorize_charge = tables.BooleanColumn() + + class Meta: + model = Member + fields = [ + "first_name", + "last_name", + "membership", + "billing_method", + "join_date", + "membership_agreement_signed_and_on_file_date", + "waiver_form_signed_and_on_file_date", + "policy_agreement", + "authorize_charge", + ] + + +class MissingPaperworkReport( + ExportMixin, + SingleTableMixin, + PermissionRequiredMixin, + ListView, +): + model = Member + permission_required = "membershipworks.view_member" + template_name = "membershipworks/missing_paperwork_report.dj.html" + table_class = MissingPaperworkTable + export_formats = ("csv", "xlsx", "ods") + + def get_queryset(self): + qs = super().get_queryset() + return ( + qs.with_is_active() + .filter( + Q(membership_agreement_signed_and_on_file_date__isnull=True) + | Q(waiver_form_signed_and_on_file_date__isnull=True), + is_active=True, + ) + .annotate( + membership=Subquery( + qs.filter( + pk=OuterRef("pk"), flags__type__in=("level", "addon") + ).values(m=GroupConcat("flags__name")) + ), + ) + )