From 42ec2a088a735fed879bcd50f3744031ab45d08e Mon Sep 17 00:00:00 2001
From: "Adrien Widart (awt)" <awt@odoo.com>
Date: Wed, 5 Apr 2023 15:17:59 +0000
Subject: [PATCH] [IMP] stock_landed_costs: set AML's account on its creation

[1] could be improved as we could even remove the `create` override
introduced by [2]. That way, we avoid:
- a useless `create` layer
- a possible write on an AML just after its creation

The method `_get_computed_account` is called during the AML creation
process:
https://github.com/odoo/odoo/blob/8c8d657c85f76bd74d663843382af3dde8d885b8/addons/account/models/account_move.py#L2058
https://github.com/odoo/odoo/blob/8c8d657c85f76bd74d663843382af3dde8d885b8/addons/account/models/account_move.py#L1933

Note: the test checks the use cases of both commits

[1] 66ea264fc2d57de85e92cac4aa5e6ee9cd80e952
[2] f36c5c8adde9a54e46c1a3a7f60d5d1e615a8ebf

OPW-3251714

closes odoo/odoo#117920

Signed-off-by: William Henrotin (whe) <whe@odoo.com>
---
 addons/stock_account/models/account_move.py   |  5 +-
 .../stock_landed_costs/models/account_move.py | 12 ++---
 .../tests/test_stock_landed_costs.py          | 51 +++++++++++++++++++
 3 files changed, 58 insertions(+), 10 deletions(-)

diff --git a/addons/stock_account/models/account_move.py b/addons/stock_account/models/account_move.py
index c08c9dc3cd5e..88d69504770a 100644
--- a/addons/stock_account/models/account_move.py
+++ b/addons/stock_account/models/account_move.py
@@ -222,7 +222,7 @@ class AccountMoveLine(models.Model):
         # with anglo-saxon accounting.
         self.ensure_one()
         self = self.with_company(self.move_id.journal_id.company_id)
-        if self.product_id.type == 'product' \
+        if self._can_use_stock_accounts() \
             and self.move_id.company_id.anglo_saxon_accounting \
             and self.move_id.is_purchase_document():
             fiscal_position = self.move_id.fiscal_position_id
@@ -231,6 +231,9 @@ class AccountMoveLine(models.Model):
                 return accounts['stock_input']
         return super(AccountMoveLine, self)._get_computed_account()
 
+    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 4959eb4ba708..ee6da53822b3 100644
--- a/addons/stock_landed_costs/models/account_move.py
+++ b/addons/stock_landed_costs/models/account_move.py
@@ -53,9 +53,6 @@ class AccountMoveLine(models.Model):
     product_type = fields.Selection(related='product_id.type', readonly=True)
     is_landed_costs_line = fields.Boolean()
 
-    def _get_landed_costs_account(self, accounts):
-        return accounts['stock_input' if self.move_id.company_id.anglo_saxon_accounting else 'expense']
-
     @api.onchange('is_landed_costs_line')
     def _onchange_is_landed_costs_line(self):
         """Mark an invoice line as a landed cost line and adapt `self.account_id`. The default
@@ -66,7 +63,7 @@ class AccountMoveLine(models.Model):
             if self.product_type != 'service':
                 self.is_landed_costs_line = False
             elif self.is_landed_costs_line:
-                aml_account = self._get_landed_costs_account(accounts)
+                aml_account = (self.move_id.company_id.anglo_saxon_accounting and accounts['stock_input']) or aml_account
             self.account_id = aml_account
 
     @api.onchange('product_id')
@@ -76,8 +73,5 @@ class AccountMoveLine(models.Model):
         else:
             self.is_landed_costs_line = False
 
-    def create(self, vals_list):
-        lines = super().create(vals_list)
-        for line in lines.filtered(lambda x: x.is_landed_costs_line and x.product_id.categ_id.property_valuation == 'real_time'):
-            line.account_id = line._get_landed_costs_account(line.product_id.product_tmpl_id._get_product_accounts())
-        return lines
+    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 9e86cdf6c0e7..29df482cc794 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,53 @@ class TestStockLandedCosts(TestStockLandedCostsCommon):
 
         self.assertEqual(len(picking_landed_cost_1.move_lines.stock_valuation_layer_ids), 5)
         self.assertEqual(len(picking_landed_cost_2.move_lines.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, account in [
+            ('manual_periodic', self.company_data['default_account_expense']),
+            ('real_time', self.env.company.property_stock_account_input_categ_id),
+        ]:
+            self.landed_cost.categ_id.property_valuation = valuation
+            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_lines.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)
-- 
GitLab