mirror of
https://github.com/pretix/pretix.git
synced 2026-04-26 23:52:35 +00:00
Add OrderPosition.ignore_from_quota_while_blocked (#3119)
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 3.2.17 on 2023-02-14 10:35
|
||||
|
||||
import django.core.serializers.json
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('pretixbase', '0232_exchangerate'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='orderposition',
|
||||
name='ignore_from_quota_while_blocked',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
@@ -2212,6 +2212,9 @@ class OrderPosition(AbstractPosition):
|
||||
description by a plugin. If the position is not blocked, the value must be ``None``, not an empty
|
||||
list.
|
||||
:type blocked: list
|
||||
:param ignore_from_quota_while_blocked: Ignore this order position from quota, as long as ``blocked`` is set. Only
|
||||
to be used carefully by specific plugins.
|
||||
:type ignore_from_quota_while_blocked: boolean
|
||||
:param valid_from: The ticket will not be considered valid before this date. If the value is ``None``, no check on
|
||||
ticket level is made.
|
||||
:type valid_from: datetime
|
||||
@@ -2257,6 +2260,7 @@ class OrderPosition(AbstractPosition):
|
||||
canceled = models.BooleanField(default=False)
|
||||
|
||||
blocked = models.JSONField(null=True, blank=True)
|
||||
ignore_from_quota_while_blocked = models.BooleanField(default=False)
|
||||
valid_from = models.DateTimeField(
|
||||
verbose_name=_("Valid from"),
|
||||
null=True,
|
||||
|
||||
@@ -1437,8 +1437,8 @@ class OrderChangeManager:
|
||||
RegenerateSecretOperation = namedtuple('RegenerateSecretOperation', ('position',))
|
||||
ChangeValidFromOperation = namedtuple('ChangeValidFromOperation', ('position', 'valid_from'))
|
||||
ChangeValidUntilOperation = namedtuple('ChangeValidUntilOperation', ('position', 'valid_until'))
|
||||
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name'))
|
||||
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name'))
|
||||
AddBlockOperation = namedtuple('AddBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
RemoveBlockOperation = namedtuple('RemoveBlockOperation', ('position', 'block_name', 'ignore_from_quota_while_blocked'))
|
||||
|
||||
def __init__(self, order: Order, user=None, auth=None, notify=True, reissue_invoice=True):
|
||||
self.order = order
|
||||
@@ -1548,11 +1548,11 @@ class OrderChangeManager:
|
||||
def change_valid_until(self, position: OrderPosition, new_value: datetime):
|
||||
self._operations.append(self.ChangeValidUntilOperation(position, new_value))
|
||||
|
||||
def add_block(self, position: OrderPosition, block_name: str):
|
||||
self._operations.append(self.AddBlockOperation(position, block_name))
|
||||
def add_block(self, position: OrderPosition, block_name: str, ignore_from_quota_while_blocked=None):
|
||||
self._operations.append(self.AddBlockOperation(position, block_name, ignore_from_quota_while_blocked))
|
||||
|
||||
def remove_block(self, position: OrderPosition, block_name: str):
|
||||
self._operations.append(self.RemoveBlockOperation(position, block_name))
|
||||
def remove_block(self, position: OrderPosition, block_name: str, ignore_from_quota_while_blocked=None):
|
||||
self._operations.append(self.RemoveBlockOperation(position, block_name, ignore_from_quota_while_blocked))
|
||||
|
||||
def change_price(self, position: OrderPosition, price: Decimal):
|
||||
tax_rule = self._current_tax_rules().get(position.pk, position.tax_rule) or TaxRule.zero()
|
||||
@@ -2258,7 +2258,9 @@ class OrderChangeManager:
|
||||
op.position.blocked = op.position.blocked + [op.block_name]
|
||||
else:
|
||||
op.position.blocked = [op.block_name]
|
||||
op.position.save(update_fields=['blocked'])
|
||||
if op.ignore_from_quota_while_blocked is not None:
|
||||
op.position.ignore_from_quota_while_blocked = op.ignore_from_quota_while_blocked
|
||||
op.position.save(update_fields=['blocked', 'ignore_from_quota_while_blocked'])
|
||||
if op.position.blocked:
|
||||
op.position.blocked_secrets.update_or_create(
|
||||
event=self.event,
|
||||
@@ -2278,7 +2280,9 @@ class OrderChangeManager:
|
||||
op.position.blocked = [b for b in op.position.blocked if b != op.block_name]
|
||||
if not op.position.blocked:
|
||||
op.position.blocked = None
|
||||
op.position.save(update_fields=['blocked'])
|
||||
if op.ignore_from_quota_while_blocked is not None:
|
||||
op.position.ignore_from_quota_while_blocked = op.ignore_from_quota_while_blocked
|
||||
op.position.save(update_fields=['blocked', 'ignore_from_quota_while_blocked'])
|
||||
if not op.position.blocked:
|
||||
try:
|
||||
bs = op.position.blocked_secrets.get(secret=op.position.secret)
|
||||
|
||||
@@ -295,6 +295,8 @@ class QuotaAvailability:
|
||||
Q(item_id__in={i['item_id'] for i in q_items if i['quota_id'] in quota_ids})
|
||||
) | Q(
|
||||
variation_id__in={i['itemvariation_id'] for i in q_vars if i['quota_id'] in quota_ids})
|
||||
).filter(
|
||||
~Q(Q(ignore_from_quota_while_blocked=True) & Q(blocked__isnull=False))
|
||||
).order_by()
|
||||
if any(q.release_after_exit for q in quotas):
|
||||
op_lookup = op_lookup.annotate(
|
||||
|
||||
@@ -483,6 +483,22 @@ class QuotaTestCase(BaseQuotaTestCase):
|
||||
with self.assertNumQueries(1):
|
||||
self.assertEqual(self.var1.check_quotas(_cache=cache, count_waitinglist=False), (Quota.AVAILABILITY_OK, 1))
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_ignore_if_blocked(self):
|
||||
q1 = self.event.quotas.create(name="Q1", size=50)
|
||||
q1.items.add(self.item1)
|
||||
|
||||
# Create orders
|
||||
order = Order.objects.create(event=self.event, status=Order.STATUS_PAID,
|
||||
expires=now() + timedelta(days=3),
|
||||
total=6)
|
||||
OrderPosition.objects.create(order=order, item=self.item1, price=2)
|
||||
OrderPosition.objects.create(order=order, item=self.item1, price=2, blocked=["foo"])
|
||||
OrderPosition.objects.create(order=order, item=self.item1, price=2, blocked=["foo"], ignore_from_quota_while_blocked=True)
|
||||
OrderPosition.objects.create(order=order, item=self.item1, price=2, ignore_from_quota_while_blocked=True)
|
||||
|
||||
self.assertEqual(self.item1.check_quotas(), (Quota.AVAILABILITY_OK, 47))
|
||||
|
||||
@classscope(attr='o')
|
||||
def test_subevent_isolation(self):
|
||||
self.event.has_subevents = True
|
||||
|
||||
Reference in New Issue
Block a user