diff --git a/src/pretix/base/services/orders.py b/src/pretix/base/services/orders.py index 1828db3c90..e63763c99a 100644 --- a/src/pretix/base/services/orders.py +++ b/src/pretix/base/services/orders.py @@ -1527,6 +1527,8 @@ class OrderChangeManager: self._invoice_dirty = True self._operations.append(self.SplitOperation(position)) + for a in position.addons.all(): + self._operations.append(self.SplitOperation(a)) def set_addons(self, addons): if self._operations: diff --git a/src/pretix/control/forms/orders.py b/src/pretix/control/forms/orders.py index f22bdd6431..701e3f4cb6 100644 --- a/src/pretix/control/forms/orders.py +++ b/src/pretix/control/forms/orders.py @@ -482,6 +482,9 @@ class OrderPositionChangeForm(forms.Form): self.fields['tax_rule'].queryset = instance.event.tax_rules.all() self.fields['tax_rule'].label_from_instance = self.taxrule_label_from_instance + if instance.addon_to_id: + del self.fields['operation_split'] + if not instance.seat and not ( instance.item.seat_category_mappings.filter(subevent=instance.subevent).exists() ): diff --git a/src/pretix/control/templates/pretixcontrol/order/change.html b/src/pretix/control/templates/pretixcontrol/order/change.html index 910a69187d..b2e4400e9b 100644 --- a/src/pretix/control/templates/pretixcontrol/order/change.html +++ b/src/pretix/control/templates/pretixcontrol/order/change.html @@ -202,10 +202,12 @@ {% bootstrap_field position.form.operation_cancel layout='inline' %} - {% bootstrap_field position.form.operation_split layout='inline' %} + {% if position.form.operation_split %} + {% bootstrap_field position.form.operation_split layout='inline' %} + {% endif %} {% if position.addons.exists %} - {% trans "Removing this position will also remove all add-ons to this position." %} + {% trans "Removing or splitting this position will also remove or split all add-ons to this position." %} {% endif %} diff --git a/src/pretix/control/views/orders.py b/src/pretix/control/views/orders.py index 2f6d3ee900..99e7106a19 100644 --- a/src/pretix/control/views/orders.py +++ b/src/pretix/control/views/orders.py @@ -1760,7 +1760,7 @@ class OrderChange(OrderView): if p.form.cleaned_data['tax_rule'] and p.form.cleaned_data['tax_rule'] != p.tax_rule: ocm.change_tax_rule(p, p.form.cleaned_data['tax_rule']) - if p.form.cleaned_data['operation_split']: + if p.form.cleaned_data.get('operation_split'): ocm.split(p) if p.form.cleaned_data['operation_secret']: diff --git a/src/tests/base/test_orders.py b/src/tests/base/test_orders.py index b50fcb0ee8..3f2661ecd4 100644 --- a/src/tests/base/test_orders.py +++ b/src/tests/base/test_orders.py @@ -1782,6 +1782,37 @@ class OrderChangeManagerTests(TestCase): assert not self.order.invoices.exists() assert not o2.invoices.exists() + @classscope(attr='o') + def test_split_include_addons(self): + self.shirt.category = self.event.categories.create(name='Add-ons', is_addon=True) + self.ticket.addons.create(addon_category=self.shirt.category) + self.ocm.add_position(self.shirt, None, Decimal('13.00'), self.op2) + self.ocm.commit() + self.order.refresh_from_db() + self.ocm = OrderChangeManager(self.order, None) + a = self.order.positions.get(addon_to=self.op2) + + old_secret = self.op2.secret + self.ocm.split(self.op2) + self.ocm.commit() + self.order.refresh_from_db() + self.op2.refresh_from_db() + a.refresh_from_db() + assert self.order.total == Decimal('23.00') + assert self.order.positions.count() == 1 + assert self.op2.order != self.order + o2 = self.op2.order + assert o2.total == Decimal('36.00') + assert o2.positions.count() == 2 + assert o2.code != self.order.code + assert o2.secret != self.order.secret + assert o2.datetime > self.order.datetime + assert a.addon_to == self.op2 + assert a.order == o2 + assert self.op2.secret != old_secret + assert not self.order.invoices.exists() + assert not o2.invoices.exists() + @classscope(attr='o') def test_split_require_approval(self): self.op2.item.require_approval = True