From 83da93b7126651251976bf48b5cca7edb67e1d5f Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Wed, 7 Feb 2024 00:25:39 -0500 Subject: [PATCH] membershipworks: Add waiver and Instructor/Vendor reports --- cmsmanage/settings/base.py | 1 + paperwork/dashboard.py | 13 ++- .../instructor_or_vendor_report.dj.html | 12 +++ .../templates/paperwork/waiver_report.dj.html | 12 +++ paperwork/urls.py | 10 +++ paperwork/views.py | 90 ++++++++++++++++++- pdm.lock | 15 +++- pyproject.toml | 1 + 8 files changed, 151 insertions(+), 3 deletions(-) create mode 100644 paperwork/templates/paperwork/instructor_or_vendor_report.dj.html create mode 100644 paperwork/templates/paperwork/waiver_report.dj.html diff --git a/cmsmanage/settings/base.py b/cmsmanage/settings/base.py index 9ba92c1..0e7fe29 100644 --- a/cmsmanage/settings/base.py +++ b/cmsmanage/settings/base.py @@ -41,6 +41,7 @@ INSTALLED_APPS = [ "django_tables2", "django_filters", "django_db_views", + "django_mysql", "tasks.apps.TasksConfig", "rentals.apps.RentalsConfig", "membershipworks.apps.MembershipworksConfig", diff --git a/paperwork/dashboard.py b/paperwork/dashboard.py index 8c0901b..2b1f999 100644 --- a/paperwork/dashboard.py +++ b/paperwork/dashboard.py @@ -13,7 +13,18 @@ class PaperworkDashboardFragment(dashboard.LinksCardDashboardFragment): @property def links(self) -> list[Link]: - links = [] + links = [ + Link( + "Waivers", + reverse("paperwork:waivers-report"), + permission="paperwork.view_waiver", + ), + Link( + "Instructors and Vendors", + reverse("paperwork:instructors-and-vendor-report"), + permission="paperwork.view_instructororvendor", + ), + ] member = Member.from_user(self.request.user) if member is not None: diff --git a/paperwork/templates/paperwork/instructor_or_vendor_report.dj.html b/paperwork/templates/paperwork/instructor_or_vendor_report.dj.html new file mode 100644 index 0000000..218a79b --- /dev/null +++ b/paperwork/templates/paperwork/instructor_or_vendor_report.dj.html @@ -0,0 +1,12 @@ +{% extends "base.dj.html" %} + +{% load render_table from django_tables2 %} + +{% block title %}Instructors and Vendors{% endblock %} +{% block admin_link %} + {% url 'admin:paperwork_instructororvendor_changelist' %} +{% endblock %} +{% block content %} + {% include "cmsmanage/components/download_table.dj.html" %} + {% render_table table %} +{% endblock %} diff --git a/paperwork/templates/paperwork/waiver_report.dj.html b/paperwork/templates/paperwork/waiver_report.dj.html new file mode 100644 index 0000000..eaa98ba --- /dev/null +++ b/paperwork/templates/paperwork/waiver_report.dj.html @@ -0,0 +1,12 @@ +{% extends "base.dj.html" %} + +{% load render_table from django_tables2 %} + +{% block title %}Waiver Report{% endblock %} +{% block admin_link %} + {% url 'admin:paperwork_waiver_changelist' %} +{% endblock %} +{% block content %} + {% include "cmsmanage/components/download_table.dj.html" %} + {% render_table table %} +{% endblock %} diff --git a/paperwork/urls.py b/paperwork/urls.py index e273c4d..2a276a2 100644 --- a/paperwork/urls.py +++ b/paperwork/urls.py @@ -25,4 +25,14 @@ urlpatterns = [ autocomplete_views.CertificationVersionAutocomplete.as_view(), name="certification_version_autocomplete", ), + path( + "waivers", + views.WaiverReport.as_view(), + name="waivers-report", + ), + path( + "instructors-and-vendors", + views.InstructorOrVendorReport.as_view(), + name="instructors-and-vendor-report", + ), ] diff --git a/paperwork/views.py b/paperwork/views.py index ed6d057..a5dd099 100644 --- a/paperwork/views.py +++ b/paperwork/views.py @@ -1,16 +1,21 @@ from django.conf import settings from django.contrib import staticfiles from django.contrib.auth.decorators import login_required +from django.contrib.auth.mixins import PermissionRequiredMixin from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseNotFound from django.shortcuts import get_object_or_404, render from django.views.generic import ListView +import django_tables2 as tables import requests import weasyprint +from django_mysql.models import GroupConcat +from django_tables2 import SingleTableMixin +from django_tables2.export.views import ExportMixin from membershipworks.models import Member -from .models import Certification, Department +from .models import Certification, Department, InstructorOrVendor, Waiver WIKI_URL = settings.WIKI_URL @@ -98,3 +103,86 @@ def certification_pdf(request, cert_name): "Content-Disposition": f'inline; filename="{filename}"', }, ) + + +class WarnEmptyColumn(tables.Column): + attrs = { + "td": { + "class": lambda value, bound_column: "table-danger" + if value == bound_column.default + else "" + } + } + + +class WaiverReportTable(tables.Table): + emergency_contact_name = WarnEmptyColumn() + emergency_contact_number = WarnEmptyColumn() + + class Meta: + model = Waiver + fields = [ + "name", + "date", + "emergency_contact_name", + "emergency_contact_number", + "waiver_version", + "guardian_name", + "guardian_relation", + "guardian_date", + ] + + +class WaiverReport(ExportMixin, SingleTableMixin, PermissionRequiredMixin, ListView): + permission_required = "paperwork.view_waiver" + template_name = "paperwork/waiver_report.dj.html" + queryset = Waiver.objects.order_by("name").all() + table_class = WaiverReportTable + table_pagination = False + + +class InstructorOrVendorTable(tables.Table): + instructor_agreement_date = WarnEmptyColumn( + "Instructor Agreement Date(s)", default="Missing" + ) + w9_date = WarnEmptyColumn(default="Missing") + + class Meta: + model = InstructorOrVendor + fields = [ + "name", + "instructor_agreement_date", + "w9_date", + "phone", + "email_address", + ] + + +class InstructorOrVendorReport( + ExportMixin, + SingleTableMixin, + PermissionRequiredMixin, + ListView, +): + permission_required = "paperwork.view_instructororvendor" + template_name = "paperwork/instructor_or_vendor_report.dj.html" + queryset = InstructorOrVendor.objects.order_by("name").all() + table_class = InstructorOrVendorTable + export_formats = ("csv", "xlsx", "ods") + + def get_table_data(self): + return ( + super() + .get_table_data() + .values("name") + .annotate( + instructor_agreement_date=GroupConcat( + "instructor_agreement_date", distinct=True, ordering="asc" + ), + w9_date=GroupConcat("w9_date", distinct=True, ordering="asc"), + phone=GroupConcat("phone", distinct=True, ordering="asc"), + email_address=GroupConcat( + "email_address", distinct=True, ordering="asc" + ), + ) + ) diff --git a/pdm.lock b/pdm.lock index f417051..3441276 100644 --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "debug", "lint", "server", "typing", "dev"] strategy = ["cross_platform"] lock_version = "4.4.1" -content_hash = "sha256:e647dfe717684c87b3a51bc1738ae7eb3d370ada3908a48c5ead3547c36a78d5" +content_hash = "sha256:88502778249494bd3f6fd407d51671f4e465065ec58427b60993d91d0808bdfd" [[package]] name = "aiohttp" @@ -499,6 +499,19 @@ files = [ {file = "django_markdownx-4.0.7-py2.py3-none-any.whl", hash = "sha256:c1975ae3053481d4c111abd38997a5b5bb89235a1e3215f995d835942925fe7b"}, ] +[[package]] +name = "django-mysql" +version = "4.12.0" +requires_python = ">=3.8" +summary = "Django-MySQL extends Django's built-in MySQL and MariaDB support their specific features not available on other databases." +dependencies = [ + "Django>=3.2", +] +files = [ + {file = "django_mysql-4.12.0-py3-none-any.whl", hash = "sha256:1c188ee3a92590da21ce23351c309bb02df3b6611926521d312a9cdf6373c3d0"}, + {file = "django_mysql-4.12.0.tar.gz", hash = "sha256:9a29b69ad30c85362984903379783b53731ee7b0cef4dfb4eb078f80e24f26d4"}, +] + [[package]] name = "django-nh3" version = "0.1.1" diff --git a/pyproject.toml b/pyproject.toml index 24a6f1d..46e85f5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,7 @@ dependencies = [ "tablib[ods,xlsx]~=3.5", "django-filter~=23.5", "django-db-views~=0.1", + "django-mysql~=4.12", ] requires-python = ">=3.11"