[IMP] mrp_subcontracting{, _dropshipping}: split subcontracting account move
Considering a subcontracting use case where: component cost = 50 service cost = 100 we post: |account, |debit, |credit ----------------------------------------------- Receipt Component from vendor |Stock Valuation |50 | |Stock Input | |50 ----------------------------------------------- Invoice Component from vendor |Stock Input |50 | |Payable | |50 ----------------------------------------------- Resupply Component to subcontractor |Stock Valuation | |50 |Stock Output |50 | ---------------------------------------------- Receive Final from subcontractor |Stock Valuation |150 | |Stock Input | |150 ---------------------------------------------- Invoice Final from subcontractor |Stock Input |100 | |Payable | |100 ----------------------------------------------- Deliver Final to client |Stock Valuation | |150 |Stock Output |150 | ----------------------------------------------- Invoice Client |Stock Output | |150 |Receivable |150 | Stock Input/Output account are not balanced. In this commit, we split the credit value when received final from subcontractor to make them balanced. |account, |debit, |credit ----------------------------------------------- Receipt Component from vendor |Stock Valuation |50 | |Stock Input | |50 ----------------------------------------------- Invoice Component from vendor |Stock Input |50 | |Payable | |50 ----------------------------------------------- Resupply Component to subcontractor |Stock Valuation | |50 |Stock Output |50 | ---------------------------------------------- Receive Final from subcontractor |Stock Valuation |150 | |Stock Input | |100 |Stock Output | |50 ---------------------------------------------- Invoice Final from subcontractor |Stock Input |100 | |Payable | |100 ----------------------------------------------- Deliver Final to client |Stock Valuation | |150 |Stock Output |150 | ----------------------------------------------- Invoice Client |Stock Output | |150 |Receivable |150 | --- closes odoo/odoo#113853 Signed-off-by: Arnold Moyaux (arm) <arm@odoo.com>
This commit is contained in:
@@ -10,3 +10,38 @@ class StockMove(models.Model):
|
||||
def _should_force_price_unit(self):
|
||||
self.ensure_one()
|
||||
return self.is_subcontract or super()._should_force_price_unit()
|
||||
|
||||
def _generate_valuation_lines_data(self, partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, svl_id, description):
|
||||
rslt = super()._generate_valuation_lines_data(partner_id, qty, debit_value, credit_value, debit_account_id, credit_account_id, svl_id, description)
|
||||
|
||||
subcontract_production = self.production_id.filtered(lambda p: p.subcontractor_id)
|
||||
if not subcontract_production:
|
||||
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 not currency.is_zero(subcontract_service_cost):
|
||||
del rslt['credit_line_vals']
|
||||
component_cost = -credit_value + subcontract_service_cost
|
||||
component_cost_account = self.product_id.product_tmpl_id.get_product_accounts()['stock_output']
|
||||
rslt['subcontract_credit_line_vals'] = {
|
||||
'name': description,
|
||||
'product_id': self.product_id.id,
|
||||
'quantity': qty,
|
||||
'product_uom_id': self.product_id.uom_id.id,
|
||||
'ref': description,
|
||||
'partner_id': partner_id,
|
||||
'balance': -subcontract_service_cost,
|
||||
'account_id': credit_account_id,
|
||||
}
|
||||
rslt['component_credit_line_vals'] = {
|
||||
'name': description,
|
||||
'product_id': self.product_id.id,
|
||||
'quantity': qty,
|
||||
'product_uom_id': self.product_id.uom_id.id,
|
||||
'ref': description,
|
||||
'partner_id': partner_id,
|
||||
'balance': component_cost,
|
||||
'account_id': component_cost_account.id,
|
||||
}
|
||||
return rslt
|
||||
|
||||
@@ -8,13 +8,20 @@ from odoo.tools.float_utils import float_round, float_compare
|
||||
from odoo.addons.mrp_subcontracting.tests.common import TestMrpSubcontractingCommon
|
||||
from odoo.addons.mrp_account.tests.test_bom_price import TestBomPriceCommon
|
||||
|
||||
|
||||
class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
def test_subcontracting_account_flow_1(self):
|
||||
# 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')
|
||||
self.env.ref('product.product_category_all').property_cost_method = 'fifo'
|
||||
product_category_all = self.env.ref('product.product_category_all')
|
||||
product_category_all.property_cost_method = 'fifo'
|
||||
product_category_all.property_valuation = 'real_time'
|
||||
stock_in_acc_id = product_category_all.property_stock_account_input_categ_id.id
|
||||
stock_out_acc_id = product_category_all.property_stock_account_output_categ_id.id
|
||||
stock_valu_acc_id = product_category_all.property_stock_valuation_account_id.id
|
||||
|
||||
# IN 10@10 comp1 10@20 comp2
|
||||
move1 = self.env['stock.move'].create({
|
||||
@@ -44,6 +51,8 @@ class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
move2.move_line_ids.qty_done = 10.0
|
||||
move2._action_done()
|
||||
|
||||
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
|
||||
@@ -70,6 +79,21 @@ class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
self.assertEqual(picking_receipt.move_ids.stock_valuation_layer_ids.value, 0)
|
||||
self.assertEqual(picking_receipt.move_ids.product_id.value_svl, 60)
|
||||
|
||||
amls = self.env['account.move.line'].search([('id', 'not in', all_amls_ids)])
|
||||
all_amls_ids += amls.ids
|
||||
self.assertRecordValues(amls, [
|
||||
# Receipt from subcontractor
|
||||
{'account_id': stock_valu_acc_id, 'product_id': self.finished.id, 'debit': 60.0, 'credit': 0.0},
|
||||
{'account_id': stock_in_acc_id, 'product_id': self.finished.id, 'debit': 0.0, 'credit': 30.0},
|
||||
{'account_id': stock_out_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_out_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_out_acc_id, 'product_id': self.comp1.id, 'debit': 10.0, 'credit': 0.0},
|
||||
])
|
||||
|
||||
# Do the same without any additionnal cost
|
||||
picking_form = Form(self.env['stock.picking'])
|
||||
picking_form.picking_type_id = self.env.ref('stock.picking_type_in')
|
||||
@@ -90,6 +114,19 @@ class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
|
||||
self.assertEqual(mo.move_finished_ids.stock_valuation_layer_ids.value, 30)
|
||||
self.assertEqual(picking_receipt.move_ids.product_id.value_svl, 90)
|
||||
|
||||
amls = self.env['account.move.line'].search([('id', 'not in', all_amls_ids)])
|
||||
self.assertRecordValues(amls, [
|
||||
# Receipt from subcontractor
|
||||
{'account_id': stock_in_acc_id, 'product_id': self.finished.id, 'debit': 0.0, 'credit': 30.0},
|
||||
{'account_id': stock_valu_acc_id, 'product_id': self.finished.id, 'debit': 30.0, 'credit': 0.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_out_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_out_acc_id, 'product_id': self.comp1.id, 'debit': 10.0, 'credit': 0.0},
|
||||
])
|
||||
|
||||
def test_subcontracting_account_backorder(self):
|
||||
""" This test uses tracked (serial and lot) component and tracked (serial) finished product
|
||||
The original subcontracting production order will be split into 4 backorders. This test
|
||||
|
||||
@@ -83,8 +83,9 @@ class TestSubcontractingDropshippingValuation(ValuationReconciliationTestCommon)
|
||||
{'account_id': stock_valu_acc_id, 'product_id': self.product_a.id, 'debit': 0.0, 'credit': 20.0},
|
||||
{'account_id': stock_out_acc_id, 'product_id': self.product_a.id, 'debit': 20.0, 'credit': 0.0},
|
||||
# Receipt from subcontractor
|
||||
{'account_id': stock_in_acc_id, 'product_id': self.product_a.id, 'debit': 0.0, 'credit': 220.0},
|
||||
{'account_id': stock_valu_acc_id, 'product_id': self.product_a.id, 'debit': 220.0, 'credit': 0.0},
|
||||
{'account_id': stock_in_acc_id, 'product_id': self.product_a.id, 'debit': 0.0, 'credit': 200.0},
|
||||
{'account_id': stock_out_acc_id, 'product_id': self.product_a.id, 'debit': 0.0, 'credit': 20.0},
|
||||
# Delivery to subcontractor
|
||||
{'account_id': stock_valu_acc_id, 'product_id': self.product_b.id, 'debit': 0.0, 'credit': 20.0},
|
||||
{'account_id': stock_out_acc_id, 'product_id': self.product_b.id, 'debit': 20.0, 'credit': 0.0},
|
||||
|
||||
Reference in New Issue
Block a user