1、cnc编程单tree视图展示刀具状态字段;2、优化制造订单的功能刀具状态字段自动更新方法,同时当工单刀具状态变化时变更缺刀备注信息,添加状态为无效刀的备注字段;3、优化当功能刀具从【刀具房】到【制造前】时进行校验,校验是否为制造订单所缺的刀,如果是则修改cnc编程单刀具状态为正常;4、优化cnc用刀校验:添加对无效刀的处理(无效刀时触发返工流程,并生成检测结果数据),优化生成的待处理数据的数据结构;
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
<field name="program_name"/>
|
<field name="program_name"/>
|
||||||
<field name="functional_tool_type_id"/>
|
<field name="functional_tool_type_id"/>
|
||||||
<field name="cutting_tool_name"/>
|
<field name="cutting_tool_name"/>
|
||||||
|
<field name="tool_state"/>
|
||||||
<field name="cutting_tool_no"/>
|
<field name="cutting_tool_no"/>
|
||||||
<field name="processing_type"/>
|
<field name="processing_type"/>
|
||||||
<field name="margin_x_y"/>
|
<field name="margin_x_y"/>
|
||||||
|
|||||||
@@ -26,22 +26,43 @@ class MrpProduction(models.Model):
|
|||||||
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
|
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
|
||||||
string='工单状态', default='未排')
|
string='工单状态', default='未排')
|
||||||
|
|
||||||
|
|
||||||
detection_result_ids = fields.One2many('sf.detection.result', 'production_id', '检测报告')
|
detection_result_ids = fields.One2many('sf.detection.result', 'production_id', '检测报告')
|
||||||
tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='功能刀具状态', default='0',
|
tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='功能刀具状态', default='0',
|
||||||
store=True, compute='_compute_tool_state')
|
store=True, compute='_compute_tool_state')
|
||||||
tool_state_remark = fields.Text(string='功能刀具状态备注', readonly=True)
|
tool_state_remark = fields.Text(string='功能刀具状态备注(缺刀)', readonly=True)
|
||||||
|
tool_state_remark2 = fields.Text(string='功能刀具状态备注(无效刀)', readonly=True)
|
||||||
|
|
||||||
@api.depends('workorder_ids.tool_state')
|
@api.depends('workorder_ids.tool_state')
|
||||||
def _compute_tool_state(self):
|
def _compute_tool_state(self):
|
||||||
for item in self:
|
for item in self:
|
||||||
if item:
|
if item:
|
||||||
if item.workorder_ids.filtered(lambda a: a.tool_state == '2' and a.state not in ('rework', '返工')):
|
workorder_ids = item.workorder_ids.filtered(lambda a: a.state not in ('rework', '返工'))
|
||||||
|
if workorder_ids.filtered(lambda a: a.tool_state == '2'):
|
||||||
item.tool_state = '2'
|
item.tool_state = '2'
|
||||||
elif item.workorder_ids.filtered(lambda a: a.tool_state == '1' and a.state not in ('rework', '返工')):
|
elif workorder_ids.filtered(lambda a: a.tool_state == '1'):
|
||||||
|
tool_state_remark = ''
|
||||||
|
data = {}
|
||||||
|
# 获取所有缺刀工单加工面对应缺的刀
|
||||||
|
for work in workorder_ids.filtered(lambda a: a.tool_state == '1'):
|
||||||
|
if work.processing_panel not in list(data.keys()):
|
||||||
|
data.update({work.processing_panel: []})
|
||||||
|
for cnc in work.cnc_ids.filtered(lambda a: a.tool_state == '1'):
|
||||||
|
if cnc.cutting_tool_name not in data[work.processing_panel]:
|
||||||
|
data[work.processing_panel].append(cnc.cutting_tool_name)
|
||||||
|
# 按格式生成缺刀提示信息
|
||||||
|
for key in data:
|
||||||
|
if data.get(key) and not data.get(key):
|
||||||
|
if tool_state_remark != '':
|
||||||
|
tool_state_remark = f'{tool_state_remark}\n{key}缺刀:{data.get(key)}'
|
||||||
|
else:
|
||||||
|
tool_state_remark = f'{key}缺刀:{data.get(key)}'
|
||||||
item.tool_state = '1'
|
item.tool_state = '1'
|
||||||
|
item.tool_state_remark = tool_state_remark
|
||||||
|
item.tool_state_remark2 = ''
|
||||||
else:
|
else:
|
||||||
item.tool_state = '0'
|
item.tool_state = '0'
|
||||||
|
item.tool_state_remark = ''
|
||||||
|
item.tool_state_remark2 = ''
|
||||||
|
|
||||||
# state = fields.Selection(selection_add=[
|
# state = fields.Selection(selection_add=[
|
||||||
# ('pending_scheduling', '待排程'),
|
# ('pending_scheduling', '待排程'),
|
||||||
|
|||||||
@@ -99,6 +99,7 @@
|
|||||||
<field name="part_drawing"/>
|
<field name="part_drawing"/>
|
||||||
<field name="tool_state"/>
|
<field name="tool_state"/>
|
||||||
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
|
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
|
||||||
|
<field name="tool_state_remark2" string="备注" attrs="{'invisible': [('tool_state', '!=', '2')]}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//header//button[@name='action_cancel']" position="replace">
|
<xpath expr="//header//button[@name='action_cancel']" position="replace">
|
||||||
<button name="action_cancel" type="object" string="取消" data-hotkey="z"
|
<button name="action_cancel" type="object" string="取消" data-hotkey="z"
|
||||||
|
|||||||
@@ -510,6 +510,7 @@
|
|||||||
<field name="sequence_number"/>
|
<field name="sequence_number"/>
|
||||||
<field name="program_name"/>
|
<field name="program_name"/>
|
||||||
<field name="cutting_tool_name"/>
|
<field name="cutting_tool_name"/>
|
||||||
|
<field name="tool_state"/>
|
||||||
<field name="cutting_tool_no"/>
|
<field name="cutting_tool_no"/>
|
||||||
<field name="processing_type"/>
|
<field name="processing_type"/>
|
||||||
<field name="margin_x_y"/>
|
<field name="margin_x_y"/>
|
||||||
|
|||||||
@@ -115,8 +115,6 @@ class FunctionalCuttingToolEntity(models.Model):
|
|||||||
# 新刀入库到线边
|
# 新刀入库到线边
|
||||||
item.create_stock_move(pre_manufacturing_id, location_id)
|
item.create_stock_move(pre_manufacturing_id, location_id)
|
||||||
item.current_shelf_location_id = location_id.id
|
item.current_shelf_location_id = location_id.id
|
||||||
# 对该刀进行校验(校验是否为制造订单所缺的刀)
|
|
||||||
item.cnc_function_tool_use_verify()
|
|
||||||
|
|
||||||
# 中控反馈该位置没有刀
|
# 中控反馈该位置没有刀
|
||||||
else:
|
else:
|
||||||
@@ -259,12 +257,13 @@ class FunctionalCuttingToolEntity(models.Model):
|
|||||||
|
|
||||||
def cnc_function_tool_use_verify(self):
|
def cnc_function_tool_use_verify(self):
|
||||||
"""
|
"""
|
||||||
cnc程序用刀可用校验
|
cnc程序用刀可用校验(校验是否是制造订单所缺刀)
|
||||||
"""
|
"""
|
||||||
cnc_processing_ids = self.env['sf.cnc.processing'].search(
|
if self.tool_name_id.name:
|
||||||
[('tool_state', '=', '1'), ('cutting_tool_name', '=', self.tool_name_id.name)])
|
cnc_processing_ids = self.env['sf.cnc.processing'].search(
|
||||||
if cnc_processing_ids:
|
[('tool_state', '=', '1'), ('cutting_tool_name', '=', self.tool_name_id.name)])
|
||||||
cnc_processing_ids.sudo().write({'tool_state': '0'})
|
if cnc_processing_ids:
|
||||||
|
cnc_processing_ids.sudo().write({'tool_state': '0'})
|
||||||
|
|
||||||
def tool_inventory_displacement_out(self):
|
def tool_inventory_displacement_out(self):
|
||||||
"""
|
"""
|
||||||
@@ -277,9 +276,6 @@ class FunctionalCuttingToolEntity(models.Model):
|
|||||||
self.current_location_id = stock_location_id.id
|
self.current_location_id = stock_location_id.id
|
||||||
self.current_shelf_location_id = False
|
self.current_shelf_location_id = False
|
||||||
|
|
||||||
if self.current_location_id.name == '刀具房':
|
|
||||||
# 对该刀进行校验(校验是否为制造订单所缺的刀)
|
|
||||||
self.cnc_function_tool_use_verify()
|
|
||||||
# self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
|
# self.barcode_id.create_stock_quant(location_inventory_id, stock_location_id,
|
||||||
# self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
|
# self.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
|
||||||
# self.functional_tool_name_id.tool_groups_id)
|
# self.functional_tool_name_id.tool_groups_id)
|
||||||
|
|||||||
@@ -35,24 +35,29 @@ class CNCprocessing(models.Model):
|
|||||||
"""
|
"""
|
||||||
cam_id = self.env['sf.cam.work.order.program.knife.plan']
|
cam_id = self.env['sf.cam.work.order.program.knife.plan']
|
||||||
production_ids = [] # 制造订单集
|
production_ids = [] # 制造订单集
|
||||||
datas = {} # 缺刀/无效刀集
|
datas = {'缺刀': {}, '无效刀': {}} # 缺刀/无效刀集
|
||||||
for cnc_processing in cnc_processing_ids:
|
for cnc_processing in cnc_processing_ids:
|
||||||
|
# ======创建字典: {'缺刀': {'制造订单1': {'加工面1': [], ...}, ...}, '无效刀': {'制造订单1': {'加工面1': [], ...}, ...}}======
|
||||||
production_name = cnc_processing.production_id.name # 制造订单
|
production_name = cnc_processing.production_id.name # 制造订单
|
||||||
processing_panel = cnc_processing.workorder_id.processing_panel # 加工面
|
processing_panel = cnc_processing.workorder_id.processing_panel # 加工面
|
||||||
if not datas.get(production_name):
|
if production_name not in list(datas['缺刀'].keys()):
|
||||||
datas.update({production_name: {}})
|
datas['缺刀'].update({production_name: {processing_panel: []}})
|
||||||
|
datas['无效刀'].update({production_name: {processing_panel: []}})
|
||||||
production_ids.append(cnc_processing.production_id)
|
production_ids.append(cnc_processing.production_id)
|
||||||
if not datas.get(production_name).get(processing_panel):
|
else:
|
||||||
datas.get(production_name).update({processing_panel: {'缺刀': [], '无效刀': []}})
|
if processing_panel not in list[datas['缺刀'].get(production_name).keys()]:
|
||||||
|
datas['缺刀'].get(production_name).update({processing_panel: []})
|
||||||
|
datas['无效刀'].get(production_name).update({processing_panel: []})
|
||||||
|
# ======================================
|
||||||
if cnc_processing.cutting_tool_name:
|
if cnc_processing.cutting_tool_name:
|
||||||
tool_name = cnc_processing.cutting_tool_name
|
tool_name = cnc_processing.cutting_tool_name
|
||||||
# 检验CNC用刀是否是功能刀具清单中的刀具
|
# 检验CNC用刀是否是功能刀具清单中的刀具
|
||||||
tool_inventory_id = self.env['sf.tool.inventory'].sudo().search([('name', '=', tool_name)])
|
tool_inventory_id = self.env['sf.tool.inventory'].sudo().search([('name', '=', tool_name)])
|
||||||
if not tool_inventory_id:
|
if not tool_inventory_id:
|
||||||
datas[production_name][processing_panel]['无效刀'].append(cnc_processing.cutting_tool_name)
|
if cnc_processing.cutting_tool_name not in datas['无效刀'][production_name][processing_panel]:
|
||||||
|
datas['无效刀'][production_name][processing_panel].append(cnc_processing.cutting_tool_name)
|
||||||
cnc_processing.tool_state = '2'
|
cnc_processing.tool_state = '2'
|
||||||
# todo 无效刀处理逻辑
|
logging.info(f'"无效刀":[{production_name}、{processing_panel}、{cnc_processing.cutting_tool_name}]')
|
||||||
|
|
||||||
# 跳过本次循环
|
# 跳过本次循环
|
||||||
continue
|
continue
|
||||||
# 校验CNC用刀在系统是否存在
|
# 校验CNC用刀在系统是否存在
|
||||||
@@ -60,28 +65,62 @@ class CNCprocessing(models.Model):
|
|||||||
[('tool_name_id', '=', tool_inventory_id.id), ('functional_tool_status', '=', '正常')])
|
[('tool_name_id', '=', tool_inventory_id.id), ('functional_tool_status', '=', '正常')])
|
||||||
# 判断线边、机内是否有满足条件的刀
|
# 判断线边、机内是否有满足条件的刀
|
||||||
if not functional_tools.filtered(lambda p: p.current_location in ('线边刀库', '机内刀库')):
|
if not functional_tools.filtered(lambda p: p.current_location in ('线边刀库', '机内刀库')):
|
||||||
datas[production_name][processing_panel]['缺刀'].append(cnc_processing.cutting_tool_name)
|
if cnc_processing.cutting_tool_name not in datas['缺刀'][production_name][processing_panel]:
|
||||||
|
datas['缺刀'][production_name][processing_panel].append(cnc_processing.cutting_tool_name)
|
||||||
cnc_processing.tool_state = '1'
|
cnc_processing.tool_state = '1'
|
||||||
|
logging.info(f'"缺刀":[{production_name}、{processing_panel}、{cnc_processing.cutting_tool_name}]')
|
||||||
# 判断是否有满足条件的刀
|
# 判断是否有满足条件的刀
|
||||||
if not functional_tools:
|
if not functional_tools:
|
||||||
# 创建CAM申请装刀记录
|
# 创建CAM申请装刀记录
|
||||||
cam_id.create_cam_work_plan(cnc_processing)
|
cam_id.create_cam_work_plan(cnc_processing)
|
||||||
logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
|
logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
|
||||||
|
logging.info(datas)
|
||||||
for production_id in production_ids:
|
for production_id in production_ids:
|
||||||
if production_id:
|
if production_id:
|
||||||
data = datas.get(production_id.name)
|
data1 = datas['无效刀'].get(production_id.name) # data1: {'加工面1': [], ...}
|
||||||
tool_state_remark = ''
|
data2 = datas['缺刀'].get(production_id.name) # data2: {'加工面1': [], ...}
|
||||||
# todo 对无效刀信息进行处理
|
tool_state_remark1 = ''
|
||||||
|
tool_state_remark2 = ''
|
||||||
|
# 对无效刀信息进行处理
|
||||||
|
for key in data1:
|
||||||
|
if data1.get(key):
|
||||||
|
if tool_state_remark1 != '':
|
||||||
|
tool_state_remark1 = f'{tool_state_remark1}\n{key}无效刀:{data1.get(key)}'
|
||||||
|
else:
|
||||||
|
tool_state_remark1 = f'{key}无效刀:{data1.get(key)}'
|
||||||
|
# 无效刀处理逻辑
|
||||||
|
# 1、创建制造订单无效刀检测结果记录
|
||||||
|
production_id.detection_result_ids.create({
|
||||||
|
'production_id': production_id.id,
|
||||||
|
'processing_panel': key,
|
||||||
|
'routing_type': 'CNC加工',
|
||||||
|
'rework_reason': 'programming', # 原因:编程(programming)
|
||||||
|
'detailed_reason': '无效功能刀具',
|
||||||
|
'test_results': '返工',
|
||||||
|
'handle_result': '待处理'
|
||||||
|
})
|
||||||
|
# 2、将制造订单状态改为返工
|
||||||
|
production_id.write({
|
||||||
|
'state': 'rework'
|
||||||
|
})
|
||||||
# 对缺刀信息进行处理
|
# 对缺刀信息进行处理
|
||||||
for key in data:
|
if tool_state_remark1 == '':
|
||||||
if tool_state_remark != '':
|
for key in data2:
|
||||||
tool_state_remark = f'{tool_state_remark}\n{key}缺刀:{data.get(key).get("缺刀")}'
|
if data2.get(key) and not data1.get(key):
|
||||||
else:
|
if tool_state_remark2 != '':
|
||||||
tool_state_remark = f'{key}缺刀:{data.get(key).get("缺刀")}'
|
tool_state_remark2 = f'{tool_state_remark2}\n{key}缺刀:{data2.get(key)}'
|
||||||
if production_id.tool_state == '1':
|
else:
|
||||||
|
tool_state_remark2 = f'{key}缺刀:{data2.get(key)}'
|
||||||
|
# 将备注信息存入制造订单功能刀具状态的备注字段
|
||||||
|
if production_id.tool_state_remark2 == '':
|
||||||
production_id.write({
|
production_id.write({
|
||||||
'tool_state_remark': tool_state_remark
|
'tool_state_remark': tool_state_remark2,
|
||||||
|
'tool_state_remark2': tool_state_remark1
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
production_id.write({
|
||||||
|
'tool_state_remark': tool_state_remark2,
|
||||||
|
'tool_state_remark2': f'{production_id.tool_state_remark1}\n{tool_state_remark1}'
|
||||||
})
|
})
|
||||||
|
|
||||||
@api.model_create_multi
|
@api.model_create_multi
|
||||||
|
|||||||
@@ -21,3 +21,40 @@ class ShelfLocation(models.Model):
|
|||||||
continue
|
continue
|
||||||
item.tool_rfid = ''
|
item.tool_rfid = ''
|
||||||
item.tool_name_id = False
|
item.tool_name_id = False
|
||||||
|
|
||||||
|
|
||||||
|
class StockMoveLine(models.Model):
|
||||||
|
_inherit = 'stock.move.line'
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
records = super(StockMoveLine, self).create(vals_list)
|
||||||
|
move_lines = records.filtered(lambda a: a.product_id.categ_id.name == '功能刀具' and a.state == 'done')
|
||||||
|
if move_lines: # 校验是否为功能刀具移动历史
|
||||||
|
self.button_function_tool_use_verify(move_lines)
|
||||||
|
return records
|
||||||
|
|
||||||
|
def button_function_tool_use_verify(self, move_lines):
|
||||||
|
"""
|
||||||
|
对所有从【刀具房】到【制造前】的功能刀具进行校验(校验是否为制造订单所缺的刀)
|
||||||
|
"""
|
||||||
|
location_id = self.env['stock.location'].search([('name', '=', '刀具房')])
|
||||||
|
location_dest_id = self.env['stock.location'].search([('name', '=', '制造前')])
|
||||||
|
line_ids = move_lines.filtered(
|
||||||
|
lambda a: a.location_id == location_id and a.location_dest_id == location_dest_id)
|
||||||
|
for line_id in line_ids:
|
||||||
|
if line_id.lot_id:
|
||||||
|
self.env['sf.functional.cutting.tool.entity'].sudo().search(
|
||||||
|
[('barcode_id', '=', line_id.lot_id.id),
|
||||||
|
('functional_tool_status', '=', '正常')]).cnc_function_tool_use_verify()
|
||||||
|
|
||||||
|
|
||||||
|
class StockPicking(models.Model):
|
||||||
|
_inherit = 'stock.picking'
|
||||||
|
|
||||||
|
def button_validate(self):
|
||||||
|
res = super().button_validate()
|
||||||
|
move_lines = self.move_line_ids.filtered(lambda a: a.product_id.categ_id.name == '功能刀具')
|
||||||
|
if move_lines:
|
||||||
|
self.env['stock.move.line'].sudo().button_function_tool_use_verify(move_lines)
|
||||||
|
return res
|
||||||
|
|||||||
Reference in New Issue
Block a user