def _total_order_value(self): total = get_cart_total(self.request) total += sum([ f.value for f in get_fees(self.request.event, self.request, total, self.invoice_address, None) ]) return total
def get_cart_is_free(request): from pretix.presale.views.cart import cart_session if not hasattr(request, '_cart_free_cache'): cs = cart_session(request) ia = get_cart_invoice_address(request) total = get_cart_total(request) fees = get_fees(request.event, request, total, ia, cs.get('payment')) request._cart_free_cache = total + sum(f.value for f in fees) == Decimal('0.00') return request._cart_free_cache
def get_cart_is_free(request): from pretix.presale.views.cart import cart_session if not hasattr(request, '_cart_free_cache'): cs = cart_session(request) ia = get_cart_invoice_address(request) total = get_cart_total(request) fees = get_fees(request.event, request, total, ia, cs.get('payment')) request._cart_free_cache = total + sum(f.value for f in fees) == Decimal('0.00') return request._cart_free_cache
def get_cart(self, answers=False, queryset=None, order=None, downloads=False): if queryset: prefetch = [] if answers: prefetch.append('item__questions') prefetch.append( Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related( 'options'))) cartpos = queryset.order_by( 'item__category__position', 'item__category_id', 'item__position', 'item__name', 'variation__value').select_related( 'item', 'variation', 'addon_to', 'subevent', 'subevent__event', 'subevent__event__organizer').prefetch_related(*prefetch) else: cartpos = self.positions lcp = list(cartpos) has_addons = {cp.addon_to.pk for cp in lcp if cp.addon_to} pos_additional_fields = defaultdict(list) for cp in lcp: responses = question_form_fields.send(sender=self.request.event, position=cp) data = cp.meta_info_data for r, response in sorted(responses, key=lambda r: str(r[0])): if response: for key, value in response.items(): pos_additional_fields[cp.pk].append({ 'answer': data.get('question_form_data', {}).get(key), 'question': value.label }) # Group items of the same variation # We do this by list manipulations instead of a GROUP BY query, as # Django is unable to join related models in a .values() query def keyfunc(pos): if isinstance(pos, OrderPosition): if pos.addon_to: i = pos.addon_to.positionid else: i = pos.positionid else: if pos.addon_to: i = pos.addon_to.pk else: i = pos.pk has_attendee_data = pos.item.admission and ( self.request.event.settings.attendee_names_asked or self.request.event.settings.attendee_emails_asked or pos_additional_fields.get(pos.pk)) addon_penalty = 1 if pos.addon_to else 0 if downloads or pos.pk in has_addons or pos.addon_to: return i, addon_penalty, pos.pk, 0, 0, 0, 0, (pos.subevent_id or 0) if answers and (has_attendee_data or pos.item.questions.all()): return i, addon_penalty, pos.pk, 0, 0, 0, 0, (pos.subevent_id or 0) return (0, addon_penalty, 0, pos.item_id, pos.variation_id, pos.price, (pos.voucher_id or 0), (pos.subevent_id or 0)) positions = [] for k, g in groupby(sorted(lcp, key=keyfunc), key=keyfunc): g = list(g) group = g[0] group.count = len(g) group.total = group.count * group.price group.net_total = group.count * group.net_price group.has_questions = answers and k[0] != "" group.tax_rule = group.item.tax_rule if answers: group.cache_answers(all=False) group.additional_answers = pos_additional_fields.get(group.pk) positions.append(group) total = sum(p.total for p in positions) net_total = sum(p.net_total for p in positions) tax_total = sum(p.total - p.net_total for p in positions) if order: fees = order.fees.all() elif positions: fees = get_fees(self.request.event, self.request, total, self.invoice_address, self.cart_session.get('payment')) else: fees = [] total += sum([f.value for f in fees]) net_total += sum([f.net_value for f in fees]) tax_total += sum([f.tax_value for f in fees]) try: first_expiry = min(p.expires for p in positions) if positions else now() total_seconds_left = max(first_expiry - now(), timedelta()).total_seconds() minutes_left = int(total_seconds_left // 60) seconds_left = int(total_seconds_left % 60) except AttributeError: first_expiry = None minutes_left = None seconds_left = None return { 'positions': positions, 'raw': cartpos, 'total': total, 'net_total': net_total, 'tax_total': tax_total, 'fees': fees, 'answers': answers, 'minutes_left': minutes_left, 'seconds_left': seconds_left, 'first_expiry': first_expiry, }
def get_cart(self, answers=False, queryset=None, order=None, downloads=False): if queryset: prefetch = [] if answers: prefetch.append('item__questions') prefetch.append('answers') cartpos = queryset.order_by( 'item__category__position', 'item__category_id', 'item__position', 'item__name', 'variation__value' ).select_related( 'item', 'variation', 'addon_to', 'subevent', 'subevent__event', 'subevent__event__organizer' ).prefetch_related( *prefetch ) else: cartpos = self.positions lcp = list(cartpos) has_addons = {cp.addon_to.pk for cp in lcp if cp.addon_to} pos_additional_fields = defaultdict(list) for cp in lcp: responses = question_form_fields.send(sender=self.request.event, position=cp) data = cp.meta_info_data for r, response in sorted(responses, key=lambda r: str(r[0])): if response: for key, value in response.items(): pos_additional_fields[cp.pk].append({ 'answer': data.get('question_form_data', {}).get(key), 'question': value.label }) # Group items of the same variation # We do this by list manipulations instead of a GROUP BY query, as # Django is unable to join related models in a .values() query def keyfunc(pos): if isinstance(pos, OrderPosition): if pos.addon_to: i = pos.addon_to.positionid else: i = pos.positionid else: if pos.addon_to: i = pos.addon_to.pk else: i = pos.pk has_attendee_data = pos.item.admission and ( self.request.event.settings.attendee_names_asked or self.request.event.settings.attendee_emails_asked or pos_additional_fields.get(pos.pk) ) addon_penalty = 1 if pos.addon_to else 0 if downloads or pos.pk in has_addons or pos.addon_to: return i, addon_penalty, pos.pk, 0, 0, 0, 0, (pos.subevent_id or 0) if answers and (has_attendee_data or pos.item.questions.all()): return i, addon_penalty, pos.pk, 0, 0, 0, 0, (pos.subevent_id or 0) return ( 0, addon_penalty, 0, pos.item_id, pos.variation_id, pos.price, (pos.voucher_id or 0), (pos.subevent_id or 0) ) positions = [] for k, g in groupby(sorted(lcp, key=keyfunc), key=keyfunc): g = list(g) group = g[0] group.count = len(g) group.total = group.count * group.price group.net_total = group.count * group.net_price group.has_questions = answers and k[0] != "" group.tax_rule = group.item.tax_rule if answers: group.cache_answers(all=False) group.additional_answers = pos_additional_fields.get(group.pk) positions.append(group) total = sum(p.total for p in positions) net_total = sum(p.net_total for p in positions) tax_total = sum(p.total - p.net_total for p in positions) if order: fees = order.fees.all() elif positions: fees = get_fees(self.request.event, self.request, total, self.invoice_address, self.cart_session.get('payment')) else: fees = [] total += sum([f.value for f in fees]) net_total += sum([f.net_value for f in fees]) tax_total += sum([f.tax_value for f in fees]) try: first_expiry = min(p.expires for p in positions) if positions else now() total_seconds_left = max(first_expiry - now(), timedelta()).total_seconds() minutes_left = int(total_seconds_left // 60) seconds_left = int(total_seconds_left % 60) except AttributeError: first_expiry = None minutes_left = None seconds_left = None return { 'positions': positions, 'raw': cartpos, 'total': total, 'net_total': net_total, 'tax_total': tax_total, 'fees': fees, 'answers': answers, 'minutes_left': minutes_left, 'seconds_left': seconds_left, 'first_expiry': first_expiry, }
def _total_order_value(self): total = get_cart_total(self.request) total += sum([f.value for f in get_fees(self.request.event, self.request, total, self.invoice_address, None)]) return total
def get_cart(self, answers=False, queryset=None, order=None, downloads=False): if queryset is not None: prefetch = [] if answers: prefetch.append('item__questions') prefetch.append(Prefetch('answers', queryset=QuestionAnswer.objects.prefetch_related('options'))) cartpos = queryset.order_by( 'item__category__position', 'item__category_id', 'item__position', 'item__name', 'variation__value' ).select_related( 'item', 'variation', 'addon_to', 'subevent', 'subevent__event', 'subevent__event__organizer', 'seat' ).prefetch_related( *prefetch ) else: cartpos = self.positions lcp = list(cartpos) has_addons = defaultdict(list) for cp in lcp: if cp.addon_to_id: has_addons[cp.addon_to_id].append(cp) pos_additional_fields = defaultdict(list) for cp in lcp: cp.item.event = self.request.event # will save some SQL queries responses = question_form_fields.send(sender=self.request.event, position=cp) data = cp.meta_info_data for r, response in sorted(responses, key=lambda r: str(r[0])): if response: for key, value in response.items(): pos_additional_fields[cp.pk].append({ 'answer': data.get('question_form_data', {}).get(key), 'question': value.label }) # Group items of the same variation # We do this by list manipulations instead of a GROUP BY query, as # Django is unable to join related models in a .values() query def keyfunc(pos, for_sorting=False): if isinstance(pos, OrderPosition): if pos.addon_to_id: i = pos.addon_to.positionid else: i = pos.positionid else: if pos.addon_to_id: i = pos.addon_to_id else: i = pos.pk has_attendee_data = pos.item.admission and ( self.request.event.settings.attendee_names_asked or self.request.event.settings.attendee_emails_asked or pos_additional_fields.get(pos.pk) ) addon_penalty = 1 if pos.addon_to_id else 0 if downloads \ or pos.pk in has_addons \ or pos.item.issue_giftcard \ or (answers and (has_attendee_data or bool(pos.item.questions.all()))): # do not use .exists() to re-use prefetch cache return ( # standalone positions are grouped by main product position id, addons below them also sorted by position id i, addon_penalty, pos.positionid if isinstance(pos, OrderPosition) else pos.pk, # all other places are only used for positions that can be grouped. We just put zeros. ) + (0, ) * 10 # positions are sorted and grouped by various attributes category_key = (pos.item.category.position, pos.item.category.id) if pos.item.category is not None else (0, 0) item_key = pos.item.position, pos.item_id variation_key = (pos.variation.position, pos.variation.id) if pos.variation is not None else (0, 0) grp = category_key + item_key + variation_key + (pos.price, (pos.voucher_id or 0), (pos.subevent_id or 0), (pos.seat_id or 0)) if pos.addon_to_id: if for_sorting: ii = pos.positionid if isinstance(pos, OrderPosition) else pos.pk else: ii = 0 return ( i, addon_penalty, ii, ) + category_key + item_key + variation_key + (pos.price, (pos.voucher_id or 0), (pos.subevent_id or 0), (pos.seat_id or 0)) return ( # These are grouped by attributes so we don't put any position ids 0, 0, 0, ) + grp positions = [] for k, g in groupby(sorted(lcp, key=partial(keyfunc, for_sorting=True)), key=keyfunc): g = list(g) group = g[0] group.count = len(g) group.total = group.count * group.price group.net_total = group.count * group.net_price group.has_questions = answers and k[0] != "" if not hasattr(group, 'tax_rule'): group.tax_rule = group.item.tax_rule group.bundle_sum = group.price + sum(a.price for a in has_addons[group.pk]) group.bundle_sum_net = group.net_price + sum(a.net_price for a in has_addons[group.pk]) if answers: group.cache_answers(all=False) group.additional_answers = pos_additional_fields.get(group.pk) positions.append(group) total = sum(p.total for p in positions) net_total = sum(p.net_total for p in positions) tax_total = sum(p.total - p.net_total for p in positions) if order: fees = order.fees.all() elif positions: fees = get_fees( self.request.event, self.request, total, self.invoice_address, self.cart_session.get('payment'), cartpos ) else: fees = [] total += sum([f.value for f in fees]) net_total += sum([f.net_value for f in fees]) tax_total += sum([f.tax_value for f in fees]) try: first_expiry = min(p.expires for p in positions) if positions else now() total_seconds_left = max(first_expiry - now(), timedelta()).total_seconds() minutes_left = int(total_seconds_left // 60) seconds_left = int(total_seconds_left % 60) except AttributeError: first_expiry = None minutes_left = None seconds_left = None return { 'positions': positions, 'invoice_address': self.invoice_address, 'all_with_voucher': all(p.voucher_id for p in positions), 'raw': cartpos, 'total': total, 'net_total': net_total, 'tax_total': tax_total, 'fees': fees, 'answers': answers, 'minutes_left': minutes_left, 'seconds_left': seconds_left, 'first_expiry': first_expiry, 'is_ordered': bool(order), 'itemcount': sum(c.count for c in positions if not c.addon_to) }