This commit is contained in:
Raphael Michel
2018-08-14 11:31:41 +02:00
parent 248b94c296
commit f60a99c357
8 changed files with 251 additions and 9 deletions

View File

@@ -35,8 +35,8 @@ from pretix.base.services.invoices import (
)
from pretix.base.services.mail import SendMailException
from pretix.base.services.orders import (
OrderChangeManager, OrderError, approve_order, cancel_order, deny_order, extend_order,
mark_order_expired, mark_order_refunded,
OrderChangeManager, OrderError, approve_order, cancel_order, deny_order,
extend_order, mark_order_expired, mark_order_refunded,
)
from pretix.base.services.tickets import (
get_cachedticket_for_order, get_cachedticket_for_position,

View File

@@ -633,7 +633,7 @@ class ConfirmStep(CartMixin, AsyncAction, TemplateFlowStep):
return eventreverse(self.request.event, 'presale:event.order', kwargs={
'order': order.code,
'secret': order.secret,
})
}) + '?thanks=1'
return eventreverse(self.request.event, 'presale:event.order.pay.complete', kwargs={
'order': order.code,
'secret': order.secret,

View File

@@ -14,9 +14,15 @@
{% if order.status != 'p' %}
<p>
{% trans "Your order has been placed successfully. See below for details." %}<br>
<strong>
{% trans "Please note that we still await your payment to complete the process." %}
</strong>
{% if order.require_approval %}
<strong>
{% trans "Please note that we still await approval by the event organizer before you can pay and complete this order." %}
</strong>
{% else %}
<strong>
{% trans "Please note that we still await your payment to complete the process." %}
</strong>
{% endif %}
</p>
{% elif order.total == 0 %}
<p>{% trans "Your order has been processed successfully! See below for details." %}</p>

View File

@@ -1143,6 +1143,80 @@ def test_order_extend_expired_quota_left(token_client, organizer, event, order,
assert order.expires.strftime("%Y-%m-%d %H:%M:%S") == newdate[:10] + " 23:59:59"
@pytest.mark.django_db
def test_order_pending_approve(token_client, organizer, event, order):
order.require_approval = True
order.save()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/{}/approve/'.format(
organizer.slug, event.slug, order.code
)
)
assert resp.status_code == 200
assert resp.data['status'] == Order.STATUS_PENDING
assert not resp.data['require_approval']
@pytest.mark.django_db
def test_order_invalid_state_approve(token_client, organizer, event, order):
order.require_approval = True
order.status = Order.STATUS_CANCELED
order.save()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/{}/approve/'.format(
organizer.slug, event.slug, order.code
)
)
assert resp.status_code == 400
order.require_approval = False
order.status = Order.STATUS_PENDING
order.save()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/{}/approve/'.format(
organizer.slug, event.slug, order.code
)
)
assert resp.status_code == 400
@pytest.mark.django_db
def test_order_pending_deny(token_client, organizer, event, order):
order.require_approval = True
order.save()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/{}/deny/'.format(
organizer.slug, event.slug, order.code
)
)
assert resp.status_code == 200
assert resp.data['status'] == Order.STATUS_CANCELED
assert resp.data['require_approval']
@pytest.mark.django_db
def test_order_invalid_state_deny(token_client, organizer, event, order):
order.require_approval = True
order.status = Order.STATUS_CANCELED
order.save()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/{}/deny/'.format(
organizer.slug, event.slug, order.code
)
)
assert resp.status_code == 400
order.require_approval = False
order.status = Order.STATUS_PENDING
order.save()
resp = token_client.post(
'/api/v1/organizers/{}/events/{}/orders/{}/deny/'.format(
organizer.slug, event.slug, order.code
)
)
assert resp.status_code == 400
ORDER_CREATE_PAYLOAD = {
"email": "dummy@dummy.test",
"locale": "en",

View File

@@ -73,6 +73,8 @@ event_permission_sub_urls = [
('post', 'can_change_orders', 'orders/ABC12/mark_pending/', 404),
('post', 'can_change_orders', 'orders/ABC12/mark_expired/', 404),
('post', 'can_change_orders', 'orders/ABC12/mark_canceled/', 404),
('post', 'can_change_orders', 'orders/ABC12/approve/', 404),
('post', 'can_change_orders', 'orders/ABC12/deny/', 404),
('post', 'can_change_orders', 'orders/ABC12/extend/', 400),
('get', 'can_view_orders', 'orders/ABC12/payments/', 404),
('get', 'can_view_orders', 'orders/ABC12/payments/1/', 404),

View File

@@ -18,8 +18,8 @@ from pretix.base.payment import FreeOrderProvider
from pretix.base.reldate import RelativeDate, RelativeDateWrapper
from pretix.base.services.invoices import generate_invoice
from pretix.base.services.orders import (
OrderChangeManager, OrderError, _create_order, expire_orders,
send_download_reminders,
OrderChangeManager, OrderError, _create_order, approve_order, deny_order,
expire_orders, send_download_reminders,
)
@@ -207,6 +207,88 @@ def test_expiring_auto_disabled(event):
assert o2.status == Order.STATUS_PENDING
@pytest.mark.django_db
def test_do_not_expire_if_approval_pending(event):
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=0, require_approval=True
)
o2 = Order.objects.create(
code='FO2', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=0,
)
expire_orders(None)
o1 = Order.objects.get(id=o1.id)
assert o1.status == Order.STATUS_PENDING
o2 = Order.objects.get(id=o2.id)
assert o2.status == Order.STATUS_EXPIRED
@pytest.mark.django_db
def test_approve(event):
djmail.outbox = []
event.settings.invoice_generate = 'True'
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=10, require_approval=True, locale='de'
)
approve_order(o1)
o1.refresh_from_db()
assert o1.expires > now()
assert o1.status == Order.STATUS_PENDING
assert not o1.require_approval
assert o1.invoices.count() == 1
assert len(djmail.outbox) == 1
assert 'awaiting payment' in djmail.outbox[0].subject
@pytest.mark.django_db
def test_approve_free(event):
djmail.outbox = []
event.settings.invoice_generate = 'True'
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=0, require_approval=True
)
approve_order(o1)
o1.refresh_from_db()
assert o1.expires > now()
assert o1.status == Order.STATUS_PAID
assert not o1.require_approval
assert o1.invoices.count() == 0
assert len(djmail.outbox) == 1
assert 'confirmed' in djmail.outbox[0].subject
@pytest.mark.django_db
def test_deny(event):
djmail.outbox = []
event.settings.invoice_generate = 'True'
o1 = Order.objects.create(
code='FOO', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() - timedelta(days=10),
total=10, require_approval=True, locale='de'
)
generate_invoice(o1)
deny_order(o1)
o1.refresh_from_db()
assert o1.expires < now()
assert o1.status == Order.STATUS_CANCELED
assert o1.require_approval
assert o1.invoices.count() == 2
assert len(djmail.outbox) == 1
assert 'denied' in djmail.outbox[0].subject
class DownloadReminderTests(TestCase):
def setUp(self):
super().setUp()

View File

@@ -92,6 +92,13 @@ def test_order_list(client, env):
response = client.get('/control/event/dummy/dummy/orders/?status=o')
assert 'FOO' in response.rendered_content
response = client.get('/control/event/dummy/dummy/orders/?status=pa')
assert 'FOO' not in response.rendered_content
env[2].require_approval = True
env[2].save()
response = client.get('/control/event/dummy/dummy/orders/?status=pa')
assert 'FOO' in response.rendered_content
q = Question.objects.create(event=env[0], question="Q", type="N", required=True)
q.items.add(env[3])
op = env[2].positions.first()
@@ -208,6 +215,40 @@ def test_order_transition_to_paid_expired_quota_left(client, env):
assert o.status == Order.STATUS_PAID
@pytest.mark.django_db
def test_order_approve(client, env):
o = Order.objects.get(id=env[2].id)
o.status = Order.STATUS_PENDING
o.require_approval = True
o.save()
q = Quota.objects.create(event=env[0], size=10)
q.items.add(env[3])
client.login(email='dummy@dummy.dummy', password='dummy')
res = client.post('/control/event/dummy/dummy/orders/FOO/approve', {
})
o = Order.objects.get(id=env[2].id)
assert res.status_code < 400
assert o.status == Order.STATUS_PENDING
assert not o.require_approval
@pytest.mark.django_db
def test_order_deny(client, env):
o = Order.objects.get(id=env[2].id)
o.status = Order.STATUS_PENDING
o.require_approval = True
o.save()
q = Quota.objects.create(event=env[0], size=10)
q.items.add(env[3])
client.login(email='dummy@dummy.dummy', password='dummy')
res = client.post('/control/event/dummy/dummy/orders/FOO/deny', {
})
o = Order.objects.get(id=env[2].id)
assert res.status_code < 400
assert o.status == Order.STATUS_CANCELED
assert o.require_approval
@pytest.mark.django_db
@pytest.mark.parametrize("process", [
# (Old status, new status, success expected)

View File

@@ -14,7 +14,7 @@ from django_countries.fields import Country
from pretix.base.decimal import round_decimal
from pretix.base.models import (
CartPosition, Event, InvoiceAddress, Item, ItemCategory, Order,
CartPosition, Event, Invoice, InvoiceAddress, Item, ItemCategory, Order,
OrderPosition, Organizer, Question, QuestionAnswer, Quota, Voucher,
)
from pretix.base.models.items import ItemAddOn, ItemVariation, SubEventItem
@@ -803,6 +803,43 @@ class CheckoutTestCase(TestCase):
self.assertEqual(OrderPosition.objects.count(), 1)
self.assertEqual(OrderPosition.objects.first().subevent, se)
def test_require_approval_no_payment_step(self):
self.event.settings.invoice_generate = 'True'
self.ticket.require_approval = True
self.ticket.save()
cr1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=42, expires=now() + timedelta(minutes=10)
)
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
doc = BeautifulSoup(response.rendered_content, "lxml")
print(doc)
self.assertEqual(len(doc.select(".thank-you")), 1)
self.assertFalse(CartPosition.objects.filter(id=cr1.id).exists())
self.assertEqual(Order.objects.count(), 1)
self.assertEqual(Order.objects.first().status, Order.STATUS_PENDING)
self.assertTrue(Order.objects.first().require_approval)
self.assertEqual(OrderPosition.objects.count(), 1)
self.assertEqual(Invoice.objects.count(), 0)
def test_require_approval_no_payment_step_free(self):
self.ticket.require_approval = True
self.ticket.save()
cr1 = CartPosition.objects.create(
event=self.event, cart_id=self.session_key, item=self.ticket,
price=0, expires=now() + timedelta(minutes=10)
)
response = self.client.post('/%s/%s/checkout/confirm/' % (self.orga.slug, self.event.slug), follow=True)
doc = BeautifulSoup(response.rendered_content, "lxml")
self.assertEqual(len(doc.select(".thank-you")), 1)
self.assertFalse(CartPosition.objects.filter(id=cr1.id).exists())
self.assertEqual(Order.objects.count(), 1)
self.assertEqual(Order.objects.first().status, Order.STATUS_PENDING)
self.assertTrue(Order.objects.first().require_approval)
self.assertEqual(OrderPosition.objects.count(), 1)
def test_free_price(self):
self.ticket.free_price = True
self.ticket.save()