[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:
@@ -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='/')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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},
|
||||
])
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user