Add Order.cancellation_date (#1629)

* Add Order.cancellation_date

* Add tests
This commit is contained in:
Raphael Michel
2020-03-25 16:37:34 +01:00
committed by GitHub
parent ad5e2df3be
commit d9d0f7b6f3
5 changed files with 62 additions and 3 deletions

View File

@@ -0,0 +1,46 @@
# Generated by Django 3.0.4 on 2020-03-25 14:40
from django.db import migrations, models
from django.db.models import OuterRef, Count, Subquery, Q
from django.utils.timezone import now
def fill_cancellation_date(apps, schema_editor):
Order = apps.get_model('pretixbase', 'Order')
LogEntry = apps.get_model('pretixbase', 'LogEntry')
OrderPosition = apps.get_model('pretixbase', 'OrderPosition')
s = OrderPosition.all.filter(
order=OuterRef('pk'),
canceled=False,
).order_by().values('order').annotate(k=Count('id')).values('k')
for o in Order.objects.annotate(
pcnt=Subquery(s)
).filter(
Q(pcnt=0) | Q(pcnt__isnull=True) | Q(status="c")
).values('id').iterator():
le = LogEntry.objects.filter(
content_type__model="order",
object_id=o['id'],
action_type='pretix.event.order.canceled'
).order_by('-datetime').only('datetime').first()
if le:
Order.objects.filter(pk=o['id']).update(
cancellation_date=le.datetime,
last_modified=now()
)
class Migration(migrations.Migration):
dependencies = [
('pretixbase', '0148_cancellationrequest'),
]
operations = [
migrations.AddField(
model_name='order',
name='cancellation_date',
field=models.DateTimeField(blank=True, null=True),
),
migrations.RunPython(fill_cancellation_date, migrations.RunPython.noop)
]

View File

@@ -152,6 +152,9 @@ class Order(LockModel, LoggedModel):
datetime = models.DateTimeField(
verbose_name=_("Date"), db_index=True
)
cancellation_date = models.DateTimeField(
null=True, blank=True
)
expires = models.DateTimeField(
verbose_name=_("Expiration date")
)

View File

@@ -109,10 +109,11 @@ def reactivate_order(order: Order, force: bool=False, user: User=None, auth=None
order.status = Order.STATUS_PAID
else:
order.status = Order.STATUS_PENDING
order.cancellation_date = None
order.set_expires(now(),
order.event.subevents.filter(id__in=[p.subevent_id for p in order.positions.all()]))
with transaction.atomic():
order.save(update_fields=['expires', 'status'])
order.save(update_fields=['expires', 'status', 'cancellation_date'])
order.log_action(
'pretix.event.order.reactivated',
user=user,
@@ -389,14 +390,16 @@ def _cancel_order(order, user=None, send_mail: bool=True, api_token=None, device
raise OrderError(_('The cancellation fee cannot be higher than the payment credit of this order.'))
order.status = Order.STATUS_PAID
order.total = cancellation_fee
order.save(update_fields=['status', 'total'])
order.cancellation_date = now()
order.save(update_fields=['status', 'cancellation_date', 'total'])
if i:
invoices.append(generate_invoice(order))
else:
with order.event.lock():
order.status = Order.STATUS_CANCELED
order.save(update_fields=['status'])
order.cancellation_date = now()
order.save(update_fields=['status', 'cancellation_date'])
for position in order.positions.all():
if position.voucher:

View File

@@ -158,6 +158,10 @@
<dd>{{ order.code }}</dd>
<dt>{% trans "Order date" %}</dt>
<dd>{{ order.datetime|date:"SHORT_DATETIME_FORMAT" }}</dd>
{% if order.cancellation_date %}
<dt>{% trans "Cancellation date" %}</dt>
<dd>{{ order.cancellation_date|date:"SHORT_DATETIME_FORMAT" }}</dd>
{% endif %}
{% if sales_channel %}
<dt>{% trans "Sales channel" %}</dt>
<dd>{{ sales_channel.verbose_name }}</dd>

View File

@@ -606,6 +606,7 @@ class OrderCancelTests(TestCase):
def test_cancel_unpaid(self):
cancel_order(self.order.pk)
self.order.refresh_from_db()
assert self.order.cancellation_date
assert self.order.status == Order.STATUS_CANCELED
assert self.order.all_logentries().last().action_type == 'pretix.event.order.canceled'
assert self.order.invoices.count() == 2
@@ -2497,6 +2498,7 @@ class OrderReactivateTest(TestCase):
code='FOO', event=self.event, email='dummy@dummy.test',
status=Order.STATUS_CANCELED, locale='en',
datetime=now(), expires=now() + timedelta(days=1),
cancellation_date=now(),
total=Decimal('46.00'),
)
self.ticket = Item.objects.create(event=self.event, name='Early-bird ticket',
@@ -2549,6 +2551,7 @@ class OrderReactivateTest(TestCase):
assert self.order.status == Order.STATUS_PAID
assert self.order.all_logentries().last().action_type == 'pretix.event.order.reactivated'
assert self.order.invoices.count() == 3
assert not self.order.cancellation_date
@classscope(attr='o')
def test_reactivate_sold_out(self):