Add a simple test mode (#1181)

- [x] Provide data model and configuration toggle
- [x] Allow to delete individual test orders
- [x] Add tests
- [x] Add a prominent warning message to the backend if test mode orders exist (even though test mode is off), as this leads to wrong statistics
- [x] Decide if and how to generate invoices for test orders as invoice numbers cannot be repeated or should not have gaps.
- [x] Decide if and how we expose test orders through the API, since our difference pull mechanism relies on the fact that orders cannot be deleted.
- [x] Decide if and how we want to couple test modes of payment providers?
- [ ] pretix.eu: Ignore test orders for billing
- [ ] Adjust payment providers: Mollie, bitpay, cash, fakepayment, sepadebit

![download](https://user-images.githubusercontent.com/64280/53009081-fe420d80-343a-11e9-8361-b8511c988598.png)
This commit is contained in:
Raphael Michel
2019-02-20 17:51:26 +01:00
committed by GitHub
parent 8ffc96bf31
commit 67059fe323
49 changed files with 759 additions and 91 deletions

View File

@@ -76,6 +76,8 @@ class Order(LockModel, LoggedModel):
:type event: Event
:param email: The email of the person who ordered this
:type email: str
:param testmode: Whether this is a test mode order
:type testmode: bool
:param locale: The locale of this order
:type locale: str
:param secret: A secret string that is required to modify the order
@@ -121,6 +123,7 @@ class Order(LockModel, LoggedModel):
verbose_name=_("Status"),
db_index=True
)
testmode = models.BooleanField(default=False)
event = models.ForeignKey(
Event,
verbose_name=_("Event"),
@@ -185,6 +188,23 @@ class Order(LockModel, LoggedModel):
def __str__(self):
return self.full_code
def gracefully_delete(self, user=None, auth=None):
if not self.testmode:
raise TypeError("Only test mode orders can be deleted.")
self.event.log_action(
'pretix.event.order.deleted', user=user, auth=auth,
data={
'code': self.code,
}
)
OrderPosition.all.filter(order=self, addon_to__isnull=False).delete()
OrderPosition.all.filter(order=self).delete()
OrderFee.all.filter(order=self).delete()
self.refunds.all().delete()
self.payments.all().delete()
self.event.cache.delete('complain_testmode_orders')
self.delete()
@property
def fees(self):
"""
@@ -490,6 +510,10 @@ class Order(LockModel, LoggedModel):
charset = list('ABCDEFGHJKLMNPQRSTUVWXYZ3789')
while True:
code = get_random_string(length=settings.ENTROPY['order_code'], allowed_chars=charset)
if self.testmode:
# Subtle way to recognize test orders while debugging: They all contain a 0 at the second place,
# even though zeros are not used outside test mode.
code = code[0] + "0" + code[2:]
if not Order.objects.filter(event__organizer=self.event.organizer, code=code).exists():
self.code = code
return