44
55from django .contrib import admin , messages
66from django .contrib .admin import SimpleListFilter
7- from django .db import transaction
87from django .db .models import Exists , OuterRef
98from django .db .models .query import QuerySet
109from django .urls import reverse
1514from import_export .resources import ModelResource
1615
1716from conferences .models .conference_voucher import ConferenceVoucher
17+ from conferences .vouchers import create_conference_voucher
1818from countries import countries
1919from countries .filters import CountryFilter
2020from custom_admin .admin import (
4949
5050logger = logging .getLogger (__name__ )
5151
52+
5253EXPORT_GRANTS_FIELDS = (
5354 "name" ,
5455 "full_name" ,
@@ -297,20 +298,20 @@ def send_reply_email_waiting_list_update(modeladmin, request, queryset):
297298
298299@admin .action (description = "Create grant vouchers" )
299300@validate_single_conference_selection
300- @transaction .atomic
301301def create_grant_vouchers (modeladmin , request , queryset ):
302- conference = queryset .first ().conference
303- existing_vouchers_by_user_id = {
304- voucher .user_id : voucher
305- for voucher in ConferenceVoucher .objects .for_conference (conference ).filter (
306- user_id__in = queryset .values_list ("user_id" , flat = True ),
307- )
308- }
302+ grants_ordered = list (queryset .order_by ("id" ).select_related ("user" , "conference" ))
303+ conference_id = grants_ordered [0 ].conference_id if grants_ordered else None
304+ user_ids = {g .user_id for g in grants_ordered if g .user_id }
309305
310- vouchers_to_create = []
311- vouchers_to_update = []
306+ existing_by_user : Dict [int , ConferenceVoucher ] = {}
307+ if conference_id is not None and user_ids :
308+ for voucher in ConferenceVoucher .objects .filter (
309+ conference_id = conference_id ,
310+ user_id__in = user_ids ,
311+ ):
312+ existing_by_user [voucher .user_id ] = voucher
312313
313- for grant in queryset . order_by ( "id" ) :
314+ for grant in grants_ordered :
314315 if grant .status != Grant .Status .confirmed :
315316 messages .error (
316317 request ,
@@ -319,45 +320,54 @@ def create_grant_vouchers(modeladmin, request, queryset):
319320 )
320321 continue
321322
322- existing_voucher = existing_vouchers_by_user_id .get (grant .user_id )
323+ if not grant .user_id :
324+ messages .error (
325+ request ,
326+ f"Grant for { grant .name } has no user linked; can't create a voucher." ,
327+ )
328+ continue
323329
324- if not existing_voucher :
330+ existing = existing_by_user .get (grant .user_id )
331+
332+ if not existing :
333+ new_voucher = create_conference_voucher (
334+ conference = grant .conference ,
335+ user = grant .user ,
336+ voucher_type = ConferenceVoucher .VoucherType .GRANT ,
337+ )
338+ existing_by_user [grant .user_id ] = new_voucher
325339 create_addition_admin_log_entry (
326340 request .user ,
327341 grant ,
328342 change_message = "Created voucher for this grant." ,
329343 )
344+ continue
330345
331- vouchers_to_create .append (
332- ConferenceVoucher (
333- conference_id = grant .conference_id ,
334- user_id = grant .user_id ,
335- voucher_code = ConferenceVoucher .generate_code (),
336- voucher_type = ConferenceVoucher .VoucherType .GRANT ,
337- )
338- )
346+ if existing .voucher_type in (
347+ ConferenceVoucher .VoucherType .GRANT ,
348+ ConferenceVoucher .VoucherType .SPEAKER ,
349+ ):
339350 continue
340351
341- if existing_voucher .voucher_type == ConferenceVoucher .VoucherType .CO_SPEAKER :
352+ if existing .voucher_type == ConferenceVoucher .VoucherType .CO_SPEAKER :
342353 messages .warning (
343354 request ,
344- f"Grant for { grant .name } already has a Co-Speaker voucher. Upgrading to a Grant voucher." ,
355+ f"Grant for { grant .name } already has a Co-Speaker voucher. "
356+ "Upgrading to a Grant voucher." ,
345357 )
346358 create_change_admin_log_entry (
347359 request .user ,
348- existing_voucher ,
360+ existing ,
349361 change_message = "Upgraded Co-Speaker voucher to Grant voucher." ,
350362 )
351363 create_change_admin_log_entry (
352364 request .user ,
353365 grant ,
354366 change_message = "Updated existing Co-Speaker voucher to grant." ,
355367 )
356- existing_voucher .voucher_type = ConferenceVoucher .VoucherType .GRANT
357- vouchers_to_update .append (existing_voucher )
358-
359- ConferenceVoucher .objects .bulk_create (vouchers_to_create , ignore_conflicts = True )
360- ConferenceVoucher .objects .bulk_update (vouchers_to_update , ["voucher_type" ])
368+ existing .voucher_type = ConferenceVoucher .VoucherType .GRANT
369+ existing .voucher_email_sent_at = None
370+ existing .save (update_fields = ["voucher_type" , "voucher_email_sent_at" ])
361371
362372 messages .success (request , "Vouchers created!" )
363373
0 commit comments