Voucher creation: Auto-select products based on seat

This commit is contained in:
Raphael Michel
2019-11-22 13:15:33 +01:00
parent ee4f75c2fb
commit 84fb25e4d9
3 changed files with 29 additions and 14 deletions

View File

@@ -78,7 +78,7 @@ class VoucherSerializer(I18nAwareModelSerializer):
if full_data.get('seat'): if full_data.get('seat'):
data['seat'] = Voucher.clean_seat_id( data['seat'] = Voucher.clean_seat_id(
full_data, full_data.get('item'), self.context.get('event'), full_data, full_data.get('item'), full_data.get('quota'), self.context.get('event'),
self.instance.pk if self.instance else None self.instance.pk if self.instance else None
) )

View File

@@ -217,11 +217,12 @@ class Voucher(LoggedModel):
self.event, self.event,
self.quota, self.quota,
self.item, self.item,
self.variation self.variation,
seats_given=bool(self.seat)
) )
@staticmethod @staticmethod
def clean_item_properties(data, event, quota, item, variation): def clean_item_properties(data, event, quota, item, variation, seats_given=False):
if quota: if quota:
if quota.event != event: if quota.event != event:
raise ValidationError(_('You cannot select a quota that belongs to a different event.')) raise ValidationError(_('You cannot select a quota that belongs to a different event.'))
@@ -240,7 +241,7 @@ class Voucher(LoggedModel):
'Otherwise it might be unclear which quotas to block.')) 'Otherwise it might be unclear which quotas to block.'))
if item.category and item.category.is_addon: if item.category and item.category.is_addon:
raise ValidationError(_('It is currently not possible to create vouchers for add-on products.')) raise ValidationError(_('It is currently not possible to create vouchers for add-on products.'))
else: elif not seats_given:
raise ValidationError(_('You need to specify either a quota or a product.')) raise ValidationError(_('You need to specify either a quota or a product.'))
@staticmethod @staticmethod
@@ -342,14 +343,18 @@ class Voucher(LoggedModel):
raise ValidationError(_('A voucher with this code already exists.')) raise ValidationError(_('A voucher with this code already exists.'))
@staticmethod @staticmethod
def clean_seat_id(data, item, event, pk): def clean_seat_id(data, item, quota, event, pk):
try: try:
if event.has_subevents: if event.has_subevents:
if not data.get('subevent'): if not data.get('subevent'):
raise ValidationError(_('You need to choose a date if you select a seat.')) raise ValidationError(_('You need to choose a date if you select a seat.'))
seat = event.seats.get(seat_guid=data.get('seat'), subevent=data.get('subevent')) seat = event.seats.select_related('product').get(
seat_guid=data.get('seat'), subevent=data.get('subevent')
)
else: else:
seat = event.seats.get(seat_guid=data.get('seat')) seat = event.seats.select_related('product').get(
seat_guid=data.get('seat')
)
except Seat.DoesNotExist: except Seat.DoesNotExist:
raise ValidationError(_('The specified seat ID "{id}" does not exist for this event.').format( raise ValidationError(_('The specified seat ID "{id}" does not exist for this event.').format(
id=data.get('seat'))) id=data.get('seat')))
@@ -359,13 +364,13 @@ class Voucher(LoggedModel):
'different voucher).').format( 'different voucher).').format(
id=seat.seat_guid)) id=seat.seat_guid))
if not item: if quota:
raise ValidationError(_('You need to choose a specific product if you select a seat.')) raise ValidationError(_('You need to choose a specific product if you select a seat.'))
if data.get('max_usages', 1) > 1: if data.get('max_usages', 1) > 1:
raise ValidationError(_('Seat-specific vouchers can only be used once.')) raise ValidationError(_('Seat-specific vouchers can only be used once.'))
if seat.product != item: if item and seat.product != item:
raise ValidationError(_('You need to choose the product "{prod}" for this seat.').format(prod=seat.product)) raise ValidationError(_('You need to choose the product "{prod}" for this seat.').format(prod=seat.product))
if not seat.is_available(ignore_voucher_id=pk): if not seat.is_available(ignore_voucher_id=pk):

View File

@@ -113,7 +113,6 @@ class VoucherForm(I18nModelForm):
} }
) )
self.fields['itemvar'].widget.choices = self.fields['itemvar'].choices self.fields['itemvar'].widget.choices = self.fields['itemvar'].choices
self.fields['itemvar'].required = True
if self.instance.event.seating_plan or self.instance.event.subevents.filter(seating_plan__isnull=False).exists(): if self.instance.event.seating_plan or self.instance.event.subevents.filter(seating_plan__isnull=False).exists():
self.fields['seat'] = forms.CharField( self.fields['seat'] = forms.CharField(
@@ -124,11 +123,14 @@ class VoucherForm(I18nModelForm):
initial=self.instance.seat.seat_guid if self.instance.seat else '', initial=self.instance.seat.seat_guid if self.instance.seat else '',
help_text=str(self.instance.seat) if self.instance.seat else '', help_text=str(self.instance.seat) if self.instance.seat else '',
) )
self.fields['itemvar'].required = False
else:
self.fields['itemvar'].required = True
def clean(self): def clean(self):
data = super().clean() data = super().clean()
if not self._errors: if not self._errors and self.data.get('itemvar'):
try: try:
itemid = quotaid = None itemid = quotaid = None
iv = self.data.get('itemvar', '') iv = self.data.get('itemvar', '')
@@ -162,7 +164,8 @@ class VoucherForm(I18nModelForm):
Voucher.clean_item_properties( Voucher.clean_item_properties(
data, self.instance.event, data, self.instance.event,
self.instance.quota, self.instance.item, self.instance.variation self.instance.quota, self.instance.item, self.instance.variation,
seats_given=data.get('seat') or data.get('seats')
) )
if not self.instance.show_hidden_items and ( if not self.instance.show_hidden_items and (
(self.instance.quota and all(i.hide_without_voucher for i in self.instance.quota.items.all())) (self.instance.quota and all(i.hide_without_voucher for i in self.instance.quota.items.all()))
@@ -190,7 +193,10 @@ class VoucherForm(I18nModelForm):
) )
Voucher.clean_voucher_code(data, self.instance.event, self.instance.pk) Voucher.clean_voucher_code(data, self.instance.event, self.instance.pk)
if 'seat' in self.fields and data.get('seat'): if 'seat' in self.fields and data.get('seat'):
self.instance.seat = Voucher.clean_seat_id(data, self.instance.item, self.instance.event, self.instance.pk) self.instance.seat = Voucher.clean_seat_id(
data, self.instance.item, self.instance.quota, self.instance.event, self.instance.pk
)
self.instance.item = self.instance.seat.product
voucher_form_validation.send(sender=self.instance.event, form=self, data=data) voucher_form_validation.send(sender=self.instance.event, form=self, data=data)
@@ -357,7 +363,10 @@ class VoucherBulkForm(VoucherForm):
data['seats'] = [] data['seats'] = []
for s in seatids: for s in seatids:
data['seat'] = s data['seat'] = s
data['seats'].append(Voucher.clean_seat_id(data, self.instance.item, self.instance.event, None)) data['seats'].append(Voucher.clean_seat_id(
data, self.instance.item, self.instance.quota, self.instance.event, None
))
self.instance.seat = data['seats'][0] # Trick model-level validation
else: else:
data['seats'] = [] data['seats'] = []
@@ -371,6 +380,7 @@ class VoucherBulkForm(VoucherForm):
obj.code = code obj.code = code
try: try:
obj.seat = self.cleaned_data['seats'].pop() obj.seat = self.cleaned_data['seats'].pop()
obj.item = obj.seat.product
except IndexError: except IndexError:
pass pass
data = dict(self.cleaned_data) data = dict(self.cleaned_data)