[FIX] stock_account: anglo-saxon accounting & storno
First issue: post a credit note Steps to reproduce: - enable anglo-saxon accounting and storno - create a storable product with sale price = 50 and cost = 30 - set costing method FIFO and automated inventory valuation on product category - create a credit note using this product - post credit note Error: There was a problem with the following move(s): - Move with id 18 The debit and credit should be negative and only one can be set Second issue: return a product In anglo-saxon accounting, returning a product means creating a reverse move. Reverse move in storno should have a negative debit/credit. opw-3110934 closes odoo/odoo#114671 X-original-commit: f24a87b1d0bb3a18ef1d2d4cd23fb34bf29d4bfb Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user