Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] mrp_workorder: various fixes #31132

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 3 additions & 4 deletions addons/mrp/models/mrp_abstract_workorder.py
Expand Up @@ -84,10 +84,9 @@ def _update_workorder_lines(self):
for move_line in move_raw.move_line_ids:
# Get workorder lines that match reservation.
candidates = move_workorder_lines._find_candidate(move_line)
while candidates:
for candidate in candidates:
if float_compare(qty_todo, 0, precision_rounding=rounding) <= 0:
break
candidate = candidates.pop()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these three lines in a single commit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also this should traceback and the branch is green... add a testcase please :(

qty_to_add = move_line.product_uom_qty - candidate.qty_done
line_values['to_update'][candidate] = {
'qty_done': candidate.qty_done + qty_to_add,
Expand Down Expand Up @@ -136,7 +135,7 @@ def _generate_lines_values(self, move, qty_to_consume):
'qty_to_consume': to_consume_in_line,
'qty_reserved': move_line.product_uom_qty,
'lot_id': move_line.lot_id.id,
'qty_done': is_tracked and 0 or to_consume_in_line
'qty_done': to_consume_in_line
}
lines.append(line)
qty_to_consume -= to_consume_in_line
Expand All @@ -159,7 +158,7 @@ def _generate_lines_values(self, move, qty_to_consume):
'product_id': move.product_id.id,
'product_uom_id': move.product_uom.id,
'qty_to_consume': qty_to_consume,
'qty_done': is_tracked and 0 or qty_to_consume
'qty_done': qty_to_consume
}
lines.append(line)
return lines
Expand Down
7 changes: 4 additions & 3 deletions addons/mrp/models/mrp_production.py
Expand Up @@ -605,7 +605,8 @@ def action_confirm(self):
for move_raw in production.move_raw_ids:
move_raw.write({
'group_id': production.procurement_group_id.id,
'unit_factor': move_raw.product_uom_qty / production.product_qty
'unit_factor': move_raw.product_uom_qty / production.product_qty,
'reference': self.name, # set reference when MO name is different than 'New'
})
production._generate_finished_moves()
production.move_raw_ids._adjust_procure_method()
Expand Down Expand Up @@ -825,8 +826,8 @@ def post_inventory(self):
moves_to_finish = order.move_finished_ids.filtered(lambda x: x.state not in ('done','cancel'))
moves_to_finish._action_done()
order.action_assign()
consume_move_lines = moves_to_do.mapped('active_move_line_ids')
for moveline in moves_to_finish.mapped('active_move_line_ids'):
consume_move_lines = moves_to_do.mapped('move_line_ids')
for moveline in moves_to_finish.mapped('move_line_ids'):
if moveline.product_id == order.product_id and moveline.move_id.has_tracking != 'none':
if any([not ml.lot_produced_id for ml in consume_move_lines]):
raise UserError(_('You can not consume without telling for which lot you consumed it'))
Expand Down
7 changes: 0 additions & 7 deletions addons/mrp/models/mrp_workorder.py
Expand Up @@ -209,9 +209,6 @@ def _get_byproduct_move_line(self, by_product_move, quantity):
'location_dest_id': by_product_move.location_dest_id.id,
}

def _link_to_quality_check(self, old_move_line, new_move_line):
return True

@api.multi
def record_production(self):
if not self:
Expand All @@ -229,10 +226,6 @@ def record_production(self):
# TODO: should be same as checking if for every workorder something has been done?
if not self.next_work_order_id:
self._update_finished_move()
self.production_id.move_finished_ids.filtered(
lambda move: move.product_id == self.product_id and
move.state not in ('done', 'cancel')
).workorder_id = self.id

# Transfer quantities from temporary to final move line or make them final
self._update_raw_moves()
Expand Down
20 changes: 3 additions & 17 deletions addons/mrp/models/stock_move.py
Expand Up @@ -16,20 +16,18 @@ class StockMoveLine(models.Model):
lot_produced_qty = fields.Float(
'Quantity Finished Product', digits=dp.get_precision('Product Unit of Measure'),
help="Informative, not used in matching")
done_wo = fields.Boolean('Done for Work Order', default=True, help="Technical Field which is False when temporarily filled in in work order") # TDE FIXME: naming
done_move = fields.Boolean('Move Done', related='move_id.is_done', readonly=False, store=True) # TDE FIXME: naming

def _get_similar_move_lines(self):
lines = super(StockMoveLine, self)._get_similar_move_lines()
if self.move_id.production_id:
finished_moves = self.move_id.production_id.move_finished_ids
finished_move_lines = finished_moves.mapped('move_line_ids')
lines |= finished_move_lines.filtered(lambda ml: ml.product_id == self.product_id and (ml.lot_id or ml.lot_name) and ml.done_wo == self.done_wo)
lines |= finished_move_lines.filtered(lambda ml: ml.product_id == self.product_id and (ml.lot_id or ml.lot_name))
if self.move_id.raw_material_production_id:
raw_moves = self.move_id.raw_material_production_id.move_raw_ids
raw_moves_lines = raw_moves.mapped('move_line_ids')
raw_moves_lines |= self.move_id.active_move_line_ids
lines |= raw_moves_lines.filtered(lambda ml: ml.product_id == self.product_id and (ml.lot_id or ml.lot_name) and ml.done_wo == self.done_wo)
lines |= raw_moves_lines.filtered(lambda ml: ml.product_id == self.product_id and (ml.lot_id or ml.lot_name))
return lines

def _reservation_is_updatable(self, quantity, reserved_quant):
Expand All @@ -46,7 +44,7 @@ def write(self, vals):
for move_line in self:
if move_line.move_id.production_id and 'lot_id' in vals:
move_line.production_id.move_raw_ids.mapped('move_line_ids')\
.filtered(lambda r: r.done_wo and not r.done_move and r.lot_produced_id == move_line.lot_id)\
.filtered(lambda r: not r.done_move and r.lot_produced_id == move_line.lot_id)\
.write({'lot_produced_id': vals['lot_id']})
production = move_line.move_id.production_id or move_line.move_id.raw_material_production_id
if production and move_line.state == 'done' and any(field in vals for field in ('lot_id', 'location_id', 'qty_done')):
Expand All @@ -71,7 +69,6 @@ class StockMove(models.Model):
workorder_id = fields.Many2one(
'mrp.workorder', 'Work Order To Consume')
# Quantities to process, in normalized UoMs
active_move_line_ids = fields.One2many('stock.move.line', 'move_id', domain=[('done_wo', '=', True)], string='Lots')
bom_line_id = fields.Many2one('mrp.bom.line', 'BoM Line')
unit_factor = fields.Float('Unit Factor')
is_done = fields.Boolean(
Expand All @@ -89,10 +86,6 @@ def _unreserve_initial_demand(self, new_move):
.filtered(lambda ml: ml.qty_done == 0.0)\
.write({'move_id': new_move, 'product_uom_qty': 0})

@api.depends('active_move_line_ids.qty_done', 'active_move_line_ids.product_uom_id')
def _compute_done_quantity(self):
super(StockMove, self)._compute_done_quantity()

@api.depends('raw_material_production_id.move_finished_ids.move_line_ids.lot_id')
def _compute_order_finished_lot_ids(self):
for move in self:
Expand All @@ -116,13 +109,6 @@ def _compute_is_locked(self):
if move.raw_material_production_id:
move.is_locked = move.raw_material_production_id.is_locked

def _get_move_lines(self):
self.ensure_one()
if self.raw_material_production_id:
return self.active_move_line_ids
else:
return super(StockMove, self)._get_move_lines()

@api.depends('state')
def _compute_is_done(self):
for move in self:
Expand Down
26 changes: 26 additions & 0 deletions addons/mrp/tests/test_order.py
Expand Up @@ -676,6 +676,32 @@ def test_product_produce_5(self):
self.assertEqual(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).quantity_done, 20, 'Update the produce quantity should not impact already produced quantity.')
mo.button_mark_done()

def test_product_produce_6(self):
""" Build some final products and change the quantity to produce
directly in the wizard. The component line should be updated .
"""
self.stock_location = self.env.ref('stock.stock_location_stock')
mo, bom, p_final, p1, p2 = self.generate_mo(qty_final=1)
self.assertEqual(len(mo), 1, 'MO should have been created')

mo.action_assign()

produce_form = Form(self.env['mrp.product.produce'].with_context({
'active_id': mo.id,
'active_ids': [mo.id],
}))
produce_form.qty_producing = 3
self.assertEqual(len(produce_form.workorder_line_ids._records), 4, 'Update the produce quantity should change the components quantity.')
self.assertEqual(sum([x['qty_done'] for x in produce_form.workorder_line_ids._records]), 15, 'Update the produce quantity should change the components quantity.')
produce_form.qty_producing = 4
self.assertEqual(len(produce_form.workorder_line_ids._records), 6, 'Update the produce quantity should change the components quantity.')
self.assertEqual(sum([x['qty_done'] for x in produce_form.workorder_line_ids._records]), 20, 'Update the produce quantity should change the components quantity.')
produce_form.qty_producing = 1
self.assertEqual(len(produce_form.workorder_line_ids._records), 2, 'Update the produce quantity should change the components quantity.')
self.assertEqual(sum([x['qty_done'] for x in produce_form.workorder_line_ids._records]), 5, 'Update the produce quantity should change the components quantity.')
produce_wizard = produce_form.save()
produce_wizard.do_produce()

def test_product_produce_uom(self):
plastic_laminate = self.env.ref('mrp.product_product_plastic_laminate')
bom = self.env.ref('mrp.mrp_bom_plastic_laminate')
Expand Down
3 changes: 1 addition & 2 deletions addons/mrp/views/stock_move_views.xml
Expand Up @@ -49,7 +49,7 @@
<field name="finished_lots_exist" invisible="1"/>
</group>
</group>
<field name="active_move_line_ids" attrs="{'invisible': [('parent.state', '=', 'draft')], 'readonly': [('is_locked', '=', True)]}" context="{'default_workorder_id': workorder_id, 'default_product_uom_id': product_uom, 'default_product_id': product_id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_production_id': production_id or raw_material_production_id}">
<field name="move_line_ids" attrs="{'invisible': [('parent.state', '=', 'draft')], 'readonly': [('is_locked', '=', True)]}" context="{'default_workorder_id': workorder_id, 'default_product_uom_id': product_uom, 'default_product_id': product_id, 'default_location_id': location_id, 'default_location_dest_id': location_dest_id, 'default_production_id': production_id or raw_material_production_id}">
<tree editable="bottom" decoration-success="product_uom_qty==qty_done" decoration-danger="(product_uom_qty &gt; 0) and (qty_done&gt;product_uom_qty)">
<field name="lot_id" attrs="{'column_invisible': [('parent.has_tracking', '=', 'none')]}" domain="[('product_id', '=', parent.product_id)]" context="{'default_product_id': parent.product_id}"/>
<field name="lot_produced_id" options="{'no_open': True, 'no_create': True}" domain="[('id', 'in', parent.order_finished_lot_ids)]" invisible="not context.get('final_lots')"/>
Expand All @@ -61,7 +61,6 @@
<field name="product_uom_id" invisible="1"/>
<field name="location_id" invisible="1"/>
<field name="location_dest_id" invisible="1"/>
<field name="done_wo" invisible="1"/>
<field name="production_id" invisible="1"/>
</tree>
</field>
Expand Down