From e95cf44c2cf2c0df43a7175f5160dbdb1adcc4fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Fri, 12 Apr 2019 19:43:53 +0200 Subject: [PATCH] Add group lines wizard issue8213 review275091002 --- account.py | 28 ++++-- invoice.py | 7 +- tests/scenario_invoice_group_line.rst | 126 ++++++++++++++++++++++++++ tests/test_account_invoice.py | 4 + 4 files changed, 154 insertions(+), 11 deletions(-) create mode 100644 tests/scenario_invoice_group_line.rst diff --git a/account.py b/account.py index 8a1f4db112..a02d001b87 100644 --- a/account.py +++ b/account.py @@ -268,16 +268,24 @@ class Reconciliation(metaclass=PoolMeta): def create(cls, vlist): Invoice = Pool().get('account.invoice') reconciliations = super(Reconciliation, cls).create(vlist) - move_ids = set() - account_ids = set() - for reconciliation in reconciliations: - move_ids |= {l.move.id for l in reconciliation.lines} - account_ids |= {l.account.id for l in reconciliation.lines} - invoices = Invoice.search([ - ('move', 'in', list(move_ids)), - ('account', 'in', list(account_ids)), - ]) - Invoice.process(invoices) + + def process(reconciliations): + move_ids = set() + others = set() + for reconciliation in reconciliations: + for line in reconciliation.lines: + move_ids.add(line.move.id) + others.update(line.reconciliations_delegated) + if others: + move_ids.update(process(cls.browse(others))) + return move_ids + move_ids = process(reconciliations) + invoices = set() + for sub_ids in grouped_slice(move_ids): + invoices.update(Invoice.search([ + ('move', 'in', list(sub_ids)), + ])) + Invoice.process(Invoice.browse(invoices)) return reconciliations @classmethod diff --git a/invoice.py b/invoice.py index 4c80f102aa..0f24acbe90 100644 --- a/invoice.py +++ b/invoice.py @@ -623,7 +623,12 @@ class Invoice(Workflow, ModelSQL, ModelView, TaxableMixin): return result def get_reconciled(self, name): - reconciliations = [l.reconciliation for l in self.lines_to_pay] + def get_reconciliation(line): + if line.reconciliation and line.reconciliation.delegate_to: + return get_reconciliation(line.reconciliation.delegate_to) + else: + return line.reconciliation + reconciliations = list(map(get_reconciliation, self.lines_to_pay)) if not reconciliations: return None elif not all(reconciliations): diff --git a/tests/scenario_invoice_group_line.rst b/tests/scenario_invoice_group_line.rst new file mode 100644 index 0000000000..70da1a4bb7 --- /dev/null +++ b/tests/scenario_invoice_group_line.rst @@ -0,0 +1,126 @@ +================ +Invoice Scenario +================ + +Imports:: + + >>> import datetime + >>> from decimal import Decimal + >>> from proteus import Model, Wizard + >>> from trytond.tests.tools import activate_modules + >>> 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 + +Install account_invoice:: + + >>> config = activate_modules('account_invoice') + +Create company:: + + >>> _ = create_company() + >>> company = get_company() + +Create fiscal year:: + + >>> fiscalyear = set_fiscalyear_invoice_sequences( + ... create_fiscalyear(company)) + >>> fiscalyear.click('create_period') + >>> period = fiscalyear.periods[0] + +Create chart of accounts:: + + >>> _ = create_chart(company) + >>> accounts = get_accounts(company) + >>> receivable = accounts['receivable'] + >>> payable = accounts['payable'] + >>> revenue = accounts['revenue'] + >>> expense = accounts['expense'] + >>> account_cash = accounts['cash'] + + >>> Journal = Model.get('account.journal') + >>> journal_cash, = Journal.find([ + ... ('code', '=', 'CASH'), + ... ]) + +Create party:: + + >>> Party = Model.get('party.party') + >>> party = Party(name='Party') + >>> party.save() + +Post customer invoice:: + + >>> Invoice = Model.get('account.invoice') + >>> invoice = Invoice() + >>> invoice.party = party + >>> line = invoice.lines.new() + >>> line.account = revenue + >>> line.quantity = 1 + >>> line.unit_price = Decimal(10) + >>> invoice.click('post') + >>> invoice.state + 'posted' + +Post supplier invoice:: + + >>> supplier_invoice = Invoice(type='in') + >>> supplier_invoice.party = party + >>> supplier_invoice.invoice_date = period.start_date + >>> line = supplier_invoice.lines.new() + >>> line.account = expense + >>> line.quantity = 1 + >>> line.unit_price = Decimal(5) + >>> supplier_invoice.click('post') + >>> supplier_invoice.state + 'posted' + +Group lines:: + + >>> Line = Model.get('account.move.line') + >>> lines = Line.find([('account', 'in', [payable.id, receivable.id])]) + >>> len(lines) + 2 + >>> group = Wizard('account.move.line.group', lines) + >>> group.form.journal = journal_cash + >>> group.execute('group') + + >>> invoice.reload() + >>> invoice.state + 'posted' + >>> supplier_invoice.reload() + >>> supplier_invoice.state + 'posted' + +Receive remaining line:: + + >>> Move = Model.get('account.move') + >>> move = Move() + >>> move.journal = journal_cash + >>> move.date = period.start_date + >>> line = move.lines.new() + >>> line.account = account_cash + >>> line.debit = Decimal(5) + >>> line = move.lines.new() + >>> line.account = receivable + >>> line.party = party + >>> line.credit = Decimal(5) + >>> move.click('post') + + >>> lines = Line.find([ + ... ('account', '=', receivable.id), + ... ('reconciliation', '=', None), + ... ]) + >>> reconcile_lines = Wizard('account.move.reconcile_lines', lines) + >>> reconcile_lines.state == 'end' + True + + >>> invoice.reload() + >>> invoice.state + 'paid' + >>> supplier_invoice.reload() + >>> supplier_invoice.state + 'paid' diff --git a/tests/test_account_invoice.py b/tests/test_account_invoice.py index d439b22050..0b079c1f54 100644 --- a/tests/test_account_invoice.py +++ b/tests/test_account_invoice.py @@ -230,6 +230,10 @@ def suite(): tearDown=doctest_teardown, encoding='utf-8', checker=doctest_checker, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite('scenario_invoice_group_line.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) suite.addTests(doctest.DocFileSuite( 'scenario_renew_fiscalyear.rst', tearDown=doctest_teardown, encoding='utf-8',