summaryrefslogtreecommitdiff
path: root/addons/mrp_subcontracting/models/mrp_production.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/mrp_subcontracting/models/mrp_production.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/mrp_subcontracting/models/mrp_production.py')
-rw-r--r--addons/mrp_subcontracting/models/mrp_production.py140
1 files changed, 140 insertions, 0 deletions
diff --git a/addons/mrp_subcontracting/models/mrp_production.py b/addons/mrp_subcontracting/models/mrp_production.py
new file mode 100644
index 00000000..a0917e15
--- /dev/null
+++ b/addons/mrp_subcontracting/models/mrp_production.py
@@ -0,0 +1,140 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from collections import defaultdict
+from odoo import fields, models, _, api
+from odoo.exceptions import UserError
+from odoo.tools.float_utils import float_compare, float_is_zero
+
+
+class MrpProduction(models.Model):
+ _inherit = 'mrp.production'
+
+ move_line_raw_ids = fields.One2many(
+ 'stock.move.line', string="Detail Component", readonly=False,
+ inverse='_inverse_move_line_raw_ids', compute='_compute_move_line_raw_ids'
+ )
+
+ @api.depends('move_raw_ids.move_line_ids')
+ def _compute_move_line_raw_ids(self):
+ for production in self:
+ production.move_line_raw_ids = production.move_raw_ids.move_line_ids
+
+ def _inverse_move_line_raw_ids(self):
+ for production in self:
+ line_by_product = defaultdict(lambda: self.env['stock.move.line'])
+ for line in production.move_line_raw_ids:
+ line_by_product[line.product_id] |= line
+ for move in production.move_raw_ids:
+ move.move_line_ids = line_by_product.pop(move.product_id, self.env['stock.move.line'])
+ for product_id, lines in line_by_product.items():
+ qty = sum(line.product_uom_id._compute_quantity(line.qty_done, product_id.uom_id) for line in lines)
+ move = production._get_move_raw_values(product_id, qty, product_id.uom_id)
+ move['additional'] = True
+ production.move_raw_ids = [(0, 0, move)]
+ production.move_raw_ids.filtered(lambda m: m.product_id == product_id)[:1].move_line_ids = lines
+
+ def subcontracting_record_component(self):
+ self.ensure_one()
+ assert self.env.context.get('subcontract_move_id')
+ if float_is_zero(self.qty_producing, precision_rounding=self.product_uom_id.rounding):
+ return {'type': 'ir.actions.act_window_close'}
+ for sml in self.move_raw_ids.move_line_ids:
+ if sml.tracking != 'none' and not sml.lot_id:
+ raise UserError(_('You must enter a serial number for each line of %s') % sml.product_id.name)
+ self._update_finished_move()
+ quantity_issues = self._get_quantity_produced_issues()
+ if quantity_issues:
+ backorder = self._generate_backorder_productions(close_mo=False)
+ # No qty to consume to avoid propagate additional move
+ # TODO avoid : stock move created in backorder with 0 as qty
+ backorder.move_raw_ids.filtered(lambda m: m.additional).product_uom_qty = 0.0
+
+ backorder.qty_producing = backorder.product_qty
+ backorder._set_qty_producing()
+
+ self.product_qty = self.qty_producing
+ subcontract_move_id = self.env['stock.move'].browse(self.env.context.get('subcontract_move_id'))
+ action = subcontract_move_id._action_record_components()
+ action.update({'res_id': backorder.id})
+ return action
+ return {'type': 'ir.actions.act_window_close'}
+
+ def _pre_button_mark_done(self):
+ if self.env.context.get('subcontract_move_id'):
+ return True
+ return super()._pre_button_mark_done()
+
+ def _update_finished_move(self):
+ """ After producing, set the move line on the subcontract picking. """
+ self.ensure_one()
+ subcontract_move_id = self.env.context.get('subcontract_move_id')
+ if subcontract_move_id:
+ subcontract_move_id = self.env['stock.move'].browse(subcontract_move_id)
+ quantity = self.qty_producing
+ if self.lot_producing_id:
+ move_lines = subcontract_move_id.move_line_ids.filtered(lambda ml: ml.lot_id == self.lot_producing_id or not ml.lot_id)
+ else:
+ move_lines = subcontract_move_id.move_line_ids.filtered(lambda ml: not ml.lot_id)
+ # Update reservation and quantity done
+ for ml in move_lines:
+ rounding = ml.product_uom_id.rounding
+ if float_compare(quantity, 0, precision_rounding=rounding) <= 0:
+ break
+ quantity_to_process = min(quantity, ml.product_uom_qty - ml.qty_done)
+ quantity -= quantity_to_process
+
+ new_quantity_done = (ml.qty_done + quantity_to_process)
+
+ # on which lot of finished product
+ if float_compare(new_quantity_done, ml.product_uom_qty, precision_rounding=rounding) >= 0:
+ ml.write({
+ 'qty_done': new_quantity_done,
+ 'lot_id': self.lot_producing_id and self.lot_producing_id.id,
+ })
+ else:
+ new_qty_reserved = ml.product_uom_qty - new_quantity_done
+ default = {
+ 'product_uom_qty': new_quantity_done,
+ 'qty_done': new_quantity_done,
+ 'lot_id': self.lot_producing_id and self.lot_producing_id.id,
+ }
+ ml.copy(default=default)
+ ml.with_context(bypass_reservation_update=True).write({
+ 'product_uom_qty': new_qty_reserved,
+ 'qty_done': 0
+ })
+
+ if float_compare(quantity, 0, precision_rounding=self.product_uom_id.rounding) > 0:
+ self.env['stock.move.line'].create({
+ 'move_id': subcontract_move_id.id,
+ 'picking_id': subcontract_move_id.picking_id.id,
+ 'product_id': self.product_id.id,
+ 'location_id': subcontract_move_id.location_id.id,
+ 'location_dest_id': subcontract_move_id.location_dest_id.id,
+ 'product_uom_qty': 0,
+ 'product_uom_id': self.product_uom_id.id,
+ 'qty_done': quantity,
+ 'lot_id': self.lot_producing_id and self.lot_producing_id.id,
+ })
+ if not self._get_quantity_to_backorder():
+ ml_reserved = subcontract_move_id.move_line_ids.filtered(lambda ml:
+ float_is_zero(ml.qty_done, precision_rounding=ml.product_uom_id.rounding) and
+ not float_is_zero(ml.product_uom_qty, precision_rounding=ml.product_uom_id.rounding))
+ ml_reserved.unlink()
+ 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 """
+ def filter_in(mo):
+ if mo.state in ('done', 'cancel'):
+ return False
+ if float_is_zero(mo.qty_producing, precision_rounding=mo.product_uom_id.rounding):
+ return False
+ if not all(line.lot_id for line in mo.move_raw_ids.filtered(lambda sm: sm.has_tracking != 'none').move_line_ids):
+ return False
+ return True
+
+ return self.filtered(filter_in)