[FIX] stock_account:make cogs multi_company safe

The aim of this commit is to make the cogs generation multi-company
safe.

2 bugs are fixed in this forwardport commit:
- The product.valuation on the line wasn't evaluated in a company safe
way.
- cogs method weren't company safe either

Before this commit:
- When posting an invoice from company B with both company A and B
selected and A being selected as "main", the cost from company A could
be selected instead of cost from company A to create the anglosaxon
lines.

- If company B's product isn't in real time valuation, cogs aren't even
created.

After this commit:
Whatever the selected companies are, the cost selected will always be from
the company that created the invoice.

closes odoo/odoo#81492

Task: #2686104 and #2713607
X-original-commit: e34caf0ec33a3001bb6343e02d34a6edb5a9f609
Signed-off-by: Laurent Smet <las@odoo.com>
Signed-off-by: Brice Bartoletti <bib@odoo.com>
This commit is contained in:
Brice bib Bartoletti
2021-12-15 22:31:24 +00:00
parent 0292e369fe
commit 078981a4c6
6 changed files with 46 additions and 13 deletions
+1 -1
View File
@@ -223,7 +223,7 @@ class PosOrder(models.Model):
.mapped('picking_ids.move_ids')\
._filter_anglo_saxon_moves(product)\
.sorted(lambda x: x.date)
price_unit = product._compute_average_price(0, quantity, moves)
price_unit = product.with_company(self.company_id)._compute_average_price(0, quantity, moves)
return price_unit
name = fields.Char(string='Order Ref', required=True, readonly=True, copy=False, default='/')
+1 -2
View File
@@ -26,8 +26,7 @@ class AccountMoveLine(models.Model):
prod_moves = moves.filtered(lambda m: m.product_id == product)
prod_qty_invoiced = factor * qty_invoiced
prod_qty_to_invoice = factor * qty_to_invoice
average_price_unit += factor * product._compute_average_price(prod_qty_invoiced, prod_qty_to_invoice, prod_moves)
average_price_unit += factor * product.with_company(self.company_id)._compute_average_price(prod_qty_invoiced, prod_qty_to_invoice, prod_moves)
price_unit = average_price_unit / bom.product_qty or price_unit
price_unit = self.product_id.uom_id._compute_price(price_unit, self.product_uom_id)
return price_unit
+2 -4
View File
@@ -110,7 +110,6 @@ class AccountMoveLine(models.Model):
self.ensure_one()
return not self.is_anglo_saxon_line and super(AccountMoveLine, self)._sale_can_be_reinvoice()
def _stock_account_get_anglo_saxon_price_unit(self):
self.ensure_one()
price_unit = super(AccountMoveLine, self)._stock_account_get_anglo_saxon_price_unit()
@@ -119,9 +118,8 @@ class AccountMoveLine(models.Model):
if so_line:
qty_to_invoice = self.product_uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
qty_invoiced = sum([x.product_uom_id._compute_quantity(x.quantity, x.product_id.uom_id) for x in so_line.invoice_lines if x.move_id.state == 'posted'])
average_price_unit = self.product_id._compute_average_price(qty_invoiced, qty_to_invoice, so_line.move_ids)
average_price_unit = self.product_id.with_company(self.company_id)._compute_average_price(qty_invoiced, qty_to_invoice, so_line.move_ids)
if average_price_unit:
price_unit = self.product_id.uom_id._compute_price(average_price_unit, self.product_uom_id)
price_unit = self.product_id.uom_id.with_company(self.company_id)._compute_price(average_price_unit, self.product_uom_id)
return price_unit
+1
View File
@@ -3,6 +3,7 @@
from . import test_anglo_saxon_valuation
from . import test_anglo_saxon_valuation_reconciliation
from . import test_anglosaxon_account
from . import test_sale_stock
from . import test_sale_stock_lead_time
from . import test_sale_stock_report
@@ -0,0 +1,36 @@
# -*- coding: utf-8 -*-
from odoo.addons.sale_stock.tests.test_anglo_saxon_valuation_reconciliation import TestValuationReconciliation
from odoo.tests import tagged
@tagged('post_install', '-at_install')
class TestAngloSaxonAccounting(TestValuationReconciliation):
def test_cogs_should_use_price_from_the_right_company(self):
"""
Reproduce the flow of creating an invoice from a sale order with company A
and posting the invoice with both companies selected and company B as the main.
"""
company_a_data = self.company_data
company_b_data = self.company_data_2
companies_with_b_first = company_b_data['company'] + company_a_data['company']
product = self.test_product_delivery
# set different cost price for the same product in the 2 companies
company_a_standard_price = 20.0
product.with_company(company_a_data['company']).standard_price = company_a_standard_price
company_b_standard_price = 10.0
product.with_company(company_b_data['company']).standard_price = company_b_standard_price
# create sale order with company A in draft (by default, self.env.user.company_id is company A)
company_a_order = self._create_sale(product, '2021-01-01')
company_a_invoice = self._create_invoice_for_so(company_a_order, product, '2021-01-10')
# Post the invoice from company A with company B
company_a_invoice.with_context(allowed_company_ids=companies_with_b_first.ids).action_post()
# check cost used for anglo_saxon_line is from company A
anglo_saxon_lines = company_a_invoice.line_ids.filtered('is_anglo_saxon_line')
self.assertRecordValues(anglo_saxon_lines, [
{'debit': 0.0, 'credit': company_a_standard_price},
{'debit': company_a_standard_price, 'credit': 0.0},
])
+5 -6
View File
@@ -106,6 +106,9 @@ class AccountMove(models.Model):
'''
lines_vals_list = []
for move in self:
# Make the loop multi-company safe when accessing models like product.product
move = move.with_company(move.company_id)
if not move.is_sale_document(include_receipts=True) or not move.company_id.anglo_saxon_accounting:
continue
@@ -116,11 +119,7 @@ class AccountMove(models.Model):
continue
# Retrieve accounts needed to generate the COGS.
accounts = (
line.product_id.product_tmpl_id
.with_company(line.company_id)
.get_product_accounts(fiscal_pos=move.fiscal_position_id)
)
accounts = line.product_id.product_tmpl_id.get_product_accounts(fiscal_pos=move.fiscal_position_id)
debit_interim_account = accounts['stock_output']
credit_expense_account = accounts['expense'] or self.journal_id.default_account_id
if not debit_interim_account or not credit_expense_account:
@@ -241,4 +240,4 @@ class AccountMoveLine(models.Model):
self.ensure_one()
if not self.product_id:
return self.price_unit
return self.product_id._stock_account_get_anglo_saxon_price_unit(uom=self.product_uom_id)
return self.product_id.with_company(self.company_id)._stock_account_get_anglo_saxon_price_unit(uom=self.product_uom_id)