mirror of
https://github.com/pretix/pretix.git
synced 2025-12-21 16:42:26 +00:00
Compare commits
5 Commits
widget-dia
...
change-sec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5e2aea766 | ||
|
|
1ddfe06b92 | ||
|
|
600009e6fb | ||
|
|
866dffe617 | ||
|
|
58a9e9b288 |
@@ -1943,9 +1943,14 @@ Manipulating individual positions
|
||||
|
||||
* ``valid_until``
|
||||
|
||||
* ``secret``
|
||||
|
||||
Changing parameters such as ``item`` or ``price`` will **not** automatically trigger creation of a new invoice,
|
||||
you need to take care of that yourself.
|
||||
|
||||
Changing ``secret`` does not cause a new PDF ticket to be sent to the customer, nor does it cause the old secret
|
||||
to be added to the revocation list, even if your ticket generator uses one.
|
||||
|
||||
**Example request**:
|
||||
|
||||
.. sourcecode:: http
|
||||
|
||||
@@ -251,7 +251,7 @@ class OrderPositionChangeSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = OrderPosition
|
||||
fields = (
|
||||
'item', 'variation', 'subevent', 'seat', 'price', 'tax_rule', 'valid_from', 'valid_until'
|
||||
'item', 'variation', 'subevent', 'seat', 'price', 'tax_rule', 'valid_from', 'valid_until', 'secret'
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -319,6 +319,7 @@ class OrderPositionChangeSerializer(serializers.ModelSerializer):
|
||||
tax_rule = validated_data.get('tax_rule', instance.tax_rule)
|
||||
valid_from = validated_data.get('valid_from', instance.valid_from)
|
||||
valid_until = validated_data.get('valid_until', instance.valid_until)
|
||||
secret = validated_data.get('secret', instance.secret)
|
||||
|
||||
change_item = None
|
||||
if item != instance.item or variation != instance.variation:
|
||||
@@ -351,6 +352,9 @@ class OrderPositionChangeSerializer(serializers.ModelSerializer):
|
||||
if valid_until != instance.valid_until:
|
||||
ocm.change_valid_until(instance, valid_until)
|
||||
|
||||
if secret != instance.secret:
|
||||
ocm.change_ticket_secret(instance, secret)
|
||||
|
||||
if self.context.get('commit', True):
|
||||
ocm.commit()
|
||||
instance.refresh_from_db()
|
||||
|
||||
@@ -1564,6 +1564,7 @@ class OrderChangeManager:
|
||||
AddFeeOperation = namedtuple('AddFeeOperation', ('fee', 'price_diff'))
|
||||
CancelFeeOperation = namedtuple('CancelFeeOperation', ('fee', 'price_diff'))
|
||||
RegenerateSecretOperation = namedtuple('RegenerateSecretOperation', ('position',))
|
||||
ChangeSecretOperation = namedtuple('ChangeSecretOperation', ('position', 'new_secret'))
|
||||
ChangeValidFromOperation = namedtuple('ChangeValidFromOperation', ('position', 'valid_from'))
|
||||
ChangeValidUntilOperation = namedtuple('ChangeValidUntilOperation', ('position', 'valid_until'))
|
||||
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
@@ -1671,6 +1672,9 @@ class OrderChangeManager:
|
||||
def regenerate_secret(self, position: OrderPosition):
|
||||
self._operations.append(self.RegenerateSecretOperation(position))
|
||||
|
||||
def change_ticket_secret(self, position: OrderPosition, new_secret: str):
|
||||
self._operations.append(self.ChangeSecretOperation(position, new_secret))
|
||||
|
||||
def change_valid_from(self, position: OrderPosition, new_value: datetime):
|
||||
self._operations.append(self.ChangeValidFromOperation(position, new_value))
|
||||
|
||||
@@ -2441,6 +2445,19 @@ class OrderChangeManager:
|
||||
'position': op.position.pk,
|
||||
'positionid': op.position.positionid,
|
||||
})
|
||||
elif isinstance(op, self.ChangeSecretOperation):
|
||||
if OrderPosition.all.filter(order__event=self.event, secret=op.new_secret).exists():
|
||||
raise OrderError('You cannot assign a position secret that already exists.')
|
||||
op.position.secret = op.new_secret
|
||||
op.position.save(update_fields=["secret"])
|
||||
if op.position in secret_dirty:
|
||||
secret_dirty.remove(op.position)
|
||||
tickets.invalidate_cache.apply_async(kwargs={'event': self.event.pk,
|
||||
'order': self.order.pk})
|
||||
self.order.log_action('pretix.event.order.changed.secret', user=self.user, auth=self.auth, data={
|
||||
'position': op.position.pk,
|
||||
'positionid': op.position.positionid,
|
||||
})
|
||||
elif isinstance(op, self.ChangeValidFromOperation):
|
||||
self.order.log_action('pretix.event.order.changed.valid_from', user=self.user, auth=self.auth, data={
|
||||
'position': op.position.pk,
|
||||
|
||||
@@ -1468,6 +1468,31 @@ def test_position_update_change_price_and_tax_rule(token_client, organizer, even
|
||||
assert op.tax_rule == tr
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_position_update_secret(token_client, organizer, event, order, item):
|
||||
with scopes_disabled():
|
||||
order.positions.create(item=item, price=Decimal('23.00'), secret='alreadyused')
|
||||
p = order.positions.first()
|
||||
psw = p.web_secret
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={'secret': 'nobodyknows'}
|
||||
)
|
||||
assert resp.status_code == 200
|
||||
p.refresh_from_db()
|
||||
with scopes_disabled():
|
||||
assert 'nobodyknows' == p.secret
|
||||
assert psw == p.web_secret
|
||||
|
||||
resp = token_client.patch(
|
||||
'/api/v1/organizers/{}/events/{}/orderpositions/{}/'.format(
|
||||
organizer.slug, event.slug, p.pk,
|
||||
), format='json', data={'secret': 'alreadyused'}
|
||||
)
|
||||
assert resp.status_code == 400
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_position_add_simple(token_client, organizer, event, order, quota, item):
|
||||
with scopes_disabled():
|
||||
|
||||
Reference in New Issue
Block a user