Add the payment amount to invoice's amount_to_pay when the payment line is unreconciled

issue10757
review371951002
This commit is contained in:
Nicolas Évrard
2021-11-28 18:56:16 +01:00
parent d1817db74b
commit e1a078ea0f
4 changed files with 198 additions and 0 deletions
+16
View File
@@ -124,6 +124,22 @@ class Payment(metaclass=PoolMeta):
clearing_move = fields.Many2One('account.move', 'Clearing Move',
readonly=True)
@property
def amount_line_paid(self):
amount = super().amount_line_paid
if self.clearing_move:
clearing_line = [l for l in self.clearing_move.lines
if l.account == self.clearing_account][0]
if (not self.line.reconciliation
and clearing_line.reconciliation):
if self.line.second_currency:
payment_amount = abs(self.line.amount_second_currency)
else:
payment_amount = abs(self.line.credit - self.line.debit)
amount -= max(min(self.amount, payment_amount), 0)
return amount
@classmethod
def __setup__(cls):
super(Payment, cls).__setup__()
+1
View File
@@ -66,6 +66,7 @@ requires.append(get_require_version('trytond'))
tests_require = [get_require_version('proteus'),
get_require_version('trytond_account_statement'),
get_require_version('trytond_account_statement_rule'),
get_require_version('trytond_account_invoice'),
'python-dateutil']
dependency_links = []
if minor_version % 2:
+176
View File
@@ -0,0 +1,176 @@
=====================
Invoice Amount to Pay
=====================
Imports::
>>> import datetime
>>> from dateutil.relativedelta import relativedelta
>>> from decimal import Decimal
>>> from proteus import Model, Wizard
>>> from trytond.tests.tools import activate_modules
>>> from trytond.modules.currency.tests.tools import get_currency
>>> from trytond.modules.company.tests.tools import (
... create_company, get_company)
>>> from trytond.modules.account.tests.tools import (
... create_fiscalyear, create_chart, get_accounts)
>>> from trytond.modules.account_invoice.tests.tools import (
... set_fiscalyear_invoice_sequences)
>>> today = datetime.date.today()
>>> yesterday = today - relativedelta(days=1)
>>> first = today + relativedelta(day=1)
Activate modules::
>>> config = activate_modules(
... ['account_payment_clearing', 'account_invoice'])
Create company::
>>> _ = create_company()
>>> company = get_company()
Create fiscal year::
>>> fiscalyear = set_fiscalyear_invoice_sequences(
... create_fiscalyear(company))
>>> fiscalyear.click('create_period')
Create chart of accounts::
>>> _ = create_chart(company)
>>> accounts = get_accounts(company)
>>> receivable = accounts['receivable']
>>> revenue = accounts['revenue']
>>> expense = accounts['expense']
>>> payable = accounts['payable']
>>> cash = accounts['cash']
>>> Account = Model.get('account.account')
>>> bank_clearing = Account(parent=payable.parent)
>>> bank_clearing.name = 'Bank Clearing'
>>> bank_clearing.type = payable.type
>>> bank_clearing.reconcile = True
>>> bank_clearing.deferral = True
>>> bank_clearing.save()
>>> Journal = Model.get('account.journal')
>>> expense_journal, = Journal.find([('code', '=', 'EXP')])
>>> revenue_journal, = Journal.find([('code', '=', 'REV')])
Create payment journal::
>>> PaymentJournal = Model.get('account.payment.journal')
>>> payment_journal = PaymentJournal(name='No Clearing',
... process_method='manual')
>>> payment_journal.save()
>>> clearing_journal = PaymentJournal(name='Clearing',
... process_method='manual', clearing_journal=expense,
... clearing_account=bank_clearing)
>>> clearing_journal.save()
Create parties::
>>> Party = Model.get('party.party')
>>> supplier = Party(name='Supplier')
>>> supplier.save()
>>> customer = Party(name='Customer')
>>> customer.save()
Create and pay an invoice without clearing::
>>> Invoice = Model.get('account.invoice')
>>> invoice = Invoice()
>>> invoice.party = customer
>>> line = invoice.lines.new()
>>> line.account = revenue
>>> line.quantity = 1
>>> line.unit_price = Decimal('100')
>>> invoice.save()
>>> invoice.click('post')
>>> invoice.amount_to_pay
Decimal('100.00')
>>> paid_line, = [l for l in invoice.move.lines if l.account == receivable]
>>> pay_line = Wizard('account.move.line.pay', [paid_line])
>>> pay_line.execute('next_')
>>> pay_line.form.journal = payment_journal
>>> pay_line.execute('next_')
>>> Payment = Model.get('account.payment')
>>> payment, = Payment.find()
>>> payment.click('approve')
>>> payment.state
'approved'
>>> process_payment = Wizard('account.payment.process', [payment])
>>> process_payment.execute('process')
>>> payment.reload()
>>> succeed = Wizard('account.payment.succeed', [payment])
>>> succeed.execute('succeed')
>>> invoice.reload()
>>> invoice.amount_to_pay
Decimal('0.00')
Create an invoice and pay it::
>>> invoice1 = Invoice()
>>> invoice1.party = customer
>>> line = invoice1.lines.new()
>>> line.account = revenue
>>> line.quantity = 1
>>> line.unit_price = Decimal('100')
>>> invoice1.save()
>>> invoice1.click('post')
>>> invoice1.amount_to_pay
Decimal('100.00')
>>> paid_line, = [l for l in invoice1.move.lines if l.account == receivable]
>>> pay_line = Wizard('account.move.line.pay', [paid_line])
>>> pay_line.execute('next_')
>>> pay_line.form.journal = clearing_journal
>>> pay_line.execute('next_')
>>> payment, = Payment.find([('state', '=', 'draft')])
>>> payment.click('approve')
>>> payment.state
'approved'
>>> process_payment = Wizard('account.payment.process', [payment])
>>> process_payment.execute('process')
>>> payment.reload()
>>> succeed = Wizard('account.payment.succeed', [payment])
>>> succeed.execute('succeed')
>>> invoice1.reload()
>>> invoice1.amount_to_pay
Decimal('0')
Unreconcile the payment line and check the amount to pay::
>>> other_line, = [l for l in paid_line.reconciliation.lines
... if l != paid_line]
>>> unreconcile = Wizard('account.move.unreconcile_lines', [paid_line])
>>> invoice1.reload()
>>> invoice1.amount_to_pay
Decimal('0.00')
Create a second invoice and reconcile its line to pay with the payment::
>>> invoice2 = Invoice()
>>> invoice2.party = customer
>>> line = invoice2.lines.new()
>>> line.account = revenue
>>> line.quantity = 1
>>> line.unit_price = Decimal('100')
>>> invoice2.save()
>>> invoice2.click('post')
>>> inv2_line, = [l for l in invoice2.move.lines if l.account == receivable]
>>> reconcile = Wizard(
... 'account.move.reconcile_lines', [inv2_line, other_line])
>>> invoice1.reload()
>>> invoice1.amount_to_pay
Decimal('100.00')
>>> invoice2.reload()
>>> invoice2.amount_to_pay
Decimal('0')
+5
View File
@@ -28,4 +28,9 @@ def suite():
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
suite.addTests(doctest.DocFileSuite(
'scenario_invoice_amount_to_pay.rst',
tearDown=doctest_teardown, encoding='utf-8',
checker=doctest_checker,
optionflags=doctest.REPORT_ONLY_FIRST_FAILURE))
return suite