Esempio n. 1
0
    def clean(self):
        data = super().clean()

        vouchers = self.instance.event.vouchers.annotate(
            code_lower=Lower('code')
        ).filter(code_lower__in=[c.lower() for c in data['codes']])
        if vouchers.exists():
            raise ValidationError(_('A voucher with one of these codes already exists.'))

        if data.get('send') and not all([data.get('send_subject'), data.get('send_message'), data.get('send_recipients')]):
            raise ValidationError(_('If vouchers should be sent by email, subject, message and recipients need to be specified.'))

        if data.get('codes') and data.get('send'):
            recp = self.cleaned_data.get('send_recipients', [])
            code_len = len(data.get('codes'))
            recp_len = sum(r.number for r in recp)
            if code_len != recp_len:
                raise ValidationError(_('You generated {codes} vouchers, but entered recipients for {recp} vouchers.').format(codes=code_len, recp=recp_len))

        if data.get('seats'):
            seatids = [s.strip() for s in data.get('seats').strip().split("\n") if s]
            if len(seatids) != len(data.get('codes')):
                raise ValidationError(_('You need to specify as many seats as voucher codes.'))
            data['seats'] = []
            for s in seatids:
                data['seat'] = s
                data['seats'].append(Voucher.clean_seat_id(
                    data, self.instance.item, self.instance.quota, self.instance.event, None
                ))
            self.instance.seat = data['seats'][0]  # Trick model-level validation
        else:
            data['seats'] = []

        return data
Esempio n. 2
0
    def get_queryset(self):
        qs = Voucher.annotate_budget_used_orders(
            self.request.event.vouchers.filter(
                waitinglistentries__isnull=True).select_related(
                    'item', 'variation', 'seat'))
        if self.filter_form.is_valid():
            qs = self.filter_form.filter_qs(qs)

        return qs.distinct()
Esempio n. 3
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
Esempio n. 4
0
    def get_form_kwargs(self):
        kwargs = super().get_form_kwargs()

        if self.copy_from:
            i = modelcopy(self.copy_from)
            i.pk = None
            kwargs['instance'] = i
        else:
            kwargs['instance'] = Voucher(event=self.request.event)
        return kwargs
Esempio n. 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,
              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
Esempio n. 6
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):
    if addon_to:
        try:
            iao = addon_to.item.addons.get(addon_category_id=item.category_id)
            if iao.price_included:
                return Decimal('0.00')
        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.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:
            custom_price = round_decimal(custom_price * (100 + item.tax_rate) /
                                         100)
        price = max(custom_price, price)

    return price
Esempio n. 7
0
    def clean(self):
        data = super().clean()

        if not self._errors:
            try:
                itemid = quotaid = None
                iv = self.data.get('itemvar', '')
                if iv.startswith('q-'):
                    quotaid = iv[2:]
                elif '-' in iv:
                    itemid, varid = iv.split('-')
                else:
                    itemid, varid = iv, None

                if itemid:
                    self.instance.item = self.instance.event.items.get(
                        pk=itemid)
                    if varid:
                        self.instance.variation = self.instance.item.variations.get(
                            pk=varid)
                    else:
                        self.instance.variation = None
                    self.instance.quota = None

                else:
                    self.instance.quota = self.instance.event.quotas.get(
                        pk=quotaid)
                    self.instance.item = None
                    self.instance.variation = None
            except ObjectDoesNotExist:
                raise ValidationError(_("Invalid product selected."))

        if 'codes' in data:
            data['codes'] = [
                a.strip() for a in data.get('codes', '').strip().split("\n")
                if a
            ]
            cnt = len(data['codes']) * data['max_usages']
        else:
            cnt = data['max_usages']

        Voucher.clean_item_properties(data, self.instance.event,
                                      self.instance.quota, self.instance.item,
                                      self.instance.variation)
        Voucher.clean_subevent(data, self.instance.event)
        Voucher.clean_max_usages(data, self.instance.redeemed)
        check_quota = Voucher.clean_quota_needs_checking(
            data,
            self.initial_instance_data,
            item_changed=data.get('itemvar') != self.initial.get('itemvar'),
            creating=not self.instance.pk)
        if check_quota:
            Voucher.clean_quota_check(data, cnt, self.initial_instance_data,
                                      self.instance.event, self.instance.quota,
                                      self.instance.item,
                                      self.instance.variation)
        Voucher.clean_voucher_code(data, self.instance.event, self.instance.pk)

        voucher_form_validation.send(sender=self.instance.event,
                                     form=self,
                                     data=data)

        return data
Esempio n. 8
0
    def validate(self, data):
        data = super().validate(data)

        full_data = self.to_internal_value(
            self.to_representation(self.instance)) if self.instance else {}
        full_data.update(data)

        Voucher.clean_item_properties(full_data, self.context.get('event'),
                                      full_data.get('quota'),
                                      full_data.get('item'),
                                      full_data.get('variation'))
        Voucher.clean_subevent(full_data, self.context.get('event'))
        Voucher.clean_max_usages(
            full_data, self.instance.redeemed if self.instance else 0)
        check_quota = Voucher.clean_quota_needs_checking(
            full_data,
            self.instance,
            item_changed=self.instance
            and (full_data.get('item') != self.instance.item
                 or full_data.get('variation') != self.instance.variation
                 or full_data.get('quota') != self.instance.quota),
            creating=not self.instance)
        if check_quota:
            Voucher.clean_quota_check(full_data, 1, self.instance,
                                      self.context.get('event'),
                                      full_data.get('quota'),
                                      full_data.get('item'),
                                      full_data.get('variation'))
        Voucher.clean_voucher_code(full_data, self.context.get('event'),
                                   self.instance.pk if self.instance else None)

        if full_data.get('seat'):
            data['seat'] = Voucher.clean_seat_id(
                full_data, full_data.get('item'), full_data.get('quota'),
                self.context.get('event'),
                self.instance.pk if self.instance else None)

        return data
Esempio n. 9
0
 def get_async_form_kwargs(self, form_kwargs, organizer=None, event=None):
     if not form_kwargs.get('instance'):
         form_kwargs['instance'] = Voucher(event=self.request.event, code=None)
     return form_kwargs
Esempio n. 10
0
    def validate(self, data):
        data = super().validate(data)

        full_data = self.to_internal_value(self.to_representation(self.instance)) if self.instance else {}
        full_data.update(data)

        Voucher.clean_item_properties(
            full_data, self.context.get('event'),
            full_data.get('quota'), full_data.get('item'), full_data.get('variation')
        )
        Voucher.clean_subevent(
            full_data, self.context.get('event')
        )
        Voucher.clean_max_usages(full_data, self.instance.redeemed if self.instance else 0)
        check_quota = Voucher.clean_quota_needs_checking(
            full_data, self.instance,
            item_changed=self.instance and (
                full_data.get('item') != self.instance.item or
                full_data.get('variation') != self.instance.variation or
                full_data.get('quota') != self.instance.quota
            ),
            creating=not self.instance
        )
        if check_quota:
            Voucher.clean_quota_check(
                full_data, 1, self.instance, self.context.get('event'),
                full_data.get('quota'), full_data.get('item'), full_data.get('variation')
            )
        Voucher.clean_voucher_code(full_data, self.context.get('event'), self.instance.pk if self.instance else None)

        return data
Esempio n. 11
0
    def clean(self):
        data = super().clean()

        if not self._errors:
            try:
                itemid = quotaid = None
                iv = self.data.get('itemvar', '')
                if iv.startswith('q-'):
                    quotaid = iv[2:]
                elif '-' in iv:
                    itemid, varid = iv.split('-')
                else:
                    itemid, varid = iv, None

                if itemid:
                    self.instance.item = self.instance.event.items.get(
                        pk=itemid)
                    if varid:
                        self.instance.variation = self.instance.item.variations.get(
                            pk=varid)
                    else:
                        self.instance.variation = None
                    self.instance.quota = None

                else:
                    self.instance.quota = self.instance.event.quotas.get(
                        pk=quotaid)
                    self.instance.item = None
                    self.instance.variation = None
            except ObjectDoesNotExist:
                raise ValidationError(_("Invalid product selected."))

        if 'codes' in data:
            data['codes'] = [
                a.strip() for a in data.get('codes', '').strip().split("\n")
                if a
            ]
            cnt = len(data['codes']) * data.get('max_usages', 0)
        else:
            cnt = data.get('max_usages', 0)

        Voucher.clean_item_properties(data, self.instance.event,
                                      self.instance.quota, self.instance.item,
                                      self.instance.variation)
        if not self.instance.show_hidden_items and (
            (self.instance.quota
             and all(i.hide_without_voucher
                     for i in self.instance.quota.items.all())) or
            (self.instance.item and self.instance.item.hide_without_voucher)):
            raise ValidationError({
                'show_hidden_items': [
                    _('The voucher only matches hidden products but you have not selected that it should show '
                      'them.')
                ]
            })
        Voucher.clean_subevent(data, self.instance.event)
        Voucher.clean_max_usages(data, self.instance.redeemed)
        check_quota = Voucher.clean_quota_needs_checking(
            data,
            self.initial_instance_data,
            item_changed=data.get('itemvar') != self.initial.get('itemvar'),
            creating=not self.instance.pk)
        if check_quota:
            Voucher.clean_quota_check(data, cnt, self.initial_instance_data,
                                      self.instance.event, self.instance.quota,
                                      self.instance.item,
                                      self.instance.variation)
        Voucher.clean_voucher_code(data, self.instance.event, self.instance.pk)

        voucher_form_validation.send(sender=self.instance.event,
                                     form=self,
                                     data=data)

        return data
Esempio n. 12
0
 def test_voucher_specify_variation_for_block_quota(self):
     with self.assertRaises(ValidationError):
         v = Voucher(item=self.item2, block_quota=True, event=self.event)
         v.clean()
Esempio n. 13
0
 def test_voucher_item_does_not_match_variation(self):
     with self.assertRaises(ValidationError):
         v = Voucher(item=self.item2, variation=self.var3, event=self.event)
         v.clean()
Esempio n. 14
0
 def test_voucher_no_item_with_quota(self):
     with self.assertRaises(ValidationError):
         v = Voucher(quota=self.quota, item=self.item1, event=self.event)
         v.clean()
Esempio n. 15
0
    def clean(self):
        data = super().clean()

        if not self._errors:
            try:
                itemid = quotaid = None
                iv = self.data.get('itemvar', '')
                if iv.startswith('q-'):
                    quotaid = iv[2:]
                elif '-' in iv:
                    itemid, varid = iv.split('-')
                else:
                    itemid, varid = iv, None

                if itemid:
                    self.instance.item = self.instance.event.items.get(pk=itemid)
                    if varid:
                        self.instance.variation = self.instance.item.variations.get(pk=varid)
                    else:
                        self.instance.variation = None
                    self.instance.quota = None

                else:
                    self.instance.quota = self.instance.event.quotas.get(pk=quotaid)
                    self.instance.item = None
                    self.instance.variation = None
            except ObjectDoesNotExist:
                raise ValidationError(_("Invalid product selected."))

        if 'codes' in data:
            data['codes'] = [a.strip() for a in data.get('codes', '').strip().split("\n") if a]
            cnt = len(data['codes']) * data.get('max_usages', 0)
        else:
            cnt = data['max_usages']

        Voucher.clean_item_properties(
            data, self.instance.event,
            self.instance.quota, self.instance.item, self.instance.variation
        )
        Voucher.clean_subevent(
            data, self.instance.event
        )
        Voucher.clean_max_usages(data, self.instance.redeemed)
        check_quota = Voucher.clean_quota_needs_checking(
            data, self.initial_instance_data,
            item_changed=data.get('itemvar') != self.initial.get('itemvar'),
            creating=not self.instance.pk
        )
        if check_quota:
            Voucher.clean_quota_check(
                data, cnt, self.initial_instance_data, self.instance.event,
                self.instance.quota, self.instance.item, self.instance.variation
            )
        Voucher.clean_voucher_code(data, self.instance.event, self.instance.pk)

        voucher_form_validation.send(sender=self.instance.event, form=self, data=data)

        return data
Esempio n. 16
0
 def get_form_kwargs(self):
     kwargs = super().get_form_kwargs()
     kwargs['instance'] = Voucher(event=self.request.event)
     return kwargs
Esempio n. 17
0
 def test_voucher_no_item_but_variation(self):
     with self.assertRaises(ValidationError):
         v = Voucher(variation=self.var1, event=self.event)
         v.clean()
Esempio n. 18
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
Esempio n. 19
0
    def clean(self):
        data = super().clean()

        if not self._errors:
            try:
                itemid = quotaid = None
                iv = self.data.get('itemvar', '')
                if iv.startswith('q-'):
                    quotaid = iv[2:]
                elif '-' in iv:
                    itemid, varid = iv.split('-')
                else:
                    itemid, varid = iv, None

                if itemid:
                    self.instance.item = self.instance.event.items.get(pk=itemid)
                    if varid:
                        self.instance.variation = self.instance.item.variations.get(pk=varid)
                    else:
                        self.instance.variation = None
                    self.instance.quota = None

                else:
                    self.instance.quota = self.instance.event.quotas.get(pk=quotaid)
                    self.instance.item = None
                    self.instance.variation = None
            except ObjectDoesNotExist:
                raise ValidationError(_("Invalid product selected."))

        if 'codes' in data:
            data['codes'] = [a.strip() for a in data.get('codes', '').strip().split("\n") if a]
            cnt = len(data['codes']) * data.get('max_usages', 0)
        else:
            cnt = data.get('max_usages', 0)

        Voucher.clean_item_properties(
            data, self.instance.event,
            self.instance.quota, self.instance.item, self.instance.variation
        )
        if self.instance.quota:
            if all(i.hide_without_voucher for i in self.instance.quota.items.all()):
                raise ValidationError({
                    'itemvar': [
                        _('The quota you selected only contains hidden products. Hidden products can currently only be '
                          'shown by using vouchers that directly apply to the product, not via a quota.')
                    ]
                })
        Voucher.clean_subevent(
            data, self.instance.event
        )
        Voucher.clean_max_usages(data, self.instance.redeemed)
        check_quota = Voucher.clean_quota_needs_checking(
            data, self.initial_instance_data,
            item_changed=data.get('itemvar') != self.initial.get('itemvar'),
            creating=not self.instance.pk
        )
        if check_quota:
            Voucher.clean_quota_check(
                data, cnt, self.initial_instance_data, self.instance.event,
                self.instance.quota, self.instance.item, self.instance.variation
            )
        Voucher.clean_voucher_code(data, self.instance.event, self.instance.pk)

        voucher_form_validation.send(sender=self.instance.event, form=self, data=data)

        return data