44 create_addition_admin_log_entry ,
55 create_change_admin_log_entry ,
66)
7+ from django .db .models import Value , IntegerField
8+
9+ from django .db .models import Sum
10+ from django .db .models .functions import Coalesce
711from conferences .models .conference_voucher import ConferenceVoucher
812from pycon .constants import UTC
913from custom_admin .admin import (
@@ -402,6 +406,7 @@ def queryset(self, request, queryset):
402406class GrantReimbursementCategoryAdmin (ConferencePermissionMixin , admin .ModelAdmin ):
403407 list_display = ("__str__" , "max_amount" , "category" , "included_by_default" )
404408 list_filter = ("conference" , "category" , "included_by_default" )
409+ search_fields = ("category" , "name" )
405410
406411
407412@admin .register (GrantReimbursement )
@@ -416,23 +421,32 @@ class GrantReimbursementAdmin(ConferencePermissionMixin, admin.ModelAdmin):
416421 autocomplete_fields = ("grant" ,)
417422
418423
424+ class GrantReimbursementInline (admin .TabularInline ):
425+ model = GrantReimbursement
426+ extra = 0
427+ autocomplete_fields = ["category" ]
428+ fields = ["category" , "granted_amount" ]
429+
430+
419431@admin .register (Grant )
420432class GrantAdmin (ExportMixin , ConferencePermissionMixin , admin .ModelAdmin ):
421433 change_list_template = "admin/grants/grant/change_list.html"
422434 resource_class = GrantResource
423435 list_display = (
424- "user_display_name " ,
436+ "user " ,
425437 "country" ,
426438 "is_proposed_speaker" ,
427439 "is_confirmed_speaker" ,
428440 "emoji_gender" ,
429441 "conference" ,
430442 "status" ,
431443 "approved_type" ,
444+ "approved_amounts_display" ,
432445 "ticket_amount" ,
433446 "travel_amount" ,
434447 "accommodation_amount" ,
435448 "total_amount" ,
449+ "total_amount_display" ,
436450 "country_type" ,
437451 "user_has_ticket" ,
438452 "has_voucher" ,
@@ -472,6 +486,7 @@ class GrantAdmin(ExportMixin, ConferencePermissionMixin, admin.ModelAdmin):
472486 "delete_selected" ,
473487 ]
474488 autocomplete_fields = ("user" ,)
489+ inlines = [GrantReimbursementInline ]
475490
476491 fieldsets = (
477492 (
@@ -607,10 +622,22 @@ def user_has_ticket(self, obj: Grant) -> bool:
607622 def has_voucher (self , obj : Grant ) -> bool :
608623 return obj .has_voucher
609624
625+ @admin .display (description = "Total" )
626+ def total_amount_display (self , obj ):
627+ return f"{ obj .total_allocated :.2f} "
628+
629+ @admin .display (description = "Approved Reimbursements" )
630+ def approved_amounts_display (self , obj ):
631+ return ", " .join (
632+ f"{ r .category .name } : { r .granted_amount } " for r in obj .reimbursements .all ()
633+ )
634+
610635 def get_queryset (self , request ):
611636 qs = (
612637 super ()
613638 .get_queryset (request )
639+ .select_related ("user" )
640+ .prefetch_related ("reimbursements__category" )
614641 .annotate (
615642 is_proposed_speaker = Exists (
616643 Submission .objects .non_cancelled ().filter (
@@ -631,6 +658,11 @@ def get_queryset(self, request):
631658 user_id = OuterRef ("user_id" ),
632659 )
633660 ),
661+ total_allocated = Coalesce (
662+ Sum ("reimbursements__granted_amount" ),
663+ Value (0 ),
664+ output_field = IntegerField (),
665+ ),
634666 )
635667 )
636668
0 commit comments