membershipworks: Add basic per-month event report
This commit is contained in:
parent
34821e1c58
commit
270e6c7837
29
membershipworks/dashboard.py
Normal file
29
membershipworks/dashboard.py
Normal file
@ -0,0 +1,29 @@
|
||||
from typing import Any
|
||||
from datetime import datetime
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
import dashboard
|
||||
|
||||
|
||||
@dashboard.register
|
||||
class MembershipworksDashboardFragment(dashboard.DashboardFragment):
|
||||
name = "MembershipWorks"
|
||||
template = "dashboard/links_card.dj.html"
|
||||
|
||||
@property
|
||||
def context(self) -> Any:
|
||||
links = {}
|
||||
|
||||
if self.request.user.has_perm("membershipworks.view_event"):
|
||||
now = datetime.now()
|
||||
links["Event Report"] = reverse(
|
||||
"membershipworks:event-report",
|
||||
kwargs={"year": now.year, "month": now.month},
|
||||
)
|
||||
|
||||
return {"links": links}
|
||||
|
||||
@property
|
||||
def visible(self) -> bool:
|
||||
return self.request.user.has_perm("doorcontrol.view_hidevent")
|
@ -436,6 +436,14 @@ class EventExt(Event):
|
||||
max_digits=13, decimal_places=4, default=0
|
||||
)
|
||||
|
||||
# TODO: ideally this would be a generated column or annotation,
|
||||
# but I couldn't get the types to work out
|
||||
@property
|
||||
def person_hours(self):
|
||||
if self.duration is None:
|
||||
return None
|
||||
return self.count * self.duration
|
||||
|
||||
class Meta:
|
||||
verbose_name = "event"
|
||||
|
||||
|
@ -0,0 +1,66 @@
|
||||
{% extends "base.dj.html" %}
|
||||
|
||||
{% load membershipworks_tags %}
|
||||
|
||||
{% block title %}Event Report{% endblock %}
|
||||
{% block content %}
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th for="column">Title</th>
|
||||
<th for="column">Date</th>
|
||||
<th for="column">Instructor</th>
|
||||
<th for="column">Category</th>
|
||||
<th for="column">Ticket Count</th>
|
||||
<th for="column">Ticket Cap</th>
|
||||
<th for="column">Meetings</th>
|
||||
<th for="column">Total Duration</th>
|
||||
<th for="column">Person Hours</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for event in object_list %}
|
||||
<tr>
|
||||
<td>
|
||||
<a href="https://membershipworks.com/admin/#!event/admin/{{ event.url }}">{{ event.title }}</a>
|
||||
</td>
|
||||
<td>{{ event.start|date }}</td>
|
||||
<td>{{ event.instructor }}</td>
|
||||
<td>{{ event.category }}</td>
|
||||
<td>{{ event.count }}</td>
|
||||
<td>{{ event.cap }}</td>
|
||||
<td>{{ event.meeting_times.count }}</td>
|
||||
<td>{{ event.duration|duration_as_hours }}</td>
|
||||
<td>{{ event.person_hours|duration_as_hours }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<nav aria-label="Page navigation">
|
||||
<ul class="pagination justify-content-center">
|
||||
{% if previous_month %}
|
||||
<li class="page-item">
|
||||
<a class="page-link"
|
||||
href="{% url 'membershipworks:event-report' previous_month|date:"Y" previous_month|date:"m" %}">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
{{ previous_month|date:"F Y" }}
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="page-item active">
|
||||
<a class="page-link" href="#">{{ month|date:"F Y" }}</a>
|
||||
</li>
|
||||
{% if next_month %}
|
||||
<li class="page-item">
|
||||
<a class="page-link"
|
||||
href="{% url 'membershipworks:event-report' next_month|date:"Y" next_month|date:"m" %}">
|
||||
{{ next_month|date:"F Y" }}
|
||||
<i class="bi bi-arrow-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</nav>
|
||||
{% endblock %}
|
0
membershipworks/templatetags/__init__.py
Normal file
0
membershipworks/templatetags/__init__.py
Normal file
12
membershipworks/templatetags/membershipworks_tags.py
Normal file
12
membershipworks/templatetags/membershipworks_tags.py
Normal file
@ -0,0 +1,12 @@
|
||||
from datetime import timedelta
|
||||
|
||||
from django import template
|
||||
|
||||
register = template.Library()
|
||||
|
||||
|
||||
@register.filter
|
||||
def duration_as_hours(td: timedelta) -> str | None:
|
||||
if td is None:
|
||||
return None
|
||||
return td.total_seconds() / 60 / 60
|
@ -1,6 +1,6 @@
|
||||
from django.urls import path
|
||||
|
||||
from .views import MemberAutocomplete, upcoming_events
|
||||
from .views import MemberAutocomplete, upcoming_events, EventReport
|
||||
|
||||
app_name = "membershipworks"
|
||||
|
||||
@ -15,4 +15,9 @@ urlpatterns = [
|
||||
upcoming_events,
|
||||
name="upcoming-events",
|
||||
),
|
||||
path(
|
||||
"event-report/<int:year>/<int:month>/",
|
||||
EventReport.as_view(month_format="%m"),
|
||||
name="event-report",
|
||||
),
|
||||
]
|
||||
|
@ -3,12 +3,13 @@ from datetime import datetime
|
||||
from django.conf import settings
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpResponse
|
||||
from django.contrib.auth.mixins import PermissionRequiredMixin
|
||||
from django.shortcuts import render
|
||||
from django.views.generic.dates import MonthArchiveView
|
||||
|
||||
from dal import autocomplete
|
||||
|
||||
from .models import Member
|
||||
from .models import Member, EventExt
|
||||
from membershipworks import MembershipWorks
|
||||
|
||||
|
||||
@ -101,3 +102,10 @@ def upcoming_events(request):
|
||||
]
|
||||
}
|
||||
return render(request, "membershipworks/upcoming_events.dj.html", context)
|
||||
|
||||
|
||||
class EventReport(PermissionRequiredMixin, MonthArchiveView):
|
||||
permission_required = "membershipworks.view_eventext"
|
||||
queryset = EventExt.objects.select_related("category", "instructor").all()
|
||||
date_field = "start"
|
||||
template_name = "membershipworks/event_report.dj.html"
|
||||
|
Loading…
Reference in New Issue
Block a user