Files
bus-manager/busManager/coord/admin.py
T
2023-09-01 15:18:20 +10:00

304 lines
11 KiB
Python

import csv
from datetime import date
from django.contrib.admin import DateFieldListFilter, BooleanFieldListFilter
from django.forms import widgets
from django.contrib import admin
from django.http import HttpResponse
from django.urls import reverse
from django.utils.html import format_html
from django.utils.http import urlencode
from django.utils.translation import gettext_lazy
from import_export.admin import ImportExportModelAdmin
from .adminClone import CloneModelAdmin
from .context_helpers import bus_roll_context, emergency_contacts_context, traveller_roll_context, \
traveller_route_context
from .email_helpers import email_companies_bus_roll, render_to_pdf, email_school_roll_csv
from .models import *
class BusRollMixin:
def show_bus_roll(self, request, queryset):
return render_to_pdf('reports/bus_roll.html', bus_roll_context(queryset))
def show_emergency_contacts(self, request, queryset):
return render_to_pdf('reports/emergency_contacts.html', emergency_contacts_context(queryset))
def email_company(self, request, queryset):
return email_companies_bus_roll(request, queryset)
email_company.short_description = "Email Bus Roll to Company"
class SchoolRollMixin:
def export_travellers_to_csv(self, request, queryset):
traveller_list = []
for school in queryset:
for travellerRoute in TravellerRoute.objects.filter(traveller__school=school):
if not travellerRoute.traveller.is_active():
continue
traveller_list.append(traveller_route_context(travellerRoute))
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = f"attachment; filename=traveller_list_{date.today()}.csv"
writer = csv.DictWriter(response, fieldnames=traveller_list[0].keys())
writer.writeheader()
writer.writerows(traveller_list)
return response
class TravellerRollMixin:
def export_to_csv(self, request, queryset):
traveller_list = traveller_roll_context(queryset)
response = HttpResponse(content_type="text/csv")
response["Content-Disposition"] = f"attachment; filename=traveller_list_{date.today()}.csv"
writer = csv.DictWriter(response, fieldnames=traveller_list[0].keys())
writer.writeheader()
writer.writerows(traveller_list)
return response
class ArchiveFilter(BooleanFieldListFilter):
parameter_name = 'is_archived'
def choices(self, changelist):
field_choices = dict(self.field.flatchoices)
for lookup, title in (
(None, gettext_lazy("All")),
("0", field_choices.get(True, gettext_lazy("Current"))),
("1", field_choices.get(False, gettext_lazy("Archived"))),
):
yield {
"selected": self.lookup_val == lookup and not self.lookup_val2,
"query_string": changelist.get_query_string(
{self.lookup_kwarg: lookup}, [self.lookup_kwarg2]
),
"display": title,
}
class HiddenNowTime(widgets.TimeInput):
pass
class MyImportExportModelAdmin(ImportExportModelAdmin):
def has_import_permission(self, request):
return request.user.is_superuser
@admin.register(Company)
class CompanyAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_display = ["name", "contact_name", "email", "buses"]
def buses(self, obj):
count = obj.bus_set.count()
url = (
reverse("admin:coord_bus_changelist")
+ "?"
+ urlencode({"company__id__exact": f"{obj.id}"})
)
return format_html('<a href="{}">{} Buses</a>', url, count)
def email(self, obj):
return format_html('<a href="mailto:{}">{}</a>', obj.contact_email, obj.contact_email)
class DriverInline(admin.StackedInline):
model = Driver
extra = 0
class BusStopInline(admin.TabularInline):
model = BusStop
extra = 0
ordering = ("am_time",)
@admin.register(Bus)
class BusesAdmin(MyImportExportModelAdmin, admin.ModelAdmin, BusRollMixin):
list_filter = ["company"]
list_display = ["route_name", "company", "contract_number", "seating_capacity", "route_travellers"]
readonly_fields = ["traveller_count"]
actions = ["email_company", "show_bus_roll", "show_emergency_contacts"]
inlines = [DriverInline, BusStopInline]
fieldsets = [
(None, {'fields': [
"company", "route_name", "contract_number", "registration",
"traveller_count", "seating_capacity", "make", "model", "notes"
]})
]
def route_travellers(self, obj):
url = (
reverse("admin:coord_traveller_changelist")
+ "?"
+ urlencode({"bus_stops__bus__id__exact": f"{obj.id}"})
)
return format_html('<a href="{}">{} Travellers</a>', url, obj.traveller_count())
@admin.register(BusStop)
class BusStopAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_filter = ["bus__company", "bus__route_name"]
list_display = ["__str__", "am_time", "pm_time", "address"]
search_fields = ["bus__route_name", "address"]
@admin.register(Suburb)
class SuburbsAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_filter = ["state"]
class TravellerRouteInline(admin.TabularInline):
model = TravellerRoute
extra = 0
@admin.register(Traveller)
class TravellerAdmin(MyImportExportModelAdmin, CloneModelAdmin, admin.ModelAdmin, TravellerRollMixin):
list_display = ["first_name", "last_name", "school", "year_level", "residential_address", "residential_suburb", "stop_route", "travel_start_date", "travel_end_date"]
list_filter = ["school", "eligibility_status", "bus_stops__bus", "residential_suburb", ("travel_end_date", DateFieldListFilter), ("is_archived", ArchiveFilter)]
search_fields = ["first_name", "last_name", "residential_address"]
cloneable_fields = ["last_name", "residential_address", "residential_suburb",
"postal_address", "postal_suburb", "eligibility_status", "shuttle",
"parent_A_firstname", "parent_A_lastname", "parent_A_phone", "parent_A_email",
"parent_B_firstname", "parent_B_lastname", "parent_B_phone", "parent_B_email",
"emergency_contact_A_firstname", "emergency_contact_A_lastname", "emergency_contact_A_phone",
"emergency_contact_A_relation", "emergency_contact_B_firstname", "emergency_contact_B_lastname",
"emergency_contact_B_phone", "emergency_contact_B_relation"]
inlines = [TravellerRouteInline]
readonly_fields = ["fare_paying", "created_on", "last_edit", "is_archived"]
actions = ["export_to_csv", "yearly_rollover"]
fieldsets = [
(None, {
'fields': [
"school",
"first_name",
"last_name",
"dob",
"year_level",
]
}),
('Address', {
'classes': ('collapse',),
'fields': [
"residential_address",
"residential_suburb",
"postal_address",
"postal_suburb",
]
}),
('Office Use', {
'classes': ('collapse',),
'fields': [
"distance_to_school",
"travel_start_date",
"travel_end_date",
"eligibility_status",
"fare_paying",
"term_1_paid",
"term_2_paid",
"term_3_paid",
"term_4_paid",
"assessment_date",
"application_form_completed",
"parent_notified",
"seat_number",
"created_on",
"last_edit",
"is_archived",
]
}),
('Adult Contacts', {
'classes': ('collapse',),
'fields': [
"parent_A_firstname",
"parent_A_lastname",
"parent_A_phone",
"parent_A_email",
"parent_B_firstname",
"parent_B_lastname",
"parent_B_phone",
"parent_B_email",
"emergency_contact_A_firstname",
"emergency_contact_A_lastname",
"emergency_contact_A_phone",
"emergency_contact_A_relation",
"emergency_contact_B_firstname",
"emergency_contact_B_lastname",
"emergency_contact_B_phone",
"emergency_contact_B_relation"
]
}),
(None, {'fields': ["notes", "shuttle"]})
]
# list_display_links = None
def yearly_rollover(self, request, queryset):
pass
def stop_route(self, obj):
stops = BusStop.objects.filter(traveller__id__exact=obj.id)
if stops.count() == 0:
return ""
if stops.count() == 1:
return stops.first()
return "Multiple"
def save_model(self, request, obj, form, change):
print("Saving")
if obj.is_archived and obj.travel_end_date is None:
obj.is_archived = False
print("Pulling out of archive")
super().save_model(request, obj, form, change)
@admin.register(TravellerRoute)
class TravellerRouteAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_display = ["traveller", "busStop"]
@admin.register(School)
class SchoolAdmin(MyImportExportModelAdmin, admin.ModelAdmin, SchoolRollMixin):
list_display = ["__str__", "address", "suburb", "school_email", "phone"]
actions = ["export_travellers_to_csv"]
def school_email(self, obj):
return format_html('<a href="mailto:{}">{}</a>', obj.email, obj.email)
@admin.register(Setting)
class SettingAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_display = ["name", "value"]
@admin.register(Shuttle)
class ShuttleAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_display = ["__str__", "school", "bus", "shuttle_travellers"]
def shuttle_travellers(self, obj):
url = (
reverse("admin:coord_traveller_changelist")
+ "?"
+ urlencode({"shuttle__id__exact": f"{obj.id}"})
)
return format_html('<a href="{}">{} Travellers</a>', url, obj.traveller_count())
@admin.register(Driver)
class DriverAdmin(MyImportExportModelAdmin, admin.ModelAdmin):
list_display = ["__str__", "route", "phone_number"]
def route(self, obj):
url = reverse("admin:coord_bus_change", args=(obj.bus.id,))
return format_html('<a href="{}">{}</a>', url, obj.bus)