Esempio n. 1
0
 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
Esempio n. 2
0
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
Esempio n. 3
0
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
Esempio n. 4
0
    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,
        }
Esempio n. 5
0
    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,
        }
Esempio n. 6
0
 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
Esempio n. 7
0
    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)
        }