138 lines
6.4 KiB
Python
138 lines
6.4 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import _, api, fields, models
|
|
|
|
|
|
class StockMove(models.Model):
|
|
_inherit = 'stock.move'
|
|
|
|
check_id = fields.One2many('quality.check', 'move_id')
|
|
note = fields.Html('Note', related='check_id.note')
|
|
worksheet_document = fields.Binary('Worksheet Image/PDF', compute='_compute_worksheet_document')
|
|
product_barcode = fields.Char(related='product_id.barcode')
|
|
move_line_ids_picked = fields.One2many('stock.move.line', 'move_id', domain=[('picked', '=', True)])
|
|
picking_type_prefill_shop_floor_lots = fields.Boolean(related='picking_type_id.prefill_shop_floor_lots')
|
|
|
|
@api.depends('check_id.worksheet_document')
|
|
def _compute_worksheet_document(self):
|
|
for record in self:
|
|
if record.check_id:
|
|
record.worksheet_document = record.check_id.worksheet_document
|
|
else:
|
|
record.worksheet_document = None
|
|
|
|
@api.depends('workorder_id')
|
|
def _compute_manual_consumption(self):
|
|
super()._compute_manual_consumption()
|
|
for move in self:
|
|
if move.product_id in move.workorder_id.check_ids.component_id and \
|
|
move.product_id not in move.raw_material_production_id.workorder_ids.check_ids.component_id:
|
|
move.manual_consumption = True
|
|
|
|
def _should_bypass_set_qty_producing(self):
|
|
production = self.raw_material_production_id or self.production_id
|
|
if production and ((self.product_id in production.workorder_ids.quality_point_ids.component_id) or self.operation_id):
|
|
return True
|
|
return super()._should_bypass_set_qty_producing()
|
|
|
|
def _action_assign(self, force_qty=False):
|
|
res = super()._action_assign(force_qty=force_qty)
|
|
for workorder in self.raw_material_production_id.workorder_ids:
|
|
for check in workorder.check_ids:
|
|
if check.test_type not in ('register_consumed_materials', 'register_byproducts'):
|
|
continue
|
|
check.write(workorder._defaults_from_move(check.move_id))
|
|
return res
|
|
|
|
@api.ondelete(at_uninstall=False)
|
|
def _unlink_quality_check(self):
|
|
self.env['quality.check'].search([('move_id', 'in', self.ids)]).unlink()
|
|
|
|
def action_add_from_catalog_raw(self):
|
|
mo = self.env['mrp.production'].browse(self.env.context.get('order_id'))
|
|
return mo.with_context(child_field='move_raw_ids', from_shop_floor=self.env.context.get('from_shop_floor')).action_add_from_catalog()
|
|
|
|
def action_pass(self, keep_hidden_lines=False):
|
|
if not keep_hidden_lines:
|
|
for record in self:
|
|
if record.has_tracking != 'none' and not record.picking_type_id.prefill_shop_floor_lots:
|
|
# Remove any reserved smls that are hidden
|
|
record.move_line_ids.filtered(lambda ml: not ml.picked).unlink()
|
|
for check in self.check_id:
|
|
check.action_next()
|
|
if not self.check_id:
|
|
self.picked = True
|
|
return True
|
|
|
|
def action_undo(self):
|
|
if self.check_id:
|
|
self.check_id.write({'quality_state': 'none'})
|
|
self.picked = False
|
|
self.quantity = self.product_uom_qty
|
|
|
|
def get_quant_from_barcode(self, barcode):
|
|
self.ensure_one()
|
|
if self.product_id.tracking == 'none':
|
|
return False
|
|
lot_id = self.env['stock.lot'].search([('name', '=', barcode), ('product_id', '=', self.product_id.id)], limit=1)
|
|
if not lot_id:
|
|
lot_id = self.env['stock.lot'].with_context(active_mo_id=self.raw_material_production_id.id).create([{
|
|
'name': barcode,
|
|
'product_id': self.product_id.id
|
|
}])
|
|
return self.env['stock.quant'].create([{
|
|
'lot_id': lot_id.id,
|
|
'product_id': self.product_id.id,
|
|
'location_id': self.warehouse_id.lot_stock_id.id
|
|
}]).id
|
|
return self.env['stock.quant'].search([('lot_id', '=', lot_id.id), ('location_id', 'child_of', self.location_id.id)], limit=1).id
|
|
|
|
def _visible_quantity(self):
|
|
self.ensure_one()
|
|
if self.env.context.get('hide_unpicked'):
|
|
return sum(
|
|
sml.product_uom_id._compute_quantity(sml.quantity, self.product_uom, rounding_method='HALF-UP')
|
|
for sml in self.move_line_ids_picked
|
|
)
|
|
return super()._visible_quantity()
|
|
|
|
def _add_from_quant(self, quant):
|
|
hide_unpicked = self.product_id.tracking != 'none' and not self.picking_type_prefill_shop_floor_lots
|
|
if hide_unpicked:
|
|
move_line = next((sml for sml in self.move_line_ids if sml._takes_from_quant(quant) and not sml.picked), False)
|
|
if move_line: # Quant already has hidden sml -> make visible
|
|
move_line.picked = True
|
|
return
|
|
remaining_qty = self.product_qty - sum(sml.quantity_product_uom for sml in self.move_line_ids if not hide_unpicked or sml.picked)
|
|
if min(remaining_qty, quant.available_quantity) > 0 and self.product_id.tracking != 'serial':
|
|
qty_to_take = min(remaining_qty, quant.available_quantity)
|
|
else:
|
|
qty_to_take = 1
|
|
move_line = next((sml for sml in self.move_line_ids if sml._takes_from_quant(quant)), False)
|
|
if move_line: # Quant already has visible sml -> increase existing sml's quantity
|
|
move_line.quantity += self.product_id.uom_id._compute_quantity(qty_to_take, self.product_uom)
|
|
else: # No sml exists for quant -> make new sml
|
|
move_line_vals = self._prepare_move_line_vals(
|
|
quantity=qty_to_take,
|
|
reserved_quant=quant)
|
|
self.env['stock.move.line'].create([{**move_line_vals, 'picked': True}])
|
|
|
|
def action_add_from_quant(self, quant_id):
|
|
self._add_from_quant(self.env['stock.quant'].browse(quant_id))
|
|
|
|
if self.product_id.tracking != 'none' and (not self.picking_type_prefill_shop_floor_lots or self in self.production_id.move_byproduct_ids):
|
|
self.move_line_ids.filtered(lambda ml: not ml.picked).unlink()
|
|
|
|
if self.check_id:
|
|
self.check_id.action_next()
|
|
|
|
|
|
class StockMoveLine(models.Model):
|
|
_inherit = 'stock.move.line'
|
|
|
|
def _takes_from_quant(self, quant):
|
|
self.ensure_one()
|
|
fields_to_match = ('location_id', 'product_id', 'owner_id', 'package_id', 'lot_id')
|
|
return all(self[field] == quant[field] for field in fields_to_match)
|