forked from CGM_Public/pretix_original
OrderChangeManager: add_position() returns a handle to the newly created position (#5557)
* OrderChangeManager: Add support for custom operations * OrderChangeManager: Add callback to AddPosition operation This is also meant as a way to fix #5548 * Refs #5557: Checkstyle fix * Refs #5557: Added tests * Refs #5557: Changes requested in the PR review * Refs #5557: Fix error in previous merge conflict * Refs #5557: PR review
This commit is contained in:
committed by
GitHub
parent
59c09e27fd
commit
8cc12fa1c7
@@ -1630,7 +1630,7 @@ class OrderChangeManager:
|
|||||||
MembershipOperation = namedtuple('MembershipOperation', ('position', 'membership'))
|
MembershipOperation = namedtuple('MembershipOperation', ('position', 'membership'))
|
||||||
CancelOperation = namedtuple('CancelOperation', ('position', 'price_diff'))
|
CancelOperation = namedtuple('CancelOperation', ('position', 'price_diff'))
|
||||||
AddOperation = namedtuple('AddOperation', ('item', 'variation', 'price', 'addon_to', 'subevent', 'seat', 'membership',
|
AddOperation = namedtuple('AddOperation', ('item', 'variation', 'price', 'addon_to', 'subevent', 'seat', 'membership',
|
||||||
'valid_from', 'valid_until', 'is_bundled'))
|
'valid_from', 'valid_until', 'is_bundled', 'result'))
|
||||||
SplitOperation = namedtuple('SplitOperation', ('position',))
|
SplitOperation = namedtuple('SplitOperation', ('position',))
|
||||||
FeeValueOperation = namedtuple('FeeValueOperation', ('fee', 'value', 'price_diff'))
|
FeeValueOperation = namedtuple('FeeValueOperation', ('fee', 'value', 'price_diff'))
|
||||||
AddFeeOperation = namedtuple('AddFeeOperation', ('fee', 'price_diff'))
|
AddFeeOperation = namedtuple('AddFeeOperation', ('fee', 'price_diff'))
|
||||||
@@ -1642,6 +1642,18 @@ class OrderChangeManager:
|
|||||||
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||||
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||||
|
|
||||||
|
class AddPositionResult:
|
||||||
|
_position: Optional[OrderPosition]
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._position = None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def position(self) -> OrderPosition:
|
||||||
|
if self._position is None:
|
||||||
|
raise RuntimeError("Order position has not been created yet. Call commit() first on OrderChangeManager.")
|
||||||
|
return self._position
|
||||||
|
|
||||||
def __init__(self, order: Order, user=None, auth=None, notify=True, reissue_invoice=True, allow_blocked_seats=False):
|
def __init__(self, order: Order, user=None, auth=None, notify=True, reissue_invoice=True, allow_blocked_seats=False):
|
||||||
self.order = order
|
self.order = order
|
||||||
self.user = user
|
self.user = user
|
||||||
@@ -1846,7 +1858,7 @@ class OrderChangeManager:
|
|||||||
|
|
||||||
def add_position(self, item: Item, variation: ItemVariation, price: Decimal, addon_to: OrderPosition = None,
|
def add_position(self, item: Item, variation: ItemVariation, price: Decimal, addon_to: OrderPosition = None,
|
||||||
subevent: SubEvent = None, seat: Seat = None, membership: Membership = None,
|
subevent: SubEvent = None, seat: Seat = None, membership: Membership = None,
|
||||||
valid_from: datetime = None, valid_until: datetime = None):
|
valid_from: datetime = None, valid_until: datetime = None) -> 'OrderChangeManager.AddPositionResult':
|
||||||
if isinstance(seat, str):
|
if isinstance(seat, str):
|
||||||
if not seat:
|
if not seat:
|
||||||
seat = None
|
seat = None
|
||||||
@@ -1905,8 +1917,11 @@ class OrderChangeManager:
|
|||||||
self._quotadiff.update(new_quotas)
|
self._quotadiff.update(new_quotas)
|
||||||
if seat:
|
if seat:
|
||||||
self._seatdiff.update([seat])
|
self._seatdiff.update([seat])
|
||||||
|
|
||||||
|
result = self.AddPositionResult()
|
||||||
self._operations.append(self.AddOperation(item, variation, price, addon_to, subevent, seat, membership,
|
self._operations.append(self.AddOperation(item, variation, price, addon_to, subevent, seat, membership,
|
||||||
valid_from, valid_until, is_bundled))
|
valid_from, valid_until, is_bundled, result))
|
||||||
|
return result
|
||||||
|
|
||||||
def split(self, position: OrderPosition):
|
def split(self, position: OrderPosition):
|
||||||
if self.order.event.settings.invoice_include_free or position.price != Decimal('0.00'):
|
if self.order.event.settings.invoice_include_free or position.price != Decimal('0.00'):
|
||||||
@@ -2525,6 +2540,7 @@ class OrderChangeManager:
|
|||||||
'valid_from': op.valid_from.isoformat() if op.valid_from else None,
|
'valid_from': op.valid_from.isoformat() if op.valid_from else None,
|
||||||
'valid_until': op.valid_until.isoformat() if op.valid_until else None,
|
'valid_until': op.valid_until.isoformat() if op.valid_until else None,
|
||||||
})
|
})
|
||||||
|
op.result._position = pos
|
||||||
elif isinstance(op, self.SplitOperation):
|
elif isinstance(op, self.SplitOperation):
|
||||||
position = position_cache.setdefault(op.position.pk, op.position)
|
position = position_cache.setdefault(op.position.pk, op.position)
|
||||||
split_positions.append(position)
|
split_positions.append(position)
|
||||||
|
|||||||
@@ -2465,6 +2465,16 @@ class OrderChangeManagerTests(TestCase):
|
|||||||
assert nop.price == Decimal('12.00')
|
assert nop.price == Decimal('12.00')
|
||||||
assert nop.subevent == se1
|
assert nop.subevent == se1
|
||||||
|
|
||||||
|
@classscope(attr='o')
|
||||||
|
def test_add_item_result_value(self):
|
||||||
|
res_shirt = self.ocm.add_position(self.shirt, None, None, None)
|
||||||
|
res_ticket2 = self.ocm.add_position(self.ticket2, None, None, None)
|
||||||
|
with self.assertRaises(RuntimeError):
|
||||||
|
_ = res_ticket2.position
|
||||||
|
self.ocm.commit()
|
||||||
|
assert res_shirt.position.item == self.shirt
|
||||||
|
assert res_ticket2.position.item == self.ticket2
|
||||||
|
|
||||||
@classscope(attr='o')
|
@classscope(attr='o')
|
||||||
def test_add_item_with_rounding(self):
|
def test_add_item_with_rounding(self):
|
||||||
self.order.tax_rounding_mode = "sum_by_net"
|
self.order.tax_rounding_mode = "sum_by_net"
|
||||||
|
|||||||
Reference in New Issue
Block a user