[IMP] mrp: active_move_lot_ids needed on stock_move as well, not just on workorder
As you open the lots in a raw material move in a production order, you should not see the temporary stock move lots from the work order. Also the quantity_done should not take into account those. They will when they press 'Done' on the workorder. When posting inventory, the temporary stock move lots on the workorder, should be transferred to the split move. For splitting and unreserving, some optimizations are done.
This commit is contained in:
@@ -72,6 +72,7 @@ class StockMove(models.Model):
|
||||
'Quantity', compute='_qty_done_compute', inverse='_qty_done_set',
|
||||
digits=dp.get_precision('Product Unit of Measure'))
|
||||
move_lot_ids = fields.One2many('stock.move.lots', 'move_id', string='Lots')
|
||||
active_move_lot_ids = fields.One2many('stock.move.lots', '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(
|
||||
@@ -93,7 +94,7 @@ class StockMove(models.Model):
|
||||
def _qty_done_compute(self):
|
||||
for move in self:
|
||||
if move.has_tracking != 'none':
|
||||
move.quantity_done = sum(move.move_lot_ids.mapped('quantity_done'))
|
||||
move.quantity_done = sum(move.move_lot_ids.filtered(lambda x: x.done_wo).mapped('quantity_done')) #TODO: change with active_move_lot_ids?
|
||||
else:
|
||||
move.quantity_done = move.quantity_done_store
|
||||
|
||||
@@ -170,6 +171,7 @@ class StockMove(models.Model):
|
||||
moves = self._filter_closed_moves()
|
||||
quant_obj = self.env['stock.quant']
|
||||
moves_todo = self.env['stock.move']
|
||||
moves_to_unreserve = self.env['stock.move']
|
||||
uom_obj = self.env['product.uom']
|
||||
for move in moves:
|
||||
rounding = move.product_uom.rounding
|
||||
@@ -188,6 +190,8 @@ class StockMove(models.Model):
|
||||
# Need to do some kind of conversion here
|
||||
qty_split = uom_obj._compute_qty(move.product_uom.id, move.product_uom_qty - move.quantity_done, move.product_id.uom_id.id)
|
||||
new_move = move.split(qty_split)
|
||||
# If you were already putting stock.move.lots on the next one in the work order, transfer those to the new move
|
||||
move.move_lot_ids.filtered(lambda x: not x.done_wo).write({'move_id': new_move})
|
||||
self.browse(new_move).quantity_done = 0.0
|
||||
main_domain = [('qty', '>', 0)]
|
||||
preferred_domain = [('reservation_id', '=', move.id)]
|
||||
@@ -203,10 +207,11 @@ class StockMove(models.Model):
|
||||
qty = uom_obj._compute_qty(move.product_uom.id, movelot.quantity_done, move.product_id.uom_id.id)
|
||||
quants = quant_obj.quants_get_preferred_domain(qty, move, lot_id=movelot.lot_id.id, domain=main_domain, preferred_domain_list=preferred_domain_list)
|
||||
self.env['stock.quant'].quants_move(quants, move, move.location_dest_id, lot_id = movelot.lot_id.id)
|
||||
move.quants_unreserve()
|
||||
moves_to_unreserve |= move
|
||||
# Next move in production order
|
||||
if move.move_dest_id:
|
||||
move.move_dest_id.action_assign()
|
||||
moves_to_unreserve.quants_unreserve()
|
||||
moves_todo.write({'state': 'done', 'date': fields.Datetime.now()})
|
||||
return moves_todo
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
<field name="workorder_id" invisible="1"/>
|
||||
</group>
|
||||
</group>
|
||||
<field name="move_lot_ids" attrs="{'readonly': [('is_done', '=', True)]}" context="{'default_workorder_id': workorder_id}">
|
||||
<field name="active_move_lot_ids" attrs="{'readonly': [('is_done', '=', True)]}" context="{'default_workorder_id': workorder_id}">
|
||||
<tree editable="bottom" decoration-success="quantity==quantity_done" decoration-danger="(quantity > 0) and (quantity_done>quantity)">
|
||||
<field name="lot_id" domain="[('product_id', '=', parent.product_id)]" context="{'default_product_id': parent.product_id}"/>
|
||||
<field name="quantity" invisible="not context.get('show_reserved') or context.get('serial') or context.get('state_done')" readonly="1"/>
|
||||
@@ -37,6 +37,7 @@
|
||||
<button name="do_plus" type="object" icon="fa-plus-square" attrs="{'invisible': [('plus_visible', '=', False)]}" invisible="not context.get('show_reserved') or context.get('state_done')"/>
|
||||
<field name="plus_visible" invisible="1"/>
|
||||
<field name="workorder_id" invisible="1"/>
|
||||
<field name="done_wo" invisible="1"/>
|
||||
</tree>
|
||||
</field>
|
||||
<footer class="oe_edit_only">
|
||||
|
||||
@@ -911,6 +911,7 @@ class StockMove(models.Model):
|
||||
:param restrict_partner_id: optional partner that can be given in order to force the new move to restrict its choice of quants to the ones belonging to this partner.
|
||||
:param context: dictionay. can contains the special key 'source_location_id' in order to force the source location when copying the move
|
||||
:returns: id of the backorder move created """
|
||||
self = self.with_prefetch() # This makes the ORM only look for one record and not 300 at a time, which improves performance
|
||||
if self.state in ('done', 'cancel'):
|
||||
raise UserError(_('You cannot split a move done'))
|
||||
elif self.state == 'draft':
|
||||
@@ -919,7 +920,6 @@ class StockMove(models.Model):
|
||||
raise UserError(_('You cannot split a draft move. It needs to be confirmed first.'))
|
||||
if float_is_zero(qty, precision_rounding=self.product_id.uom_id.rounding) or self.product_qty <= qty:
|
||||
return self.id
|
||||
|
||||
# HALF-UP rounding as only rounding errors will be because of propagation of error from default UoM
|
||||
uom_qty = self.env['product.uom']._compute_qty_obj(self.product_id.uom_id, qty, self.product_uom, rounding_method='HALF-UP')
|
||||
defaults = {
|
||||
@@ -938,12 +938,11 @@ class StockMove(models.Model):
|
||||
if self.env.context.get('source_location_id'):
|
||||
defaults['location_id'] = self.env.context['source_location_id']
|
||||
new_move = self.copy(defaults)
|
||||
|
||||
# ctx = context.copy()
|
||||
# TDE CLEANME: used only in write in this file, to clean
|
||||
# ctx['do_not_propagate'] = True
|
||||
self.with_context(do_not_propagate=True).write({'product_uom_qty': self.product_uom_qty - uom_qty})
|
||||
|
||||
|
||||
if self.move_dest_id and self.propagate and self.move_dest_id.state not in ('done', 'cancel'):
|
||||
new_move_prop = self.move_dest_id.split(qty)
|
||||
new_move.write({'move_dest_id': new_move_prop})
|
||||
@@ -972,10 +971,5 @@ class StockMove(models.Model):
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
def quants_unreserve(self):
|
||||
# TDE FIXME: do in batch
|
||||
for move in self:
|
||||
if move.reserved_quant_ids:
|
||||
# if move has a picking_id, write on that picking that pack_operation might have changed and need to be recomputed
|
||||
if move.partially_available:
|
||||
move.write({'partially_available': False})
|
||||
move.reserved_quant_ids.sudo().write({'reservation_id': False})
|
||||
self.filtered(lambda x: x.partially_available).write({'partially_available': False})
|
||||
self.mapped('reserved_quant_ids').sudo().write({'reservation_id': False})
|
||||
Reference in New Issue
Block a user