mirror of
https://github.com/pretix/pretix.git
synced 2026-05-03 14:54:04 +00:00
Fix #571 -- Partial payments and refunds
This commit is contained in:
@@ -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'),
|
||||
)
|
||||
shirt = Item.objects.create(event=event, name='T-Shirt', default_price=12)
|
||||
shirt_red = ItemVariation.objects.create(item=shirt, default_price=14, value="Red")
|
||||
|
||||
@@ -25,13 +25,13 @@ def env():
|
||||
code='1Z3AS', event=event,
|
||||
status=Order.STATUS_PENDING,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23,
|
||||
)
|
||||
o2 = Order.objects.create(
|
||||
code='6789Z', event=event,
|
||||
status=Order.STATUS_CANCELED,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23,
|
||||
)
|
||||
quota = Quota.objects.create(name="Test", size=2, event=event)
|
||||
item1 = Item.objects.create(event=event, name="Ticket", default_price=23)
|
||||
@@ -56,23 +56,6 @@ def test_discard(env, client):
|
||||
assert trans.payer == ''
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_accept_wrong_amount(env, client):
|
||||
job = BankImportJob.objects.create(event=env[0])
|
||||
trans = BankTransaction.objects.create(event=env[0], import_job=job, payer='Foo',
|
||||
state=BankTransaction.STATE_INVALID,
|
||||
amount=12, date='unknown', order=env[2])
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
r = json.loads(client.post('/control/event/{}/{}/banktransfer/action/'.format(env[0].organizer.slug, env[0].slug), {
|
||||
'action_{}'.format(trans.pk): 'accept',
|
||||
}).content.decode('utf-8'))
|
||||
assert r['status'] == 'ok'
|
||||
trans.refresh_from_db()
|
||||
assert trans.state == BankTransaction.STATE_VALID
|
||||
env[2].refresh_from_db()
|
||||
assert env[2].status == Order.STATUS_PAID
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_assign_order(env, client):
|
||||
job = BankImportJob.objects.create(event=env[0])
|
||||
|
||||
@@ -28,13 +28,13 @@ def env():
|
||||
code='1Z3AS', event=event,
|
||||
status=Order.STATUS_PENDING,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23
|
||||
)
|
||||
o2 = Order.objects.create(
|
||||
code='6789Z', event=event,
|
||||
status=Order.STATUS_CANCELED,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23
|
||||
)
|
||||
quota = Quota.objects.create(name="Test", size=2, event=event)
|
||||
item1 = Item.objects.create(event=event, name="Ticket", default_price=23)
|
||||
|
||||
@@ -7,7 +7,8 @@ from django.core.files.uploadedfile import SimpleUploadedFile
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import (
|
||||
Event, Item, Order, OrderPosition, Organizer, Quota, Team, User,
|
||||
Event, Item, Order, OrderPayment, OrderPosition, Organizer, Quota, Team,
|
||||
User,
|
||||
)
|
||||
from pretix.plugins.banktransfer.models import BankImportJob
|
||||
from pretix.plugins.banktransfer.tasks import process_banktransfers
|
||||
@@ -28,19 +29,19 @@ def env():
|
||||
code='1Z3AS', event=event,
|
||||
status=Order.STATUS_PENDING,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23
|
||||
)
|
||||
o2 = Order.objects.create(
|
||||
code='6789Z', event=event,
|
||||
status=Order.STATUS_CANCELED,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23
|
||||
)
|
||||
Order.objects.create(
|
||||
code='GS89Z', event=event,
|
||||
status=Order.STATUS_CANCELED,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23, payment_provider='banktransfer'
|
||||
total=23
|
||||
)
|
||||
quota = Quota.objects.create(name="Test", size=2, event=event)
|
||||
item1 = Item.objects.create(event=event, name="Ticket", default_price=23)
|
||||
@@ -110,7 +111,43 @@ def test_mark_paid(env, job):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_check_amount(env, job):
|
||||
def test_underpaid(env, job):
|
||||
process_banktransfers(job, [{
|
||||
'payer': 'Karla Kundin',
|
||||
'reference': 'Bestellung DUMMY1Z3AS',
|
||||
'date': '2016-01-26',
|
||||
'amount': '22.50'
|
||||
}])
|
||||
env[2].refresh_from_db()
|
||||
assert env[2].status == Order.STATUS_PENDING
|
||||
p = env[2].payments.last()
|
||||
assert p.amount == Decimal('22.50')
|
||||
assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED
|
||||
assert env[2].pending_sum == Decimal('0.50')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_in_parts(env, job):
|
||||
process_banktransfers(job, [{
|
||||
'payer': 'Karla Kundin',
|
||||
'reference': 'Bestellung DUMMY1Z3AS',
|
||||
'date': '2016-01-26',
|
||||
'amount': '10.00'
|
||||
}])
|
||||
process_banktransfers(job, [{
|
||||
'payer': 'Karla Kundin',
|
||||
'reference': 'Bestellung DUMMY1Z3AS',
|
||||
'date': '2016-01-26',
|
||||
'amount': '13.00'
|
||||
}])
|
||||
env[2].refresh_from_db()
|
||||
assert env[2].status == Order.STATUS_PAID
|
||||
assert env[2].payments.count() == 2
|
||||
assert env[2].pending_sum == Decimal('0.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_overpaid(env, job):
|
||||
process_banktransfers(job, [{
|
||||
'payer': 'Karla Kundin',
|
||||
'reference': 'Bestellung DUMMY1Z3AS',
|
||||
@@ -118,7 +155,11 @@ def test_check_amount(env, job):
|
||||
'amount': '23.50'
|
||||
}])
|
||||
env[2].refresh_from_db()
|
||||
assert env[2].status == Order.STATUS_PENDING
|
||||
assert env[2].status == Order.STATUS_PAID
|
||||
p = env[2].payments.last()
|
||||
assert p.amount == Decimal('23.50')
|
||||
assert p.state == OrderPayment.PAYMENT_STATE_CONFIRMED
|
||||
assert env[2].pending_sum == Decimal('-0.50')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
|
||||
@@ -6,7 +6,7 @@ import pytest
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import (
|
||||
Event, Order, Organizer, RequiredAction, Team, User,
|
||||
Event, Order, OrderPayment, OrderRefund, Organizer, Team, User,
|
||||
)
|
||||
from pretix.plugins.paypal.models import ReferencedPayPalObject
|
||||
|
||||
@@ -26,8 +26,13 @@ def env():
|
||||
code='FOOBAR', event=event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=Decimal('13.37'), payment_provider='paypal',
|
||||
payment_info=json.dumps({
|
||||
total=Decimal('13.37'),
|
||||
)
|
||||
o1.payments.create(
|
||||
amount=o1.total,
|
||||
provider='paypal',
|
||||
state=OrderPayment.PAYMENT_STATE_CONFIRMED,
|
||||
info=json.dumps({
|
||||
"id": "PAY-5YK922393D847794YKER7MUI",
|
||||
"create_time": "2013-02-19T22:01:53Z",
|
||||
"update_time": "2013-02-19T22:01:55Z",
|
||||
@@ -150,6 +155,33 @@ def get_test_charge(order: Order):
|
||||
}
|
||||
|
||||
|
||||
def get_test_refund(order: Order):
|
||||
return {
|
||||
'refund_from_received_amount': {'value': '13.30', 'currency': 'EUR'},
|
||||
'amount': {'total': '13.37', 'currency': 'EUR'},
|
||||
'sale_id': '1G495778AR8401726',
|
||||
'update_time': '2018-07-24T07:50:07Z',
|
||||
'total_refunded_amount': {'value': '13.37', 'currency': 'EUR'},
|
||||
'refund_reason_code': 'REFUND',
|
||||
'invoice_number': 'Test',
|
||||
'parent_payment': 'PAY-0UB50445HE155450FLNLNMUY',
|
||||
'state': 'completed',
|
||||
'create_time': '2018-07-24T07:50:07Z',
|
||||
'refund_from_transaction_fee': {'value': '0.07', 'currency': 'EUR'},
|
||||
'id': '93M41501U3542574L',
|
||||
'refund_to_payer': {'value': '13.37', 'currency': 'EUR'},
|
||||
'links': [
|
||||
{'method': 'GET', 'rel': 'self',
|
||||
'href': 'https://api.sandbox.paypal.com/v1/payments/refund/93M41501U3542574L'},
|
||||
{'method': 'GET',
|
||||
'rel': 'parent_payment',
|
||||
'href': 'https://api.sandbox.paypal.com/v1/payments/payment/PAY-0UB50445HE155450FLNLNMUY'},
|
||||
{'method': 'GET', 'rel': 'sale',
|
||||
'href': 'https://api.sandbox.paypal.com/v1/payments/sale/1G495778AR8401726'}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_all_good(env, client, monkeypatch):
|
||||
charge = get_test_charge(env[1])
|
||||
@@ -191,6 +223,7 @@ def test_webhook_global(env, client, monkeypatch):
|
||||
order = env[1]
|
||||
order.status = Order.STATUS_PENDING
|
||||
order.save()
|
||||
order.payments.update(state=OrderPayment.PAYMENT_STATE_PENDING)
|
||||
|
||||
charge = get_test_charge(env[1])
|
||||
monkeypatch.setattr("paypalrestsdk.Sale.find", lambda *args: charge)
|
||||
@@ -231,6 +264,7 @@ def test_webhook_mark_paid(env, client, monkeypatch):
|
||||
order = env[1]
|
||||
order.status = Order.STATUS_PENDING
|
||||
order.save()
|
||||
order.payments.update(state=OrderPayment.PAYMENT_STATE_PENDING)
|
||||
|
||||
charge = get_test_charge(env[1])
|
||||
monkeypatch.setattr("paypalrestsdk.Sale.find", lambda *args: charge)
|
||||
@@ -269,8 +303,10 @@ def test_webhook_mark_paid(env, client, monkeypatch):
|
||||
def test_webhook_refund1(env, client, monkeypatch):
|
||||
charge = get_test_charge(env[1])
|
||||
charge['state'] = 'refunded'
|
||||
refund = get_test_refund(env[1])
|
||||
|
||||
monkeypatch.setattr("paypalrestsdk.Sale.find", lambda *args: charge)
|
||||
monkeypatch.setattr("paypalrestsdk.Refund.find", lambda *args: refund)
|
||||
monkeypatch.setattr("pretix.plugins.paypal.payment.Paypal.init_api", lambda *args: None)
|
||||
|
||||
client.post('/dummy/dummy/paypal/webhook/', json.dumps(
|
||||
@@ -309,21 +345,22 @@ def test_webhook_refund1(env, client, monkeypatch):
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_PAID
|
||||
|
||||
ra = RequiredAction.objects.get(action_type="pretix.plugins.paypal.refund")
|
||||
client.login(username='dummy@dummy.dummy', password='dummy')
|
||||
client.post('/control/event/dummy/dummy/paypal/refund/{}/'.format(ra.pk))
|
||||
|
||||
order = env[1]
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_REFUNDED
|
||||
r = order.refunds.first()
|
||||
assert r.provider == 'paypal'
|
||||
assert r.amount == order.total
|
||||
assert r.payment == order.payments.first()
|
||||
assert r.state == OrderRefund.REFUND_STATE_EXTERNAL
|
||||
assert r.source == OrderRefund.REFUND_SOURCE_EXTERNAL
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_refund2(env, client, monkeypatch):
|
||||
charge = get_test_charge(env[1])
|
||||
charge['state'] = 'refunded'
|
||||
refund = get_test_refund(env[1])
|
||||
|
||||
monkeypatch.setattr("paypalrestsdk.Sale.find", lambda *args: charge)
|
||||
monkeypatch.setattr("paypalrestsdk.Refund.find", lambda *args: refund)
|
||||
monkeypatch.setattr("pretix.plugins.paypal.payment.Paypal.init_api", lambda *args: None)
|
||||
|
||||
client.post('/dummy/dummy/paypal/webhook/', json.dumps(
|
||||
@@ -331,7 +368,7 @@ def test_webhook_refund2(env, client, monkeypatch):
|
||||
# Sample obtained in the webhook simulator
|
||||
"id": "WH-2N242548W9943490U-1JU23391CS4765624",
|
||||
"create_time": "2014-10-31T15:42:24Z",
|
||||
"resource_type": "sale",
|
||||
"resource_type": "refund",
|
||||
"event_type": "PAYMENT.SALE.REFUNDED",
|
||||
"summary": "A 0.01 USD sale payment was refunded",
|
||||
"resource": {
|
||||
@@ -356,10 +393,9 @@ def test_webhook_refund2(env, client, monkeypatch):
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_PAID
|
||||
|
||||
ra = RequiredAction.objects.get(action_type="pretix.plugins.paypal.refund")
|
||||
client.login(username='dummy@dummy.dummy', password='dummy')
|
||||
client.post('/control/event/dummy/dummy/paypal/refund/{}/'.format(ra.pk))
|
||||
|
||||
order = env[1]
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_REFUNDED
|
||||
r = order.refunds.first()
|
||||
assert r.provider == 'paypal'
|
||||
assert r.amount == order.total
|
||||
assert r.payment == order.payments.first()
|
||||
assert r.state == OrderRefund.REFUND_STATE_EXTERNAL
|
||||
assert r.source == OrderRefund.REFUND_SOURCE_EXTERNAL
|
||||
|
||||
@@ -32,7 +32,7 @@ def env():
|
||||
o1 = Order.objects.create(
|
||||
code='FOO', event=event, status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=0, payment_provider='banktransfer'
|
||||
total=0
|
||||
)
|
||||
op1 = OrderPosition.objects.create(
|
||||
order=o1, item=shirt, variation=shirt_red,
|
||||
|
||||
@@ -35,7 +35,7 @@ def env():
|
||||
o1 = Order.objects.create(
|
||||
code='FOO', event=event, status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=0, payment_provider='banktransfer'
|
||||
total=0
|
||||
)
|
||||
op1 = OrderPosition.objects.create(
|
||||
order=o1, item=shirt, variation=shirt_red,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -6,7 +6,7 @@ import pytest
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import (
|
||||
Event, Order, Organizer, RequiredAction, Team, User,
|
||||
Event, Order, OrderPayment, OrderRefund, Organizer, Team, User,
|
||||
)
|
||||
from pretix.plugins.stripe.models import ReferencedStripeObject
|
||||
|
||||
@@ -26,7 +26,7 @@ def env():
|
||||
code='FOOBAR', event=event, email='dummy@dummy.test',
|
||||
status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=Decimal('13.37'), payment_provider='stripe'
|
||||
total=Decimal('13.37'),
|
||||
)
|
||||
return event, o1
|
||||
|
||||
@@ -129,7 +129,7 @@ def test_webhook_all_good(env, client, monkeypatch):
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_mark_paid(env, client, monkeypatch):
|
||||
def test_webhook_mark_paid_without_reference_and_payment(env, client, monkeypatch):
|
||||
order = env[1]
|
||||
order.status = Order.STATUS_PENDING
|
||||
order.save()
|
||||
@@ -164,6 +164,13 @@ def test_webhook_mark_paid(env, client, monkeypatch):
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_partial_refund(env, client, monkeypatch):
|
||||
charge = get_test_charge(env[1])
|
||||
|
||||
payment = env[1].payments.create(
|
||||
provider='stripe', amount=env[1].total, info=json.dumps(charge)
|
||||
)
|
||||
ReferencedStripeObject.objects.create(order=env[1], reference="ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
payment=payment)
|
||||
|
||||
charge['refunds'] = {
|
||||
"object": "list",
|
||||
"data": [
|
||||
@@ -209,13 +216,10 @@ def test_webhook_partial_refund(env, client, monkeypatch):
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_PAID
|
||||
|
||||
ra = RequiredAction.objects.get(action_type="pretix.plugins.stripe.refund")
|
||||
client.login(username='dummy@dummy.dummy', password='dummy')
|
||||
client.post('/control/event/dummy/dummy/stripe/refund/{}/'.format(ra.pk))
|
||||
|
||||
order = env[1]
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_REFUNDED
|
||||
ra = order.refunds.first()
|
||||
assert ra.state == OrderRefund.REFUND_STATE_EXTERNAL
|
||||
assert ra.source == 'external'
|
||||
assert ra.amount == Decimal('123.00')
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@@ -227,6 +231,48 @@ def test_webhook_global(env, client, monkeypatch):
|
||||
charge = get_test_charge(env[1])
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", lambda *args, **kwargs: charge)
|
||||
|
||||
payment = order.payments.create(
|
||||
provider='stripe', amount=order.total, info=json.dumps(charge), state=OrderPayment.PAYMENT_STATE_CREATED
|
||||
)
|
||||
ReferencedStripeObject.objects.create(order=order, reference="ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
payment=payment)
|
||||
|
||||
client.post('/_stripe/webhook/', json.dumps(
|
||||
{
|
||||
"id": "evt_18otImGGWE2Ias8TUyVRDB1G",
|
||||
"object": "event",
|
||||
"api_version": "2016-03-07",
|
||||
"created": 1472729052,
|
||||
"data": {
|
||||
"object": {
|
||||
"id": "ch_18TY6GGGWE2Ias8TZHanef25",
|
||||
"object": "charge",
|
||||
# Rest of object is ignored anway
|
||||
}
|
||||
},
|
||||
"livemode": True,
|
||||
"pending_webhooks": 1,
|
||||
"request": "req_977XOWC8zk51Z9",
|
||||
"type": "charge.succeeded"
|
||||
}
|
||||
), content_type='application_json')
|
||||
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_PAID
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_webhook_global_legacy_reference(env, client, monkeypatch):
|
||||
order = env[1]
|
||||
order.status = Order.STATUS_PENDING
|
||||
order.save()
|
||||
|
||||
charge = get_test_charge(env[1])
|
||||
monkeypatch.setattr("stripe.Charge.retrieve", lambda *args, **kwargs: charge)
|
||||
|
||||
payment = order.payments.create(
|
||||
provider='stripe', amount=order.total, info=json.dumps(charge), state=OrderPayment.PAYMENT_STATE_CREATED
|
||||
)
|
||||
ReferencedStripeObject.objects.create(order=order, reference="ch_18TY6GGGWE2Ias8TZHanef25")
|
||||
|
||||
client.post('/_stripe/webhook/', json.dumps(
|
||||
@@ -251,3 +297,4 @@ def test_webhook_global(env, client, monkeypatch):
|
||||
|
||||
order.refresh_from_db()
|
||||
assert order.status == Order.STATUS_PAID
|
||||
assert list(order.payments.all()) == [payment]
|
||||
|
||||
@@ -39,7 +39,7 @@ def order(item):
|
||||
o = Order.objects.create(event=item.event, status=Order.STATUS_PENDING,
|
||||
expires=now() + datetime.timedelta(hours=1),
|
||||
total=13, code='DUMMY', email='dummy@dummy.test',
|
||||
datetime=now(), payment_provider='banktransfer', locale='en')
|
||||
datetime=now(), locale='en')
|
||||
OrderPosition.objects.create(order=o, item=item, price=13)
|
||||
return o
|
||||
|
||||
@@ -148,7 +148,7 @@ def test_sendmail_multi_locales(logged_in_client, sendmail_url, event, item):
|
||||
o = Order.objects.create(event=item.event, status=Order.STATUS_PAID,
|
||||
expires=now() + datetime.timedelta(hours=1),
|
||||
total=13, code='DUMMY', email='dummy@dummy.test',
|
||||
datetime=now(), payment_provider='banktransfer',
|
||||
datetime=now(),
|
||||
locale='de')
|
||||
OrderPosition.objects.create(order=o, item=item, price=13)
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ def env0():
|
||||
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'),
|
||||
)
|
||||
shirt = Item.objects.create(event=event, name='T-Shirt', default_price=12)
|
||||
shirt_red = ItemVariation.objects.create(item=shirt, default_price=14, value="Red")
|
||||
|
||||
Reference in New Issue
Block a user