summaryrefslogtreecommitdiff
path: root/addons/mrp_subcontracting/models
diff options
context:
space:
mode:
Diffstat (limited to 'addons/mrp_subcontracting/models')
-rw-r--r--addons/mrp_subcontracting/models/mrp_production.py5
-rw-r--r--addons/mrp_subcontracting/models/stock_move.py23
-rw-r--r--addons/mrp_subcontracting/models/stock_picking.py86
3 files changed, 69 insertions, 45 deletions
diff --git a/addons/mrp_subcontracting/models/mrp_production.py b/addons/mrp_subcontracting/models/mrp_production.py
index fcc77b32e63..e546bf1b034 100644
--- a/addons/mrp_subcontracting/models/mrp_production.py
+++ b/addons/mrp_subcontracting/models/mrp_production.py
@@ -125,3 +125,8 @@ class MrpProduction(models.Model):
for ml in subcontract_move_id.move_line_ids:
ml.product_uom_qty = ml.qty_done
subcontract_move_id._recompute_state()
+
+ def _subcontracting_filter_to_done(self):
+ """ Filter subcontracting production where composant is already recorded and should be consider to be validate """
+ mos = self.filtered(lambda mo: mo.state not in ('done', 'cancel'))
+ return mos.filtered(lambda pro: all(line.lot_id for line in pro.move_raw_ids.filtered(lambda sm: sm.has_tracking != 'none').move_line_ids))
diff --git a/addons/mrp_subcontracting/models/stock_move.py b/addons/mrp_subcontracting/models/stock_move.py
index 32817a4ca8b..45f5bcce5eb 100644
--- a/addons/mrp_subcontracting/models/stock_move.py
+++ b/addons/mrp_subcontracting/models/stock_move.py
@@ -51,11 +51,18 @@ class StockMove(models.Model):
""" If the initial demand is updated then also update the linked
subcontract order to the new quantity.
"""
- if 'product_uom_qty' in values:
- if self.env.context.get('cancel_backorder') is False:
- return super(StockMove, self).write(values)
+ if 'product_uom_qty' in values and self.env.context.get('cancel_backorder') is not False:
self.filtered(lambda m: m.is_subcontract and m.state not in ['draft', 'cancel', 'done'])._update_subcontract_order_qty(values['product_uom_qty'])
- return super(StockMove, self).write(values)
+ res = super().write(values)
+ if 'date' in values:
+ for move in self:
+ if move.state in ('done', 'cancel') or not move.is_subcontract:
+ continue
+ move.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel')).write({
+ 'date_planned_finished': move.date,
+ 'date_planned_start': move.date,
+ })
+ return res
def action_show_details(self):
""" Open the produce wizard in order to register tracked components for
@@ -97,10 +104,10 @@ class StockMove(models.Model):
def _action_cancel(self):
for move in self:
if move.is_subcontract:
- production = move.move_orig_ids.production_id
+ active_production = move.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel'))
moves = self.env.context.get('moves_todo')
- if not moves or production not in moves.move_orig_ids.production_id:
- production._action_cancel()
+ if not moves or active_production not in moves.move_orig_ids.production_id:
+ active_production.with_context(skip_activity=True).action_cancel()
return super()._action_cancel()
def _action_confirm(self, merge=True, merge_into=False):
@@ -192,7 +199,7 @@ class StockMove(models.Model):
break
if quantity_to_remove >= production.product_qty:
quantity_to_remove -= production.product_qty
- production.action_cancel()
+ production.with_context(skip_activity=True).action_cancel()
else:
self.env['change.production.qty'].with_context(skip_activity=True).create({
'mo_id': production.id,
diff --git a/addons/mrp_subcontracting/models/stock_picking.py b/addons/mrp_subcontracting/models/stock_picking.py
index 6faebd8a809..23949e6cac9 100644
--- a/addons/mrp_subcontracting/models/stock_picking.py
+++ b/addons/mrp_subcontracting/models/stock_picking.py
@@ -4,7 +4,7 @@
from datetime import timedelta
from odoo import api, fields, models
-from odoo.tools.float_utils import float_is_zero
+from odoo.tools.float_utils import float_compare, float_is_zero
class StockPicking(models.Model):
@@ -41,39 +41,48 @@ class StockPicking(models.Model):
# -------------------------------------------------------------------------
def _action_done(self):
res = super(StockPicking, self)._action_done()
+
+ for move in self.move_lines.filtered(lambda move: move.is_subcontract):
+ # Auto set qty_producing/lot_producing_id of MO if there isn't tracked component
+ # If there is tracked component, the flow use subcontracting_record_component instead
+ if move._has_tracked_subcontract_components():
+ continue
+ production = move.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel'))[-1:]
+ if not production:
+ continue
+ # Manage additional quantities
+ quantity_done_move = move.product_uom._compute_quantity(move.quantity_done, production.product_uom_id)
+ if float_compare(production.product_qty, quantity_done_move, precision_rounding=production.product_uom_id.rounding) == -1:
+ change_qty = self.env['change.production.qty'].create({
+ 'mo_id': production.id,
+ 'product_qty': quantity_done_move
+ })
+ change_qty.with_context(skip_activity=True).change_prod_qty()
+ # Create backorder MO for each move lines
+ for move_line in move.move_line_ids:
+ if move_line.lot_id:
+ production.lot_producing_id = move_line.lot_id
+ production.qty_producing = move_line.product_uom_id._compute_quantity(move_line.qty_done, production.product_uom_id)
+ production._set_qty_producing()
+ if move_line != move.move_line_ids[-1]:
+ backorder = production._generate_backorder_productions(close_mo=False)
+ # The move_dest_ids won't be set because the _split filter out done move
+ backorder.move_finished_ids.filtered(lambda mo: mo.product_id == move.product_id).move_dest_ids = production.move_finished_ids.filtered(lambda mo: mo.product_id == move.product_id).move_dest_ids
+ production.product_qty = production.qty_producing
+ production = backorder
+
for picking in self:
- # Auto set qty_producing if not tracked component
- for move in picking.move_lines.filtered(lambda move: move.is_subcontract):
- if not move._has_tracked_subcontract_components():
- production = move.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel'))
- if production:
- qty_done_production_uom = move.product_uom._compute_quantity(move.quantity_done, production.product_uom_id)
- production.qty_producing += qty_done_production_uom
- for move in (production.move_raw_ids | production.move_finished_ids.filtered(lambda m: m.product_id != production.product_id)):
- if move.state in ('done', 'cancel'):
- continue
- if float_is_zero(move.product_uom_qty, precision_rounding=move.product_uom.rounding):
- continue
- new_qty = production.product_uom_id._compute_quantity(
- (production.qty_producing - production.qty_produced) * move.unit_factor, production.product_uom_id,
- rounding_method='HALF-UP')
- move.move_line_ids.filtered(lambda ml: ml.state not in ('done', 'cancel')).qty_done = 0
- move.move_line_ids = move._set_quantity_done_prepare_vals(new_qty)
-
- productions_to_done = picking.move_lines.move_orig_ids.production_id.filtered(lambda p: p.state not in ('done', 'cancel'))
- # TODO : to change in master with field on mrp
- productions_to_done = productions_to_done.filtered(lambda pro: all(line.lot_id for line in pro.move_raw_ids.filtered(lambda sm: sm.has_tracking != 'none').move_line_ids))
- for subcontracted_production in productions_to_done:
- if subcontracted_production.state == 'progress':
- subcontracted_production._post_inventory()
- else:
- subcontracted_production.with_context(subcontract_move_id=True).button_mark_done()
- # For concistency, set the date on production move before the date
- # on picking. (Tracability report + Product Moves menu item)
- minimum_date = min(picking.move_line_ids.mapped('date'))
- production_moves = subcontracted_production.move_raw_ids | subcontracted_production.move_finished_ids
- production_moves.write({'date': minimum_date - timedelta(seconds=1)})
- production_moves.move_line_ids.write({'date': minimum_date - timedelta(seconds=1)})
+ productions_to_done = picking._get_subcontracted_productions()._subcontracting_filter_to_done()
+ production_ids_backorder = []
+ if not self.env.context.get('cancel_backorder'):
+ production_ids_backorder = productions_to_done.filtered(lambda mo: mo.state == "progress").ids
+ productions_to_done.with_context(subcontract_move_id=True, mo_ids_to_backorder=production_ids_backorder).button_mark_done()
+ # For concistency, set the date on production move before the date
+ # on picking. (Traceability report + Product Moves menu item)
+ minimum_date = min(picking.move_line_ids.mapped('date'))
+ production_moves = productions_to_done.move_raw_ids | productions_to_done.move_finished_ids
+ production_moves.write({'date': minimum_date - timedelta(seconds=1)})
+ production_moves.move_line_ids.write({'date': minimum_date - timedelta(seconds=1)})
return res
def action_record_components(self):
@@ -81,7 +90,9 @@ class StockPicking(models.Model):
for move in self.move_lines:
if not move._has_tracked_subcontract_components():
continue
- production = move.move_orig_ids.production_id[-1:]
+ productions = move.move_orig_ids.production_id
+ productions_to_done = productions._subcontracting_filter_to_done()
+ production = (productions - productions_to_done)[-1:]
if not production:
continue
return move._action_record_components()
@@ -94,8 +105,7 @@ class StockPicking(models.Model):
return self.picking_type_id.code == 'incoming' and any(m.is_subcontract for m in self.move_lines)
def _get_subcontracted_productions(self):
- self.ensure_one()
- return self.move_lines.mapped('move_orig_ids.production_id')
+ return self.move_lines.move_orig_ids.production_id
def _get_warehouse(self, subcontract_move):
return subcontract_move.warehouse_id or self.picking_type_id.warehouse_id
@@ -117,7 +127,8 @@ class StockPicking(models.Model):
'location_src_id': subcontract_move.picking_id.partner_id.with_company(subcontract_move.company_id).property_stock_subcontractor.id,
'location_dest_id': subcontract_move.picking_id.partner_id.with_company(subcontract_move.company_id).property_stock_subcontractor.id,
'product_qty': subcontract_move.product_uom_qty,
- 'picking_type_id': warehouse.subcontracting_type_id.id
+ 'picking_type_id': warehouse.subcontracting_type_id.id,
+ 'date_planned_start': subcontract_move.date
}
return vals
@@ -127,6 +138,7 @@ class StockPicking(models.Model):
mo = self.env['mrp.production'].with_company(move.company_id).create(self._prepare_subcontract_mo_vals(move, bom))
self.env['stock.move'].create(mo._get_moves_raw_values())
self.env['stock.move'].create(mo._get_moves_finished_values())
+ mo.date_planned_finished = move.date # Avoid to have the picking late depending of the MO
mo.action_confirm()
# Link the finished to the receipt move.