mirror of
https://github.com/pretix/pretix.git
synced 2026-05-04 15:04:03 +00:00
Improvements for bank transfer importing (#1762)
Co-authored-by: Raphael Michel <michel@rami.io> Co-authored-by: Raphael Michel <mail@raphaelmichel.de>
This commit is contained in:
@@ -191,29 +191,33 @@ EXPECTED = [
|
||||
[
|
||||
{'amount': '-800.00',
|
||||
'date': '2002-11-01',
|
||||
'payer': 'MUELLER - 234567',
|
||||
'payer': 'MUELLER',
|
||||
'iban': '234567',
|
||||
'reference': 'Miete November'},
|
||||
{'amount': '3000.00',
|
||||
'date': '2002-11-02',
|
||||
'payer': 'MUELLER - 0847564700',
|
||||
'payer': 'MUELLER',
|
||||
'iban': '0847564700',
|
||||
'reference': 'Gehalt Oktober Firma Mustermann GmbH'},
|
||||
],
|
||||
[
|
||||
{'amount': '-400.62',
|
||||
'date': '2012-02-02',
|
||||
'payer': 'MARTHAMUELLER -',
|
||||
'payer': 'MARTHAMUELLER',
|
||||
'reference': 'RECHNUNGSNR. 1210815 KUNDENNR. 01234 22222222 DATUM 01.02.2012'},
|
||||
{'amount': '-1210.00',
|
||||
'date': '2012-02-03',
|
||||
'reference': 'MIETE GOETHESTR. 12',
|
||||
'payer': 'ABC IMMOBILIEN GMBH - 3333333333'},
|
||||
'payer': 'ABC IMMOBILIEN GMBH',
|
||||
'iban': '3333333333'},
|
||||
{'amount': '30.00',
|
||||
'date': '2012-02-03',
|
||||
'payer': 'STEFAN SCHMIDT -',
|
||||
'payer': 'STEFAN SCHMIDT',
|
||||
'reference': 'RECHNUNG 20120188 STEFAN SCHMIDTKUNDENR. 4711,'},
|
||||
{'amount': '89.97',
|
||||
'date': '2012-02-03',
|
||||
'payer': 'PETER PETERSEN - 5555555555',
|
||||
'payer': 'PETER PETERSEN',
|
||||
'iban': '5555555555',
|
||||
'reference': 'RECHNUNG 20120165 PETER PETERSEN'}
|
||||
],
|
||||
[
|
||||
@@ -228,12 +232,21 @@ EXPECTED = [
|
||||
{'amount': '-50000.00', 'date': '2002-03-24', 'reference': ''}
|
||||
],
|
||||
[
|
||||
{'amount': '12.00', 'date': '2017-08-23', 'payer': 'Peter Schneider - DE13495179316396679327', 'reference':
|
||||
'Democon-Abcde (Peter Schneider ), Kategorie: Alles - E innahmen - Veranstaltungen Democon #1111'},
|
||||
{'amount': '12.00', 'date': '2017-08-23', 'payer': 'Peter Schneider - DE13495179316396679327', 'reference':
|
||||
'Democon-Abcde (Peter Schneider ), Kategorie: Alles - E innahmen - Veranstaltungen Democon #1111'},
|
||||
{'amount': '12.00', 'date': '2017-08-24', 'payer': 'Peter Schneider - DE13495179316396679327', 'reference':
|
||||
'Democon-Abcde (Peter Schneider ), Kategorie: Alles- E innahmen - Veranstaltungen Democon #1111'},
|
||||
{'amount': '12.00',
|
||||
'date': '2017-08-23',
|
||||
'payer': 'Peter Schneider',
|
||||
'iban': 'DE13495179316396679327',
|
||||
'reference': 'Democon-Abcde (Peter Schneider ), Kategorie: Alles - E innahmen - Veranstaltungen Democon #1111'},
|
||||
{'amount': '12.00',
|
||||
'date': '2017-08-23',
|
||||
'payer': 'Peter Schneider',
|
||||
'iban': 'DE13495179316396679327',
|
||||
'reference': 'Democon-Abcde (Peter Schneider ), Kategorie: Alles - E innahmen - Veranstaltungen Democon #1111'},
|
||||
{'amount': '12.00',
|
||||
'date': '2017-08-24',
|
||||
'payer': 'Peter Schneider',
|
||||
'iban': 'DE13495179316396679327',
|
||||
'reference': 'Democon-Abcde (Peter Schneider ), Kategorie: Alles- E innahmen - Veranstaltungen Democon #1111'},
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
21
src/tests/plugins/banktransfer/test_parsing.py
Normal file
21
src/tests/plugins/banktransfer/test_parsing.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from datetime import date
|
||||
|
||||
from pretix.plugins.banktransfer.tasks import parse_date
|
||||
|
||||
|
||||
def test_date_formats():
|
||||
dt = date(year=2020, month=7, day=1)
|
||||
assert dt == parse_date("01.07.2020")
|
||||
assert dt == parse_date("01.07.20")
|
||||
assert dt == parse_date("1.7.2020")
|
||||
assert dt == parse_date("1.7.20")
|
||||
|
||||
assert dt == parse_date("07/01/2020")
|
||||
assert dt == parse_date("07/01/20")
|
||||
assert dt == parse_date("7/1/2020")
|
||||
assert dt == parse_date("7/1/20")
|
||||
|
||||
assert dt == parse_date("2020/07/01")
|
||||
|
||||
assert dt == parse_date("2020-07-01")
|
||||
assert dt == parse_date("2020-7-1")
|
||||
88
src/tests/plugins/banktransfer/test_refund.py
Normal file
88
src/tests/plugins/banktransfer/test_refund.py
Normal file
@@ -0,0 +1,88 @@
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.utils.timezone import now
|
||||
from django_scopes import scope
|
||||
|
||||
from pretix.base.models import (
|
||||
Event, Order, OrderPayment, OrderRefund, Organizer, Team, User,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env():
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
event = Event.objects.create(
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
|
||||
)
|
||||
user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
|
||||
t = Team.objects.create(organizer=event.organizer, can_view_orders=True, can_change_orders=True)
|
||||
t.members.add(user)
|
||||
t.limit_events.add(event)
|
||||
order = Order.objects.create(
|
||||
code='1Z3AS', event=event, email='admin@localhost',
|
||||
status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23
|
||||
)
|
||||
payment = OrderPayment.objects.create(
|
||||
order=order,
|
||||
amount=Decimal("23"),
|
||||
provider='banktransfer',
|
||||
state=OrderPayment.PAYMENT_STATE_CONFIRMED,
|
||||
info=json.dumps({
|
||||
'payer': "Abc Def",
|
||||
'iban': "DE27520521540534534466",
|
||||
'bic': "HELADEF1MEG",
|
||||
})
|
||||
)
|
||||
return event, user, payment
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_perform_refund(client, env):
|
||||
event, user, payment = env
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
assert not OrderRefund.objects.exists()
|
||||
url = "/control/event/dummy/dummy/orders/1Z3AS/refund"
|
||||
r = client.post(url, {
|
||||
f"refund-{payment.id}": "23.00",
|
||||
"start-mode": "full",
|
||||
"perform": True,
|
||||
})
|
||||
assert r.status_code == 302
|
||||
with scope(organizer=event.organizer):
|
||||
assert OrderRefund.objects.exists()
|
||||
refund = OrderRefund.objects.first()
|
||||
assert refund.payment == payment
|
||||
assert refund.info_data == {
|
||||
'payer': "Abc Def",
|
||||
'iban': "DE27520521540534534466",
|
||||
'bic': "HELADEF1MEG",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
def test_cannot_perform_refund_with_invalid_iban(client, env):
|
||||
event, user, payment = env
|
||||
payment.info_data = {
|
||||
'payer': "Abc Def",
|
||||
'iban': "DE27520521540534534467", # invalid IBAN
|
||||
'bic': "HELADEF1MEG",
|
||||
}
|
||||
payment.save()
|
||||
assert not payment.payment_provider.payment_refund_supported(payment)
|
||||
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
url = "/control/event/dummy/dummy/orders/1Z3AS/refund"
|
||||
r = client.post(url, {
|
||||
f"refund-{payment.id}": "23.00",
|
||||
"start-mode": "full",
|
||||
"perform": True,
|
||||
})
|
||||
assert r.status_code == 200 # no successfull POST
|
||||
with scope(organizer=event.organizer):
|
||||
assert not OrderRefund.objects.exists()
|
||||
135
src/tests/plugins/banktransfer/test_refund_export.py
Normal file
135
src/tests/plugins/banktransfer/test_refund_export.py
Normal file
@@ -0,0 +1,135 @@
|
||||
import json
|
||||
from datetime import timedelta
|
||||
from decimal import Decimal
|
||||
|
||||
import pytest
|
||||
from django.utils.timezone import now
|
||||
|
||||
from pretix.base.models import Event, Order, OrderRefund, Organizer, Team, User
|
||||
from pretix.plugins.banktransfer.models import RefundExport
|
||||
from pretix.plugins.banktransfer.views import (
|
||||
_row_key_func, _unite_transaction_rows,
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def env():
|
||||
o = Organizer.objects.create(name='Dummy', slug='dummy')
|
||||
event = Event.objects.create(
|
||||
organizer=o, name='Dummy', slug='dummy',
|
||||
date_from=now(), plugins='pretix.plugins.banktransfer,pretix.plugins.paypal'
|
||||
)
|
||||
user = User.objects.create_user('dummy@dummy.dummy', 'dummy')
|
||||
t = Team.objects.create(organizer=event.organizer, can_view_orders=True, can_change_orders=True)
|
||||
t.members.add(user)
|
||||
t.limit_events.add(event)
|
||||
order = Order.objects.create(
|
||||
code='1Z3AS', event=event, email='admin@localhost',
|
||||
status=Order.STATUS_PAID,
|
||||
datetime=now(), expires=now() + timedelta(days=10),
|
||||
total=23
|
||||
)
|
||||
refund = OrderRefund.objects.create(
|
||||
order=order,
|
||||
amount=Decimal("23"),
|
||||
provider='banktransfer',
|
||||
state=OrderRefund.REFUND_STATE_CREATED,
|
||||
info=json.dumps({
|
||||
'payer': "Abc Def",
|
||||
'iban': "DE27520521540534534466",
|
||||
'bic': "HELADEF1MEG",
|
||||
})
|
||||
)
|
||||
return event, user, refund
|
||||
|
||||
|
||||
url_prefixes = [
|
||||
"/control/event/dummy/dummy/",
|
||||
"/control/organizer/dummy/"
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize("url_prefix", url_prefixes)
|
||||
def test_export_refunds_as_sepa_xml(client, env, url_prefix):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
r = client.post(f'{url_prefix}banktransfer/refunds/', {"unite_transactions": True}, follow=True)
|
||||
assert b"SEPA" in r.content
|
||||
r = client.get(f'{url_prefix}banktransfer/sepa-export/{RefundExport.objects.last().id}/')
|
||||
assert r.status_code == 200
|
||||
r = client.post(f'{url_prefix}banktransfer/sepa-export/{RefundExport.objects.last().id}/', {
|
||||
"account_holder": "Fission Festival",
|
||||
"iban": "DE71720690050653667120",
|
||||
"bic": "GENODEF1AIL",
|
||||
})
|
||||
assert "DE27520521540534534466" in "".join(str(part) for part in r.streaming_content)
|
||||
|
||||
|
||||
@pytest.mark.django_db
|
||||
@pytest.mark.parametrize("url_prefix", url_prefixes)
|
||||
def test_export_refunds(client, env, url_prefix):
|
||||
client.login(email='dummy@dummy.dummy', password='dummy')
|
||||
r = client.get(f'{url_prefix}banktransfer/refunds/')
|
||||
assert r.status_code == 200
|
||||
r = client.post(f'{url_prefix}banktransfer/refunds/', {"unite_transactions": True}, follow=True)
|
||||
assert r.status_code == 200
|
||||
refund = RefundExport.objects.last()
|
||||
assert refund is not None
|
||||
assert b"Download CSV" in r.content
|
||||
r = client.get(f'{url_prefix}banktransfer/export/{refund.id}/')
|
||||
assert r.status_code == 200
|
||||
assert "DE27520521540534534466" in "".join(str(part) for part in r.streaming_content)
|
||||
|
||||
|
||||
def test_unite_transaction_rows():
|
||||
rows = sorted([
|
||||
{
|
||||
'payer': "Abc Def",
|
||||
'iban': 'DE12345678901234567890',
|
||||
'bic': 'HARKE9000',
|
||||
'id': "ROLLA-R-1",
|
||||
'amount': Decimal("42.23"),
|
||||
},
|
||||
{
|
||||
'payer': "First Last",
|
||||
'iban': 'DE111111111111111111111',
|
||||
'bic': 'ikswez2020',
|
||||
'id': "PARTY-R-1",
|
||||
'amount': Decimal("6.50"),
|
||||
}
|
||||
], key=_row_key_func)
|
||||
|
||||
assert _unite_transaction_rows(rows) == rows
|
||||
|
||||
rows = sorted(rows + [
|
||||
{
|
||||
'payer': "Abc Def",
|
||||
'iban': 'DE12345678901234567890',
|
||||
'bic': 'HARKE9000',
|
||||
'id': "ROLLA-R-1",
|
||||
'amount': Decimal("7.77"),
|
||||
},
|
||||
{
|
||||
'payer': "Another Last",
|
||||
'iban': 'DE111111111111111111111',
|
||||
'bic': 'ikswez2020',
|
||||
'id': "PARTY-R-2",
|
||||
'amount': Decimal("13.50"),
|
||||
}
|
||||
], key=_row_key_func)
|
||||
|
||||
assert _unite_transaction_rows(rows) == sorted([
|
||||
{
|
||||
'payer': "Abc Def",
|
||||
'iban': 'DE12345678901234567890',
|
||||
'bic': 'HARKE9000',
|
||||
'id': "ROLLA-R-1",
|
||||
'amount': Decimal("50.00"),
|
||||
},
|
||||
{
|
||||
'payer': 'Another Last, First Last',
|
||||
'iban': 'DE111111111111111111111',
|
||||
'bic': 'ikswez2020',
|
||||
'id': 'PARTY-R-1, PARTY-R-2',
|
||||
'amount': Decimal('20.00'),
|
||||
}], key=_row_key_func)
|
||||
Reference in New Issue
Block a user