diff --git a/addons/stock_account/models/product.py b/addons/stock_account/models/product.py index fc17c917d88..c373dce26d2 100644 --- a/addons/stock_account/models/product.py +++ b/addons/stock_account/models/product.py @@ -648,6 +648,11 @@ class ProductProduct(models.Model): debit_account_id = product_accounts[product.id]['stock_valuation'].id credit_account_id = product_accounts[product.id]['stock_input'].id value = out_stock_valuation_layer.value + if out_stock_valuation_layer.currency_id.compare_amounts(value, 0) < 0: + # Swap accounts makes a negative value in accounting + debit_account_id = product_accounts[product.id]['stock_output'].id + credit_account_id = product_accounts[product.id]['stock_valuation'].id + move_vals = { 'journal_id': product_accounts[product.id]['stock_journal'].id, 'company_id': self.env.company.id, diff --git a/addons/stock_account/tests/test_stockvaluationlayer.py b/addons/stock_account/tests/test_stockvaluationlayer.py index 77b3c62ae9f..2c68e564f88 100644 --- a/addons/stock_account/tests/test_stockvaluationlayer.py +++ b/addons/stock_account/tests/test_stockvaluationlayer.py @@ -939,6 +939,12 @@ class TestStockValuationChangeValuation(TestStockValuationCommon): 'property_stock_journal': cls.stock_journal.id, }) + def _get_stock_account_balance(self, stock_valuation_layer): + """Return the accounting balance from the stock valuation account for the given SVL""" + stock_valuation_account = stock_valuation_layer.product_id.categ_id.property_stock_valuation_account_id + return stock_valuation_layer.account_move_id.line_ids.filtered(lambda line: line.account_id == stock_valuation_account).balance + + def test_standard_manual_to_auto_1(self): self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' self.product1.product_tmpl_id.categ_id.property_valuation = 'manual_periodic' @@ -962,6 +968,9 @@ class TestStockValuationChangeValuation(TestStockValuationCommon): # An accounting entry should only be created for the replenish now that the category is perpetual. self.assertEqual(len(self.product1.stock_valuation_layer_ids.mapped('account_move_id')), 1) self.assertEqual(len(self.product1.stock_valuation_layer_ids), 3) + # Check the entry's value + last_svl = self.product1.stock_valuation_layer_ids.sorted()[-1] + self.assertEqual(self._get_stock_account_balance(last_svl), self.product1.value_svl) for svl in self.product1.stock_valuation_layer_ids.sorted()[-2:]: self.assertEqual(svl.description, 'Valuation method change for product category All: from manual_periodic to real_time.') @@ -996,6 +1005,33 @@ class TestStockValuationChangeValuation(TestStockValuationCommon): # An accounting entry should only be created for the replenish now that the category is perpetual. self.assertEqual(len(self.product1.stock_valuation_layer_ids.mapped('account_move_id')), 1) self.assertEqual(len(self.product1.stock_valuation_layer_ids), 3) + # Check the entry's value + last_svl = self.product1.stock_valuation_layer_ids.sorted()[-1] + self.assertEqual(self._get_stock_account_balance(last_svl), self.product1.value_svl) + + def test_standard_manual_to_auto_3(self): + self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard' + self.product1.product_tmpl_id.categ_id.property_valuation = 'manual_periodic' + self.product1.product_tmpl_id.standard_price = 10 + self._make_out_move(self.product1, 10, force_assign=True) + + self.assertEqual(self.product1.value_svl, -100) + self.assertEqual(self.product1.quantity_svl, -10) + self.assertEqual(len(self.product1.stock_valuation_layer_ids.account_move_id), 0) + self.assertEqual(len(self.product1.stock_valuation_layer_ids), 1) + + self.product1.product_tmpl_id.categ_id.property_valuation = 'real_time' + + self.assertEqual(self.product1.value_svl, -100) + self.assertEqual(self.product1.quantity_svl, -10) + # An accounting entry should only be created for the replenish now that the category is perpetual. + self.assertEqual(len(self.product1.stock_valuation_layer_ids.account_move_id), 1) + self.assertEqual(len(self.product1.stock_valuation_layer_ids), 3) + # Check the entry's value + last_svl = self.product1.stock_valuation_layer_ids.sorted()[-1] + self.assertEqual(self._get_stock_account_balance(last_svl), self.product1.value_svl) + for svl in self.product1.stock_valuation_layer_ids.sorted()[-2:]: + self.assertEqual(svl.description, 'Valuation method change for product category All: from manual_periodic to real_time.') def test_standard_auto_to_manual_1(self): self.product1.product_tmpl_id.categ_id.property_cost_method = 'standard'