basket: make credit payments only when invoice is really paid (#85794)
gitea/lingo/pipeline/head This commit looks good
Details
gitea/lingo/pipeline/head This commit looks good
Details
This commit is contained in:
parent
6aa201e461
commit
a1837bae53
|
@ -31,8 +31,8 @@ from lingo.invoicing.models import (
|
|||
CreditAssignment,
|
||||
DraftInvoice,
|
||||
Invoice,
|
||||
InvoiceLinePayment,
|
||||
Payment,
|
||||
PaymentType,
|
||||
Regie,
|
||||
)
|
||||
from lingo.utils.requests_wrapper import requests as requests_wrapper
|
||||
|
@ -82,6 +82,7 @@ class Basket(models.Model):
|
|||
basket = cls.objects.filter(invoice=invoice).first()
|
||||
if not basket:
|
||||
return
|
||||
basket.make_payments_with_credits()
|
||||
basket.status = 'completed'
|
||||
basket.completed_at = now()
|
||||
basket.save()
|
||||
|
@ -92,12 +93,7 @@ class Basket(models.Model):
|
|||
line.notify(notification_type)
|
||||
|
||||
def revert_assignments(self):
|
||||
payments = list(
|
||||
InvoiceLinePayment.objects.filter(line__invoice=self.invoice).values_list('payment', flat=True)
|
||||
)
|
||||
InvoiceLinePayment.objects.filter(line__invoice=self.invoice).delete()
|
||||
CreditAssignment.objects.filter(payment__in=payments).delete()
|
||||
Payment.objects.filter(pk__in=payments).delete()
|
||||
CreditAssignment.objects.filter(invoice=self.invoice).delete()
|
||||
|
||||
def cancel(self):
|
||||
self.notify('cancel')
|
||||
|
@ -137,20 +133,17 @@ class Basket(models.Model):
|
|||
def is_expired(self):
|
||||
return self.status == 'expired' or self.expiry_at <= now()
|
||||
|
||||
@cached_property
|
||||
@property
|
||||
def total_amount(self):
|
||||
if self.invoice is not None:
|
||||
return self.invoice.total_amount
|
||||
return self.draft_invoice.total_amount
|
||||
|
||||
@cached_property
|
||||
@property
|
||||
def credit_amount(self):
|
||||
if self.invoice is not None:
|
||||
payment_line_qs = InvoiceLinePayment.objects.filter(
|
||||
line__invoice=self.invoice,
|
||||
payment__payment_type__slug='credit',
|
||||
)
|
||||
return -sum(pl.amount for pl in payment_line_qs)
|
||||
assignment_qs = CreditAssignment.objects.filter(invoice=self.invoice)
|
||||
return -sum(a.amount for a in assignment_qs)
|
||||
|
||||
if self.total_amount < 0:
|
||||
return 0
|
||||
|
@ -160,7 +153,7 @@ class Basket(models.Model):
|
|||
available_credit = sum(c.remaining_amount for c in credit_qs)
|
||||
return -min(self.total_amount, available_credit)
|
||||
|
||||
@cached_property
|
||||
@property
|
||||
def remaining_amount(self):
|
||||
return self.total_amount + self.credit_amount
|
||||
|
||||
|
@ -169,6 +162,26 @@ class Basket(models.Model):
|
|||
regie=self.regie,
|
||||
basket=self,
|
||||
)
|
||||
assignment_qs = CreditAssignment.objects.filter(invoice=self.invoice)
|
||||
assigned_amount = sum(a.amount for a in assignment_qs)
|
||||
if assigned_amount == self.invoice.remaining_amount:
|
||||
# invoice totally paid with credits, make payment
|
||||
self.make_payments_with_credits()
|
||||
|
||||
def make_payments_with_credits(self):
|
||||
assignment_qs = CreditAssignment.objects.filter(invoice=self.invoice)
|
||||
assigned_amount = sum(a.amount for a in assignment_qs)
|
||||
if assigned_amount > 0:
|
||||
payment_type, dummy = PaymentType.objects.get_or_create(
|
||||
regie=self.regie, slug='credit', defaults={'label': _('Credit')}
|
||||
)
|
||||
payment = Payment.make_payment(
|
||||
regie=self.regie,
|
||||
amount=assigned_amount,
|
||||
payment_type=payment_type,
|
||||
invoices=[self.invoice],
|
||||
)
|
||||
CreditAssignment.objects.filter(invoice=self.invoice).update(payment=payment)
|
||||
|
||||
|
||||
class BasketLine(models.Model):
|
||||
|
|
|
@ -86,20 +86,26 @@ class BasketValidateView(LoginRequiredMixin, FormView):
|
|||
# do nothing
|
||||
return redirect(reverse('lingo-basket-detail'))
|
||||
|
||||
if self.basket.draft_invoice.total_amount >= 0:
|
||||
if self.basket.total_amount >= 0:
|
||||
self.generate_invoice()
|
||||
return pay_invoice(request, self.basket.regie, self.basket.invoice)
|
||||
else:
|
||||
self.generate_credit()
|
||||
if self.basket.remaining_amount > 0:
|
||||
return pay_invoice(
|
||||
request=request,
|
||||
regie=self.basket.regie,
|
||||
invoice=self.basket.invoice,
|
||||
amount=self.basket.remaining_amount,
|
||||
)
|
||||
return redirect(reverse('lingo-basket-detail'))
|
||||
|
||||
self.generate_credit()
|
||||
return redirect(reverse('lingo-basket-detail'))
|
||||
|
||||
def generate_invoice(self):
|
||||
self.basket.invoice = self.basket.draft_invoice.promote()
|
||||
self.basket.invoice.refresh_from_db() # refresh amounts
|
||||
self.basket.assign_credits()
|
||||
self.basket.invoice.refresh_from_db() # refresh amounts
|
||||
|
||||
if self.basket.invoice.remaining_amount == 0:
|
||||
if self.basket.remaining_amount == 0:
|
||||
self.basket.status = 'completed'
|
||||
self.basket.validated_at = now()
|
||||
self.basket.paid_at = now()
|
||||
|
|
|
@ -125,12 +125,14 @@ def pay_demo(request):
|
|||
return pay(request, transaction=transaction)
|
||||
|
||||
|
||||
def pay_invoice(request, regie, invoice):
|
||||
def pay_invoice(request, regie, invoice, amount):
|
||||
if amount <= 0:
|
||||
return HttpResponseBadRequest('negative or null amount')
|
||||
backend = get_object_or_404(PaymentBackend, regie=regie)
|
||||
transaction = Transaction.objects.create(
|
||||
status=0,
|
||||
invoice=invoice,
|
||||
amount=invoice.total_amount,
|
||||
amount=amount,
|
||||
backend=backend,
|
||||
next_url=reverse_lazy('lingo-basket-detail'),
|
||||
)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('invoicing', '0076_line_new_fields'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='creditassignment',
|
||||
name='invoice',
|
||||
field=models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.PROTECT, to='invoicing.invoice'
|
||||
),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,19 @@
|
|||
from django.db import migrations
|
||||
|
||||
|
||||
def forward(apps, schema_editor):
|
||||
CreditAssignment = apps.get_model('invoicing', 'CreditAssignment')
|
||||
InvoiceLinePayment = apps.get_model('invoicing', 'InvoiceLinePayment')
|
||||
for ca in CreditAssignment.objects.all():
|
||||
ca.invoice = InvoiceLinePayment.objects.filter(payment=ca.payment).first().line.invoice
|
||||
ca.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('invoicing', '0077_credit_assignment'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RunPython(forward, reverse_code=migrations.RunPython.noop),
|
||||
]
|
|
@ -0,0 +1,23 @@
|
|||
import django.db.models.deletion
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
('invoicing', '0078_credit_assignment'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='creditassignment',
|
||||
name='invoice',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='invoicing.invoice'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='creditassignment',
|
||||
name='payment',
|
||||
field=models.ForeignKey(
|
||||
null=True, on_delete=django.db.models.deletion.PROTECT, to='invoicing.payment'
|
||||
),
|
||||
),
|
||||
]
|
|
@ -1418,16 +1418,14 @@ class InvoicePayment:
|
|||
|
||||
|
||||
class CreditAssignment(models.Model):
|
||||
payment = models.ForeignKey(Payment, on_delete=models.PROTECT)
|
||||
invoice = models.ForeignKey(Invoice, on_delete=models.PROTECT)
|
||||
payment = models.ForeignKey(Payment, on_delete=models.PROTECT, null=True)
|
||||
credit = models.ForeignKey(Credit, on_delete=models.PROTECT)
|
||||
amount = models.DecimalField(max_digits=9, decimal_places=2)
|
||||
created_at = models.DateTimeField(auto_now_add=True)
|
||||
|
||||
@classmethod
|
||||
def make_assignments(cls, regie, basket):
|
||||
payment_type, dummy = PaymentType.objects.get_or_create(
|
||||
regie=regie, slug='credit', defaults={'label': _('Credit')}
|
||||
)
|
||||
credit_qs = (
|
||||
Credit.objects.select_for_update()
|
||||
.filter(remaining_amount__gt=0, regie=regie, payer_external_id=basket.payer_external_id)
|
||||
|
@ -1438,18 +1436,11 @@ class CreditAssignment(models.Model):
|
|||
amount_to_assign = min(available_credit, basket.invoice.remaining_amount)
|
||||
if amount_to_assign == 0:
|
||||
return
|
||||
# make a payment 'credit'
|
||||
payment = Payment.make_payment(
|
||||
regie=regie,
|
||||
amount=amount_to_assign,
|
||||
payment_type=payment_type,
|
||||
invoices=[basket.invoice],
|
||||
)
|
||||
# and assign credits
|
||||
# assign credits
|
||||
for credit in credit_qs:
|
||||
paid_amount = decimal.Decimal(min(credit.remaining_amount, amount_to_assign))
|
||||
CreditAssignment.objects.create(
|
||||
payment=payment,
|
||||
invoice=basket.invoice,
|
||||
credit=credit,
|
||||
amount=paid_amount,
|
||||
)
|
||||
|
|
|
@ -3084,6 +3084,14 @@ def test_list_credits(mock_payer, app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/credits/', 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',
|
||||
)
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=42,
|
||||
|
@ -3113,6 +3121,7 @@ def test_list_credits(mock_payer, app, user):
|
|||
user_last_name='Name1',
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
|
@ -3162,6 +3171,7 @@ def test_list_credits(mock_payer, app, user):
|
|||
mock_payer.return_value = 'payer:1'
|
||||
mock_payer.side_effect = None
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=41,
|
||||
|
@ -3185,6 +3195,14 @@ def test_list_credits_for_payer(app, user):
|
|||
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',
|
||||
)
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=42,
|
||||
|
@ -3214,6 +3232,7 @@ def test_list_credits_for_payer(app, user):
|
|||
user_last_name='Name1',
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
|
@ -3249,6 +3268,7 @@ def test_list_credits_for_payer(app, user):
|
|||
credit.regie = regie
|
||||
credit.save()
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=41,
|
||||
|
@ -3269,6 +3289,14 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
PaymentType.create_defaults(regie)
|
||||
app.get('/api/regie/foo/credits/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',
|
||||
)
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=42,
|
||||
|
@ -3298,6 +3326,7 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
user_last_name='Name1',
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
|
@ -3312,6 +3341,7 @@ def test_list_history_credits(mock_payer, app, user):
|
|||
# credit fully assigned
|
||||
mock_payer.reset_mock()
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=41,
|
||||
|
@ -3369,6 +3399,14 @@ def test_list_history_credits_for_payer(app, user):
|
|||
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',
|
||||
)
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=42,
|
||||
|
@ -3398,6 +3436,7 @@ def test_list_history_credits_for_payer(app, user):
|
|||
user_last_name='Name1',
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
|
@ -3410,6 +3449,7 @@ def test_list_history_credits_for_payer(app, user):
|
|||
|
||||
# credit fully assigned
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment,
|
||||
credit=credit,
|
||||
amount=41,
|
||||
|
|
|
@ -289,15 +289,19 @@ def test_basket_invoice_pdf(app, simple_user):
|
|||
# invoice with credit and assignment
|
||||
basket.status = 'tobepaid'
|
||||
basket.save()
|
||||
PaymentType.create_defaults(regie)
|
||||
payment = Payment.objects.create(
|
||||
credit = Credit.objects.create(
|
||||
regie=regie,
|
||||
amount=10,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
InvoiceLinePayment.objects.create(
|
||||
payment=payment,
|
||||
line=basket.invoice.lines.first(),
|
||||
CreditLine.objects.create(
|
||||
credit=credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=10,
|
||||
unit_amount=1,
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=basket.invoice,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
)
|
||||
resp = app.get('/basket/invoice/pdf/?html', status=200)
|
||||
|
@ -443,7 +447,7 @@ def test_basket_validate_generate_invoice(app, simple_user):
|
|||
|
||||
resp = app.get('/basket/validate/')
|
||||
with mock.patch('lingo.basket.views.pay_invoice') as pay_invoice:
|
||||
pay_invoice.side_effect = lambda *args: redirect(reverse('lingo-basket-detail'))
|
||||
pay_invoice.side_effect = lambda *args, **kwargs: redirect(reverse('lingo-basket-detail'))
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/basket/')
|
||||
basket.refresh_from_db()
|
||||
|
@ -501,7 +505,7 @@ def test_basket_validate_generate_invoice(app, simple_user):
|
|||
basket.save()
|
||||
resp = app.get('/basket/validate/')
|
||||
with mock.patch('lingo.basket.views.pay_invoice') as pay_invoice:
|
||||
pay_invoice.side_effect = lambda *args: redirect(reverse('lingo-basket-detail'))
|
||||
pay_invoice.side_effect = lambda *args, **kwargs: redirect(reverse('lingo-basket-detail'))
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.endswith('/basket/')
|
||||
basket.refresh_from_db()
|
||||
|
@ -512,30 +516,25 @@ def test_basket_validate_generate_invoice(app, simple_user):
|
|||
invoice = Invoice.objects.latest('pk')
|
||||
assert basket.invoice == invoice
|
||||
assert invoice.total_amount == 10
|
||||
assert invoice.paid_amount == 4
|
||||
assert invoice.remaining_amount == 6
|
||||
assert invoice.paid_amount == 0
|
||||
assert invoice.remaining_amount == 10
|
||||
credit1.refresh_from_db()
|
||||
assert credit1.remaining_amount == 0
|
||||
assert credit1.assigned_amount == 1
|
||||
credit2.refresh_from_db()
|
||||
assert credit2.remaining_amount == 0
|
||||
assert credit2.assigned_amount == 3
|
||||
assert Payment.objects.count() == 1
|
||||
payment = Payment.objects.latest('pk')
|
||||
assert payment.amount == 4
|
||||
assert payment.payment_type.slug == 'credit'
|
||||
assert Payment.objects.count() == 0
|
||||
assert CreditAssignment.objects.count() == 2
|
||||
assignment1, assignment2 = CreditAssignment.objects.all().order_by('pk')
|
||||
assert assignment1.amount == 1
|
||||
assert assignment1.payment == payment
|
||||
assert assignment1.invoice == invoice
|
||||
assert assignment1.payment is None
|
||||
assert assignment1.credit == credit1
|
||||
assert assignment2.amount == 3
|
||||
assert assignment2.payment == payment
|
||||
assert assignment2.invoice == invoice
|
||||
assert assignment2.payment is None
|
||||
assert assignment2.credit == credit2
|
||||
assert payment.invoicelinepayment_set.count() == 1
|
||||
invoicelinepayment = InvoiceLinePayment.objects.latest('pk')
|
||||
assert invoicelinepayment.line == invoice.lines.get()
|
||||
assert invoicelinepayment.amount == 4
|
||||
|
||||
|
||||
def test_basket_validate_generate_invoice_nothing_to_pay(app, simple_user):
|
||||
|
@ -583,10 +582,7 @@ def test_basket_validate_generate_invoice_nothing_to_pay(app, simple_user):
|
|||
)
|
||||
|
||||
resp = app.get('/basket/validate/')
|
||||
with mock.patch('lingo.basket.views.pay_invoice') as pay_invoice, mock.patch(
|
||||
'lingo.utils.requests_wrapper.RequestsSession.send'
|
||||
) as mock_send:
|
||||
pay_invoice.side_effect = lambda *args: redirect(reverse('lingo-basket-detail'))
|
||||
with mock.patch('lingo.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
||||
resp = resp.form.submit()
|
||||
assert {x[0][0].url for x in mock_send.call_args_list} == set()
|
||||
assert resp.location.endswith('/basket/')
|
||||
|
@ -599,6 +595,7 @@ def test_basket_validate_generate_invoice_nothing_to_pay(app, simple_user):
|
|||
assert basket.invoice == invoice
|
||||
assert invoice.total_amount == 0
|
||||
assert Credit.objects.count() == 0
|
||||
assert Payment.objects.count() == 0
|
||||
|
||||
# total is zero, but with credits
|
||||
invoice_line2.delete()
|
||||
|
@ -622,10 +619,7 @@ def test_basket_validate_generate_invoice_nothing_to_pay(app, simple_user):
|
|||
basket.save()
|
||||
|
||||
resp = app.get('/basket/validate/')
|
||||
with mock.patch('lingo.basket.views.pay_invoice') as pay_invoice, mock.patch(
|
||||
'lingo.utils.requests_wrapper.RequestsSession.send'
|
||||
) as mock_send:
|
||||
pay_invoice.side_effect = lambda *args: redirect(reverse('lingo-basket-detail'))
|
||||
with mock.patch('lingo.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
||||
resp = resp.form.submit()
|
||||
assert {x[0][0].url for x in mock_send.call_args_list} == {
|
||||
'http://validation1.com/',
|
||||
|
@ -653,6 +647,7 @@ def test_basket_validate_generate_invoice_nothing_to_pay(app, simple_user):
|
|||
assert CreditAssignment.objects.count() == 1
|
||||
assignment = CreditAssignment.objects.latest('pk')
|
||||
assert assignment.amount == 1
|
||||
assert assignment.invoice == invoice
|
||||
assert assignment.payment == payment
|
||||
assert assignment.credit == credit
|
||||
assert payment.invoicelinepayment_set.count() == 1
|
||||
|
@ -797,7 +792,7 @@ def test_basket_cancel(app, simple_user):
|
|||
date_payment_deadline=datetime.date(2023, 4, 22),
|
||||
date_due=datetime.date(2023, 4, 23),
|
||||
)
|
||||
invoice_line = InvoiceLine.objects.create(
|
||||
InvoiceLine.objects.create(
|
||||
slug='event-a-foo-bar',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -815,11 +810,6 @@ def test_basket_cancel(app, simple_user):
|
|||
)
|
||||
app.get('/basket/cancel/', status=404)
|
||||
# the invoice is partially paid with a credit
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=1,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
)
|
||||
credit = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
|
@ -831,15 +821,10 @@ def test_basket_cancel(app, simple_user):
|
|||
unit_amount=1,
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
payment=payment,
|
||||
invoice=invoice,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
)
|
||||
InvoiceLinePayment.objects.create(
|
||||
payment=payment,
|
||||
line=invoice_line,
|
||||
amount=1,
|
||||
)
|
||||
|
||||
# a not closed line
|
||||
line = BasketLine.objects.create(
|
||||
|
@ -858,8 +843,6 @@ def test_basket_cancel(app, simple_user):
|
|||
|
||||
# good payer_nameid
|
||||
assert CreditAssignment.objects.count() == 1
|
||||
assert Payment.objects.count() == 1
|
||||
assert InvoiceLinePayment.objects.count() == 1
|
||||
basket.payer_nameid = 'ab' * 16
|
||||
basket.save()
|
||||
resp = app.get('/basket/cancel/')
|
||||
|
@ -873,8 +856,6 @@ def test_basket_cancel(app, simple_user):
|
|||
invoice.refresh_from_db()
|
||||
assert invoice.cancelled_at is not None
|
||||
assert CreditAssignment.objects.count() == 0
|
||||
assert Payment.objects.count() == 0
|
||||
assert InvoiceLinePayment.objects.count() == 0
|
||||
|
||||
basket.status = 'tobepaid'
|
||||
basket.cancelled_at = None
|
||||
|
|
|
@ -13,9 +13,6 @@ from lingo.invoicing.models import (
|
|||
DraftInvoiceLine,
|
||||
Invoice,
|
||||
InvoiceLine,
|
||||
InvoiceLinePayment,
|
||||
Payment,
|
||||
PaymentType,
|
||||
Regie,
|
||||
)
|
||||
|
||||
|
@ -24,7 +21,6 @@ pytestmark = pytest.mark.django_db
|
|||
|
||||
def test_basket_expiration():
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
PaymentType.create_defaults(regie)
|
||||
draft_invoice = DraftInvoice.objects.create(
|
||||
regie=regie,
|
||||
date_publication=datetime.date(2023, 4, 21),
|
||||
|
@ -37,7 +33,7 @@ def test_basket_expiration():
|
|||
date_payment_deadline=datetime.date(2023, 4, 22),
|
||||
date_due=datetime.date(2023, 4, 23),
|
||||
)
|
||||
invoice_line = InvoiceLine.objects.create(
|
||||
InvoiceLine.objects.create(
|
||||
slug='event-a-foo-bar',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -58,11 +54,6 @@ def test_basket_expiration():
|
|||
user_external_id='user:1',
|
||||
)
|
||||
# the invoice is partially paid with a credit
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=1,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
)
|
||||
credit = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
|
@ -74,15 +65,10 @@ def test_basket_expiration():
|
|||
unit_amount=1,
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
payment=payment,
|
||||
invoice=invoice,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
)
|
||||
InvoiceLinePayment.objects.create(
|
||||
payment=payment,
|
||||
line=invoice_line,
|
||||
amount=1,
|
||||
)
|
||||
# other credit used on another invoice
|
||||
draft_invoice2 = DraftInvoice.objects.create(
|
||||
regie=regie,
|
||||
|
@ -96,7 +82,7 @@ def test_basket_expiration():
|
|||
date_payment_deadline=datetime.date(2023, 4, 22),
|
||||
date_due=datetime.date(2023, 4, 23),
|
||||
)
|
||||
invoice_line2 = InvoiceLine.objects.create(
|
||||
InvoiceLine.objects.create(
|
||||
slug='event-a-foo-bar',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -111,11 +97,6 @@ def test_basket_expiration():
|
|||
invoice=invoice2,
|
||||
expiry_at=now() + datetime.timedelta(minutes=1),
|
||||
)
|
||||
payment2 = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=1,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
)
|
||||
credit2 = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
|
@ -127,15 +108,10 @@ def test_basket_expiration():
|
|||
unit_amount=1,
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
payment=payment2,
|
||||
invoice=invoice2,
|
||||
credit=credit2,
|
||||
amount=1,
|
||||
)
|
||||
InvoiceLinePayment.objects.create(
|
||||
payment=payment2,
|
||||
line=invoice_line2,
|
||||
amount=1,
|
||||
)
|
||||
|
||||
for status in ['open', 'tobepaid', 'cancelled', 'expired', 'completed']:
|
||||
basket.status = status
|
||||
|
@ -148,8 +124,6 @@ def test_basket_expiration():
|
|||
|
||||
# open basket, expire it immediatly after expiry_at is passed
|
||||
assert CreditAssignment.objects.count() == 2
|
||||
assert Payment.objects.count() == 2
|
||||
assert InvoiceLinePayment.objects.count() == 2
|
||||
basket.status = 'open'
|
||||
basket.expiry_at = now()
|
||||
basket.save()
|
||||
|
@ -162,8 +136,6 @@ def test_basket_expiration():
|
|||
invoice.refresh_from_db()
|
||||
assert invoice.cancelled_at is not None
|
||||
assert CreditAssignment.objects.count() == 1
|
||||
assert Payment.objects.count() == 1
|
||||
assert InvoiceLinePayment.objects.count() == 1
|
||||
|
||||
# tobepaid basket, expire it 1 hour after expiry_at is passed
|
||||
line.expiration_callback_url = 'http://expiration1.com'
|
||||
|
@ -211,7 +183,6 @@ def test_basket_expiration():
|
|||
|
||||
def test_basket_amounts_with_draft_invoice():
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
PaymentType.create_defaults(regie)
|
||||
draft_invoice = DraftInvoice.objects.create(
|
||||
regie=regie,
|
||||
date_publication=datetime.date(2023, 4, 21),
|
||||
|
@ -230,12 +201,6 @@ def test_basket_amounts_with_draft_invoice():
|
|||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 0
|
||||
|
||||
def reset_cached_properties():
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
del basket.total_amount
|
||||
del basket.credit_amount
|
||||
del basket.remaining_amount
|
||||
|
||||
# basket with items, no credits
|
||||
DraftInvoiceLine.objects.create(
|
||||
slug='event-a',
|
||||
|
@ -245,7 +210,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 1
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 1
|
||||
|
@ -258,7 +223,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=9,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 10
|
||||
|
@ -268,7 +233,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 10
|
||||
|
@ -280,7 +245,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
@ -296,7 +261,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
@ -313,7 +278,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
@ -325,7 +290,7 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=9,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -10
|
||||
assert basket.remaining_amount == 0
|
||||
|
@ -337,23 +302,32 @@ def test_basket_amounts_with_draft_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -10
|
||||
assert basket.remaining_amount == 0
|
||||
|
||||
# credit with assignment
|
||||
payment = Payment.objects.create(
|
||||
invoice = Invoice.objects.create(
|
||||
regie=regie,
|
||||
amount=10,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
date_publication=datetime.date(2023, 4, 21),
|
||||
date_payment_deadline=datetime.date(2023, 4, 22),
|
||||
date_due=datetime.date(2023, 4, 23),
|
||||
)
|
||||
InvoiceLine.objects.create(
|
||||
slug='event-a',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
invoice=invoice,
|
||||
quantity=10,
|
||||
unit_amount=1,
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
payment=payment,
|
||||
invoice=invoice,
|
||||
credit=credit,
|
||||
amount=2,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.draft_invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -9
|
||||
assert basket.remaining_amount == 1
|
||||
|
@ -361,7 +335,6 @@ def test_basket_amounts_with_draft_invoice():
|
|||
|
||||
def test_basket_amounts_with_invoice():
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
PaymentType.create_defaults(regie)
|
||||
draft_invoice = DraftInvoice.objects.create(
|
||||
regie=regie,
|
||||
date_publication=datetime.date(2023, 4, 21),
|
||||
|
@ -387,14 +360,8 @@ def test_basket_amounts_with_invoice():
|
|||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 0
|
||||
|
||||
def reset_cached_properties():
|
||||
basket.invoice.refresh_from_db()
|
||||
del basket.total_amount
|
||||
del basket.credit_amount
|
||||
del basket.remaining_amount
|
||||
|
||||
# basket with items, no credits
|
||||
line1 = InvoiceLine.objects.create(
|
||||
InvoiceLine.objects.create(
|
||||
slug='event-a',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -402,12 +369,12 @@ def test_basket_amounts_with_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.invoice.refresh_from_db()
|
||||
assert basket.total_amount == 1
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 1
|
||||
|
||||
line2 = InvoiceLine.objects.create(
|
||||
InvoiceLine.objects.create(
|
||||
slug='event-a',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
|
@ -415,7 +382,7 @@ def test_basket_amounts_with_invoice():
|
|||
quantity=9,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 10
|
||||
|
@ -425,7 +392,7 @@ def test_basket_amounts_with_invoice():
|
|||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 10
|
||||
|
@ -437,22 +404,17 @@ def test_basket_amounts_with_invoice():
|
|||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == 0
|
||||
assert basket.remaining_amount == 10
|
||||
|
||||
payment = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=10,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
)
|
||||
InvoiceLinePayment.objects.create(
|
||||
payment=payment,
|
||||
line=line1,
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
credit=credit,
|
||||
amount=1,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -1
|
||||
assert basket.remaining_amount == 9
|
||||
|
@ -464,12 +426,12 @@ def test_basket_amounts_with_invoice():
|
|||
quantity=9,
|
||||
unit_amount=1,
|
||||
)
|
||||
InvoiceLinePayment.objects.create(
|
||||
payment=payment,
|
||||
line=line2,
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
credit=credit,
|
||||
amount=9,
|
||||
)
|
||||
reset_cached_properties()
|
||||
basket.invoice.refresh_from_db()
|
||||
assert basket.total_amount == 10
|
||||
assert basket.credit_amount == -10
|
||||
assert basket.remaining_amount == 0
|
||||
|
|
|
@ -8,7 +8,16 @@ from django.utils.timezone import now
|
|||
|
||||
from lingo.basket.models import Basket, BasketLine, BasketLineItem
|
||||
from lingo.epayment.models import PaymentBackend, Transaction
|
||||
from lingo.invoicing.models import DraftInvoice, DraftInvoiceLine, Invoice, Payment, PaymentType, Regie
|
||||
from lingo.invoicing.models import (
|
||||
Credit,
|
||||
CreditAssignment,
|
||||
CreditLine,
|
||||
DraftInvoice,
|
||||
DraftInvoiceLine,
|
||||
Payment,
|
||||
PaymentType,
|
||||
Regie,
|
||||
)
|
||||
from tests.utils import login
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
@ -230,3 +239,128 @@ def test_basket_payment(app, simple_user):
|
|||
assert payment.get_invoice_payments()[0].invoice.paid_amount == 10
|
||||
assert payment.get_invoice_payments()[0].invoice.remaining_amount == 0
|
||||
assert {x[0][0].url for x in mock_send.call_args_list} == {'http://payment1.com/'}
|
||||
|
||||
|
||||
def test_basket_payment_with_assigned_credits(app, simple_user):
|
||||
app = login(app, username='user', password='user')
|
||||
|
||||
regie = Regie.objects.create(label='Foo')
|
||||
PaymentType.create_defaults(regie)
|
||||
PaymentBackend.objects.create(label='Test', service='dummy', regie=regie)
|
||||
invoice = DraftInvoice.objects.create(
|
||||
regie=regie,
|
||||
date_publication=datetime.date(2023, 4, 21),
|
||||
date_payment_deadline=datetime.date(2023, 4, 22),
|
||||
date_due=datetime.date(2023, 4, 23),
|
||||
)
|
||||
DraftInvoiceLine.objects.create(
|
||||
slug='event-a-foo-bar',
|
||||
label='Event A',
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
invoice=invoice,
|
||||
quantity=10,
|
||||
unit_amount=1,
|
||||
user_external_id='user:1',
|
||||
)
|
||||
|
||||
basket = Basket.objects.create(
|
||||
regie=regie,
|
||||
draft_invoice=invoice,
|
||||
payer_nameid='ab' * 16,
|
||||
payer_external_id='payer:1',
|
||||
expiry_at=now() + datetime.timedelta(hours=1),
|
||||
)
|
||||
line = BasketLine.objects.create(
|
||||
basket=basket,
|
||||
closed=False,
|
||||
user_external_id='user:1',
|
||||
payment_callback_url='http://payment1.com',
|
||||
)
|
||||
BasketLineItem.objects.create(
|
||||
line=line,
|
||||
label='Event A',
|
||||
subject='Réservation',
|
||||
details='Lun 06/11, Mar 07/11',
|
||||
quantity=10,
|
||||
unit_amount=1,
|
||||
)
|
||||
line.closed = True
|
||||
line.save()
|
||||
|
||||
credit1 = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=credit1,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=1,
|
||||
unit_amount=1,
|
||||
)
|
||||
credit2 = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=credit2,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_regie = Regie.objects.create(label='Foo')
|
||||
other_credit = Credit.objects.create(
|
||||
regie=other_regie, # other regie
|
||||
payer_external_id='payer:1',
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
other_credit = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:2', # other payer
|
||||
)
|
||||
CreditLine.objects.create(
|
||||
credit=other_credit,
|
||||
event_date=datetime.date(2022, 9, 1),
|
||||
quantity=3,
|
||||
unit_amount=1,
|
||||
)
|
||||
|
||||
resp = app.get('/basket/validate/')
|
||||
resp = resp.form.submit()
|
||||
assert resp.location.startswith('https://dummy-payment.entrouvert.com/')
|
||||
assert Transaction.objects.all().count() == 1
|
||||
transaction = Transaction.objects.all().first()
|
||||
assert transaction.status == 0
|
||||
assert transaction.amount == 6
|
||||
|
||||
with mock.patch('lingo.utils.requests_wrapper.RequestsSession.send') as mock_send:
|
||||
app.get(
|
||||
reverse('lingo-epayment-explicit-return', kwargs={'transaction_id': transaction.id})
|
||||
+ f'?transaction_id={transaction.order_id}&origin=origin&ok=1&signed=1'
|
||||
).follow()
|
||||
assert Payment.objects.count() == 2
|
||||
payment1, payment2 = Payment.objects.all().order_by('pk')
|
||||
assert payment1.amount == 6
|
||||
assert payment1.payment_type.slug == 'creditcard'
|
||||
assert payment1.get_invoice_payments()[0].invoice.paid_amount == 10
|
||||
assert payment1.get_invoice_payments()[0].invoice.remaining_amount == 0
|
||||
assert payment2.amount == 4
|
||||
assert payment2.payment_type.slug == 'credit'
|
||||
assert payment2.get_invoice_payments()[0].invoice.paid_amount == 10
|
||||
assert payment2.get_invoice_payments()[0].invoice.remaining_amount == 0
|
||||
assert {x[0][0].url for x in mock_send.call_args_list} == {'http://payment1.com/'}
|
||||
assert payment1.get_invoice_payments()[0].invoice == payment2.get_invoice_payments()[0].invoice
|
||||
assert CreditAssignment.objects.count() == 2
|
||||
assignment1, assignment2 = CreditAssignment.objects.all().order_by('pk')
|
||||
assert assignment1.amount == 1
|
||||
assert assignment1.invoice == payment2.get_invoice_payments()[0].invoice
|
||||
assert assignment1.payment == payment2
|
||||
assert assignment1.credit == credit1
|
||||
assert assignment2.amount == 3
|
||||
assert assignment2.invoice == payment2.get_invoice_payments()[0].invoice
|
||||
assert assignment2.payment == payment2
|
||||
assert assignment2.credit == credit2
|
||||
|
|
|
@ -2147,6 +2147,12 @@ def test_regie_credits(app, admin_user):
|
|||
Agenda.objects.create(label='Agenda A', regie=regie)
|
||||
Agenda.objects.create(label='Agenda B', regie=regie)
|
||||
PaymentType.create_defaults(regie)
|
||||
invoice = 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,
|
||||
)
|
||||
credit1 = Credit.objects.create(
|
||||
regie=regie,
|
||||
payer_external_id='payer:1',
|
||||
|
@ -2217,6 +2223,7 @@ def test_regie_credits(app, admin_user):
|
|||
payment1.set_number()
|
||||
payment1.save()
|
||||
credit_assignment1 = CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment1,
|
||||
credit=credit1,
|
||||
amount=1,
|
||||
|
@ -2244,6 +2251,7 @@ def test_regie_credits(app, admin_user):
|
|||
payment2.set_number()
|
||||
payment2.save()
|
||||
credit_assignment2 = CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment2,
|
||||
credit=credit2,
|
||||
amount=0.5,
|
||||
|
@ -2256,6 +2264,7 @@ def test_regie_credits(app, admin_user):
|
|||
payment3.set_number()
|
||||
payment3.save()
|
||||
credit_assignment3 = CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment3,
|
||||
credit=credit2,
|
||||
amount=0.5,
|
||||
|
|
|
@ -693,12 +693,19 @@ def test_credit_assignments():
|
|||
assert credit2.assigned_amount == 0
|
||||
assert credit2.remaining_amount == 25
|
||||
|
||||
invoice = 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,
|
||||
)
|
||||
payment1 = Payment.objects.create(
|
||||
regie=regie,
|
||||
amount=17,
|
||||
payment_type=PaymentType.objects.get(regie=regie, slug='credit'),
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment1,
|
||||
amount=7,
|
||||
credit=credit1,
|
||||
|
@ -713,6 +720,7 @@ def test_credit_assignments():
|
|||
assert credit2.remaining_amount == 25
|
||||
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment1,
|
||||
amount=10,
|
||||
credit=credit2,
|
||||
|
@ -732,6 +740,7 @@ def test_credit_assignments():
|
|||
payment_type=PaymentType.objects.get(regie=regie, slug='check'),
|
||||
)
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment2,
|
||||
amount=15,
|
||||
credit=credit1,
|
||||
|
@ -746,6 +755,7 @@ def test_credit_assignments():
|
|||
assert credit2.remaining_amount == 15
|
||||
|
||||
credit_assignment = CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment2,
|
||||
amount=20,
|
||||
credit=credit1,
|
||||
|
@ -763,6 +773,7 @@ def test_credit_assignments():
|
|||
with transaction.atomic():
|
||||
with pytest.raises(IntegrityError) as excinfo:
|
||||
CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment2,
|
||||
amount=25.01,
|
||||
credit=credit2,
|
||||
|
@ -812,6 +823,7 @@ def test_credit_assignments():
|
|||
assert credit2.remaining_amount == 50
|
||||
|
||||
credit_assignment = CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment2,
|
||||
amount=-5,
|
||||
credit=credit2,
|
||||
|
@ -826,6 +838,7 @@ def test_credit_assignments():
|
|||
assert credit2.remaining_amount == 55
|
||||
|
||||
credit_assignment = CreditAssignment.objects.create(
|
||||
invoice=invoice,
|
||||
payment=payment2,
|
||||
amount=-5,
|
||||
credit=credit2,
|
||||
|
|
Loading…
Reference in New Issue