mirror of
https://github.com/OCA/manufacture.git
synced 2025-01-28 16:37:15 +02:00
172 lines
7.6 KiB
Python
172 lines
7.6 KiB
Python
# License LGPL-3.0 or later (https://www.gnu.org/licenses/lgpl).
|
|
# Copyright 2019 Odoo
|
|
# Copyright 2020 Tecnativa - Alexandre Díaz
|
|
# Copyright 2020 Tecnativa - Pedro M. Baeza
|
|
|
|
from datetime import timedelta
|
|
|
|
from odoo import api, fields, models
|
|
|
|
|
|
class StockPicking(models.Model):
|
|
_inherit = 'stock.picking'
|
|
|
|
display_action_record_components = fields.Boolean(
|
|
compute='_compute_display_action_record_components')
|
|
|
|
@api.depends('state')
|
|
def _compute_display_action_record_components(self):
|
|
for picking in self:
|
|
# Hide if not encoding state
|
|
if picking.state in ('draft', 'cancel', 'done'):
|
|
picking.display_action_record_components = False
|
|
continue
|
|
if not picking._is_subcontract():
|
|
picking.display_action_record_components = False
|
|
continue
|
|
# Hide if no components are track
|
|
subcontracted_productions = picking\
|
|
._get_subcontracted_productions()
|
|
subcontracted_moves = subcontracted_productions.mapped(
|
|
'move_raw_ids')
|
|
if all(subcontracted_move.has_tracking == 'none'
|
|
for subcontracted_move in subcontracted_moves):
|
|
picking.display_action_record_components = False
|
|
continue
|
|
# Hide if the production is to close
|
|
if not subcontracted_productions.filtered(lambda mo: (
|
|
not mo.check_to_done and mo.state != 'done'
|
|
)):
|
|
picking.display_action_record_components = False
|
|
continue
|
|
picking.display_action_record_components = True
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Action methods
|
|
# -------------------------------------------------------------------------
|
|
|
|
def action_done(self):
|
|
productions = self.env['mrp.production']
|
|
for picking in self:
|
|
for move in picking.move_lines:
|
|
if not move.is_subcontract:
|
|
continue
|
|
production = move.move_orig_ids.mapped('production_id')
|
|
if move._has_tracked_subcontract_components():
|
|
move.move_orig_ids.filtered(
|
|
lambda m: m.state not in ('done', 'cancel')
|
|
).move_line_ids.unlink()
|
|
move_finished_ids = move.move_orig_ids.filtered(
|
|
lambda m: m.state not in ('done', 'cancel'))
|
|
for ml in move.move_line_ids:
|
|
ml.copy({
|
|
'picking_id': False,
|
|
'production_id':
|
|
move_finished_ids.production_id.id,
|
|
'move_id': move_finished_ids.id,
|
|
'qty_done': ml.qty_done,
|
|
'result_package_id': False,
|
|
'location_id': move_finished_ids.location_id.id,
|
|
'location_dest_id':
|
|
move_finished_ids.location_dest_id.id,
|
|
})
|
|
else:
|
|
for move_line in move.move_line_ids:
|
|
produce = self.env['mrp.product.produce'].with_context(
|
|
default_production_id=production.id,
|
|
active_id=production.id).create({
|
|
'production_id': production.id,
|
|
'product_id': production.product_id.id,
|
|
'product_qty': move_line.qty_done,
|
|
'product_uom_id': move_line.product_uom_id.id,
|
|
'lot_id': move_line.lot_id.id,
|
|
})
|
|
produce._onchange_product_qty()
|
|
produce.do_produce()
|
|
productions |= production
|
|
for subcontracted_production in productions:
|
|
if subcontracted_production.check_to_done:
|
|
subcontracted_production.button_mark_done()
|
|
else:
|
|
subcontracted_production.post_inventory()
|
|
res = super(StockPicking, self).action_done()
|
|
for subcontracted_production in productions:
|
|
# For consistency, 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 = subcontracted_production.move_raw_ids\
|
|
| subcontracted_production.move_finished_ids
|
|
production_moves.write({
|
|
'date': minimum_date - timedelta(seconds=1),
|
|
})
|
|
production_moves.mapped('move_line_ids').write({
|
|
'date': minimum_date - timedelta(seconds=1),
|
|
})
|
|
return res
|
|
|
|
def action_record_components(self):
|
|
self.ensure_one()
|
|
for move in self.move_lines:
|
|
if not move._has_tracked_subcontract_components():
|
|
continue
|
|
production = move.move_orig_ids.mapped("production_id")
|
|
if not production or production.state in ('done', 'to_close'):
|
|
continue
|
|
return move._action_record_components()
|
|
|
|
# -------------------------------------------------------------------------
|
|
# Subcontract helpers
|
|
# -------------------------------------------------------------------------
|
|
def _is_subcontract(self):
|
|
self.ensure_one()
|
|
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')
|
|
|
|
def _get_warehouse(self, subcontract_move):
|
|
return subcontract_move.warehouse_id\
|
|
or self.picking_type_id.warehouse_id
|
|
|
|
def _prepare_subcontract_mo_vals(self, subcontract_move, bom):
|
|
subcontract_move.ensure_one()
|
|
group = self.env['procurement.group'].create({
|
|
'name': self.name,
|
|
'partner_id': self.partner_id.id,
|
|
})
|
|
product = subcontract_move.product_id
|
|
warehouse = self._get_warehouse(subcontract_move)
|
|
vals = {
|
|
'company_id': subcontract_move.company_id.id,
|
|
'procurement_group_id': group.id,
|
|
'product_id': product.id,
|
|
'product_uom_id': subcontract_move.product_uom.id,
|
|
'bom_id': bom.id,
|
|
'location_src_id':
|
|
subcontract_move.picking_id.partner_id.with_context(
|
|
force_company=subcontract_move.company_id.id)
|
|
.property_stock_subcontractor.id,
|
|
'location_dest_id':
|
|
subcontract_move.picking_id.partner_id.with_context(
|
|
force_company=subcontract_move.company_id.id)
|
|
.property_stock_subcontractor.id,
|
|
'product_qty': subcontract_move.product_uom_qty,
|
|
'picking_type_id': warehouse.subcontracting_type_id.id
|
|
}
|
|
return vals
|
|
|
|
def _subcontracted_produce(self, subcontract_details):
|
|
self.ensure_one()
|
|
for move, bom in subcontract_details:
|
|
mo = self.env['mrp.production'].with_context(
|
|
force_company=move.company_id.id
|
|
).create(self._prepare_subcontract_mo_vals(move, bom))
|
|
# Link the finished to the receipt move.
|
|
finished_move = mo.move_finished_ids.filtered(
|
|
lambda m: m.product_id == move.product_id)
|
|
finished_move.write({'move_dest_ids': [(4, move.id, False)]})
|
|
mo.action_assign()
|