143 lines
6.2 KiB
Python
143 lines
6.2 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class StockPicking(models.Model):
|
|
_inherit = "stock.picking"
|
|
|
|
check_ids = fields.One2many('quality.check', 'picking_id', 'Checks')
|
|
quality_check_todo = fields.Boolean('Pending checks', compute='_compute_check')
|
|
quality_check_fail = fields.Boolean(compute='_compute_check')
|
|
quality_alert_ids = fields.One2many('quality.alert', 'picking_id', 'Alerts')
|
|
quality_alert_count = fields.Integer(compute='_compute_quality_alert_count')
|
|
|
|
def _compute_check(self):
|
|
for picking in self:
|
|
todo = False
|
|
fail = False
|
|
checkable_products = picking.mapped('move_line_ids').mapped('product_id')
|
|
for check in picking.check_ids:
|
|
if check.quality_state == 'none' and (check.product_id in checkable_products or check.measure_on == 'operation'):
|
|
todo = True
|
|
elif check.quality_state == 'fail':
|
|
fail = True
|
|
if fail and todo:
|
|
break
|
|
picking.quality_check_fail = fail
|
|
picking.quality_check_todo = todo
|
|
|
|
def _compute_quality_alert_count(self):
|
|
for picking in self:
|
|
picking.quality_alert_count = len(picking.quality_alert_ids)
|
|
|
|
@api.depends('quality_check_todo')
|
|
def _compute_show_validate(self):
|
|
super()._compute_show_validate()
|
|
for picking in self:
|
|
if picking.quality_check_todo:
|
|
picking.show_validate = False
|
|
|
|
def check_quality(self):
|
|
self.ensure_one()
|
|
checkable_products = self.mapped('move_line_ids').mapped('product_id')
|
|
checks = self.check_ids.filtered(lambda check: check.quality_state == 'none' and (check.product_id in checkable_products or check.measure_on == 'operation'))
|
|
if checks:
|
|
return checks.action_open_quality_check_wizard()
|
|
return False
|
|
|
|
def _create_backorder(self):
|
|
res = super(StockPicking, self)._create_backorder()
|
|
if self.env.context.get('skip_check'):
|
|
return res
|
|
for backorder in res:
|
|
backorder.backorder_id.check_ids.filtered(lambda qc: qc.quality_state == 'none').unlink()
|
|
backorder.move_ids._create_quality_checks()
|
|
return res
|
|
|
|
def _action_done(self):
|
|
# Do the check before transferring
|
|
product_to_check = self.mapped('move_line_ids').filtered(lambda x: x.qty_done != 0).mapped('product_id')
|
|
if self.mapped('check_ids').filtered(lambda x: x.quality_state == 'none' and x.product_id in product_to_check):
|
|
raise UserError(_('You still need to do the quality checks!'))
|
|
return super(StockPicking, self)._action_done()
|
|
|
|
def _pre_action_done_hook(self):
|
|
res = super()._pre_action_done_hook()
|
|
if res is True:
|
|
pickings_to_check_quality = self._check_for_quality_checks()
|
|
if pickings_to_check_quality:
|
|
return pickings_to_check_quality[0].with_context(pickings_to_check_quality=pickings_to_check_quality.ids).check_quality()
|
|
return res
|
|
|
|
def _check_for_quality_checks(self):
|
|
quality_pickings = self.env['stock.picking']
|
|
for picking in self:
|
|
product_to_check = picking.mapped('move_line_ids').filtered(lambda ml: ml.qty_done != 0).mapped('product_id')
|
|
if picking.mapped('check_ids').filtered(lambda qc: qc.quality_state == 'none' and qc.product_id in product_to_check):
|
|
quality_pickings |= picking
|
|
return quality_pickings
|
|
|
|
def action_cancel(self):
|
|
"""
|
|
调拨单取消后,关联取消质量检查单
|
|
"""
|
|
context = self.env.context
|
|
if not context.get('cancel_check_picking') and self.sudo().mapped('check_ids').filtered(
|
|
lambda x: x.quality_state in ['pass', 'fail']):
|
|
self.env.cr.rollback()
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'res_model': 'picking.check.cancel.wizard',
|
|
'name': '取消质检单',
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
'context': {
|
|
'default_picking_id': self.id,
|
|
'cancel_check_picking': True}
|
|
}
|
|
elif self.check_ids.filtered(lambda x: x.quality_state != 'cancel'):
|
|
self.sudo().mapped('check_ids').filtered(lambda x: x.quality_state != 'cancel').write({
|
|
'quality_state': 'cancel'
|
|
})
|
|
res = super(StockPicking, self).action_cancel()
|
|
# self.sudo().mapped('check_ids').filtered(lambda x: x.quality_state == 'none').unlink()
|
|
return res
|
|
|
|
def action_open_quality_check_picking(self):
|
|
action = self.env["ir.actions.actions"]._for_xml_id("quality_control.quality_check_action_picking")
|
|
action['context'] = {
|
|
'search_default_picking_id': [self.id],
|
|
'default_picking_id': self.id,
|
|
'show_lots_text': self.show_lots_text,
|
|
}
|
|
return action
|
|
|
|
def button_quality_alert(self):
|
|
self.ensure_one()
|
|
action = self.env["ir.actions.actions"]._for_xml_id("quality_control.quality_alert_action_check")
|
|
action['views'] = [(False, 'form')]
|
|
action['context'] = {
|
|
'default_product_id': self.product_id.id,
|
|
'default_product_tmpl_id': self.product_id.product_tmpl_id.id,
|
|
'default_picking_id': self.id,
|
|
}
|
|
return action
|
|
|
|
def open_quality_alert_picking(self):
|
|
self.ensure_one()
|
|
action = self.env["ir.actions.actions"]._for_xml_id("quality_control.quality_alert_action_check")
|
|
action['context'] = {
|
|
'default_product_id': self.product_id.id,
|
|
'default_product_tmpl_id': self.product_id.product_tmpl_id.id,
|
|
'default_picking_id': self.id,
|
|
}
|
|
action['domain'] = [('id', 'in', self.quality_alert_ids.ids)]
|
|
action['views'] = [(False, 'tree'),(False,'form')]
|
|
if self.quality_alert_count == 1:
|
|
action['views'] = [(False, 'form')]
|
|
action['res_id'] = self.quality_alert_ids.id
|
|
return action
|