2446 lines
84 KiB
Python
2446 lines
84 KiB
Python
import datetime
|
|
import decimal
|
|
import random
|
|
import uuid
|
|
from unittest import mock
|
|
|
|
import pytest
|
|
from django.utils.timezone import make_aware
|
|
|
|
from lingo.invoicing.models import (
|
|
Campaign,
|
|
DraftInvoice,
|
|
DraftInvoiceLine,
|
|
InjectedLine,
|
|
Invoice,
|
|
InvoiceLine,
|
|
InvoicePayment,
|
|
PayerError,
|
|
Payment,
|
|
PaymentType,
|
|
Pool,
|
|
Regie,
|
|
)
|
|
|
|
pytestmark = pytest.mark.django_db
|
|
|
|
|
|
def test_regies_empty(app, user):
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
resp = app.get('/api/regies/')
|
|
data = resp.json
|
|
assert data['data'] == []
|
|
|
|
|
|
def test_regies(app, user):
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
Regie.objects.create(label='Bar')
|
|
Regie.objects.create(label='Foo')
|
|
resp = app.get('/api/regies/')
|
|
data = resp.json
|
|
assert data['data'] == [
|
|
{'id': 'bar', 'text': 'Bar', 'slug': 'bar'},
|
|
{'id': 'foo', 'text': 'Foo', 'slug': 'foo'},
|
|
]
|
|
|
|
|
|
def test_payment_types(app, user):
|
|
regie = Regie.objects.create(label='Bar')
|
|
PaymentType.create_defaults(regie)
|
|
PaymentType.objects.create(regie=regie, label='Foo')
|
|
PaymentType.objects.create(regie=regie, label='Disabled', disabled=True)
|
|
|
|
app.get('/api/regie/%s/payment-types/' % regie.slug, status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
resp = app.get('/api/regie/%s/payment-types/' % regie.slug)
|
|
data = resp.json
|
|
assert data['data'] == [
|
|
{'id': 'cash', 'text': 'Cash', 'slug': 'cash'},
|
|
{'id': 'cesu', 'text': 'CESU', 'slug': 'cesu'},
|
|
{'id': 'check', 'text': 'Check', 'slug': 'check'},
|
|
{'id': 'creditcard', 'text': 'Credit card', 'slug': 'creditcard'},
|
|
{'id': 'directdebit', 'text': 'Direct debit', 'slug': 'directdebit'},
|
|
{'id': 'foo', 'text': 'Foo', 'slug': 'foo'},
|
|
{'id': 'holidaycheck', 'text': 'Holiday check', 'slug': 'holidaycheck'},
|
|
{'id': 'online', 'text': 'Online', 'slug': 'online'},
|
|
]
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_list_invoices(mock_payer, app, user):
|
|
app.get('/api/regie/foo/invoices/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoices/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/invoices/', status=404)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
invoice.refresh_from_db()
|
|
|
|
# invoice remaining_amount is 0
|
|
assert invoice.remaining_amount == 0
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
assert mock_payer.call_args_list == [mock.call(regie, mock.ANY, 'foobar')]
|
|
|
|
# invoice with something to pay
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'amount': 42,
|
|
'total_amount': 42,
|
|
'remaining_amount': 42,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': True,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
]
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# part of amount was already paid
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=1,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
)
|
|
invoice_payment = InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=1,
|
|
)
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'amount': 41,
|
|
'total_amount': 42,
|
|
'remaining_amount': 41,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': True,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
]
|
|
|
|
# invoice is paid
|
|
invoice_payment.amount = 42
|
|
invoice_payment.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# no matching payer id
|
|
invoice_payment.amount = 1
|
|
invoice_payment.save()
|
|
mock_payer.return_value = 'payer:unknown'
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# payer error
|
|
mock_payer.side_effect = PayerError
|
|
app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'}, status=404)
|
|
|
|
# campaign is not finalized
|
|
mock_payer.side_effect = None
|
|
mock_payer.return_value = 'payer:1'
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert len(resp.json['data']) == 1
|
|
|
|
|
|
def test_list_invoices_for_payer(app, user):
|
|
app.get('/api/regie/foo/invoices/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoices/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/invoices/', status=404)
|
|
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
invoice.refresh_from_db()
|
|
|
|
# invoice remaining_amount is 0
|
|
assert invoice.remaining_amount == 0
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# invoice with something to pay
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'amount': 42,
|
|
'total_amount': 42,
|
|
'remaining_amount': 42,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
]
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# part of amount was already paid
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=1,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
)
|
|
invoice_payment = InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=1,
|
|
)
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'amount': 41,
|
|
'total_amount': 42,
|
|
'remaining_amount': 41,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
]
|
|
|
|
# invoice is paid
|
|
invoice_payment.amount = 42
|
|
invoice_payment.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# campaign is not finalized
|
|
invoice_payment.amount = 1
|
|
invoice_payment.save()
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
resp = app.get('/api/regie/foo/invoices/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert len(resp.json['data']) == 1
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_list_history_invoices(mock_payer, app, user):
|
|
app.get('/api/regie/foo/invoices/history/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoices/history/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/invoices/history/', status=404)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
)
|
|
invoice_payment = InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=2,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
# invoice remaining_amount is not 0
|
|
assert invoice.remaining_amount != 0
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
assert mock_payer.call_args_list == [mock.call(regie, mock.ANY, 'foobar')]
|
|
|
|
# invoice with nothing to pay
|
|
invoice_payment.amount = 42
|
|
invoice_payment.save()
|
|
invoice.refresh_from_db()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'amount': 0,
|
|
'total_amount': 42,
|
|
'remaining_amount': 0,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': True,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': True,
|
|
'pay_limit_date': '',
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
]
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# no matching payer id
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
mock_payer.return_value = 'payer:unknown'
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# payer error
|
|
mock_payer.side_effect = PayerError
|
|
app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'}, status=404)
|
|
|
|
# campaign is not finalized
|
|
mock_payer.side_effect = None
|
|
mock_payer.return_value = 'payer:1'
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert len(resp.json['data']) == 1
|
|
|
|
|
|
def test_list_history_invoices_for_payer(app, user):
|
|
app.get('/api/regie/foo/invoices/history/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoices/history/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/invoices/history/', status=404)
|
|
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
)
|
|
invoice_payment = InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=2,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
# invoice remaining_amount is not 0
|
|
assert invoice.remaining_amount != 0
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# invoice with nothing to pay
|
|
invoice_payment.amount = 42
|
|
invoice_payment.save()
|
|
invoice.refresh_from_db()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'amount': 0,
|
|
'total_amount': 42,
|
|
'remaining_amount': 0,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': True,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': True,
|
|
'pay_limit_date': '',
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
]
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# campaign is not finalized
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.regie = regie
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
resp = app.get('/api/regie/foo/invoices/history/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert len(resp.json['data']) == 1
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_detail_invoice(mock_payer, app, user):
|
|
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == {
|
|
'amount': 42,
|
|
'total_amount': 42,
|
|
'remaining_amount': 42,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': True,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# part of amount was already paid
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=1,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
)
|
|
invoice_payment = InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=1,
|
|
)
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == {
|
|
'amount': 41,
|
|
'total_amount': 42,
|
|
'remaining_amount': 41,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': True,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
|
|
# invoice is paid
|
|
invoice_payment.amount = 42
|
|
invoice_payment.save()
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == {
|
|
'amount': 0,
|
|
'total_amount': 42,
|
|
'remaining_amount': 0,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': True,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': True,
|
|
'pay_limit_date': '',
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
|
|
# no matching payer id
|
|
invoice_payment.amount = 1
|
|
invoice_payment.save()
|
|
mock_payer.return_value = 'payer:unknown'
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# campaign is not finalized
|
|
mock_payer.return_value = 'payer:1'
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=200)
|
|
|
|
|
|
def test_detail_invoice_for_payer(app, user):
|
|
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/' % str(uuid.uuid4()), params={'payer_external_id': 'payer:1'}, status=404
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == {
|
|
'amount': 42,
|
|
'total_amount': 42,
|
|
'remaining_amount': 42,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}, status=404
|
|
)
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}, status=404
|
|
)
|
|
|
|
# part of amount was already paid
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=1,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
)
|
|
invoice_payment = InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=1,
|
|
)
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == {
|
|
'amount': 41,
|
|
'total_amount': 42,
|
|
'remaining_amount': 41,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': False,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': False,
|
|
'pay_limit_date': datetime.date.today().isoformat(),
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
|
|
# invoice is paid
|
|
invoice_payment.amount = 42
|
|
invoice_payment.save()
|
|
resp = app.get('/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == {
|
|
'amount': 0,
|
|
'total_amount': 42,
|
|
'remaining_amount': 0,
|
|
'created': datetime.date.today().isoformat(),
|
|
'display_id': 'F%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
invoice.created_at.strftime('%y-%m'),
|
|
),
|
|
'has_pdf': True,
|
|
'has_payments_pdf': True,
|
|
'id': str(invoice.uuid),
|
|
'label': 'My invoice',
|
|
'online_payment': False,
|
|
'paid': True,
|
|
'pay_limit_date': '',
|
|
'due_date': invoice.date_due.isoformat(),
|
|
'payment_deadline_date': invoice.date_payment_deadline.isoformat(),
|
|
}
|
|
|
|
# campaign is not finalized
|
|
invoice_payment.amount = 1
|
|
invoice_payment.save()
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}, status=404
|
|
)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}, status=200
|
|
)
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_pdf_invoice(mock_payer, app, user):
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'})
|
|
assert resp.headers['Content-Disposition'] == 'attachment; filename="%s.pdf"' % invoice.formatted_number
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# no matching payer id
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
mock_payer.return_value = 'payer:unknown'
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# payer error
|
|
mock_payer.side_effect = PayerError
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# campaign is not finalized
|
|
mock_payer.side_effect = None
|
|
mock_payer.return_value = 'payer:1'
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=200)
|
|
|
|
|
|
def test_pdf_invoice_for_payer(app, user):
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.get('/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(uuid.uuid4()),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}
|
|
)
|
|
assert resp.headers['Content-Disposition'] == 'attachment; filename="%s.pdf"' % invoice.formatted_number
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
# campaign is not finalized
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.regie = regie
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=200,
|
|
)
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_pdf_invoice_payments(mock_payer, app, user):
|
|
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
PaymentType.create_defaults(regie)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
payer_external_id='payer:1',
|
|
)
|
|
payment.set_number()
|
|
payment.save()
|
|
InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount == 0
|
|
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'})
|
|
assert resp.headers['Content-Disposition'] == 'attachment; filename="A-%s.pdf"' % invoice.formatted_number
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# no matching payer id
|
|
invoice.regie = regie
|
|
invoice.save()
|
|
mock_payer.return_value = 'payer:unknown'
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# payer error
|
|
mock_payer.side_effect = PayerError
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# campaign is not finalized
|
|
mock_payer.side_effect = None
|
|
mock_payer.return_value = 'payer:1'
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=200
|
|
)
|
|
|
|
# invoice has remaining_amount
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount > 0
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
|
|
def test_pdf_invoice_payments_for_payer(app, user):
|
|
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.get('/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(uuid.uuid4()),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
PaymentType.create_defaults(regie)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
payer_external_id='payer:1',
|
|
)
|
|
payment.set_number()
|
|
payment.save()
|
|
InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount == 0
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid), params={'payer_external_id': 'payer:1'}
|
|
)
|
|
assert resp.headers['Content-Disposition'] == 'attachment; filename="A-%s.pdf"' % invoice.formatted_number
|
|
|
|
# publication date is in the future
|
|
invoice.date_publication = datetime.date.today() + datetime.timedelta(days=1)
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
invoice.date_publication = datetime.date.today()
|
|
invoice.regie = other_regie
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
# campaign is not finalized
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.regie = regie
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=200,
|
|
)
|
|
|
|
# invoice has remaining_amount
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount > 0
|
|
app.get(
|
|
'/api/regie/foo/invoice/%s/payments/pdf/' % str(invoice.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
|
|
def test_pay_invoice(app, user):
|
|
app.post('/api/regie/foo/invoice/%s/pay/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.post('/api/regie/foo/invoice/%s/pay/' % str(uuid.uuid4()), status=404)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
payer_first_name='Foo',
|
|
payer_last_name='Bar',
|
|
)
|
|
app.post('/api/regie/foo/invoice/%s/pay/' % str(uuid.uuid4()), status=404)
|
|
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
|
|
# no payment type 'online'
|
|
resp = app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid), status=404)
|
|
|
|
# no payment type 'online' for the regie
|
|
other_regie = Regie.objects.create(label='Bar')
|
|
PaymentType.create_defaults(other_regie)
|
|
resp = app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid), status=404)
|
|
|
|
PaymentType.create_defaults(regie) # create default payment types
|
|
resp = app.post('/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid))
|
|
assert Payment.objects.count() == 1
|
|
assert InvoicePayment.objects.count() == 1
|
|
payment = Payment.objects.latest('pk')
|
|
assert resp.json == {'data': {'id': str(payment.uuid)}, 'err': 0}
|
|
assert payment.regie == regie
|
|
assert payment.amount == 42
|
|
assert payment.payment_type.slug == 'online'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id is None
|
|
assert payment.order_date is None
|
|
assert payment.number == 1
|
|
assert payment.formatted_number == 'R%02d-%s-0000001' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
(invoice_payment,) = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment.amount == 42
|
|
assert invoice_payment.invoice == invoice
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount == 0
|
|
assert invoice.paid_amount == 42
|
|
|
|
InvoicePayment.objects.all().delete()
|
|
Payment.objects.all().delete()
|
|
resp = app.post(
|
|
'/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid),
|
|
params={'transaction_id': 'foobar', 'transaction_date': 'foobaz'},
|
|
)
|
|
assert Payment.objects.count() == 1
|
|
assert InvoicePayment.objects.count() == 1
|
|
payment = Payment.objects.latest('pk')
|
|
assert resp.json == {'data': {'id': str(payment.uuid)}, 'err': 0}
|
|
assert payment.regie == regie
|
|
assert payment.amount == 42
|
|
assert payment.payment_type.slug == 'online'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id == 'foobar'
|
|
assert payment.order_date is None
|
|
assert payment.number == 2
|
|
assert payment.formatted_number == 'R%02d-%s-0000002' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
assert payment.payer_external_id == 'payer:1'
|
|
assert payment.payer_first_name == 'Foo'
|
|
assert payment.payer_last_name == 'Bar'
|
|
(invoice_payment,) = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment.amount == 42
|
|
assert invoice_payment.invoice == invoice
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount == 0
|
|
assert invoice.paid_amount == 42
|
|
|
|
InvoicePayment.objects.all().delete()
|
|
Payment.objects.all().delete()
|
|
resp = app.post(
|
|
'/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid),
|
|
params={'transaction_id': 'foobar', 'transaction_date': '2023-04-13T16:06:42'},
|
|
)
|
|
assert Payment.objects.count() == 1
|
|
assert InvoicePayment.objects.count() == 1
|
|
payment = Payment.objects.latest('pk')
|
|
assert resp.json == {'data': {'id': str(payment.uuid)}, 'err': 0}
|
|
assert payment.regie == regie
|
|
assert payment.amount == 42
|
|
assert payment.payment_type.slug == 'online'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id == 'foobar'
|
|
assert payment.order_date == make_aware(datetime.datetime(2023, 4, 13, 18, 6, 42))
|
|
assert payment.number == 3
|
|
assert payment.formatted_number == 'R%02d-%s-0000003' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
assert payment.payer_external_id == 'payer:1'
|
|
assert payment.payer_first_name == 'Foo'
|
|
assert payment.payer_last_name == 'Bar'
|
|
(invoice_payment,) = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment.amount == 42
|
|
assert invoice_payment.invoice == invoice
|
|
invoice.refresh_from_db()
|
|
assert invoice.remaining_amount == 0
|
|
assert invoice.paid_amount == 42
|
|
|
|
# campaign is not finalized
|
|
InvoicePayment.objects.all().delete()
|
|
Payment.objects.all().delete()
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
finalized=False,
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=False,
|
|
)
|
|
invoice.refresh_from_db()
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.post(
|
|
'/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid),
|
|
params={'transaction_id': 'foobar', 'transaction_date': '2023-04-13T16:06:42'},
|
|
status=404,
|
|
)
|
|
|
|
# campaign is finalized
|
|
campaign.finalized = True
|
|
campaign.save()
|
|
app.post(
|
|
'/api/regie/foo/invoice/%s/pay/' % str(invoice.uuid),
|
|
params={'transaction_id': 'foobar', 'transaction_date': '2023-04-13T16:06:42'},
|
|
status=200,
|
|
)
|
|
|
|
|
|
def test_add_draft_invoice(app, user):
|
|
app.post('/api/regie/foo/draft-invoices/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
resp = app.post('/api/regie/foo/draft-invoices/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
resp = app.post('/api/regie/foo/draft-invoices/', status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'date_due': ['This field is required.'],
|
|
'date_payment_deadline': ['This field is required.'],
|
|
'date_publication': ['This field is required.'],
|
|
'label': ['This field is required.'],
|
|
'payer_external_id': ['This field is required.'],
|
|
'payer_first_name': ['This field is required.'],
|
|
'payer_last_name': ['This field is required.'],
|
|
}
|
|
|
|
for demat in [True, False, None]:
|
|
params = {
|
|
'date_due': '2023-04-23',
|
|
'date_payment_deadline': '2023-04-22',
|
|
'date_publication': '2023-04-21',
|
|
'label': 'Foo Bar',
|
|
'payer_external_id': 'payer:1',
|
|
'payer_first_name': 'First',
|
|
'payer_last_name': 'Last',
|
|
}
|
|
if demat is not None:
|
|
params['payer_demat'] = demat
|
|
resp = app.post('/api/regie/foo/draft-invoices/', params=params)
|
|
assert resp.json['err'] == 0
|
|
invoice = DraftInvoice.objects.latest('pk')
|
|
assert resp.json['data'] == {'draft_invoice_id': str(invoice.uuid)}
|
|
assert invoice.label == 'Foo Bar'
|
|
assert invoice.total_amount == 0
|
|
assert invoice.date_publication == datetime.date(2023, 4, 21)
|
|
assert invoice.date_payment_deadline == datetime.date(2023, 4, 22)
|
|
assert invoice.date_due == datetime.date(2023, 4, 23)
|
|
assert invoice.date_debit is None
|
|
assert invoice.regie == regie
|
|
assert invoice.payer_external_id == 'payer:1'
|
|
assert invoice.payer_first_name == 'First'
|
|
assert invoice.payer_last_name == 'Last'
|
|
assert invoice.payer_demat is bool(demat)
|
|
assert invoice.payer_direct_debit is False
|
|
assert invoice.pool is None
|
|
assert invoice.lines.count() == 0
|
|
|
|
|
|
def test_add_draft_invoice_line(app, user):
|
|
app.post('/api/regie/foo/draft-invoice/%s/lines/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.post('/api/regie/foo/draft-invoice/%s/lines/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.post('/api/regie/foo/draft-invoice/%s/lines/' % str(uuid.uuid4()), status=404)
|
|
|
|
invoice = DraftInvoice.objects.create(
|
|
date_publication=datetime.date(2023, 4, 21),
|
|
date_payment_deadline=datetime.date(2023, 4, 22),
|
|
date_due=datetime.date(2023, 4, 23),
|
|
regie=regie,
|
|
payer_external_id=random.choice(['payer:1', 'payer:2']),
|
|
payer_first_name=random.choice(['First', 'Fiirst']),
|
|
payer_last_name=random.choice(['Last', 'Laast']),
|
|
payer_demat=random.choice([True, False]),
|
|
payer_direct_debit=random.choice([True, False]),
|
|
)
|
|
|
|
app.post('/api/regie/fooooo/draft-invoice/%s/lines/' % str(invoice.uuid), status=404)
|
|
|
|
resp = app.post('/api/regie/foo/draft-invoice/%s/lines/' % str(invoice.uuid), status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'event_date': ['This field is required.'],
|
|
'label': ['This field is required.'],
|
|
'quantity': ['This field is required.'],
|
|
'slug': ['This field is required.'],
|
|
'unit_amount': ['This field is required.'],
|
|
'user_external_id': ['This field is required.'],
|
|
'user_first_name': ['This field is required.'],
|
|
'user_last_name': ['This field is required.'],
|
|
}
|
|
|
|
params = {
|
|
'event_date': '2023-04-21',
|
|
'label': 'Bar Foo',
|
|
'quantity': '2',
|
|
'slug': 'bar-foo',
|
|
'unit_amount': '21',
|
|
'user_external_id': 'user:1',
|
|
'user_first_name': 'First1',
|
|
'user_last_name': 'Last1',
|
|
}
|
|
resp = app.post('/api/regie/foo/draft-invoice/%s/lines/' % str(invoice.uuid), params=params)
|
|
assert resp.json['err'] == 0
|
|
line = DraftInvoiceLine.objects.latest('pk')
|
|
assert resp.json['data'] == {'draft_line_id': line.pk}
|
|
assert line.invoice == invoice
|
|
assert line.event_date == datetime.date(2023, 4, 21)
|
|
assert line.slug == 'bar-foo'
|
|
assert line.label == 'Bar Foo'
|
|
assert line.quantity == 2
|
|
assert line.unit_amount == 21
|
|
assert line.total_amount == 42
|
|
assert line.user_external_id == 'user:1'
|
|
assert line.user_first_name == 'First1'
|
|
assert line.user_last_name == 'Last1'
|
|
assert line.payer_external_id == invoice.payer_external_id
|
|
assert line.payer_first_name == invoice.payer_first_name
|
|
assert line.payer_last_name == invoice.payer_last_name
|
|
assert line.payer_demat == invoice.payer_demat
|
|
assert line.payer_direct_debit == invoice.payer_direct_debit
|
|
assert line.details == {}
|
|
assert line.pool is None
|
|
invoice.refresh_from_db()
|
|
assert invoice.total_amount == 42
|
|
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.post('/api/regie/foo/draft-invoice/%s/lines/' % str(invoice.uuid), status=404)
|
|
|
|
|
|
def test_close_draft_invoice(app, user):
|
|
app.post('/api/regie/foo/draft-invoice/%s/close/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.post('/api/regie/foo/draft-invoice/%s/close/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.post('/api/regie/foo/draft-invoice/%s/close/' % str(uuid.uuid4()), status=404)
|
|
|
|
invoice = DraftInvoice.objects.create(
|
|
date_publication=datetime.date(2023, 4, 21),
|
|
date_payment_deadline=datetime.date(2023, 4, 22),
|
|
date_due=datetime.date(2023, 4, 23),
|
|
regie=regie,
|
|
payer_external_id=random.choice(['payer:1', 'payer:2']),
|
|
payer_first_name=random.choice(['First', 'Fiirst']),
|
|
payer_last_name=random.choice(['Last', 'Laast']),
|
|
payer_demat=random.choice([True, False]),
|
|
payer_direct_debit=random.choice([True, False]),
|
|
)
|
|
line = DraftInvoiceLine.objects.create(
|
|
event_date=datetime.date(2023, 4, 21),
|
|
quantity=1,
|
|
unit_amount=42,
|
|
invoice=invoice,
|
|
)
|
|
line.refresh_from_db()
|
|
invoice.refresh_from_db()
|
|
|
|
app.post('/api/regie/fooooo/draft-invoice/%s/close/' % str(invoice.uuid), status=404)
|
|
|
|
resp = app.post('/api/regie/foo/draft-invoice/%s/close/' % str(invoice.uuid))
|
|
assert resp.json['err'] == 0
|
|
final_invoice = Invoice.objects.latest('pk')
|
|
today = datetime.date.today()
|
|
assert resp.json['data'] == {'invoice_id': str(final_invoice.uuid)}
|
|
assert final_invoice.date_publication == invoice.date_publication
|
|
assert final_invoice.date_payment_deadline == invoice.date_payment_deadline
|
|
assert final_invoice.date_due == invoice.date_due
|
|
assert final_invoice.date_debit == invoice.date_debit
|
|
assert final_invoice.regie == regie
|
|
assert final_invoice.pool is None
|
|
assert final_invoice.payer_external_id == invoice.payer_external_id
|
|
assert final_invoice.payer_first_name == invoice.payer_first_name
|
|
assert final_invoice.payer_last_name == invoice.payer_last_name
|
|
assert final_invoice.payer_demat == invoice.payer_demat
|
|
assert final_invoice.payer_direct_debit == invoice.payer_direct_debit
|
|
assert final_invoice.total_amount == invoice.total_amount == 42
|
|
assert final_invoice.number == 1
|
|
assert final_invoice.formatted_number == 'F%02d-%s-0000001' % (regie.pk, today.strftime('%y-%m'))
|
|
|
|
final_line = InvoiceLine.objects.order_by('pk')[0]
|
|
assert final_line.event_date == line.event_date
|
|
assert final_line.slug == line.slug
|
|
assert final_line.label == line.label
|
|
assert final_line.quantity == line.quantity
|
|
assert final_line.unit_amount == line.unit_amount
|
|
assert final_line.total_amount == line.total_amount
|
|
assert final_line.user_external_id == line.user_external_id
|
|
assert final_line.user_first_name == line.user_first_name
|
|
assert final_line.user_last_name == line.user_last_name
|
|
assert final_line.payer_external_id == line.payer_external_id
|
|
assert final_line.payer_first_name == line.payer_first_name
|
|
assert final_line.payer_last_name == line.payer_last_name
|
|
assert final_line.payer_demat == line.payer_demat
|
|
assert final_line.payer_direct_debit == line.payer_direct_debit
|
|
assert final_line.details == line.details
|
|
assert final_line.pool is None
|
|
assert final_line.invoice == final_invoice
|
|
|
|
campaign = Campaign.objects.create(
|
|
regie=regie,
|
|
date_start=datetime.date(2022, 9, 1),
|
|
date_end=datetime.date(2022, 10, 1),
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
date_debit=datetime.date(2022, 11, 15),
|
|
)
|
|
pool = Pool.objects.create(
|
|
campaign=campaign,
|
|
draft=True,
|
|
)
|
|
invoice.pool = pool
|
|
invoice.save()
|
|
app.post('/api/regie/foo/draft-invoice/%s/close/' % str(invoice.uuid), status=404)
|
|
|
|
|
|
def test_add_injected_line(app, user):
|
|
app.post('/api/regie/foo/injected-lines/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
resp = app.post('/api/regie/foo/injected-lines/', status=404)
|
|
|
|
regie = Regie.objects.create(slug='foo')
|
|
resp = app.post('/api/regie/foo/injected-lines/', status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'event_date': ['This field is required.'],
|
|
'slug': ['This field is required.'],
|
|
'label': ['This field is required.'],
|
|
'amount': ['This field is required.'],
|
|
'user_external_id': ['This field is required.'],
|
|
'payer_external_id': ['This field is required.'],
|
|
}
|
|
|
|
params = {
|
|
'event_date': '2023-01-17',
|
|
'slug': 'foobar',
|
|
'label': 'Foo Bar',
|
|
'amount': 2,
|
|
'user_external_id': 'user:1',
|
|
'payer_external_id': 'payer:1',
|
|
}
|
|
resp = app.post('/api/regie/foo/injected-lines/', params=params)
|
|
assert resp.json['err'] == 0
|
|
injected_line = InjectedLine.objects.get(pk=resp.json['id'])
|
|
assert injected_line.event_date == datetime.date(2023, 1, 17)
|
|
assert injected_line.slug == 'foobar'
|
|
assert injected_line.label == 'Foo Bar'
|
|
assert injected_line.amount == 2
|
|
assert injected_line.user_external_id == 'user:1'
|
|
assert injected_line.payer_external_id == 'payer:1'
|
|
assert injected_line.regie == regie
|
|
|
|
params.update(
|
|
{
|
|
'amount': -70,
|
|
}
|
|
)
|
|
resp = app.post('/api/regie/foo/injected-lines/', params=params)
|
|
assert resp.json['err'] == 0
|
|
injected_line = InjectedLine.objects.get(pk=resp.json['id'])
|
|
assert injected_line.event_date == datetime.date(2023, 1, 17)
|
|
assert injected_line.slug == 'foobar'
|
|
assert injected_line.label == 'Foo Bar'
|
|
assert injected_line.amount == -70
|
|
assert injected_line.user_external_id == 'user:1'
|
|
assert injected_line.payer_external_id == 'payer:1'
|
|
assert injected_line.regie == regie
|
|
|
|
|
|
def test_add_payment(app, user):
|
|
app.post('/api/regie/foo/payments/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
resp = app.post('/api/regie/foo/payments/', status=404)
|
|
|
|
regie = Regie.objects.create(slug='foo')
|
|
resp = app.post('/api/regie/foo/payments/', status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'amount': ['This field is required.'],
|
|
'payment_type': ['This field is required.'],
|
|
'invoices': ['This field is required.'],
|
|
}
|
|
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'foo', # unknown payment type
|
|
'invoices': 'foo, %s' % str(uuid.uuid4()),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'payment_type': ['Object with slug=foo does not exist.'],
|
|
'invoices': {'0': ['Must be a valid UUID.']},
|
|
}
|
|
|
|
# unknown payment type for this regie
|
|
other_regie = Regie.objects.create(slug='bar')
|
|
PaymentType.create_defaults(other_regie)
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'check',
|
|
'invoices': str(uuid.uuid4()),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'payment_type': ['Object with slug=check does not exist.'],
|
|
}
|
|
|
|
PaymentType.create_defaults(regie) # create default payment types
|
|
PaymentType.objects.filter(slug='check').update(disabled=True) # disabled payment type
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'check',
|
|
'invoices': str(uuid.uuid4()),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {
|
|
'payment_type': ['Object with slug=check does not exist.'],
|
|
}
|
|
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'cash',
|
|
'invoices': str(uuid.uuid4()),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'invoices': ['Unknown invoice %s' % params['invoices']]}
|
|
|
|
invoice11 = Invoice.objects.create(
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice11,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice12 = Invoice.objects.create(
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice12,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice13 = Invoice.objects.create(
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:2',
|
|
)
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice13,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice14 = Invoice.objects.create(
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today() - datetime.timedelta(days=1), # past date
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice13,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice21 = Invoice.objects.create(
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice21,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
|
|
other_invoice = Invoice.objects.create(
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=other_regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=other_invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'cash',
|
|
'invoices': ','.join([str(invoice11.uuid), str(other_invoice.uuid)]), # not the same regie
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'invoices': ['Unknown invoice %s' % other_invoice.uuid]}
|
|
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'cash',
|
|
'invoices': ','.join([str(invoice11.uuid), str(invoice13.uuid)]), # not the same payer
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'invoices': ['Can not create payment for invoices of different payers.']}
|
|
|
|
params = {
|
|
'amount': 64,
|
|
'payment_type': 'cash',
|
|
'invoices': ','.join([str(invoice11.uuid), str(invoice14.uuid)]), # too late for invoice14
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'invoices': ['The invoice due date has passed (%s).' % invoice14.uuid]}
|
|
|
|
params = {
|
|
'amount': 0,
|
|
'payment_type': 'cash',
|
|
'invoices': ','.join([str(invoice11.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'amount': ['Ensure this value is greater than or equal to 0.01.']}
|
|
|
|
params = {
|
|
'amount': -0.01,
|
|
'payment_type': 'cash',
|
|
'invoices': ','.join([str(invoice11.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'amount': ['Ensure this value is greater than or equal to 0.01.']}
|
|
|
|
params = {
|
|
'amount': 10,
|
|
'payment_type': 'cash',
|
|
'invoices': ','.join([str(invoice11.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params)
|
|
assert Payment.objects.count() == 1
|
|
assert InvoicePayment.objects.count() == 1
|
|
payment = Payment.objects.latest('pk')
|
|
assert payment.regie == regie
|
|
assert payment.amount == 10
|
|
assert payment.payment_type.slug == 'cash'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id is None
|
|
assert payment.order_date is None
|
|
assert payment.number == 1
|
|
assert payment.formatted_number == 'R%02d-%s-0000001' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
(invoice_payment,) = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment.amount == 10
|
|
assert invoice_payment.invoice == invoice11
|
|
invoice11.refresh_from_db()
|
|
assert invoice11.paid_amount == 10
|
|
assert invoice11.remaining_amount == 32
|
|
invoice12.refresh_from_db()
|
|
assert invoice12.paid_amount == 0
|
|
assert invoice12.remaining_amount == 42
|
|
|
|
PaymentType.objects.all().update(disabled=False)
|
|
params = {
|
|
'amount': 10,
|
|
'payment_type': 'check',
|
|
'invoices': ','.join([str(invoice11.uuid), str(invoice12.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params)
|
|
assert Payment.objects.count() == 2
|
|
assert InvoicePayment.objects.count() == 2
|
|
payment = Payment.objects.latest('pk')
|
|
assert payment.regie == regie
|
|
assert payment.amount == 10
|
|
assert payment.payment_type.slug == 'check'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id is None
|
|
assert payment.order_date is None
|
|
assert payment.number == 2
|
|
assert payment.formatted_number == 'R%02d-%s-0000002' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
(invoice_payment,) = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment.amount == 10
|
|
assert invoice_payment.invoice == invoice11
|
|
invoice11.refresh_from_db()
|
|
assert invoice11.paid_amount == 20
|
|
assert invoice11.remaining_amount == 22
|
|
invoice12.refresh_from_db()
|
|
assert invoice12.paid_amount == 0
|
|
assert invoice12.remaining_amount == 42
|
|
|
|
params = {
|
|
'amount': 22.01,
|
|
'payment_type': 'check',
|
|
'invoices': ','.join([str(invoice12.uuid), str(invoice11.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params)
|
|
assert Payment.objects.count() == 3
|
|
assert InvoicePayment.objects.count() == 4
|
|
payment = Payment.objects.latest('pk')
|
|
assert payment.regie == regie
|
|
assert payment.amount == decimal.Decimal('22.01')
|
|
assert payment.payment_type.slug == 'check'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id is None
|
|
assert payment.order_date is None
|
|
assert payment.number == 3
|
|
assert payment.formatted_number == 'R%02d-%s-0000003' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
invoice_payment1, invoice_payment2 = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment1.amount == 22
|
|
assert invoice_payment1.invoice == invoice11 # older invoice first
|
|
assert invoice_payment2.amount == decimal.Decimal('0.01')
|
|
assert invoice_payment2.invoice == invoice12
|
|
invoice11.refresh_from_db()
|
|
assert invoice11.paid_amount == 42
|
|
assert invoice11.remaining_amount == 0
|
|
invoice12.refresh_from_db()
|
|
assert invoice12.paid_amount == decimal.Decimal('0.01')
|
|
assert invoice12.remaining_amount == decimal.Decimal('41.99')
|
|
|
|
# to much
|
|
params = {
|
|
'amount': 42,
|
|
'payment_type': 'check',
|
|
'invoices': ','.join([str(invoice11.uuid), str(invoice12.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params, status=400)
|
|
assert resp.json['err']
|
|
assert resp.json['errors'] == {'amount': ['Amount is bigger than sum of invoices remaining amounts.']}
|
|
|
|
params = {
|
|
'amount': 41.99,
|
|
'payment_type': 'check',
|
|
'invoices': ','.join([str(invoice11.uuid), str(invoice12.uuid)]),
|
|
}
|
|
resp = app.post('/api/regie/foo/payments/', params=params)
|
|
assert Payment.objects.count() == 4
|
|
assert InvoicePayment.objects.count() == 5
|
|
payment = Payment.objects.latest('pk')
|
|
assert payment.regie == regie
|
|
assert payment.amount == decimal.Decimal('41.99')
|
|
assert payment.payment_type.slug == 'check'
|
|
assert payment.payment_type.regie == regie
|
|
assert payment.order_id is None
|
|
assert payment.order_date is None
|
|
assert payment.number == 4
|
|
assert payment.formatted_number == 'R%02d-%s-0000004' % (
|
|
regie.pk,
|
|
datetime.date.today().strftime('%y-%m'),
|
|
)
|
|
(invoice_payment,) = payment.invoicepayment_set.order_by('pk')
|
|
assert invoice_payment.amount == decimal.Decimal('41.99')
|
|
assert invoice_payment.invoice == invoice12
|
|
invoice11.refresh_from_db()
|
|
assert invoice11.paid_amount == 42
|
|
assert invoice11.remaining_amount == 0
|
|
invoice12.refresh_from_db()
|
|
assert invoice12.paid_amount == 42
|
|
assert invoice12.remaining_amount == 0
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_list_payments(mock_payer, app, user):
|
|
app.get('/api/regie/foo/payments/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/payments/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/payments/', status=404)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
PaymentType.create_defaults(regie)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
payer_external_id='payer:1',
|
|
)
|
|
payment.set_number()
|
|
payment.save()
|
|
InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=42,
|
|
)
|
|
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/payments/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'id': str(payment.uuid),
|
|
'display_id': 'R%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
payment.created_at.strftime('%y-%m'),
|
|
),
|
|
'payment_type': 'Cash',
|
|
'amount': 42,
|
|
'created': datetime.date.today().isoformat(),
|
|
'has_pdf': True,
|
|
}
|
|
]
|
|
assert mock_payer.call_args_list == [mock.call(regie, mock.ANY, 'foobar')]
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
payment.regie = other_regie
|
|
payment.save()
|
|
resp = app.get('/api/regie/foo/payments/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# no matching payer id
|
|
payment.regie = regie
|
|
payment.save()
|
|
mock_payer.return_value = 'payer:unknown'
|
|
resp = app.get('/api/regie/foo/payments/', params={'NameID': 'foobar'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
# payer error
|
|
mock_payer.side_effect = PayerError
|
|
app.get('/api/regie/foo/payments/', params={'NameID': 'foobar'}, status=404)
|
|
|
|
|
|
def test_list_payments_for_payer(app, user):
|
|
app.get('/api/regie/foo/payments/', status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/payments/', status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
PaymentType.create_defaults(regie)
|
|
app.get('/api/regie/foo/payments/', status=404)
|
|
|
|
resp = app.get('/api/regie/foo/payments/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
PaymentType.create_defaults(regie)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
payer_external_id='payer:1',
|
|
)
|
|
payment.set_number()
|
|
payment.save()
|
|
InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=42,
|
|
)
|
|
|
|
resp = app.get('/api/regie/foo/payments/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == [
|
|
{
|
|
'id': str(payment.uuid),
|
|
'display_id': 'R%02d-%s-0000001'
|
|
% (
|
|
regie.pk,
|
|
payment.created_at.strftime('%y-%m'),
|
|
),
|
|
'payment_type': 'Cash',
|
|
'amount': 42,
|
|
'created': datetime.date.today().isoformat(),
|
|
'has_pdf': True,
|
|
}
|
|
]
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
payment.regie = other_regie
|
|
payment.save()
|
|
resp = app.get('/api/regie/foo/payments/', params={'payer_external_id': 'payer:1'})
|
|
assert resp.json['err'] == 0
|
|
assert resp.json['data'] == []
|
|
|
|
payment.regie = regie
|
|
payment.save()
|
|
|
|
|
|
@mock.patch.object(Regie, 'get_payer_external_id_from_nameid', autospec=True)
|
|
def test_pdf_payment(mock_payer, app, user):
|
|
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date.today(),
|
|
date_due=datetime.date(2022, 10, 31),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
PaymentType.create_defaults(regie)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=42,
|
|
)
|
|
|
|
mock_payer.return_value = 'payer:1'
|
|
resp = app.get('/api/regie/foo/payment/%s/pdf/' % str(payment.uuid), params={'NameID': 'foobar'})
|
|
assert resp.headers['Content-Disposition'] == 'attachment; filename="%s.pdf"' % payment.formatted_number
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
payment.regie = other_regie
|
|
payment.save()
|
|
resp = app.get(
|
|
'/api/regie/foo/payment/%s/pdf/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404
|
|
)
|
|
|
|
# no matching payer id
|
|
mock_payer.return_value = 'payer:unknown'
|
|
resp = app.get('/api/regie/foo/payment/%s/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
# payer error
|
|
mock_payer.side_effect = PayerError
|
|
app.get('/api/regie/foo/payment/%s/' % str(payment.uuid), params={'NameID': 'foobar'}, status=404)
|
|
|
|
|
|
def test_pdf_payment_for_payer(app, user):
|
|
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=403)
|
|
app.authorization = ('Basic', ('john.doe', 'password'))
|
|
|
|
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
regie = Regie.objects.create(label='Foo')
|
|
app.get('/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()), status=404)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/payment/%s/pdf/' % str(uuid.uuid4()),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|
|
|
|
invoice = Invoice.objects.create(
|
|
label='My invoice',
|
|
date_publication=datetime.date(2022, 10, 1),
|
|
date_payment_deadline=datetime.date(2022, 10, 31),
|
|
date_due=datetime.date.today(),
|
|
regie=regie,
|
|
payer_external_id='payer:1',
|
|
)
|
|
invoice.set_number()
|
|
invoice.save()
|
|
InvoiceLine.objects.create(
|
|
event_date=datetime.date.today(),
|
|
invoice=invoice,
|
|
quantity=1,
|
|
unit_amount=42,
|
|
)
|
|
invoice.refresh_from_db()
|
|
PaymentType.create_defaults(regie)
|
|
payment = Payment.objects.create(
|
|
regie=regie,
|
|
amount=42,
|
|
payment_type=PaymentType.objects.get(regie=regie, slug='cash'),
|
|
payer_external_id='payer:1',
|
|
)
|
|
InvoicePayment.objects.create(
|
|
payment=payment,
|
|
invoice=invoice,
|
|
amount=42,
|
|
)
|
|
|
|
resp = app.get(
|
|
'/api/regie/foo/payment/%s/pdf/' % str(payment.uuid), params={'payer_external_id': 'payer:1'}
|
|
)
|
|
assert resp.headers['Content-Disposition'] == 'attachment; filename="%s.pdf"' % payment.formatted_number
|
|
|
|
# other regie
|
|
other_regie = Regie.objects.create(label='Other Foo')
|
|
payment.regie = other_regie
|
|
payment.save()
|
|
resp = app.get(
|
|
'/api/regie/foo/payment/%s/pdf/' % str(payment.uuid),
|
|
params={'payer_external_id': 'payer:1'},
|
|
status=404,
|
|
)
|