mirror of
https://github.com/pretix/pretix.git
synced 2026-08-14 11:26:26 +00:00
Improve order change
This commit is contained in:
@@ -1736,7 +1736,7 @@ class OrderChangeManager:
|
||||
if position.issued_gift_cards.exists():
|
||||
raise OrderError(self.error_messages['gift_card_change'])
|
||||
|
||||
self._totaldiff_guesstimate += price.gross - position.price
|
||||
self._totaldiff_guesstimate += price.gross - position.price + position.price_includes_rounding_correction
|
||||
|
||||
if self.order.event.settings.invoice_include_free or price.gross != Decimal('0.00') or position.price != Decimal('0.00'):
|
||||
self._invoice_dirty = True
|
||||
@@ -2362,10 +2362,15 @@ class OrderChangeManager:
|
||||
'new_price': op.price.gross
|
||||
})
|
||||
position.price = op.price.gross
|
||||
position.price_includes_rounding_correction = Decimal("0.00")
|
||||
position.tax_rate = op.price.rate
|
||||
position.tax_value = op.price.tax
|
||||
position.tax_value_includes_rounding_correction = Decimal("0.00")
|
||||
position.tax_code = op.price.code
|
||||
position.save(update_fields=['price', 'tax_rate', 'tax_value', 'tax_code'])
|
||||
position.save(update_fields=[
|
||||
'price', 'price_includes_rounding_correction', 'tax_rate', 'tax_value',
|
||||
'tax_value_includes_rounding_correction', 'tax_code'
|
||||
])
|
||||
elif isinstance(op, self.TaxRuleOperation):
|
||||
if isinstance(op.position, OrderPosition):
|
||||
position = position_cache.setdefault(op.position.pk, op.position)
|
||||
|
||||
@@ -1568,6 +1568,63 @@ 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_with_rounding_change_impossible(self):
|
||||
# Order starts with 2*100€ tickets, but rounding corrects it to 199€. Then, the user tries to force both prices
|
||||
# to 100€. No luck.
|
||||
self.order.status = Order.STATUS_PAID
|
||||
self.order.tax_rounding_mode = "sum_by_net"
|
||||
self.order.save()
|
||||
self.op1.price = Decimal("100.00")
|
||||
self.op1._calculate_tax(tax_rule=self.tr19)
|
||||
self.op1.save()
|
||||
self.op2.price = Decimal("100.00")
|
||||
self.op2._calculate_tax(tax_rule=self.tr19)
|
||||
self.op2.save()
|
||||
self.order.refresh_from_db()
|
||||
self.ocm.regenerate_secret(self.op1)
|
||||
self.ocm.commit() # Force re-rounding
|
||||
self.order.refresh_from_db()
|
||||
self.ocm = OrderChangeManager(self.order, None)
|
||||
assert self.order.total == Decimal("199.99")
|
||||
|
||||
self.ocm.change_price(self.op1, Decimal('100.00'))
|
||||
self.ocm.change_price(self.op2, Decimal('100.00'))
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.op2.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.total == Decimal("199.99")
|
||||
assert self.op1.price == Decimal('99.99')
|
||||
assert self.op2.price == Decimal('100.00')
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_change_price_with_rounding_change_autocorrected(self):
|
||||
self.order.status = Order.STATUS_PAID
|
||||
self.order.tax_rounding_mode = "sum_by_net"
|
||||
self.order.save()
|
||||
self.op1.price = Decimal("0.00")
|
||||
self.op1._calculate_tax(tax_rule=self.tr19)
|
||||
self.op1.save()
|
||||
self.op2.price = Decimal("100.00")
|
||||
self.op2._calculate_tax(tax_rule=self.tr19)
|
||||
self.op2.save()
|
||||
self.order.refresh_from_db()
|
||||
self.ocm.regenerate_secret(self.op1)
|
||||
self.ocm.commit() # Force re-rounding
|
||||
self.order.refresh_from_db()
|
||||
self.ocm = OrderChangeManager(self.order, None)
|
||||
assert self.order.total == Decimal("100.00")
|
||||
|
||||
self.ocm.change_price(self.op1, Decimal('100.00'))
|
||||
self.ocm.commit()
|
||||
self.op1.refresh_from_db()
|
||||
self.op2.refresh_from_db()
|
||||
self.order.refresh_from_db()
|
||||
assert self.order.total == Decimal("199.99")
|
||||
assert self.op1.price == Decimal('99.99')
|
||||
assert self.op2.price == Decimal('100.00')
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_change_price_net_success(self):
|
||||
self.tr7.price_includes_tax = False
|
||||
|
||||
@@ -219,3 +219,29 @@ def test_round_currency_without_decimals():
|
||||
assert sum(l.price for l in lines) == Decimal("49990.00")
|
||||
assert sum(l.tax_value for l in lines) == Decimal("7982.00")
|
||||
assert sum(l.price - l.tax_value for l in lines) == Decimal("42008.00")
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize("rounding_mode", [
|
||||
"sum_by_net",
|
||||
"sum_by_net_keep_gross",
|
||||
])
|
||||
def test_do_not_touch_free(rounding_mode):
|
||||
l1 = OrderPosition(
|
||||
price=Decimal("0.00"),
|
||||
)
|
||||
l1._calculate_tax(tax_rule=TaxRule(rate=Decimal("7.00")), invoice_address=InvoiceAddress())
|
||||
l2 = OrderPosition(
|
||||
price=Decimal("23.00"),
|
||||
)
|
||||
l2._calculate_tax(tax_rule=TaxRule(rate=Decimal("7.00")), invoice_address=InvoiceAddress())
|
||||
apply_rounding(rounding_mode, "EUR", [l1, l2])
|
||||
assert l2.price == Decimal("23.01")
|
||||
assert l2.price_includes_rounding_correction == Decimal("0.01")
|
||||
assert l2.tax_value == Decimal("1.51")
|
||||
assert l2.tax_value_includes_rounding_correction == Decimal("0.01")
|
||||
assert l2.tax_rate == Decimal("7.00")
|
||||
assert l1.price == Decimal("0.00")
|
||||
assert l1.price_includes_rounding_correction == Decimal("0.00")
|
||||
assert l1.tax_value == Decimal("0.00")
|
||||
assert l1.tax_value_includes_rounding_correction == Decimal("0.00")
|
||||
|
||||
Reference in New Issue
Block a user