Fix #571 -- Partial payments and refunds

This commit is contained in:
Raphael Michel
2018-06-26 12:09:36 +02:00
parent 8e7af49206
commit 18a378976b
115 changed files with 6026 additions and 1598 deletions

View File

@@ -5,9 +5,9 @@ from decimal import Decimal
import pytest
from django.test import RequestFactory
from django.utils.timezone import now
from stripe import APIConnectionError, CardError, StripeError
from stripe.error import APIConnectionError, CardError, StripeError
from pretix.base.models import Event, Order, Organizer
from pretix.base.models import Event, Order, OrderRefund, Organizer
from pretix.base.payment import PaymentException
from pretix.plugins.stripe.payment import StripeCC
@@ -23,7 +23,7 @@ def env():
code='FOOBAR', event=event, email='dummy@dummy.test',
status=Order.STATUS_PENDING,
datetime=now(), expires=now() + timedelta(days=10),
total=Decimal('13.37'), payment_provider='banktransfer'
total=Decimal('13.37')
)
return event, o1
@@ -39,11 +39,16 @@ def factory():
return RequestFactory()
class MockedRefunds():
pass
class MockedCharge():
def __init__(self):
self.status = ''
self.paid = False
self.id = 'ch_123345345'
self.refunds = MockedRefunds()
def refresh(self):
pass
@@ -72,7 +77,10 @@ def test_perform_success(env, factory, monkeypatch):
req.session = {}
prov.checkout_prepare(req, {})
assert 'payment_stripe_token' in req.session
prov.payment_perform(req, order)
payment = order.payments.create(
provider='stripe_cc', amount=order.total
)
prov.execute_payment(req, payment)
order.refresh_from_db()
assert order.status == Order.STATUS_PAID
@@ -102,7 +110,10 @@ def test_perform_success_zero_decimal_currency(env, factory, monkeypatch):
req.session = {}
prov.checkout_prepare(req, {})
assert 'payment_stripe_token' in req.session
prov.payment_perform(req, order)
payment = order.payments.create(
provider='stripe_cc', amount=order.total
)
prov.execute_payment(req, payment)
order.refresh_from_db()
assert order.status == Order.STATUS_PAID
@@ -125,7 +136,10 @@ def test_perform_card_error(env, factory, monkeypatch):
prov.checkout_prepare(req, {})
assert 'payment_stripe_token' in req.session
with pytest.raises(PaymentException):
prov.payment_perform(req, order)
payment = order.payments.create(
provider='stripe_cc', amount=order.total
)
prov.execute_payment(req, payment)
order.refresh_from_db()
assert order.status == Order.STATUS_PENDING
@@ -148,7 +162,10 @@ def test_perform_stripe_error(env, factory, monkeypatch):
prov.checkout_prepare(req, {})
assert 'payment_stripe_token' in req.session
with pytest.raises(PaymentException):
prov.payment_perform(req, order)
payment = order.payments.create(
provider='stripe_cc', amount=order.total
)
prov.execute_payment(req, payment)
order.refresh_from_db()
assert order.status == Order.STATUS_PENDING
@@ -175,7 +192,10 @@ def test_perform_failed(env, factory, monkeypatch):
prov.checkout_prepare(req, {})
assert 'payment_stripe_token' in req.session
with pytest.raises(PaymentException):
prov.payment_perform(req, order)
payment = order.payments.create(
provider='stripe_cc', amount=order.total
)
prov.execute_payment(req, payment)
order.refresh_from_db()
assert order.status == Order.STATUS_PENDING
@@ -185,26 +205,26 @@ def test_refund_success(env, factory, monkeypatch):
event, order = env
def charge_retr(*args, **kwargs):
def refund_create():
def refund_create(amount):
pass
c = MockedCharge()
c.refunds = MockedCharge()
c.refunds.create = refund_create
return c
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
order.status = Order.STATUS_PAID
order.payment_info = json.dumps({
p = order.payments.create(provider='stripe_cc', amount=order.total, info=json.dumps({
'id': 'ch_123345345'
})
}))
order.save()
prov = StripeCC(event)
req = factory.post('/', data={'auto_refund': 'auto'})
req.user = None
prov.order_control_refund_perform(req, order)
order.refresh_from_db()
assert order.status == Order.STATUS_REFUNDED
refund = order.refunds.create(
provider='stripe_cc', amount=order.total, payment=p,
)
prov.execute_refund(refund)
refund.refresh_from_db()
assert refund.state == OrderRefund.REFUND_STATE_DONE
@pytest.mark.django_db
@@ -212,23 +232,24 @@ def test_refund_unavailable(env, factory, monkeypatch):
event, order = env
def charge_retr(*args, **kwargs):
def refund_create():
def refund_create(amount):
raise APIConnectionError(message='Foo')
c = MockedCharge()
c.refunds = object()
c.refunds.create = refund_create()
c.refunds.create = refund_create
return c
monkeypatch.setattr("stripe.Charge.retrieve", charge_retr)
order.status = Order.STATUS_PAID
order.payment_info = json.dumps({
p = order.payments.create(provider='stripe_cc', amount=order.total, info=json.dumps({
'id': 'ch_123345345'
})
}))
order.save()
prov = StripeCC(event)
req = factory.get('/')
req.user = None
prov.order_control_refund_perform(req, order)
order.refresh_from_db()
assert order.status == Order.STATUS_PAID
refund = order.refunds.create(
provider='stripe_cc', amount=order.total, payment=p
)
with pytest.raises(PaymentException):
prov.execute_refund(refund)
refund.refresh_from_db()
assert refund.state != OrderRefund.REFUND_STATE_DONE