diff --git a/addons/stock_account/models/stock_move.py b/addons/stock_account/models/stock_move.py index 63b779f17a2..11743b0484b 100644 --- a/addons/stock_account/models/stock_move.py +++ b/addons/stock_account/models/stock_move.py @@ -486,10 +486,9 @@ class StockMove(models.Model): 'product_id': self.product_id.id, 'quantity': qty, 'product_uom_id': self.product_id.uom_id.id, + 'balance': -diff_amount, 'ref': description, 'partner_id': partner_id, - 'credit': diff_amount > 0 and diff_amount or 0, - 'debit': diff_amount < 0 and -diff_amount or 0, 'account_id': price_diff_account.id, } return rslt @@ -522,6 +521,7 @@ class StockMove(models.Model): 'stock_move_id': self.id, 'stock_valuation_layer_ids': [(6, None, [svl_id])], 'move_type': 'entry', + 'is_storno': self.env.context.get('is_returned') and self.env.company.account_storno, } def _account_analytic_entry_move(self): @@ -557,7 +557,7 @@ class StockMove(models.Model): # warehouse of the same company, the transit location belongs to this company, so we don't need to create accounting entries if self._is_in(): if self._is_returned(valued_type='in'): - am_vals.append(self.with_company(company_to)._prepare_account_move_vals(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost)) + am_vals.append(self.with_company(company_to).with_context(is_returned=True)._prepare_account_move_vals(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost)) else: am_vals.append(self.with_company(company_to)._prepare_account_move_vals(acc_src, acc_valuation, journal_id, qty, description, svl_id, cost)) @@ -565,7 +565,7 @@ class StockMove(models.Model): if self._is_out(): cost = -1 * cost if self._is_returned(valued_type='out'): - am_vals.append(self.with_company(company_from)._prepare_account_move_vals(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost)) + am_vals.append(self.with_company(company_from).with_context(is_returned=True)._prepare_account_move_vals(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost)) else: am_vals.append(self.with_company(company_from)._prepare_account_move_vals(acc_valuation, acc_dest, journal_id, qty, description, svl_id, cost)) @@ -579,10 +579,10 @@ class StockMove(models.Model): am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_valuation, acc_dest, journal_id, qty, description, svl_id, cost)) elif self._is_dropshipped_returned(): if cost > 0: - am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost)) + am_vals.append(self.with_company(self.company_id).with_context(is_returned=True)._prepare_account_move_vals(acc_valuation, acc_src, journal_id, qty, description, svl_id, cost)) else: cost = -1 * cost - am_vals.append(self.with_company(self.company_id)._prepare_account_move_vals(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost)) + am_vals.append(self.with_company(self.company_id).with_context(is_returned=True)._prepare_account_move_vals(acc_dest, acc_valuation, journal_id, qty, description, svl_id, cost)) return am_vals diff --git a/addons/stock_account/tests/test_account_move.py b/addons/stock_account/tests/test_account_move.py index df051789024..3805dfc823f 100644 --- a/addons/stock_account/tests/test_account_move.py +++ b/addons/stock_account/tests/test_account_move.py @@ -4,7 +4,7 @@ from odoo.addons.account.tests.common import AccountTestInvoicingCommon from odoo.addons.stock_account.tests.test_stockvaluation import _create_accounting_data from odoo.tests.common import tagged, Form - +from odoo import fields class TestAccountMoveStockCommon(AccountTestInvoicingCommon): @classmethod @@ -117,3 +117,29 @@ class TestAccountMove(TestAccountMoveStockCommon): self.assertEqual(len(invoice.mapped("line_ids")), 4) self.assertEqual(len(invoice.mapped("line_ids").filtered(lambda l: l.display_type == 'cogs')), 2) self.assertEqual(len(invoice.mapped("line_ids.currency_id")), 2) + + def test_storno_accounting(self): + """Storno accounting uses negative numbers on debit/credit to cancel other moves. + This test checks that we do the same for the anglosaxon lines when storno is enabled. + """ + self.env.company.account_storno = True + self.env.company.anglo_saxon_accounting = True + + move = self.env['account.move'].create({ + 'move_type': 'out_refund', + 'invoice_date': fields.Date.from_string('2019-01-01'), + 'partner_id': self.partner_a.id, + 'currency_id': self.currency_data['currency'].id, + 'invoice_line_ids': [ + (0, None, {'product_id': self.product_A.id}), + ] + }) + move.action_post() + + stock_output_line = move.line_ids.filtered(lambda l: l.account_id == self.stock_output_account) + self.assertEqual(stock_output_line.debit, 0) + self.assertEqual(stock_output_line.credit, -10) + + expense_line = move.line_ids.filtered(lambda l: l.account_id == self.product_A.property_account_expense_id) + self.assertEqual(expense_line.debit, -10) + self.assertEqual(expense_line.credit, 0) diff --git a/addons/stock_account/tests/test_stockvaluationlayer.py b/addons/stock_account/tests/test_stockvaluationlayer.py index aa17d061f78..72c2796e4a3 100644 --- a/addons/stock_account/tests/test_stockvaluationlayer.py +++ b/addons/stock_account/tests/test_stockvaluationlayer.py @@ -1022,7 +1022,7 @@ class TestStockValuationChangeValuation(TestStockValuationCommon): self.assertAlmostEqual(abs(move.stock_valuation_layer_ids.value), 1123.39) @tagged('post_install', '-at_install') -class TestAngloSaxonAccounting(AccountTestInvoicingCommon): +class TestAngloSaxonAccounting(AccountTestInvoicingCommon, TestStockValuationCommon): @classmethod def setUpClass(cls, chart_template_ref=None): super().setUpClass(chart_template_ref=chart_template_ref) @@ -1103,38 +1103,6 @@ class TestAngloSaxonAccounting(AccountTestInvoicingCommon): 'property_stock_journal': cls.company_data['default_journal_misc'].id, }) - def _make_in_move(self, product, quantity, unit_cost=None, create_picking=False, loc_dest=None, pick_type=None): - """ Helper to create and validate a receipt move. - """ - unit_cost = unit_cost or product.standard_price - loc_dest = loc_dest or self.stock_location - pick_type = pick_type or self.picking_type_in - in_move = self.env['stock.move'].create({ - 'name': 'in %s units @ %s per unit' % (str(quantity), str(unit_cost)), - 'product_id': product.id, - 'location_id': self.supplier_location.id, - 'location_dest_id': loc_dest.id, - 'product_uom': self.uom_unit.id, - 'product_uom_qty': quantity, - 'price_unit': unit_cost, - 'picking_type_id': pick_type.id, - }) - - if create_picking: - picking = self.env['stock.picking'].create({ - 'picking_type_id': in_move.picking_type_id.id, - 'location_id': in_move.location_id.id, - 'location_dest_id': in_move.location_dest_id.id, - }) - in_move.write({'picking_id': picking.id}) - - in_move._action_confirm() - in_move._action_assign() - in_move.move_line_ids.qty_done = quantity - in_move._action_done() - - return in_move.with_context(svl=True) - def test_avco_and_credit_note(self): """ When reversing an invoice that contains some anglo-saxo AML, the new anglo-saxo AML should have the same value @@ -1174,3 +1142,29 @@ class TestAngloSaxonAccounting(AccountTestInvoicingCommon): self.assertEqual(len(anglo_lines), 2) self.assertEqual(abs(anglo_lines[0].balance), 10) self.assertEqual(abs(anglo_lines[1].balance), 10) + + def test_return_delivery_storno(self): + """ When using STORNO accounting, reverse accounting moves should have negative values for credit/debit. + """ + self.env.company.account_storno = True + self.product1.categ_id.property_cost_method = 'fifo' + + self._make_in_move(self.product1, 10, unit_cost=10) + out_move = self._make_out_move(self.product1, 10, create_picking=True) + return_move = self._make_return(out_move, 10) + + valuation_line = out_move.account_move_ids.line_ids.filtered(lambda l: l.account_id == self.stock_valuation_account) + stock_out_line = out_move.account_move_ids.line_ids.filtered(lambda l: l.account_id == self.stock_output_account) + + self.assertEqual(valuation_line.credit, 100) + self.assertEqual(valuation_line.debit, 0) + self.assertEqual(stock_out_line.credit, 0) + self.assertEqual(stock_out_line.debit, 100) + + valuation_line = return_move.account_move_ids.line_ids.filtered(lambda l: l.account_id == self.stock_valuation_account) + stock_out_line = return_move.account_move_ids.line_ids.filtered(lambda l: l.account_id == self.stock_output_account) + + self.assertEqual(valuation_line.credit, -100) + self.assertEqual(valuation_line.debit, 0) + self.assertEqual(stock_out_line.credit, 0) + self.assertEqual(stock_out_line.debit, -100)