diff --git a/CHANGELOG b/CHANGELOG index 2734305ceb..6f0ea028f0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Use invoice amount to pay as line amount when creating lines from origins * Rename Origin field informations to information Version 5.0.0 - 2018-10-01 diff --git a/statement.py b/statement.py index 90f7602484..63a6a2abc0 100644 --- a/statement.py +++ b/statement.py @@ -248,6 +248,51 @@ class Statement(Workflow, ModelSQL, ModelView): return ((getattr(self, 'end_balance', 0) or 0) - (getattr(self, 'start_balance', 0) or 0)) + @fields.depends('origins', 'lines', 'journal', 'company') + def on_change_origins(self): + if not self.journal or not self.origins or not self.company: + return + if self.journal.currency != self.company.currency: + return + + invoices = set() + for line in self.lines: + if (getattr(line, 'invoice', None) + and line.invoice.currency == self.company.currency): + invoices.add(line.invoice) + for origin in self.origins: + for line in origin.lines: + if (getattr(line, 'invoice', None) + and line.invoice.currency == self.company.currency): + invoices.add(line.invoice) + invoice_id2amount_to_pay = {} + for invoice in invoices: + if invoice.type == 'out': + sign = -1 + else: + sign = 1 + invoice_id2amount_to_pay[invoice.id] = sign * invoice.amount_to_pay + + origins = list(self.origins) + for origin in origins: + lines = list(origin.lines) + for line in lines: + if (getattr(line, 'invoice', None) and line.id + and line.invoice.id in invoice_id2amount_to_pay): + amount_to_pay = invoice_id2amount_to_pay[line.invoice.id] + if (amount_to_pay + and getattr(line, 'amount', None) + and (line.amount >= 0) == (amount_to_pay <= 0)): + if abs(line.amount) > abs(amount_to_pay): + line.amount = amount_to_pay.copy_sign(line.amount) + else: + invoice_id2amount_to_pay[line.invoice.id] = ( + line.amount + amount_to_pay) + else: + line.invoice = None + origin.lines = lines + self.origins = origins + @fields.depends('lines', 'journal', 'company') def on_change_lines(self): pool = Pool() diff --git a/tests/scenario_statement_origin_invoices.rst b/tests/scenario_statement_origin_invoices.rst new file mode 100644 index 0000000000..3ed0ff98d5 --- /dev/null +++ b/tests/scenario_statement_origin_invoices.rst @@ -0,0 +1,128 @@ +========================================== +Account Statement Origin Invoices Scenario +========================================== + +Imports:: + + >>> import datetime + >>> from decimal import Decimal + >>> from proteus import Model, Wizard, Report + >>> 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 + >>> today = datetime.date.today() + +Install account_statement:: + + >>> config = activate_modules('account_statement') + +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'] + >>> cash = accounts['cash'] + +Create parties:: + + >>> Party = Model.get('party.party') + >>> customer = Party(name="Customer") + >>> customer.save() + +Create 2 customer invoices:: + + >>> Invoice = Model.get('account.invoice') + >>> customer_invoice1 = Invoice(type='out') + >>> customer_invoice1.party = customer + >>> invoice_line = customer_invoice1.lines.new() + >>> invoice_line.quantity = 1 + >>> invoice_line.unit_price = Decimal('100') + >>> invoice_line.account = revenue + >>> invoice_line.description = 'Test' + >>> customer_invoice1.click('post') + >>> customer_invoice1.state + 'posted' + + >>> customer_invoice2 = Invoice(type='out') + >>> customer_invoice2.party = customer + >>> invoice_line = customer_invoice2.lines.new() + >>> invoice_line.quantity = 1 + >>> invoice_line.unit_price = Decimal('150') + >>> invoice_line.account = revenue + >>> invoice_line.description = 'Test' + >>> customer_invoice2.click('post') + >>> customer_invoice2.state + 'posted' + +Create Account Journal:: + + >>> Sequence = Model.get('ir.sequence') + >>> AccountJournal = Model.get('account.journal') + + >>> sequence = Sequence(name="Satement", + ... code='account.journal', + ... company=company, + ... ) + >>> sequence.save() + >>> account_journal = AccountJournal(name="Statement", + ... type='statement', + ... sequence=sequence, + ... ) + >>> account_journal.save() + +Create a statement with origins:: + + >>> StatementJournal = Model.get('account.statement.journal') + >>> Statement = Model.get('account.statement') + >>> journal_number = StatementJournal(name="Number", + ... journal=account_journal, + ... account=cash, + ... validation='number_of_lines', + ... ) + >>> journal_number.save() + + >>> statement = Statement(name="number origins") + >>> statement.journal = journal_number + >>> statement.number_of_lines = 1 + >>> origin = statement.origins.new() + >>> origin.date = today + >>> origin.amount = Decimal('180.00') + >>> statement.click('validate_statement') + +Pending amount is used to fill all invoices:: + + >>> origin, = statement.origins + >>> line = origin.lines.new() + >>> line.invoice = customer_invoice1 + >>> line.amount + Decimal('100.00') + >>> line.party == customer + True + >>> line.account == receivable + True + >>> origin.pending_amount + Decimal('80.00') + >>> line = origin.lines.new() + >>> line.invoice = customer_invoice2 + >>> line.amount + Decimal('80.00') + >>> line.party == customer + True + >>> line.account == receivable + True diff --git a/tests/test_account_statement.py b/tests/test_account_statement.py index 0262a23c21..a484de1394 100644 --- a/tests/test_account_statement.py +++ b/tests/test_account_statement.py @@ -25,4 +25,9 @@ def suite(): tearDown=doctest_teardown, encoding='utf-8', checker=doctest_checker, optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) + suite.addTests(doctest.DocFileSuite( + 'scenario_statement_origin_invoices.rst', + tearDown=doctest_teardown, encoding='utf-8', + checker=doctest_checker, + optionflags=doctest.REPORT_ONLY_FIRST_FAILURE)) return suite