From e9528d87419205d85b491a38edf1d95fff20dadc Mon Sep 17 00:00:00 2001 From: "Adrien Widart (awt)" Date: Wed, 5 Apr 2023 15:17:59 +0000 Subject: [PATCH] [FIX] stock_landed_costs: set AML's account on its creation To reproduce the issue: 1. create a product category with inventory valuation set as Manual 2. create a landed cost product using above category 3. enable anglo saxon accounting in accounting settings 4. create a vendor bill with this product and click save Error: An error is displayed because of a missing account When creating the AML, `_compute_account_id` tries to find the appropriate account. However, for a landed cost, it always use the the stock accounts, even if they are not defined. We should rather recycle `/stock_account._compute_account_id` which already handle such a situation. OPW-3251714 closes odoo/odoo#119564 X-original-commit: 9416be3cbe630ed693a0285f203e1de9f45acc7a Signed-off-by: William Henrotin (whe) Signed-off-by: Adrien Widart --- addons/stock_account/models/account_move.py | 5 +- .../stock_landed_costs/models/account_move.py | 10 ++-- .../tests/test_stock_landed_costs.py | 50 +++++++++++++++++++ .../tests/test_stockvaluationlayer.py | 2 + 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/addons/stock_account/models/account_move.py b/addons/stock_account/models/account_move.py index 64d1bea1ec1..d0d8b24289b 100644 --- a/addons/stock_account/models/account_move.py +++ b/addons/stock_account/models/account_move.py @@ -263,7 +263,7 @@ class AccountMoveLine(models.Model): def _compute_account_id(self): super()._compute_account_id() input_lines = self.filtered(lambda line: ( - line.product_id.type == 'product' + line._can_use_stock_accounts() and line.move_id.company_id.anglo_saxon_accounting and line.move_id.is_purchase_document() )) @@ -394,6 +394,9 @@ class AccountMoveLine(models.Model): return svl_vals_list + def _can_use_stock_accounts(self): + return self.product_id.type == 'product' + def _stock_account_get_anglo_saxon_price_unit(self): self.ensure_one() if not self.product_id: diff --git a/addons/stock_landed_costs/models/account_move.py b/addons/stock_landed_costs/models/account_move.py index 1b75e669e23..00e1caffc56 100644 --- a/addons/stock_landed_costs/models/account_move.py +++ b/addons/stock_landed_costs/models/account_move.py @@ -53,13 +53,6 @@ class AccountMoveLine(models.Model): product_type = fields.Selection(related='product_id.detailed_type', readonly=True) is_landed_costs_line = fields.Boolean() - @api.depends('is_landed_costs_line') - def _compute_account_id(self): - landed_costs_lines = self.filtered(lambda l: l.is_landed_costs_line and l.move_id.company_id.anglo_saxon_accounting) - for line in landed_costs_lines: - line.account_id = line.product_id.product_tmpl_id._get_product_accounts()['stock_input'] - super(AccountMoveLine, self - landed_costs_lines)._compute_account_id() - @api.onchange('product_id') def _onchange_product_id_landed_costs(self): if self.product_id.landed_cost_ok: @@ -75,3 +68,6 @@ class AccountMoveLine(models.Model): def _get_stock_valuation_layers(self, move): layers = super()._get_stock_valuation_layers(move) return layers.filtered(lambda svl: not svl.stock_landed_cost_id) + + def _can_use_stock_accounts(self): + return super()._can_use_stock_accounts() or (self.product_id.type == 'service' and self.product_id.landed_cost_ok) diff --git a/addons/stock_landed_costs/tests/test_stock_landed_costs.py b/addons/stock_landed_costs/tests/test_stock_landed_costs.py index b7cba600258..d44c30aab32 100644 --- a/addons/stock_landed_costs/tests/test_stock_landed_costs.py +++ b/addons/stock_landed_costs/tests/test_stock_landed_costs.py @@ -4,6 +4,7 @@ from odoo.addons.stock_landed_costs.tests.common import TestStockLandedCostsCommon from odoo.exceptions import ValidationError from odoo.tests import tagged +from odoo import fields @tagged('post_install', '-at_install') @@ -159,3 +160,52 @@ class TestStockLandedCosts(TestStockLandedCostsCommon): self.assertEqual(len(picking_landed_cost_1.move_ids.stock_valuation_layer_ids), 5) self.assertEqual(len(picking_landed_cost_2.move_ids.stock_valuation_layer_ids), 5) + + def test_aml_account_selection(self): + """ + Process a PO with a landed cost, then create and post the bill. The + account of the landed cost AML should be: + - Expense if the categ valuation is manual + - Stock IN if the categ valuation is real time + """ + self.landed_cost.landed_cost_ok = True + + for valuation in ['manual_periodic', 'real_time']: + self.landed_cost.categ_id.property_valuation = valuation + account_name = 'stock_input' if valuation == 'real_time' else 'expense' + account = self.landed_cost.product_tmpl_id.get_product_accounts()[account_name] + po = self.env['purchase.order'].create({ + 'partner_id': self.partner_a.id, + 'currency_id': self.company_data['currency'].id, + 'order_line': [ + (0, 0, { + 'name': self.product_a.name, + 'product_id': self.product_a.id, + 'product_qty': 1.0, + 'product_uom': self.product_a.uom_po_id.id, + 'price_unit': 100.0, + 'taxes_id': False, + }), + (0, 0, { + 'name': self.landed_cost.name, + 'product_id': self.landed_cost.id, + 'product_qty': 1.0, + 'price_unit': 100.0, + }), + ], + }) + po.button_confirm() + + receipt = po.picking_ids + receipt.move_ids.quantity_done = 1 + receipt.button_validate() + po.order_line[1].qty_received = 1 + + po.action_create_invoice() + bill = po.invoice_ids + bill.invoice_date = fields.Date.today() + bill._post() + + landed_cost_aml = bill.invoice_line_ids.filtered(lambda l: l.product_id == self.landed_cost) + self.assertEqual(bill.state, 'posted', 'Incorrect value with valuation %s' % valuation) + self.assertEqual(landed_cost_aml.account_id, account, 'Incorrect value with valuation %s' % valuation) diff --git a/addons/stock_landed_costs/tests/test_stockvaluationlayer.py b/addons/stock_landed_costs/tests/test_stockvaluationlayer.py index adab1849497..88c8cb737e5 100644 --- a/addons/stock_landed_costs/tests/test_stockvaluationlayer.py +++ b/addons/stock_landed_costs/tests/test_stockvaluationlayer.py @@ -22,6 +22,7 @@ class TestStockValuationLCCommon(TestStockLandedCostsCommon): 'name': 'product1', 'type': 'service', 'categ_id': cls.stock_account_product_categ.id, + 'landed_cost_ok': True, }) def setUp(self): @@ -434,6 +435,7 @@ class TestStockValuationLCFIFOVB(TestStockValuationLCCommon): vb = Form(self.env['account.move'].with_context(default_move_type='in_invoice')) vb.partner_id = self.vendor1 vb.invoice_date = vb.date + self.productlc1.landed_cost_ok = True with vb.invoice_line_ids.new() as inv_line: inv_line.product_id = self.productlc1 inv_line.price_unit = 50