[FIX] mrp_account: copy extra_cost to backorder

In a subcontracting flow, a production order is created to reflect the
subcontractor work. An extra cost is set on this production order
corresponding to the purchase order line price unit. If the
subcontracting product is tracked, we may create some backorder to save
all the lot/serial numbers. As the extra_cost is not copied, the first
lot/serial number will have the corresponding stock valuation layer with
the correct quantity. The following ones will only have the cost of the
components as value.

closes odoo/odoo#69245

Opw: 2487450
X-original-commit: 262c2ba8773c698ccde499b095794ab0fc780699
Signed-off-by: Arnold Moyaux <amoyaux@users.noreply.github.com>
Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
This commit is contained in:
William Henrotin
2021-04-14 15:05:37 +00:00
parent 82526e8a1f
commit 67e575e6fd
2 changed files with 74 additions and 0 deletions
@@ -70,6 +70,11 @@ class MrpProduction(models.Model):
# able to produce orders
AccountAnalyticLine.create(vals)
def _get_backorder_mo_vals(self):
res = super()._get_backorder_mo_vals()
res['extra_cost'] = self.extra_cost
return res
def button_mark_done(self):
res = super(MrpProduction, self).button_mark_done()
for order in self:
@@ -63,3 +63,72 @@ class TestAccountSubcontractingFlows(TestMrpSubcontractingCommon):
self.assertEqual(mo.move_finished_ids.stock_valuation_layer_ids.value, 60)
self.assertEqual(picking_receipt.move_lines.stock_valuation_layer_ids.value, 0)
self.assertEqual(picking_receipt.move_lines.product_id.value_svl, 60)
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
ensure the extra cost asked from the subcontractor is added correctly on all the finished
product valuation layer. Not only the first one. """
todo_nb = 4
self.comp2.tracking = 'lot'
self.comp1.tracking = 'serial'
self.comp2.standard_price = 100
self.finished.tracking = 'serial'
self.env.ref('product.product_category_all').property_cost_method = 'fifo'
# Create a receipt picking from the subcontractor
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 = todo_nb
picking_receipt = picking_form.save()
# Mimic the extra cost on the po line
picking_receipt.move_lines.price_unit = 50
picking_receipt.action_confirm()
# We should be able to call the 'record_components' button
self.assertTrue(picking_receipt.display_action_record_components)
lot_comp2 = self.env['stock.production.lot'].create({
'name': 'lot_comp2',
'product_id': self.comp2.id,
'company_id': self.env.company.id,
})
serials_finished = []
serials_comp1 = []
for i in range(todo_nb):
serials_finished.append(self.env['stock.production.lot'].create({
'name': 'serial_fin_%s' % i,
'product_id': self.finished.id,
'company_id': self.env.company.id,
}))
serials_comp1.append(self.env['stock.production.lot'].create({
'name': 'serials_comp1_%s' % i,
'product_id': self.comp1.id,
'company_id': self.env.company.id,
}))
for i in range(todo_nb):
action = picking_receipt.action_record_components()
mo = self.env['mrp.production'].browse(action['res_id'])
mo_form = Form(mo.with_context(**action['context']), view=action['view_id'])
mo_form.lot_producing_id = serials_finished[i]
with mo_form.move_line_raw_ids.edit(0) as ml:
self.assertEqual(ml.product_id, self.comp1)
ml.lot_id = serials_comp1[i]
with mo_form.move_line_raw_ids.edit(1) as ml:
self.assertEqual(ml.product_id, self.comp2)
ml.lot_id = lot_comp2
mo = mo_form.save()
mo.subcontracting_record_component()
# We should not be able to call the 'record_components' button
picking_receipt.button_validate()
f_layers = self.finished.stock_valuation_layer_ids
self.assertEqual(len(f_layers), 4)
for layer in f_layers:
self.assertEqual(layer.value, 100 + 50)