예제 #1
0
def get_price(item: Item, variation: ItemVariation = None,
              voucher: Voucher = None, custom_price: Decimal = None,
              subevent: SubEvent = None, custom_price_is_net: bool = False,
              addon_to: AbstractPosition = None, invoice_address: InvoiceAddress = None) -> TaxedPrice:
    if addon_to:
        try:
            iao = addon_to.item.addons.get(addon_category_id=item.category_id)
            if iao.price_included:
                return TAXED_ZERO
        except ItemAddOn.DoesNotExist:
            pass

    price = item.default_price
    if subevent and item.pk in subevent.item_price_overrides:
        price = subevent.item_price_overrides[item.pk]

    if variation is not None:
        if variation.default_price is not None:
            price = variation.default_price
        if subevent and variation.pk in subevent.var_price_overrides:
            price = subevent.var_price_overrides[variation.pk]

    if voucher:
        price = voucher.calculate_price(price)

    if item.tax_rule:
        tax_rule = item.tax_rule
    else:
        tax_rule = TaxRule(
            name='',
            rate=Decimal('0.00'),
            price_includes_tax=True,
            eu_reverse_charge=False,
        )
    price = tax_rule.tax(price)

    if item.free_price and custom_price is not None and custom_price != "":
        if not isinstance(custom_price, Decimal):
            custom_price = Decimal(str(custom_price).replace(",", "."))
        if custom_price > 100000000:
            raise ValueError('price_too_high')
        if custom_price_is_net:
            price = tax_rule.tax(max(custom_price, price.net), base_price_is='net')
        else:
            price = tax_rule.tax(max(custom_price, price.gross), base_price_is='gross')

    if invoice_address and not tax_rule.tax_applicable(invoice_address):
        price.tax = Decimal('0.00')
        price.rate = Decimal('0.00')
        price.gross = price.net
        price.name = ''

    price.gross = round_decimal(price.gross, item.event.currency)
    price.net = round_decimal(price.net, item.event.currency)
    price.tax = price.gross - price.net

    return price
예제 #2
0
파일: cart.py 프로젝트: FlaviaBastos/pretix
def get_fees(event, request, total, invoice_address, provider):
    fees = []

    if provider and total != 0:
        provider = event.get_payment_providers().get(provider)
        if provider:
            payment_fee = provider.calculate_fee(total)

            if payment_fee:
                payment_fee_tax_rule = event.settings.tax_rate_default or TaxRule.zero()
                if payment_fee_tax_rule.tax_applicable(invoice_address):
                    payment_fee_tax = payment_fee_tax_rule.tax(payment_fee, base_price_is='gross')
                    fees.append(OrderFee(
                        fee_type=OrderFee.FEE_TYPE_PAYMENT,
                        value=payment_fee,
                        tax_rate=payment_fee_tax.rate,
                        tax_value=payment_fee_tax.tax,
                        tax_rule=payment_fee_tax_rule
                    ))
                else:
                    fees.append(OrderFee(
                        fee_type=OrderFee.FEE_TYPE_PAYMENT,
                        value=payment_fee,
                        tax_rate=Decimal('0.00'),
                        tax_value=Decimal('0.00'),
                        tax_rule=payment_fee_tax_rule
                    ))

    for recv, resp in fee_calculation_for_cart.send(sender=event, request=request, invoice_address=invoice_address,
                                                    total=total):
        fees += resp

    return fees
예제 #3
0
def get_fees(event, request, total, invoice_address, provider):
    fees = []

    if provider and total != 0:
        provider = event.get_payment_providers().get(provider)
        if provider:
            payment_fee = provider.calculate_fee(total)

            if payment_fee:
                payment_fee_tax_rule = event.settings.tax_rate_default or TaxRule.zero(
                )
                if payment_fee_tax_rule.tax_applicable(invoice_address):
                    payment_fee_tax = payment_fee_tax_rule.tax(
                        payment_fee, base_price_is='gross')
                    fees.append(
                        OrderFee(fee_type=OrderFee.FEE_TYPE_PAYMENT,
                                 value=payment_fee,
                                 tax_rate=payment_fee_tax.rate,
                                 tax_value=payment_fee_tax.tax,
                                 tax_rule=payment_fee_tax_rule))
                else:
                    fees.append(
                        OrderFee(fee_type=OrderFee.FEE_TYPE_PAYMENT,
                                 value=payment_fee,
                                 tax_rate=Decimal('0.00'),
                                 tax_value=Decimal('0.00'),
                                 tax_rule=payment_fee_tax_rule))

    for recv, resp in fee_calculation_for_cart.send(
            sender=event, request=request, invoice_address=invoice_address):
        fees += resp

    return fees
예제 #4
0
def get_price(item: Item, variation: ItemVariation = None,
              voucher: Voucher = None, custom_price: Decimal = None,
              subevent: SubEvent = None, custom_price_is_net: bool = False,
              addon_to: AbstractPosition = None, invoice_address: InvoiceAddress = None) -> TaxedPrice:
    if addon_to:
        try:
            iao = addon_to.item.addons.get(addon_category_id=item.category_id)
            if iao.price_included:
                return TAXED_ZERO
        except ItemAddOn.DoesNotExist:
            pass

    price = item.default_price
    if subevent and item.pk in subevent.item_price_overrides:
        price = subevent.item_price_overrides[item.pk]

    if variation is not None:
        if variation.default_price is not None:
            price = variation.default_price
        if subevent and variation.pk in subevent.var_price_overrides:
            price = subevent.var_price_overrides[variation.pk]

    if voucher:
        price = voucher.calculate_price(price)

    if item.tax_rule:
        tax_rule = item.tax_rule
    else:
        tax_rule = TaxRule(
            name='',
            rate=Decimal('0.00'),
            price_includes_tax=True,
            eu_reverse_charge=False,
        )
    price = tax_rule.tax(price)

    if item.free_price and custom_price is not None and custom_price != "":
        if not isinstance(custom_price, Decimal):
            custom_price = Decimal(str(custom_price).replace(",", "."))
        if custom_price > 100000000:
            raise ValueError('price_too_high')
        if custom_price_is_net:
            price = tax_rule.tax(max(custom_price, price.net), base_price_is='net')
        else:
            price = tax_rule.tax(max(custom_price, price.gross), base_price_is='gross')

    if invoice_address and not tax_rule.tax_applicable(invoice_address):
        price.tax = Decimal('0.00')
        price.rate = Decimal('0.00')
        price.gross = price.net
        price.name = ''

    return price
예제 #5
0
def get_price(item: Item, variation: ItemVariation = None,
              voucher: Voucher = None, custom_price: Decimal = None,
              subevent: SubEvent = None, custom_price_is_net: bool = False,
              custom_price_is_tax_rate: Decimal=None,
              addon_to: AbstractPosition = None, invoice_address: InvoiceAddress = None,
              force_custom_price: bool = False, bundled_sum: Decimal = Decimal('0.00'),
              max_discount: Decimal = None, tax_rule=None) -> TaxedPrice:
    if addon_to:
        try:
            iao = addon_to.item.addons.get(addon_category_id=item.category_id)
            if iao.price_included:
                return TAXED_ZERO
        except ItemAddOn.DoesNotExist:
            pass

    price = item.default_price
    if subevent and item.pk in subevent.item_price_overrides:
        price = subevent.item_price_overrides[item.pk]

    if variation is not None:
        if variation.default_price is not None:
            price = variation.default_price
        if subevent and variation.pk in subevent.var_price_overrides:
            price = subevent.var_price_overrides[variation.pk]

    if voucher:
        price = voucher.calculate_price(price, max_discount=max_discount)

    if tax_rule is not None:
        tax_rule = tax_rule
    elif item.tax_rule:
        tax_rule = item.tax_rule
    else:
        tax_rule = TaxRule(
            name='',
            rate=Decimal('0.00'),
            price_includes_tax=True,
            eu_reverse_charge=False,
        )

    if force_custom_price and custom_price is not None and custom_price != "":
        if custom_price_is_net:
            price = tax_rule.tax(custom_price, base_price_is='net', invoice_address=invoice_address,
                                 subtract_from_gross=bundled_sum)
        else:
            price = tax_rule.tax(custom_price, base_price_is='gross', invoice_address=invoice_address,
                                 subtract_from_gross=bundled_sum)
    elif item.free_price and custom_price is not None and custom_price != "":
        if not isinstance(custom_price, Decimal):
            custom_price = Decimal(str(custom_price).replace(",", "."))
        if custom_price > 100000000:
            raise ValueError('price_too_high')

        price = tax_rule.tax(price, invoice_address=invoice_address)

        if custom_price_is_net:
            price = tax_rule.tax(max(custom_price, price.net), base_price_is='net',
                                 invoice_address=invoice_address, subtract_from_gross=bundled_sum)
        else:
            price = tax_rule.tax(max(custom_price, price.gross), base_price_is='gross', gross_price_is_tax_rate=custom_price_is_tax_rate,
                                 invoice_address=invoice_address, subtract_from_gross=bundled_sum)
    else:
        price = tax_rule.tax(price, invoice_address=invoice_address, subtract_from_gross=bundled_sum)

    price.gross = round_decimal(price.gross, item.event.currency)
    price.net = round_decimal(price.net, item.event.currency)
    price.tax = price.gross - price.net

    return price
예제 #6
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', 'variation').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])):
                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()
                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:
            payment_fee = order.payment_fee
            tax_total += order.payment_fee_tax_value
            payment_fee_net = order.payment_fee - order.payment_fee_tax_value
            net_total += payment_fee_net
            payment_fee_tax_rule = order.payment_fee_tax_rule
            payment_fee_tax_rate = order.payment_fee_tax_rate
        else:
            payment_fee = self.get_payment_fee(total)
            payment_fee_tax_rule = self.request.event.settings.tax_rate_default or TaxRule.zero(
            )

            iapk = self.request.session.get('invoice_address_{}'.format(
                self.request.event.pk))
            ia = None
            if payment_fee_tax_rule.eu_reverse_charge and iapk:
                try:
                    ia = InvoiceAddress.objects.get(pk=iapk,
                                                    order__isnull=True)
                except InvoiceAddress.DoesNotExist:
                    pass

            if payment_fee_tax_rule.tax_applicable(ia):
                payment_fee_tax = payment_fee_tax_rule.tax(
                    payment_fee, base_price_is='gross')
                tax_total += payment_fee_tax.tax
                net_total += payment_fee_tax.net
                payment_fee_net = payment_fee_tax.net
                payment_fee_tax_rate = payment_fee_tax.rate
            else:
                net_total += payment_fee
                payment_fee_net = payment_fee
                payment_fee_tax_rate = Decimal('0.00')

        try:
            first_expiry = min(p.expires
                               for p in positions) if positions else now()
            minutes_left = max(first_expiry - now(), timedelta()).seconds // 60
        except AttributeError:
            first_expiry = None
            minutes_left = None

        return {
            'positions': positions,
            'raw': cartpos,
            'total': total + payment_fee,
            'net_total': net_total,
            'tax_total': tax_total,
            'payment_fee': payment_fee,
            'payment_fee_net': payment_fee_net,
            'payment_fee_tax_rate': payment_fee_tax_rate,
            'payment_fee_tax_rule': payment_fee_tax_rule,
            'answers': answers,
            'minutes_left': minutes_left,
            'first_expiry': first_expiry,
        }