def _label(self, event, item_or_variation, avail, override_price=None, initial=False): if isinstance(item_or_variation, ItemVariation): variation = item_or_variation item = item_or_variation.item price = variation.price label = variation.value else: item = item_or_variation price = item.default_price label = item.name if override_price: price = override_price if self.price_included: price = TAXED_ZERO else: price = item.tax(price) if not price.gross: n = '{name}'.format( name=label ) elif not price.rate: n = _('{name} (+ {price})').format( name=label, price=money_filter(price.gross, event.currency) ) elif event.settings.display_net_prices: n = _('{name} (+ {price} plus {taxes}% {taxname})').format( name=label, price=money_filter(price.net, event.currency), taxes=number_format(price.rate), taxname=price.name ) else: n = _('{name} (+ {price} incl. {taxes}% {taxname})').format( name=label, price=money_filter(price.gross, event.currency), taxes=number_format(price.rate), taxname=price.name ) if not initial: if avail[0] < Quota.AVAILABILITY_RESERVED: n += ' – {}'.format(_('SOLD OUT')) elif avail[0] < Quota.AVAILABILITY_OK: n += ' – {}'.format(_('Currently unavailable')) else: if avail[1] is not None and item.do_show_quota_left: n += ' – {}'.format(_('%(num)s currently available') % {'num': avail[1]}) if not isinstance(item_or_variation, ItemVariation) and item.picture: n = escape(n) n += '<br>' n += '<a href="{}" class="productpicture" data-title="{}" data-lightbox={}>'.format( item.picture.url, escape(escape(item.name)), item.id ) n += '<img src="{}" alt="{}">'.format( thumb(item.picture, '60x60^'), escape(item.name) ) n += '</a>' n = mark_safe(n) return n
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 price = variation.price label = variation.value else: item = item_or_variation price = item.default_price label = item.name if override_price: price = override_price if self.price_included: price = TAXED_ZERO else: price = item.tax(price) if not price.gross: n = '{name}'.format( name=label ) elif not price.rate: n = _('{name} (+ {price})').format( name=label, price=money_filter(price.gross, event.currency) ) elif event.settings.display_net_prices: n = _('{name} (+ {price} plus {taxes}% {taxname})').format( name=label, price=money_filter(price.net, event.currency), taxes=number_format(price.rate), taxname=price.name ) else: n = _('{name} (+ {price} incl. {taxes}% {taxname})').format( name=label, price=money_filter(price.gross, event.currency), taxes=number_format(price.rate), taxname=price.name ) if avail[0] < 20: n += ' – {}'.format(_('SOLD OUT')) elif avail[0] < 100: n += ' – {}'.format(_('Currently unavailable')) else: if avail[1] is not None and event.settings.show_quota_left: n += ' – {}'.format(_('%(num)s currently available') % {'num': avail[1]}) if not isinstance(item_or_variation, ItemVariation) and item.picture: n = escape(n) n += '<br>' n += '<a href="{}" class="productpicture" data-title="{}" data-lightbox={}>'.format( item.picture.url, escape(escape(item.name)), item.id ) n += '<img src="{}" alt="{}">'.format( thumb(item.picture, '60x60^'), escape(item.name) ) n += '</a>' n = mark_safe(n) return n
def __init__(self, *args, **kwargs): """ Takes additional keyword arguments: :param iao: The ItemAddOn object :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 """ self.iao = kwargs.pop('iao') category = self.iao.addon_category self.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') self.price_included = kwargs.pop('price_included') self.sales_channel = kwargs.pop('sales_channel') self.base_position = kwargs.pop('base_position') super().__init__(*args, **kwargs) 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_available( channel=self.sales_channel, allow_addons=True ).select_related('tax_rule').prefetch_related( Prefetch('quotas', to_attr='_subevent_quotas', queryset=self.event.quotas.filter(subevent=subevent)), Prefetch('variations', to_attr='available_variations', queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).prefetch_related( Prefetch('quotas', to_attr='_subevent_quotas', queryset=self.event.quotas.filter(subevent=subevent)) ).distinct()), 'event' ).annotate( quotac=Count('quotas'), has_variations=Count('variations') ).filter( quotac__gt=0 ).order_by('category__position', 'category_id', 'position', 'name') item_cache[ckey] = items else: items = item_cache[ckey] self.vars_cache = {} for i in items: if i.hidden_if_available: q = i.hidden_if_available.availability(_cache=quota_cache) if q[0] == Quota.AVAILABILITY_OK: continue if i.has_variations: choices = [('', _('no selection'), '')] for v in i.available_variations: cached_availability = v.check_quotas(subevent=subevent, _cache=quota_cache) if self.event.settings.hide_sold_out and cached_availability[0] < Quota.AVAILABILITY_RESERVED: continue if v._subevent_quotas: self.vars_cache[v.pk] = v choices.append( (v.pk, self._label(self.event, v, cached_availability, override_price=var_price_override.get(v.pk)), v.description) ) n = i.name if i.picture: n = escape(n) n += '<br>' n += '<a href="{}" class="productpicture" data-title="{}" data-lightbox="{}">'.format( i.picture.url, escape(escape(i.name)), i.id ) n += '<img src="{}" alt="{}">'.format( thumb(i.picture, '60x60^'), escape(i.name) ) n += '</a>' n = mark_safe(n) field = AddOnVariationField( choices=choices, label=n, required=False, widget=AddOnRadioSelect, help_text=rich_text(str(i.description)), initial=current_addons.get(i.pk), ) field.item = i if len(choices) > 1: self.fields['item_%s' % i.pk] = field else: if not i._subevent_quotas: continue cached_availability = i.check_quotas(subevent=subevent, _cache=quota_cache) if self.event.settings.hide_sold_out and cached_availability[0] < Quota.AVAILABILITY_RESERVED: continue field = forms.BooleanField( label=self._label(self.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)), ) field.item = i self.fields['item_%s' % i.pk] = field
def __init__(self, *args, **kwargs): """ Takes additional keyword arguments: :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') self.price_included = kwargs.pop('price_included') self.sales_channel = kwargs.pop('sales_channel') super().__init__(*args, **kwargs) 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_available( channel=self.sales_channel, allow_addons=True ).select_related('tax_rule').prefetch_related( 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).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[ckey] = items else: 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(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) ) n = i.name if i.picture: n = escape(n) n += '<br>' n += '<a href="{}" class="productpicture" data-title="{}" data-lightbox="{}">'.format( i.picture.url, escape(escape(i.name)), i.id ) n += '<img src="{}" alt="{}">'.format( thumb(i.picture, '60x60^'), escape(i.name) ) n += '</a>' n = mark_safe(n) field = AddOnVariationField( choices=choices, label=n, required=False, widget=AddOnRadioSelect, 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: 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, 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