diff --git a/busManager/coord/admin.py b/busManager/coord/admin.py
index 8a68d14..092625e 100644
--- a/busManager/coord/admin.py
+++ b/busManager/coord/admin.py
@@ -9,6 +9,8 @@ from django.utils.http import urlencode
from import_export.admin import ImportExportModelAdmin
from .adminClone import CloneModelAdmin
+from .context_helpers import bus_roll_context
+from .email_helpers import email_companies_bus_roll, render_to_pdf
from .models import *
from .views import bus_roll
@@ -33,11 +35,11 @@ class ExportCsvMixin:
class BusRollMixin:
- def bus_roll(self, request, queryset):
- return bus_roll(request, queryset)
+ def show_bus_roll(self, request, queryset):
+ return render_to_pdf('reports/bus_roll.html', bus_roll_context(queryset))
def email_company(self, request, queryset):
- pass
+ return email_companies_bus_roll(request, queryset)
email_company.short_description = "Email Bus Roll to Company"
@@ -81,7 +83,7 @@ class BusesAdmin(MyImportExportModelAdmin, admin.ModelAdmin, BusRollMixin):
list_filter = ["company"]
list_display = ["route_name", "company", "contract_number", "route_travellers"]
readonly_fields = ["traveller_count"]
- actions = ["email_company", "bus_roll"]
+ actions = ["email_company", "show_bus_roll"]
inlines = [DriverInline, BusStopInline]
fieldsets = [
(None, {'fields': [
diff --git a/busManager/coord/context_helpers.py b/busManager/coord/context_helpers.py
new file mode 100644
index 0000000..d62f85c
--- /dev/null
+++ b/busManager/coord/context_helpers.py
@@ -0,0 +1,40 @@
+from coord.models import Bus, BusStop, TravellerRoute
+
+
+def bus_roll_context(queryset=None):
+ bus_routes = []
+ if queryset is None:
+ buses = Bus.objects.all()
+ else:
+ buses = queryset
+
+ for bus in buses:
+ bus_route = []
+
+ for bus_stop in BusStop.objects.filter(bus=bus):
+ traveller_list = []
+ for trav_route in TravellerRoute.objects.filter(busStop=bus_stop):
+ traveller = trav_route.traveller
+ if not traveller.is_active():
+ continue
+ is_fared = "---"
+ if traveller.eligibility_status == "2":
+ is_fared = "Y"
+ traveller_list.append({
+ 'display': f"{traveller} ({traveller.get_year_level_display()}, {traveller.school.shortName})",
+ 'isFared': is_fared
+ })
+ stop_result = {
+ 'stop_num': bus_stop.get_stop_number(),
+ 'name': bus_stop.address,
+ 'am': bus_stop.am_time,
+ 'pm': bus_stop.pm_time,
+ 'travellers': traveller_list
+ }
+ # print(traveller_list)
+ bus_route.append(stop_result)
+
+ # Todo Add shuttles
+
+ bus_routes.append({'bus': bus, 'stops': bus_route})
+ return {'routes': bus_routes}
diff --git a/busManager/coord/email_helpers.py b/busManager/coord/email_helpers.py
new file mode 100644
index 0000000..7e7791a
--- /dev/null
+++ b/busManager/coord/email_helpers.py
@@ -0,0 +1,47 @@
+from datetime import date
+from io import BytesIO
+
+from django.contrib.admin.views.decorators import staff_member_required
+from django.core.mail import send_mail, EmailMessage
+from django.http import HttpResponse
+from django.template.loader import get_template
+from xhtml2pdf import pisa
+
+from coord.context_helpers import bus_roll_context
+from coord.models import Company
+
+
+def render_to_pdf(template, context):
+ html = get_template(template).render(context)
+ result = BytesIO()
+ pdf = pisa.pisaDocument(BytesIO(html.encode("ISO-8859-1")), result)
+ if pdf.err:
+ return HttpResponse("Invalid PDF", status_code=400, content_type='text/plan')
+ return HttpResponse(result.getvalue(), content_type='application/pdf')
+
+
+@staff_member_required
+def email_companies_bus_roll(request, query_set=None):
+ html_template = 'reports/bus_roll.html'
+ context = bus_roll_context(query_set)
+
+ for company in Company.objects.all():
+ company_route = []
+ for route in context.get("routes"):
+ bus = route.get("bus")
+ if route.get("bus").company == company:
+ company_route.append(route)
+ if not company_route:
+ continue
+ company_context = {'routes': company_route}
+ pdf = render_to_pdf(html_template, company_context)
+
+ subject = "Echuca Schools Bus Roll"
+ message = f"A new bus roll for {company.name} has been generated"
+ email_from = "bus.manager@education.vic.gov.au"
+ recipient = ["john.mullins@education.vic.gov.au", "nicole.edwards@education.vic.gov.au"]
+ email = EmailMessage(subject, message, email_from, recipient)
+ email.attach(f"school_bus_roll_{date.today()}.pdf", pdf.content)
+ email.send()
+
+ return render_to_pdf(html_template, context)
diff --git a/busManager/coord/templates/reports/bus_roll.html b/busManager/coord/templates/reports/bus_roll.html
index f875fc4..f4e9928 100644
--- a/busManager/coord/templates/reports/bus_roll.html
+++ b/busManager/coord/templates/reports/bus_roll.html
@@ -6,35 +6,24 @@
width: 100%;
}
- table.traveller th {
- text-align: left;
- border-bottom: 2px solid #000;
- }
-
-
table.traveller td {
- table-layout: fixed;
- border-bottom: 2px solid #000;
- border-right-style: dashed;
- width: 100%;
- min-width: 30px;
+ border: 2px solid #000;
}
-
hr {
- border: 2px solid;
+ border: 3px solid;
}
{% for route in routes %}
-
{{ route.route_name }}
+ {{ route.bus.route_name }}
{% for stop in route.stops %}
-
+
- | Student |
- Fare |
- Mon AM |
- Mon PM |
- Tue AM |
- Tue PM |
- Wed AM |
- Wed PM |
- Thu AM |
- Thu PM |
- Fri AM |
- Fri PM |
+ Student |
+ Fare |
+ Mon AM |
+ Mon PM |
+ Tue AM |
+ Tue PM |
+ Wed AM |
+ Wed PM |
+ Thu AM |
+ Thu PM |
+ Fri AM |
+ Fri PM |
{% for traveller in stop.travellers %}
- | {{ traveller.display }} |
- {{ traveller.isFared }} |
+ {{ traveller.display }} |
+ {{ traveller.isFared }} |
|
|
|
diff --git a/busManager/coord/urls.py b/busManager/coord/urls.py
index affe351..0badad9 100644
--- a/busManager/coord/urls.py
+++ b/busManager/coord/urls.py
@@ -6,5 +6,6 @@ urlpatterns = [
path("roll", views.bus_roll, name="Student Roll"),
path("contacts", views.emergency_contacts, name="Emergency Contacts"),
path("stops", views.bus_summary, name="Stop Summary"),
- path("summary", views.bus_numbers, name="Bus Summary")
+ path("summary", views.bus_numbers, name="Bus Summary"),
+ path("testemail", views.TestEmail, name="Test Email")
]
diff --git a/busManager/coord/views.py b/busManager/coord/views.py
index c2c31b2..67ff878 100644
--- a/busManager/coord/views.py
+++ b/busManager/coord/views.py
@@ -2,6 +2,8 @@ from django.contrib.admin.views.decorators import staff_member_required
from django.http import HttpResponse
from django.shortcuts import render
from django.views.generic import ListView
+
+from .context_helpers import bus_roll_context
from .models import Company, Bus, Traveller, BusStop, TravellerRoute, Shuttle, Driver
@@ -46,43 +48,7 @@ def bus_numbers(request):
@staff_member_required
def bus_roll(request, queryset=None):
- bus_routes = []
- if queryset is None:
- buses = Bus.objects.all()
- else:
- buses = queryset
-
- for bus in buses:
- bus_route = []
-
- for bus_stop in BusStop.objects.filter(bus=bus):
- traveller_list = []
- for trav_route in TravellerRoute.objects.filter(busStop=bus_stop):
- traveller = trav_route.traveller
- if not traveller.is_active():
- continue
- is_fared = "---"
- if traveller.eligibility_status == "2":
- is_fared = "Y"
- traveller_list.append({
- 'display': f"{traveller} ({traveller.get_year_level_display()}, {traveller.school.shortName})",
- 'isFared': is_fared
- })
- stop_result = {
- 'stop_num': bus_stop.get_stop_number(),
- 'name': bus_stop.address,
- 'am': bus_stop.am_time,
- 'pm': bus_stop.pm_time,
- 'travellers': traveller_list
- }
- # print(traveller_list)
- bus_route.append(stop_result)
-
- # Todo Add shuttles
-
- bus_routes.append({'route_name': bus.route_name, 'stops': bus_route})
-
- return render(request, 'reports/bus_roll.html', {'routes': bus_routes})
+ return render(request, 'reports/bus_roll.html', bus_roll_context(queryset))
@staff_member_required
diff --git a/requirements.txt b/requirements.txt
index 3e38630..e175673 100644
Binary files a/requirements.txt and b/requirements.txt differ