diff --git a/src/pretix/base/models/items.py b/src/pretix/base/models/items.py index 90a19935bf..acd2bd7753 100644 --- a/src/pretix/base/models/items.py +++ b/src/pretix/base/models/items.py @@ -821,7 +821,8 @@ class Item(LoggedModel): def ask_attendee_data(self): return self.admission and self.personalized - def tax(self, price=None, base_price_is='auto', currency=None, invoice_address=None, override_tax_rate=None, include_bundled=False): + def tax(self, price=None, base_price_is='auto', currency=None, invoice_address=None, override_tax_rate=None, + include_bundled=False, force_fixed_gross_price=False): price = price if price is not None else self.default_price bundled_sum = Decimal('0.00') @@ -850,7 +851,7 @@ class Item(LoggedModel): else: t = self.tax_rule.tax(price, base_price_is=base_price_is, invoice_address=invoice_address, override_tax_rate=override_tax_rate, currency=currency or self.event.currency, - subtract_from_gross=bundled_sum) + subtract_from_gross=bundled_sum, force_fixed_gross_price=force_fixed_gross_price) if bundled_sum: t.name = "MIXED!" diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 863f9bfdf0..e82c75c00f 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -1689,7 +1689,8 @@ class OrderChangeManager: def change_price(self, position: OrderPosition, price: Decimal): tax_rule = self._current_tax_rules().get(position.pk, position.tax_rule) or TaxRule.zero() - price = tax_rule.tax(price, base_price_is='gross') + price = tax_rule.tax(price, base_price_is='gross', invoice_address=self._invoice_address, + force_fixed_gross_price=True) if position.issued_gift_cards.exists(): raise OrderError(self.error_messages['gift_card_change']) @@ -1754,7 +1755,8 @@ class OrderChangeManager: self._operations.append(self.AddFeeOperation(fee, fee.value)) def change_fee(self, fee: OrderFee, value: Decimal): - value = (fee.tax_rule or TaxRule.zero()).tax(value, base_price_is='gross') + value = (fee.tax_rule or TaxRule.zero()).tax(value, base_price_is='gross', invoice_address=self._invoice_address, + force_fixed_gross_price=True) self._totaldiff += value.gross - fee.value self._invoice_dirty = True self._operations.append(self.FeeValueOperation(fee, value, value.gross - fee.value)) @@ -1789,7 +1791,8 @@ class OrderChangeManager: if price is None: price = get_price(item, variation, subevent=subevent, invoice_address=self._invoice_address) elif not isinstance(price, TaxedPrice): - price = item.tax(price, base_price_is='gross', invoice_address=self._invoice_address) + price = item.tax(price, base_price_is='gross', invoice_address=self._invoice_address, + force_fixed_gross_price=True) except TaxRule.SaleNotAllowed: raise OrderError(self.error_messages['tax_rule_country_blocked']) diff --git a/src/tests/base/test_orders.py b/src/tests/base/test_orders.py index 7be563b7c3..64df5682ba 100644 --- a/src/tests/base/test_orders.py +++ b/src/tests/base/test_orders.py @@ -1581,6 +1581,27 @@ class OrderChangeManagerTests(TestCase): assert round_decimal(self.op1.price * (1 - 100 / (100 + self.op1.tax_rate))) == self.op1.tax_value assert self.order.total == self.op1.price + self.op2.price + @classscope(attr='o') + def test_change_price_reverse_charge_success(self): + self._enable_reverse_charge() + self.op1.tax_rate = Decimal("0.00") + self.op1.tax_value = Decimal("0.00") + self.op1.tax_code = "AE" + self.op1.save() + self.op2.tax_rate = Decimal("0.00") + self.op2.tax_value = Decimal("0.00") + self.op2.tax_code = "AE" + self.op2.save() + self.ocm.change_price(self.op1, Decimal('1000.00')) + self.ocm.commit() + self.op1.refresh_from_db() + self.order.refresh_from_db() + assert self.op1.item == self.ticket + assert self.op1.price == Decimal('1000.00') + assert self.op1.tax_value == Decimal('0.00') + assert self.op1.tax_rate == Decimal('0.00') + assert self.order.total == self.op1.price + self.op2.price + @classscope(attr='o') def test_cancel_success(self): s = self.op1.secret @@ -1994,6 +2015,22 @@ class OrderChangeManagerTests(TestCase): assert nop.positionid == 3 assert self.order.transactions.filter(item=self.shirt).last().tax_code == "AE" + @classscope(attr='o') + def test_add_item_with_price_reverse_charge(self): + self._enable_reverse_charge() + self.ocm.add_position(self.shirt, None, Decimal("1.00"), None) + self.ocm.commit() + self.order.refresh_from_db() + assert self.order.positions.count() == 3 + nop = self.order.positions.last() + assert nop.item == self.shirt + assert nop.price == Decimal('1.00') + assert nop.tax_rate == Decimal('0.00') + assert nop.tax_value == Decimal('0.00') + assert self.order.total == self.op1.price + self.op2.price + nop.price + assert nop.positionid == 3 + assert self.order.transactions.filter(item=self.shirt).last().tax_code == "AE" + @classscope(attr='o') def test_add_item_custom_price(self): self.ocm.add_position(self.shirt, None, Decimal('13.00'), None)