import csv from datetime import date 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 import_export.admin import ImportExportModelAdmin from rangefilter.filters import DateRangeFilterBuilder from .adminClone import CloneModelAdmin from .context_helpers import * from .email_helpers import email_companies_bus_roll, render_to_pdf, email_school_roll from .models import * from .utils.send_sms import send_sms 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 ShuttleRollMixin: def show_shuttle_roll(self, request, queryset): if queryset is None: buses = None else: buses = [] for shuttle in queryset: if shuttle.bus not in buses: buses.append(shuttle.bus) return render_to_pdf('reports/bus_roll.html', bus_roll_context(buses, include_bus_stops=False)) class SchoolRollMixin: def email_travellers_to_school(self, request, queryset): return email_school_roll(request, queryset) def show_school_travellers(self, request, queryset): return render_to_pdf('reports/school_roll.html', school_roll_context(queryset)) 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 confirmation_letter(self, request, queryset): return render_to_pdf('mail/confirmation_letter.html', confirmation_letter_context(queryset)) def send_sms(self, request, queryset): return send_sms(self, request, queryset) 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 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('{} Buses', url, count) def email(self, obj): return format_html('{}', 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('{} Travellers', 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 FamilyInline(admin.StackedInline): model = Family classes = ['collapse'] extra = 0 class TravellerRouteInline(admin.TabularInline): model = TravellerRoute extra = 0 @admin.register(Traveller) class TravellerAdmin(MyImportExportModelAdmin, admin.ModelAdmin, TravellerRollMixin): list_display = ["first_name", "last_name", "school", "year_level", "is_active", "address", "stop_route", "shuttle", "travel_start_date", "travel_end_date"] list_filter = [ "is_active", "school", "year_level", "eligibility_status", "bus_stops__bus", "shuttle", ("travel_start_date", DateRangeFilterBuilder( title="Start date" )), ("travel_end_date", DateRangeFilterBuilder( title="End date" )) ] search_fields = ["first_name", "last_name", "address"] inlines = [FamilyInline, TravellerRouteInline] readonly_fields = ["travel_start_date", "travel_end_date", "fare_paying", "created_on", "last_edit", "is_active", "address"] actions = ["export_to_csv", "send_sms", "confirmation_letter", "letter_creator"] fieldsets = [ (None, { 'fields': [ "is_active", "school", "first_name", "last_name", "year_level", "dob", "address", ] }), ('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", ] }), (None, {'fields': ["notes", "shuttle"]}) ] # list_display_links = None 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): # if obj.is_archived and obj.travel_end_date is None: # obj.is_archived = False # 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 = ["email_travellers_to_school", "show_school_travellers", "export_travellers_to_csv"] def school_email(self, obj): return format_html('{}', obj.email, obj.email) @admin.register(Setting) class SettingAdmin(MyImportExportModelAdmin, admin.ModelAdmin): list_display = ["name", "value"] @admin.register(Shuttle) class ShuttleAdmin(MyImportExportModelAdmin, admin.ModelAdmin, ShuttleRollMixin): list_display = ["__str__", "school", "bus", "shuttle_travellers"] actions = ["show_shuttle_roll"] def shuttle_travellers(self, obj): url = ( reverse("admin:coord_traveller_changelist") + "?" + urlencode({"shuttle__id__exact": f"{obj.id}"}) ) return format_html('{} Travellers', 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('{}', url, obj.bus)