import csv from django.contrib.admin import DateFieldListFilter from django.contrib.admin.views.decorators import staff_member_required 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 .adminClone import CloneModelAdmin from .context_helpers import bus_roll_context, emergency_contacts_context from .email_helpers import email_companies_bus_roll, render_to_pdf from .models import * class ExportCsvMixin: def export_as_csv(self, request, queryset): meta = self.model._meta field_names = [field.name for field in meta.fields] response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename={}.csv'.format(meta) writer = csv.writer(response) writer.writerow(field_names) for obj in queryset: row = writer.writerow([getattr(obj, field) for field in field_names]) return response export_as_csv.short_description = "Export Selected" 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 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"] # change_form_template = 'admin/change_form_busStops.html' def export_as_csv(self, request, queryset): pass @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): 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"] 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"] 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 actions = ["yearly_rollover"] 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): list_display = ["__str__", "address", "suburb", "school_email", "phone"] 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): 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('{} 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)