from django.core import mail from django.contrib import admin, messages from django.db.models import Value from django.db.models.functions import Now, Concat, LPad from .models import ( CmsRedRiverVeteransScholarship, Department, CertificationDefinition, Certification, CertificationVersion, InstructorOrVendor, SpecialProgram, Waiver, ) from .forms import CertificationForm from .certification_emails import all_certification_emails @admin.register(Department) class DepartmentAdmin(admin.ModelAdmin): search_fields = ["name"] list_display = [ "name", "parent", "has_mailing_list", "shop_lead_flag", "list_reply_to_address", ] class CertificationVersionInline(admin.TabularInline): model = CertificationVersion extra = 1 readonly_fields = ( "semantic_version", "is_latest", "is_current", ) @admin.display(description="Latest", boolean=True) def is_latest(self, obj): return obj.is_latest @admin.display(description="Current", boolean=True) def is_current(self, obj): return obj.is_current @admin.register(CertificationDefinition) class CertificationDefinitionAdmin(admin.ModelAdmin): search_fields = ["certification_name"] list_display = [ "certification_name", "department", "latest_semantic_version", ] list_filter = ["department"] inlines = [CertificationVersionInline] @admin.display(description="Latest Version") def latest_semantic_version(self, obj): return obj.latest_version().semantic_version() @admin.register(Certification) class CertificationAdmin(admin.ModelAdmin): form = CertificationForm search_fields = [ "name", "certification_version__definition__certification_name", "certification_version__definition__department__name", ] autocomplete_fields = ["member"] exclude = ["shop_lead_notified"] def get_queryset(self, request): qs = super().get_queryset(request) return qs.prefetch_related("certification_version__definition__department") @admin.display( description="Certification Name", ordering="certification_version__definition__certification_name", ) def certification_name(self, obj): return obj.certification_version.definition.certification_name @admin.display( description="Certification Version", ordering=( Concat( LPad("certification_version__major", 4, Value("0")), LPad("certification_version__minor", 4, Value("0")), LPad("certification_version__patch", 4, Value("0")), "certification_version__prerelease", "certification_version__approval_date", ) ), ) def certification_semantic_version(self, obj): return obj.certification_version.semantic_version() @admin.display(description="Current", boolean=True) def is_current(self, obj): return obj.certification_version.is_current @admin.display( description="Department", ordering="certification_version__definition__department", ) def certification_department(self, obj): return obj.certification_version.definition.department list_display = [ "certification_name", "name", "certification_semantic_version", "is_current", "certification_department", "date", "shop_lead_notified", "certified_by", ] list_display_links = [ "certification_name", "name", ] list_filter = [ "certification_version__definition__department", ("shop_lead_notified", admin.EmptyFieldListFilter), ] actions = ["send_notifications"] @admin.action( description="Notify Shop Leads and Members of selected certifications" ) def send_notifications(self, request, queryset): try: emails = list(all_certification_emails(queryset)) with mail.get_connection() as conn: conn.send_messages(emails) for cert in queryset: cert.shop_lead_notified = Now() cert.save() self.message_user( request, f"{len(emails)} notifications sent for {len(queryset)} certifications", messages.SUCCESS, ) except Exception as e: self.message_user( request, f"Failed to send notifications! {e}", messages.ERROR, ) raise @admin.register(InstructorOrVendor) class InstructorOrVendorAdmin(admin.ModelAdmin): search_fields = ["name"] list_display = [ "name", "instructor_agreement_date", "w9_date", "phone", "email_address", ] @admin.register(SpecialProgram) class SpecialProgramAdmin(admin.ModelAdmin): search_fields = ["program_name"] list_display = [ "program_name", "discount_percent", "discount_code", "membership_code", "start_date", "end_date", "program_amount", "program_status", ] @admin.register(Waiver) class WaiverAdmin(admin.ModelAdmin): search_fields = ["name"] list_display = [ "name", "date", "emergency_contact_name", "emergency_contact_number", "waiver_version", "guardian_name", "guardian_relation", "guardian_date", ] admin.site.register(CmsRedRiverVeteransScholarship)