diff --git a/addons/account/models/account_journal_dashboard.py b/addons/account/models/account_journal_dashboard.py index 106eebb37fa..c24b1be061d 100644 --- a/addons/account/models/account_journal_dashboard.py +++ b/addons/account/models/account_journal_dashboard.py @@ -185,8 +185,8 @@ class account_journal(models.Model): self.env.cr.execute(query, query_args) query_results_drafts = self.env.cr.dictfetchall() - today = datetime.today() - query = """SELECT amount_total, currency_id AS currency, type, date_invoice, company_id FROM account_invoice WHERE journal_id = %s AND date <= %s AND state = 'open';""" + today = fields.Date.today() + query = """SELECT residual_signed as amount_total, currency_id AS currency, type, date_invoice, company_id FROM account_invoice WHERE journal_id = %s AND date <= %s AND state = 'open';""" self.env.cr.execute(query, (self.id, today)) late_query_results = self.env.cr.dictfetchall() (number_waiting, sum_waiting) = self._count_results_and_sum_amounts(query_results_to_pay, currency) @@ -226,13 +226,23 @@ class account_journal(models.Model): gather the bills in draft state data, and the arguments dictionary to use to run it as its second. """ - return ("""SELECT state, amount_total, currency_id AS currency, type, date_invoice, company_id - FROM account_invoice + # there is no account_move_lines for draft invoices, so no relevant residual_signed value + return ("""SELECT state, + (CASE WHEN inv.type in ('out_invoice', 'in_invoice') + THEN inv.amount_total + ELSE (-1 * inv.amount_total) + END) AS amount_total, + inv.currency_id AS currency, + inv.type, + inv.date_invoice, + inv.company_id + FROM account_invoice inv WHERE journal_id = %(journal_id)s AND state = 'draft';""", {'journal_id':self.id}) def _count_results_and_sum_amounts(self, results_dict, target_currency): """ Loops on a query result to count the total number of invoices and sum their amount_total field (expressed in the given target currency). + amount_total must be signed ! """ rslt_count = 0 rslt_sum = 0.0 @@ -240,9 +250,9 @@ class account_journal(models.Model): cur = self.env['res.currency'].browse(result.get('currency')) company = self.env['res.company'].browse(result.get('company_id')) or self.env.user.company_id rslt_count += 1 - type_factor = result.get('type') in ('in_refund', 'out_refund') and -1 or 1 - rslt_sum += type_factor * cur._convert( - result.get('amount_total'), target_currency, company, result.get('date_invoice') or fields.Date.today()) + amount = result.get('amount_total', 0) + rslt_sum += cur._convert( + amount, target_currency, company, result.get('date_invoice') or fields.Date.today()) return (rslt_count, rslt_sum) @api.multi diff --git a/addons/account/tests/test_account_customer_invoice.py b/addons/account/tests/test_account_customer_invoice.py index 0906eae595b..8e2e825ae2b 100644 --- a/addons/account/tests/test_account_customer_invoice.py +++ b/addons/account/tests/test_account_customer_invoice.py @@ -1,3 +1,5 @@ +from unittest.mock import patch + from odoo.addons.account.tests.account_test_users import AccountTestUsers import datetime from odoo.tests import tagged @@ -165,3 +167,119 @@ class TestAccountCustomerInvoice(AccountTestUsers): )) self.assertEquals(invoice.amount_untaxed, sum([x.base for x in invoice.tax_line_ids])) + + def test_customer_invoice_dashboard(self): + def patched_today(*args, **kwargs): + return '2019-01-22' + + date_invoice = '2019-01-21' + partner3 = self.env.ref('base.res_partner_3') + account_id = self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_revenue').id)], limit=1).id + + journal = self.env['account.journal'].create({ + 'name': 'sale_0', + 'code': 'SALE0', + 'type': 'sale', + }) + + invoice_line_data = [ + (0, 0, + { + 'product_id': self.env.ref('product.product_product_1').id, + 'quantity': 40.0, + 'account_id': account_id, + 'name': 'product test 1', + 'discount': 10.00, + 'price_unit': 2.27, + } + ) + ] + + invoice = self.env['account.invoice'].create(dict( + name="Test Customer Invoice", + journal_id=journal.id, + partner_id=partner3.id, + invoice_line_ids=invoice_line_data, + date_invoice=date_invoice, + )) + + refund_line_data = [ + (0, 0, + { + 'product_id': self.env.ref('product.product_product_1').id, + 'quantity': 1.0, + 'account_id': account_id, + 'name': 'product test 1', + 'price_unit': 13.3, + } + )] + + refund = self.env['account.invoice'].create(dict( + name="Test Customer Refund", + type='out_refund', + journal_id=journal.id, + partner_id=partner3.id, + invoice_line_ids=refund_line_data, + date_invoice=date_invoice, + )) + + # Check Draft + dashboard_data = journal.get_journal_dashboard_datas() + + self.assertEquals(dashboard_data['number_draft'], 2) + self.assertEquals(dashboard_data['sum_draft'], '$ 68.42') + + self.assertEquals(dashboard_data['number_waiting'], 0) + self.assertEquals(dashboard_data['sum_waiting'], '$ 0.00') + + # Check Both + invoice.action_invoice_open() + + dashboard_data = journal.get_journal_dashboard_datas() + self.assertEquals(dashboard_data['number_draft'], 1) + self.assertEquals(dashboard_data['sum_draft'], '$ -13.30') + + self.assertEquals(dashboard_data['number_waiting'], 1) + self.assertEquals(dashboard_data['sum_waiting'], '$ 81.72') + + # Check waiting payment + refund.action_invoice_open() + + dashboard_data = journal.get_journal_dashboard_datas() + self.assertEquals(dashboard_data['number_draft'], 0) + self.assertEquals(dashboard_data['sum_draft'], '$ 0.00') + + self.assertEquals(dashboard_data['number_waiting'], 2) + self.assertEquals(dashboard_data['sum_waiting'], '$ 68.42') + + # Check partial + receivable_account = refund.move_id.line_ids.mapped('account_id').filtered(lambda a: a.internal_type == 'receivable') + payment_move = self.env['account.move'].create({ + 'journal_id': journal.id, + }) + payment_move_line = self.env['account.move.line'].with_context(check_move_validity=False).create({ + 'move_id': payment_move.id, + 'account_id': receivable_account.id, + 'debit': 10.00, + }) + self.env['account.move.line'].with_context(check_move_validity=False).create({ + 'move_id': payment_move.id, + 'account_id': self.env['account.account'].search([('user_type_id', '=', self.env.ref('account.data_account_type_liquidity').id)], limit=1).id, + 'credit': 10.00, + }) + + payment_move.post() + + refund.register_payment(payment_move_line) + + dashboard_data = journal.get_journal_dashboard_datas() + self.assertEquals(dashboard_data['number_draft'], 0) + self.assertEquals(dashboard_data['sum_draft'], '$ 0.00') + + self.assertEquals(dashboard_data['number_waiting'], 2) + self.assertEquals(dashboard_data['sum_waiting'], '$ 78.42') + + with patch('odoo.fields.Date.today', patched_today): + dashboard_data = journal.get_journal_dashboard_datas() + self.assertEquals(dashboard_data['number_late'], 2) + self.assertEquals(dashboard_data['sum_late'], '$ 78.42')