[FIX] mrp_subcontracting_account: subcontract cost don't match the price

When doing subcontracting with standard price product. If
Final procut cost != Components cost + subcontracting cost
When posting account entries for final product, the amount of componets
entry is adjusted for the difference of the two costs.
After this commit, we will post components cost according to it's price
so that it can match the value change of the stock. We adjust the amount
on subcontracting cost for the cost difference.
NOTE: the remaining of subcontracting cost will be post in price
difference account when create vendor bill.

Task-3223451

X-original-commit: 514f5b51ad30cce0048abb4cf343e830f0288b36
Part-of: odoo/odoo#132282
This commit is contained in:
yhu-odoo
2023-08-19 11:00:59 +02:00
parent be911c2c58
commit 77a8616263
2 changed files with 62 additions and 3 deletions
@@ -19,10 +19,17 @@ class StockMove(models.Model):
return rslt
# split the credit line to two, one for component cost, one for subcontracting service cost
currency = self.company_id.currency_id
subcontract_service_cost = currency.round(subcontract_production.extra_cost * qty)
if self.product_id.cost_method == 'standard':
# In case of standard price, the component cost is the cost of the product
# the subcontracting service cost may not represent the real cost of the subcontracting service
# the difference should be posted in price difference account in the end
component_cost = currency.round(sum(m.price_unit * m.product_uom_qty for m in subcontract_production.move_raw_ids))
subcontract_service_cost = credit_value - component_cost
else:
subcontract_service_cost = currency.round(subcontract_production.extra_cost * qty)
component_cost = credit_value - subcontract_service_cost
if not currency.is_zero(subcontract_service_cost):
del rslt['credit_line_vals']
component_cost = -credit_value + subcontract_service_cost
service_cost_account = self.product_id.product_tmpl_id.get_product_accounts()['stock_input']
rslt['subcontract_credit_line_vals'] = {
'name': description,
@@ -41,7 +48,7 @@ class StockMove(models.Model):
'product_uom_id': self.product_id.uom_id.id,
'ref': description,
'partner_id': partner_id,
'balance': component_cost,
'balance': -component_cost,
'account_id': credit_account_id,
}
return rslt
@@ -336,6 +336,58 @@ class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
{'quantity': 2, 'value': 2 * (10 + 20 + 50)},
])
def test_subcontract_cost_different_when_standard_price(self):
"""Test when subcontracting with standard price when
Final product cost != Components cost + Subcontracting cost
When posting the account entries for receiving final product, the
subcontracting cost will be adjusted based on the difference of the cost.
"""
# pylint: disable=bad-whitespace
self.stock_location = self.env.ref('stock.stock_location_stock')
self.customer_location = self.env.ref('stock.stock_location_customers')
self.supplier_location = self.env.ref('stock.stock_location_suppliers')
self.uom_unit = self.env.ref('uom.product_uom_unit')
product_category_all = self.env.ref('product.product_category_all')
product_category_all.property_cost_method = 'standard'
product_category_all.property_valuation = 'real_time'
stock_in_acc_id = product_category_all.property_stock_account_input_categ_id.id
stock_valu_acc_id = product_category_all.property_stock_valuation_account_id.id
stock_cop_acc_id = product_category_all.property_stock_account_production_cost_id.id
self.comp1.standard_price = 10
self.comp2.standard_price = 20
self.finished.standard_price = 40
all_amls_ids = self.env['account.move.line'].search([]).ids
picking_form = Form(self.env['stock.picking'])
picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
picking_form.partner_id = self.subcontractor_partner1
with picking_form.move_ids_without_package.new() as move:
move.product_id = self.finished
move.product_uom_qty = 1
picking_receipt = picking_form.save()
# subcontracting cost is 15
picking_receipt.move_ids.price_unit = 15.0
picking_receipt.action_confirm()
picking_receipt.move_ids.quantity_done = 1.0
picking_receipt._action_done()
amls = self.env['account.move.line'].search([('id', 'not in', all_amls_ids)])
self.assertRecordValues(amls, [
# Receipt from subcontractor
{'account_id': stock_valu_acc_id, 'product_id': self.finished.id, 'debit': 40.0, 'credit': 0.0},
{'account_id': stock_in_acc_id, 'product_id': self.finished.id, 'debit': 0.0, 'credit': 10.0}, # adjust according to the difference
{'account_id': stock_cop_acc_id, 'product_id': self.finished.id, 'debit': 0.0, 'credit': 30.0},
# Delivery com2 to subcontractor
{'account_id': stock_valu_acc_id, 'product_id': self.comp2.id, 'debit': 0.0, 'credit': 20.0},
{'account_id': stock_cop_acc_id, 'product_id': self.comp2.id, 'debit': 20.0, 'credit': 0.0},
# Delivery com2 to subcontractor
{'account_id': stock_valu_acc_id, 'product_id': self.comp1.id, 'debit': 0.0, 'credit': 10.0},
{'account_id': stock_cop_acc_id, 'product_id': self.comp1.id, 'debit': 10.0, 'credit': 0.0},
])
class TestBomPriceSubcontracting(TestBomPriceCommon):