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 %} -
+
- - - + + + @@ -44,23 +33,23 @@
Stop Number #{{ stop.stop_num }}Pickup TimeDrop-off TimeStop Number #{{ stop.stop_num }}Pickup TimeDrop-off Time
{{ stop.name }}
- - - - - - - - - - - - + + + + + + + + + + + + {% for traveller in stop.travellers %} - - + + 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
StudentFareMon AMMon PMTue AMTue PMWed AMWed PMThu AMThu PMFri AMFri PMStudentFareMon AMMon PMTue AMTue PMWed AMWed PMThu AMThu PMFri AMFri PM
{{ traveller.display }}{{ traveller.isFared }}{{ traveller.display }}{{ traveller.isFared }}