forked from CGM_Public/pretix_original
Add sub-events and relative date settings (#503)
* Data model * little crud * SubEventItemForm etc * Drop SubEventItem.active, quota editor * Fix failing tests * First frontend stuff * Addons form stuff * Quota calculation * net price display on EventIndex * Add tests, solve some bugs * Correct quota selection in more places, consolidate pricing logic * Fix failing quota tests * Fix TypeError * Add tests for checkout * Fixed a bug in QuotaForm * Prevent immutable cart if a quota was removed from an item * Add tests for pricing * Handle waiting list * Filter in check-in list * Fixed import lost in rebase * Fix waiting list widget * Voucher management * Voucher redemption * Fix broken tests * Add subevents to OrderChangeManager * Create a subevent during event creation * Fix bulk voucher creation * Introduce subevent.active * Copy from for subevents * Show active in list * ICal download for subevents * Check start and end of presale * Failing tests / show cart logic * Test * Rebase migrations * REST API integration of sub-events * Integrate quota calculation into the traditional quota form * Make subevent argument to add_position optional * Log-display foo * pretixdroid and subevents * Filter by subevent * Add more tests * Some mor tests * Rebase fixes * More tests * Relative dates * Restrict selection in relative datetime widgets * Filter subevent list * Re-label has_subevents * Rebase fixes, subevents in calendar view * Performance and caching issues * Refactor calendar templates * Permission tests * Calendar fixes and month selection * subevent selection * Rename subevents to dates * Add tests for calendar views
This commit is contained in:
@@ -10,6 +10,7 @@ from django.utils.formats import number_format
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
from pretix.base.decimal import round_decimal
|
||||
from pretix.base.models import ItemVariation, Question
|
||||
from pretix.base.models.orders import InvoiceAddress, OrderPosition
|
||||
from pretix.base.templatetags.rich_text import rich_text
|
||||
@@ -274,7 +275,7 @@ class AddOnsForm(forms.Form):
|
||||
This form class is responsible for selecting add-ons to a product in the cart.
|
||||
"""
|
||||
|
||||
def _label(self, event, item_or_variation, avail):
|
||||
def _label(self, event, item_or_variation, avail, override_price=None):
|
||||
if isinstance(item_or_variation, ItemVariation):
|
||||
variation = item_or_variation
|
||||
item = item_or_variation.item
|
||||
@@ -287,6 +288,11 @@ class AddOnsForm(forms.Form):
|
||||
price_net = item.default_price_net
|
||||
label = item.name
|
||||
|
||||
if override_price:
|
||||
price = override_price
|
||||
tax_value = round_decimal(price * (1 - 100 / (100 + item.tax_rate)))
|
||||
price_net = price - tax_value
|
||||
|
||||
if not price:
|
||||
n = '{name}'.format(
|
||||
name=label
|
||||
@@ -319,19 +325,29 @@ class AddOnsForm(forms.Form):
|
||||
|
||||
:param category: The category to choose from
|
||||
:param event: The event this belongs to
|
||||
:param subevent: The event the parent cart position belongs to
|
||||
:param initial: The current set of add-ons
|
||||
:param quota_cache: A shared dictionary for quota caching
|
||||
:param item_cache: A shared dictionary for item/category caching
|
||||
"""
|
||||
category = kwargs.pop('category')
|
||||
event = kwargs.pop('event')
|
||||
subevent = kwargs.pop('subevent')
|
||||
current_addons = kwargs.pop('initial')
|
||||
quota_cache = kwargs.pop('quota_cache')
|
||||
item_cache = kwargs.pop('item_cache')
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
if category.pk not in item_cache:
|
||||
if subevent:
|
||||
item_price_override = subevent.item_price_overrides
|
||||
var_price_override = subevent.var_price_overrides
|
||||
else:
|
||||
item_price_override = {}
|
||||
var_price_override = {}
|
||||
|
||||
ckey = '{}-{}'.format(subevent.pk if subevent else 0, category.pk)
|
||||
if ckey not in item_cache:
|
||||
# Get all items to possibly show
|
||||
items = category.items.filter(
|
||||
Q(active=True)
|
||||
@@ -339,26 +355,37 @@ class AddOnsForm(forms.Form):
|
||||
& Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
|
||||
& Q(hide_without_voucher=False)
|
||||
).prefetch_related(
|
||||
'variations__quotas', # for .availability()
|
||||
Prefetch('quotas', queryset=event.quotas.all()),
|
||||
Prefetch('quotas',
|
||||
to_attr='_subevent_quotas',
|
||||
queryset=event.quotas.filter(subevent=subevent)),
|
||||
Prefetch('variations', to_attr='available_variations',
|
||||
queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).distinct()),
|
||||
queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).prefetch_related(
|
||||
Prefetch('quotas',
|
||||
to_attr='_subevent_quotas',
|
||||
queryset=event.quotas.filter(subevent=subevent))
|
||||
).distinct()),
|
||||
).annotate(
|
||||
quotac=Count('quotas'),
|
||||
has_variations=Count('variations')
|
||||
).filter(
|
||||
quotac__gt=0
|
||||
).order_by('category__position', 'category_id', 'position', 'name')
|
||||
item_cache[category.pk] = items
|
||||
item_cache[ckey] = items
|
||||
else:
|
||||
items = item_cache[category.pk]
|
||||
items = item_cache[ckey]
|
||||
|
||||
for i in items:
|
||||
if i.has_variations:
|
||||
choices = [('', _('no selection'), '')]
|
||||
for v in i.available_variations:
|
||||
cached_availability = v.check_quotas(_cache=quota_cache)
|
||||
choices.append((v.pk, self._label(event, v, cached_availability), v.description))
|
||||
cached_availability = v.check_quotas(subevent=subevent, _cache=quota_cache)
|
||||
if v._subevent_quotas:
|
||||
choices.append(
|
||||
(v.pk,
|
||||
self._label(event, v, cached_availability,
|
||||
override_price=var_price_override.get(v.pk)),
|
||||
v.description)
|
||||
)
|
||||
|
||||
field = AddOnVariationField(
|
||||
choices=choices,
|
||||
@@ -368,13 +395,17 @@ class AddOnsForm(forms.Form):
|
||||
help_text=rich_text(str(i.description)),
|
||||
initial=current_addons.get(i.pk),
|
||||
)
|
||||
if len(choices) > 1:
|
||||
self.fields['item_%s' % i.pk] = field
|
||||
else:
|
||||
cached_availability = i.check_quotas(_cache=quota_cache)
|
||||
if not i._subevent_quotas:
|
||||
continue
|
||||
cached_availability = i.check_quotas(subevent=subevent, _cache=quota_cache)
|
||||
field = forms.BooleanField(
|
||||
label=self._label(event, i, cached_availability),
|
||||
label=self._label(event, i, cached_availability,
|
||||
override_price=item_price_override.get(i.pk)),
|
||||
required=False,
|
||||
initial=i.pk in current_addons,
|
||||
help_text=rich_text(str(i.description)),
|
||||
)
|
||||
|
||||
self.fields['item_%s' % i.pk] = field
|
||||
self.fields['item_%s' % i.pk] = field
|
||||
|
||||
Reference in New Issue
Block a user