From 129f8a4d7d6b1da5672b4b398f05c33385cb09e6 Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Wed, 10 Jul 2024 16:23:24 +0800
Subject: [PATCH 1/5] =?UTF-8?q?1=E3=80=81=E9=87=8D=E6=9E=84=E5=B7=A5?=
=?UTF-8?q?=E5=8D=95cnc=E7=BC=96=E7=A8=8B=E7=94=A8=E5=88=80=E6=A0=A1?=
=?UTF-8?q?=E9=AA=8C=E6=96=B9=E6=B3=95=EF=BC=9B=E5=88=B6=E9=80=A0=E8=AE=A2?=
=?UTF-8?q?=E5=8D=95=E3=80=81=E5=B7=A5=E5=8D=95=E3=80=81cnc=E7=BC=96?=
=?UTF-8?q?=E7=A8=8B=E5=8D=95=E6=B7=BB=E5=8A=A0=E5=88=80=E5=85=B7=E7=8A=B6?=
=?UTF-8?q?=E6=80=81=E5=AD=97=E6=AE=B5=EF=BC=8C=E5=B9=B6=E4=B8=94=E6=A0=B9?=
=?UTF-8?q?=E6=8D=AEcnc=E7=BC=96=E7=A8=8B=E5=8D=95=E5=88=80=E5=85=B7?=
=?UTF-8?q?=E7=8A=B6=E6=80=81=E8=87=AA=E5=8A=A8=E8=AE=A1=E7=AE=97=E5=88=B6?=
=?UTF-8?q?=E9=80=A0=E8=AE=A2=E5=8D=95=E3=80=81=E5=B7=A5=E5=8D=95=E5=88=80?=
=?UTF-8?q?=E5=85=B7=E7=8A=B6=E6=80=81=E5=AD=97=E6=AE=B5=E7=9A=84=E5=80=BC?=
=?UTF-8?q?=EF=BC=9B=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95form=E9=A1=B5?=
=?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=B1=95=E7=A4=BA=E5=8A=9F=E8=83=BD=E5=88=80?=
=?UTF-8?q?=E5=85=B7=E7=8A=B6=E6=80=81=E5=AD=97=E6=AE=B5=EF=BC=9B2?=
=?UTF-8?q?=E3=80=81=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E6=8B=86=E8=A7=A3?=
=?UTF-8?q?=E5=8D=95=E5=88=80=E5=85=B7=E7=89=A9=E6=96=99=E9=80=89=E6=8B=A9?=
=?UTF-8?q?=E7=9B=AE=E6=A0=87=E8=B4=A7=E4=BD=8D=E6=B7=BB=E5=8A=A0=E8=BF=87?=
=?UTF-8?q?=E6=BB=A4=E6=B7=BB=E5=8A=A0=E4=B8=BA=E5=8F=AA=E9=80=89=E6=8B=A9?=
=?UTF-8?q?=E6=89=80=E5=B1=9E=E8=B4=A7=E5=8C=BA=E6=98=AF=E5=88=80=E5=85=B7?=
=?UTF-8?q?=E6=88=BF=E7=9A=84=E8=B4=A7=E4=BD=8D=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/models/mrp_production.py | 15 +++++
sf_manufacturing/models/mrp_workorder.py | 15 +++++
.../views/mrp_production_addional_change.xml | 8 ++-
sf_manufacturing/views/mrp_workorder_view.xml | 2 +
sf_tool_management/models/base.py | 61 +++++++-----------
sf_tool_management/models/mrp_workorder.py | 63 +++++++++++++++++--
6 files changed, 120 insertions(+), 44 deletions(-)
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index 36bdb13d..f9492a37 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -24,6 +24,21 @@ class MrpProduction(models.Model):
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
string='工单状态', default='未排')
+ tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='功能刀具状态', default='0',
+ store=True, compute='_compute_tool_state')
+ tool_state_remark = fields.Text(string='功能刀具状态备注', readonly=True)
+
+ @api.depends('workorder_ids.tool_state')
+ def _compute_tool_state(self):
+ for item in self:
+ if item:
+ if item.workorder_ids.filtered(lambda a: a.tool_state == '2'):
+ item.tool_state = '2'
+ elif item.workorder_ids.filtered(lambda a: a.tool_state == '1'):
+ item.tool_state = '1'
+ else:
+ item.tool_state = '0'
+
# state = fields.Selection(selection_add=[
# ('pending_scheduling', '待排程'),
# ('pending_processing', '待加工'),
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 4b9371c2..4fefc154 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -158,6 +158,21 @@ class ResMrpWorkOrder(models.Model):
# 加工图纸
processing_drawing = fields.Binary(string='加工图纸')
+ # 功能刀具状态
+ tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='功能刀具状态', default='0',
+ store=True, compute='_compute_tool_state')
+
+ @api.depends('cnc_ids.tool_state')
+ def _compute_tool_state(self):
+ for item in self:
+ if item:
+ if item.cnc_ids.filtered(lambda a: a.tool_state == '2'):
+ item.tool_state = '2'
+ elif item.cnc_ids.filtered(lambda a: a.tool_state == '1'):
+ item.tool_state = '1'
+ else:
+ item.tool_state = '0'
+
@api.depends('production_id')
def _compute_save_name(self):
"""
diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml
index b5e348b9..bfda7c93 100644
--- a/sf_manufacturing/views/mrp_production_addional_change.xml
+++ b/sf_manufacturing/views/mrp_production_addional_change.xml
@@ -87,9 +87,11 @@
-
+
+
+
-
+
+
+
diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml
index dc5b4a56..dfc74a1c 100644
--- a/sf_manufacturing/views/mrp_workorder_view.xml
+++ b/sf_manufacturing/views/mrp_workorder_view.xml
@@ -19,6 +19,7 @@
+
@@ -121,6 +122,7 @@
+
diff --git a/sf_tool_management/models/base.py b/sf_tool_management/models/base.py
index b77e6469..5156a295 100644
--- a/sf_tool_management/models/base.py
+++ b/sf_tool_management/models/base.py
@@ -313,42 +313,27 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
'applicant': None,
'sf_functional_tool_assembly_id': None})
- def create_cam_work_plan(self, cnc_processing_ids):
+ def create_cam_work_plan(self, cnc_processing):
"""
根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划
"""
- for cnc_processing in cnc_processing_ids:
- status = False
- if cnc_processing.cutting_tool_name:
- functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search(
- [('name', '=', cnc_processing.cutting_tool_name)])
- if functional_tools:
- for functional_tool in functional_tools:
- if functional_tool.on_tool_stock_num == 0:
- if functional_tool.tool_stock_num == 0 and functional_tool.side_shelf_num == 0:
- status = True
- else:
- status = True
- if status:
- knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
- 'name': cnc_processing.workorder_id.production_id.name,
- 'cam_procedure_code': cnc_processing.program_name,
- 'filename': cnc_processing.cnc_id.name,
- 'functional_tool_name': cnc_processing.cutting_tool_name,
- 'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
- 'process_type': cnc_processing.processing_type,
- 'margin_x_y': float(cnc_processing.margin_x_y),
- 'margin_z': float(cnc_processing.margin_z),
- 'finish_depth': float(cnc_processing.depth_of_processing_z),
- 'extension_length': float(cnc_processing.cutting_tool_extension_length),
- 'shank_model': cnc_processing.cutting_tool_handle_type,
- 'estimated_processing_time': cnc_processing.estimated_processing_time,
- })
- logging.info('CAM工单程序用刀计划创建成功!!!')
- # 创建装刀请求
- knife_plan.apply_for_tooling()
- else:
- logging.info('功能刀具【%s】满足CNC用刀需求!!!' % cnc_processing.cutting_tool_name)
+ knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
+ 'name': cnc_processing.workorder_id.production_id.name,
+ 'cam_procedure_code': cnc_processing.program_name,
+ 'filename': cnc_processing.cnc_id.name,
+ 'functional_tool_name': cnc_processing.cutting_tool_name,
+ 'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
+ 'process_type': cnc_processing.processing_type,
+ 'margin_x_y': float(cnc_processing.margin_x_y),
+ 'margin_z': float(cnc_processing.margin_z),
+ 'finish_depth': float(cnc_processing.depth_of_processing_z),
+ 'extension_length': float(cnc_processing.cutting_tool_extension_length),
+ 'shank_model': cnc_processing.cutting_tool_handle_type,
+ 'estimated_processing_time': cnc_processing.estimated_processing_time,
+ })
+ logging.info('CAM工单程序用刀计划创建成功!!!')
+ # 创建装刀请求
+ knife_plan.apply_for_tooling()
def unlink_cam_plan(self, production):
for item in production:
@@ -834,7 +819,7 @@ class FunctionalToolDismantle(models.Model):
integral_lot_id = fields.Many2one('stock.lot', string='整体式刀具批次', compute='_compute_functional_tool_num',
store=True)
integral_freight_id = fields.Many2one('sf.shelf.location', '整体式刀具目标货位',
- domain="[('product_id', 'in', (integral_product_id, False))]")
+ domain="[('product_id', 'in', (integral_product_id, False)),('location_id.name', '=', '刀具房')]")
# 刀片
blade_product_id = fields.Many2one('product.product', string='刀片', compute='_compute_functional_tool_num',
@@ -844,7 +829,7 @@ class FunctionalToolDismantle(models.Model):
blade_brand_id = fields.Many2one('sf.machine.brand', string='刀片品牌', related='blade_product_id.brand_id')
blade_lot_id = fields.Many2one('stock.lot', string='刀片批次', compute='_compute_functional_tool_num', store=True)
blade_freight_id = fields.Many2one('sf.shelf.location', '刀片目标货位',
- domain="[('product_id', 'in', (blade_product_id, False))]")
+ domain="[('product_id', 'in', (blade_product_id, False)),('location_id.name', '=', '刀具房')]")
# 刀杆
bar_product_id = fields.Many2one('product.product', string='刀杆', compute='_compute_functional_tool_num',
@@ -854,7 +839,7 @@ class FunctionalToolDismantle(models.Model):
bar_brand_id = fields.Many2one('sf.machine.brand', string='刀杆品牌', related='bar_product_id.brand_id')
bar_lot_id = fields.Many2one('stock.lot', string='刀杆批次', compute='_compute_functional_tool_num', store=True)
bar_freight_id = fields.Many2one('sf.shelf.location', '刀杆目标货位',
- domain="[('product_id', 'in', (bar_product_id, False))]")
+ domain="[('product_id', 'in', (bar_product_id, False)),('location_id.name', '=', '刀具房')]")
# 刀盘
pad_product_id = fields.Many2one('product.product', string='刀盘', compute='_compute_functional_tool_num',
@@ -864,7 +849,7 @@ class FunctionalToolDismantle(models.Model):
pad_brand_id = fields.Many2one('sf.machine.brand', string='刀盘品牌', related='pad_product_id.brand_id')
pad_lot_id = fields.Many2one('stock.lot', string='刀盘批次', compute='_compute_functional_tool_num', store=True)
pad_freight_id = fields.Many2one('sf.shelf.location', '刀盘目标货位',
- domain="[('product_id', 'in', (pad_product_id, False))]")
+ domain="[('product_id', 'in', (pad_product_id, False)),('location_id.name', '=', '刀具房')]")
# 夹头
chuck_product_id = fields.Many2one('product.product', string='夹头', compute='_compute_functional_tool_num',
@@ -874,7 +859,7 @@ class FunctionalToolDismantle(models.Model):
chuck_brand_id = fields.Many2one('sf.machine.brand', string='夹头品牌', related='chuck_product_id.brand_id')
chuck_lot_id = fields.Many2one('stock.lot', string='夹头批次', compute='_compute_functional_tool_num', store=True)
chuck_freight_id = fields.Many2one('sf.shelf.location', '夹头目标货位',
- domain="[('product_id', 'in', (chuck_product_id, False))]")
+ domain="[('product_id', 'in', (chuck_product_id, False)),('location_id.name', '=', '刀具房')]")
@api.onchange('functional_tool_id')
def _onchange_freight(self):
diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py
index e21941ca..a2886add 100644
--- a/sf_tool_management/models/mrp_workorder.py
+++ b/sf_tool_management/models/mrp_workorder.py
@@ -10,6 +10,8 @@ class CNCprocessing(models.Model):
_inherit = 'sf.cnc.processing'
_description = 'CNC加工用刀检测'
+ tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='刀具状态', default='0')
+
# ==========MES装刀指令接口==========
# def register_cnc_processing(self, knife_plan):
# config = self.env['res.config.settings'].get_values()
@@ -29,13 +31,66 @@ class CNCprocessing(models.Model):
# else:
# raise ValidationError("MES装刀指令发送失败")
+ def cnc_tool_checkout(self, cnc_processing_ids):
+ """
+ 根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划
+ """
+ cam_id = self.env['sf.cam.work.order.program.knife.plan']
+ production_ids = [] # 制造订单集
+ datas = {} # 缺刀/无效刀集
+ for cnc_processing in cnc_processing_ids:
+ production_name = cnc_processing.production_id.name # 制造订单
+ processing_panel = cnc_processing.workorder_id.processing_panel # 加工面
+ if not datas.get(production_name):
+ datas.update({production_name: {}})
+ production_ids.append(cnc_processing.production_id)
+ if not datas.get(production_name).get(processing_panel):
+ datas.get(production_name).update({processing_panel: {'缺刀': [], '无效刀': []}})
+ if cnc_processing.cutting_tool_name:
+ tool_name = cnc_processing.cutting_tool_name
+ # 检验CNC用刀是否是功能刀具清单中的刀具
+ tool_inventory_id = self.env['sf.tool.inventory'].sudo().search([('name', '=', tool_name)])
+ if not tool_inventory_id:
+ datas[production_name][processing_panel]['无效刀'].append(cnc_processing.cutting_tool_name)
+ cnc_processing.tool_state = '2'
+ # todo 无效刀处理逻辑
+
+ # 跳过本次循环
+ continue
+ # 校验CNC用刀在系统是否存在
+ functional_tools = self.env['sf.functional.cutting.tool.entity'].sudo().search(
+ [('tool_name_id', '=', tool_inventory_id.id), ('functional_tool_status', '=', '正常')])
+ # 判断线边、机内是否有满足条件的刀
+ if not functional_tools.filtered(lambda p: p.current_location in ('线边刀库', '机内刀库')):
+ datas[production_name][processing_panel]['缺刀'].append(cnc_processing.cutting_tool_name)
+ cnc_processing.tool_state = '1'
+ # 判断是否有满足条件的刀
+ if not functional_tools:
+ # 创建CAM申请装刀记录
+ cam_id.create_cam_work_plan(cnc_processing)
+ logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
+ for production_id in production_ids:
+ if production_id:
+ data = datas.get(production_id.name)
+ tool_state_remark = ''
+ # todo 对无效刀信息进行处理
+
+ # 对缺刀信息进行处理
+ for key in data:
+ if tool_state_remark != '':
+ tool_state_remark = f'{tool_state_remark}\n{key}缺刀:{data.get(key).get("缺刀")}'
+ else:
+ tool_state_remark = f'{key}缺刀:{data.get(key).get("缺刀")}'
+ if production_id.tool_state == '1':
+ production_id.write({
+ 'tool_state_remark': tool_state_remark
+ })
+
@api.model_create_multi
def create(self, vals):
obj = super(CNCprocessing, self).create(vals)
- for item in obj:
- # 调用CAM工单程序用刀计划创建方法
- self.env['sf.cam.work.order.program.knife.plan'].create_cam_work_plan(item)
- logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
+ # 调用CAM工单程序用刀计划创建方法
+ self.cnc_tool_checkout(obj)
return obj
From 134e23ea2fc82c145bfa32d8662ea3308a183b54 Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Wed, 10 Jul 2024 16:25:18 +0800
Subject: [PATCH 2/5] =?UTF-8?q?1=E3=80=81=E9=87=8D=E6=9E=84=E5=B7=A5?=
=?UTF-8?q?=E5=8D=95=E5=B7=A5=E5=BA=8F=E7=9A=84=E7=94=9F=E6=88=90=E6=96=B9?=
=?UTF-8?q?=E6=B3=95=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/models/mrp_production.py | 130 +++++++++++++---------
1 file changed, 75 insertions(+), 55 deletions(-)
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index f9492a37..0b4da7cc 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -536,70 +536,90 @@ class MrpProduction(models.Model):
def _reset_work_order_sequence(self):
for rec in self:
- sequence_list = {}
+ workorder_ids = rec.workorder_ids.filtered(lambda item: item.state in ('返工', 'rework'))
# 产品模型类型
model_type_id = rec.product_id.product_model_type_id
# 产品加工面板
model_processing_panel = rec.product_id.model_processing_panel
- if model_type_id:
- if model_processing_panel:
- tmpl_num = 1
- panel_list = model_processing_panel.split(',')
- for panel in panel_list:
- panel_sequence_list = {}
- # 成品工序
- product_routing_tmpl_ids = model_type_id.product_routing_tmpl_ids
- if product_routing_tmpl_ids:
- for tmpl_id in product_routing_tmpl_ids:
- panel_sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
- tmpl_num += 1
- sequence_list.update({panel: panel_sequence_list})
- # 表面工艺工序
- # 模型类型的表面工艺工序模版
- surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
- # 产品选择的表面工艺
- model_process_parameters_ids = rec.product_id.model_process_parameters_ids
- process_dict = {}
- if model_process_parameters_ids:
- for process_parameters_id in model_process_parameters_ids:
- process_id = process_parameters_id.process_id
- for surface_tmpl_id in surface_tmpl_ids:
- if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
- surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
- process_dict.update({int(process_id.category_id.code): '%s-%s' % (
- surface_tmpl_name, process_parameters_id.name)})
- process_list = sorted(process_dict.keys())
- for process_num in process_list:
- sequence_list.update({process_dict.get(process_num): tmpl_num})
- tmpl_num += 1
- # 坯料工序
- tmpl_num = 1
- embryo_routing_tmpl_ids = model_type_id.embryo_routing_tmpl_ids
- if embryo_routing_tmpl_ids:
- for tmpl_id in embryo_routing_tmpl_ids:
- sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
+ if not workorder_ids:
+ sequence_list = {}
+ if model_type_id:
+ if model_processing_panel:
+ tmpl_num = 1
+ panel_list = model_processing_panel.split(',')
+ for panel in panel_list:
+ panel_sequence_list = {}
+ # 成品工序
+ product_routing_tmpl_ids = model_type_id.product_routing_tmpl_ids
+ if product_routing_tmpl_ids:
+ for tmpl_id in product_routing_tmpl_ids:
+ panel_sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
+ tmpl_num += 1
+ sequence_list.update({panel: panel_sequence_list})
+ # 表面工艺工序
+ # 模型类型的表面工艺工序模版
+ surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
+ # 产品选择的表面工艺
+ model_process_parameters_ids = rec.product_id.model_process_parameters_ids
+ process_dict = {}
+ if model_process_parameters_ids:
+ for process_parameters_id in model_process_parameters_ids:
+ process_id = process_parameters_id.process_id
+ for surface_tmpl_id in surface_tmpl_ids:
+ if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
+ surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
+ process_dict.update({int(process_id.category_id.code): '%s-%s' % (
+ surface_tmpl_name, process_parameters_id.name)})
+ process_list = sorted(process_dict.keys())
+ for process_num in process_list:
+ sequence_list.update({process_dict.get(process_num): tmpl_num})
tmpl_num += 1
+ # 坯料工序
+ tmpl_num = 1
+ embryo_routing_tmpl_ids = model_type_id.embryo_routing_tmpl_ids
+ if embryo_routing_tmpl_ids:
+ for tmpl_id in embryo_routing_tmpl_ids:
+ sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
+ tmpl_num += 1
+ else:
+ raise ValidationError('该产品【加工面板】为空!')
else:
- raise ValidationError('该产品【加工面板】为空!')
+ raise ValidationError('该产品没有选择【模版类型】!')
- else:
- raise ValidationError('该产品没有选择【模版类型】!')
-
- for work in rec.workorder_ids:
- if sequence_list.get(work.name):
- work.sequence = sequence_list[work.name]
- elif sequence_list.get(work.processing_panel):
- processing_panel = sequence_list.get(work.processing_panel)
- if processing_panel.get(work.name):
- work.sequence = processing_panel[work.name]
+ for work in rec.workorder_ids:
+ if sequence_list.get(work.name):
+ work.sequence = sequence_list[work.name]
+ elif sequence_list.get(work.processing_panel):
+ processing_panel = sequence_list.get(work.processing_panel)
+ if processing_panel.get(work.name):
+ work.sequence = processing_panel[work.name]
+ else:
+ raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
else:
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
- else:
- raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
- # if work.name == '获取CNC加工程序':
- # work.button_start()
- # #work.fetchCNC()
- # work.button_finish()
+ # 当单个面触发返工时,将新生成的工单插入到返工工单下方,并且后面的所以工单工序重排
+ elif rec.workorder_ids.filtered(lambda item: item.sequence == 0):
+ # 获取新增的返工工单
+ work_ids = rec.workorder_ids.filtered(lambda item: item.sequence == 0)
+ # 获取当前返工面最后一个工单工序
+ sequence_max = sorted(
+ rec.workorder_ids.filtered(lambda item: item.processing_panel == work_ids[0].processing_panel),
+ key=lambda item: item.sequence, reverse=True)[0].sequence
+ # 对当前返工工单之后的工单工序进行重排
+ work_order_ids = rec.workorder_ids.filtered(lambda item: item.sequence > sequence_max)
+ for work_id in work_order_ids:
+ work_id.sequence = work_id.sequence + 3
+ # 生成新增的返工工单的工序
+ # 成品工序
+ panel_sequence_list = {}
+ product_routing_tmpl_ids = model_type_id.product_routing_tmpl_ids
+ if product_routing_tmpl_ids:
+ for tmpl_id in product_routing_tmpl_ids:
+ sequence_max += 1
+ panel_sequence_list.update({tmpl_id.route_workcenter_id.name: sequence_max})
+ for work_id in work_ids:
+ if panel_sequence_list.get(work_id.name):
+ work_id.sequence = panel_sequence_list[work_id.name]
# 创建工单并进行排序
def _create_workorder(self, item):
From 77815c45a0519967fcaecb1ef3093c052897f0d8 Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Thu, 11 Jul 2024 16:37:20 +0800
Subject: [PATCH 3/5] =?UTF-8?q?1=E3=80=81=E5=BD=93=E6=A3=80=E6=B5=8B?=
=?UTF-8?q?=E5=88=B0=E7=BC=BA=E5=88=80=E5=B7=A5=E5=8D=95=E9=9C=80=E8=A6=81?=
=?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E4=BB=8E=E5=88=80?=
=?UTF-8?q?=E5=85=B7=E6=88=BF=E5=87=BA=E5=BA=93=E5=88=B0=E7=BA=BF=E8=BE=B9?=
=?UTF-8?q?=E5=88=80=E6=9E=B6=E6=97=B6=EF=BC=8C=E6=9B=B4=E6=94=B9cnc?=
=?UTF-8?q?=E7=BC=96=E7=A8=8B=E5=8D=95=E7=9A=84=E5=8A=9F=E8=83=BD=E5=88=80?=
=?UTF-8?q?=E5=85=B7=E7=8A=B6=E6=80=81=E4=B8=BA=E6=AD=A3=E5=B8=B8=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/models/mrp_production.py | 4 ++--
sf_manufacturing/models/mrp_workorder.py | 2 ++
sf_tool_management/models/functional_tool.py | 15 +++++++++++++++
sf_tool_management/models/mrp_workorder.py | 2 --
4 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index 0b4da7cc..0c3ab335 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -32,9 +32,9 @@ class MrpProduction(models.Model):
def _compute_tool_state(self):
for item in self:
if item:
- if item.workorder_ids.filtered(lambda a: a.tool_state == '2'):
+ if item.workorder_ids.filtered(lambda a: a.tool_state == '2' and a.state not in ('rework', '返工')):
item.tool_state = '2'
- elif item.workorder_ids.filtered(lambda a: a.tool_state == '1'):
+ elif item.workorder_ids.filtered(lambda a: a.tool_state == '1' and a.state not in ('rework', '返工')):
item.tool_state = '1'
else:
item.tool_state = '0'
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 4fefc154..944bf402 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -1135,6 +1135,8 @@ class CNCprocessing(models.Model):
program_path = fields.Char('程序文件路径')
program_create_date = fields.Datetime('程序创建日期')
+ tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='刀具状态', default='0')
+
# mrs下发编程单创建CNC加工
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
cnc_processing = None
diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py
index 4e791fe5..4138bfe3 100644
--- a/sf_tool_management/models/functional_tool.py
+++ b/sf_tool_management/models/functional_tool.py
@@ -115,6 +115,8 @@ class FunctionalCuttingToolEntity(models.Model):
# 新刀入库到线边
item.create_stock_move(pre_manufacturing_id, location_id)
item.current_shelf_location_id = location_id.id
+ # 对该刀进行校验(校验是否为制造订单所缺的刀)
+ item.cnc_function_tool_use_verify()
# 中控反馈该位置没有刀
else:
@@ -255,6 +257,15 @@ class FunctionalCuttingToolEntity(models.Model):
result['domain'] = [('id', '=', self.safe_inventory_id.id)]
return result
+ def cnc_function_tool_use_verify(self):
+ """
+ cnc程序用刀可用校验
+ """
+ cnc_processing_ids = self.env['sf.cnc.processing'].search(
+ [('tool_state', '=', '1'), ('cutting_tool_name', '=', self.tool_name_id.name)])
+ if cnc_processing_ids:
+ cnc_processing_ids.sudo().write({'tool_state': '0'})
+
def tool_inventory_displacement_out(self):
"""
机床当前刀库实时信息接口,功能刀具出库
@@ -265,6 +276,10 @@ class FunctionalCuttingToolEntity(models.Model):
self.create_stock_move(stock_location_id, False)
self.current_location_id = stock_location_id.id
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.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
# self.functional_tool_name_id.tool_groups_id)
diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py
index a2886add..f3476864 100644
--- a/sf_tool_management/models/mrp_workorder.py
+++ b/sf_tool_management/models/mrp_workorder.py
@@ -10,8 +10,6 @@ class CNCprocessing(models.Model):
_inherit = 'sf.cnc.processing'
_description = 'CNC加工用刀检测'
- tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='刀具状态', default='0')
-
# ==========MES装刀指令接口==========
# def register_cnc_processing(self, knife_plan):
# config = self.env['res.config.settings'].get_values()
From 37977be8620916916169f2ec593f37072ecbad2a Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Tue, 16 Jul 2024 10:40:18 +0800
Subject: [PATCH 4/5] =?UTF-8?q?1=E3=80=81=E5=B7=A5=E5=8D=95=E8=A7=A3?=
=?UTF-8?q?=E7=BB=91=E6=97=B6=E6=B7=BB=E5=8A=A0=E4=BA=8C=E6=AC=A1=E6=A0=A1?=
=?UTF-8?q?=E9=AA=8C=E6=98=AF=E5=90=A6=E8=A7=A3=E7=BB=91=E6=88=90=E5=8A=9F?=
=?UTF-8?q?=EF=BC=9B2=E3=80=81=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95?=
=?UTF-8?q?=E5=88=9B=E5=BB=BA=E6=8E=A5=E5=8F=A3=E6=B7=BB=E5=8A=A0=E8=AF=A6?=
=?UTF-8?q?=E6=83=85=E4=BF=A1=E6=81=AF=E2=80=98=E5=A4=87=E6=B3=A8=E2=80=99?=
=?UTF-8?q?=E5=AD=97=E6=AE=B5=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_manufacturing/models/mrp_workorder.py | 18 ++++++++++--------
sf_sale/models/sale_order.py | 1 +
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py
index 944bf402..eb036294 100644
--- a/sf_manufacturing/models/mrp_workorder.py
+++ b/sf_manufacturing/models/mrp_workorder.py
@@ -13,7 +13,7 @@ from dateutil.relativedelta import relativedelta
# import subprocess
from odoo import api, fields, models, SUPERUSER_ID, _
from odoo.addons.sf_base.commons.common import Common
-from odoo.exceptions import UserError
+from odoo.exceptions import UserError,ValidationError
from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
@@ -1019,13 +1019,15 @@ class ResMrpWorkOrder(models.Model):
if workorder.state != 'done':
is_production_id = False
if record.routing_type == '解除装夹':
- for workorder in record.production_id.workorder_ids:
- if workorder.processing_panel == record.processing_panel:
- rfid_code = workorder.rfid_code
- workorder.write({'rfid_code_old': rfid_code,
- 'rfid_code': False})
- workorder.rfid_code_old = rfid_code
- workorder.rfid_code = False
+ for workorder in record.production_id.workorder_ids.filtered(
+ lambda a: a.processing_panel == record.processing_panel):
+ rfid_code = workorder.rfid_code
+ workorder.write({'rfid_code_old': rfid_code,
+ 'rfid_code': False})
+ if workorder.rfid_code:
+ raise ValidationError(f'【{workorder.name}】工单解绑失败,请重新点击完成按钮!!!')
+ workorder.rfid_code_old = rfid_code
+ workorder.rfid_code = False
if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']:
logging.info('product_qty:%s' % record.production_id.product_qty)
for move_raw_id in record.production_id.move_raw_ids:
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py
index 2791c760..b7da1898 100644
--- a/sf_sale/models/sale_order.py
+++ b/sf_sale/models/sale_order.py
@@ -113,6 +113,7 @@ class ReSaleOrder(models.Model):
'price_unit': product.list_price,
'product_uom_qty': item['number'],
'model_glb_file': base64.b64decode(item['model_file']),
+ 'remark': item.get('remark')
}
return self.env['sale.order.line'].with_context(skip_procurement=True).create(vals)
From 25ac346cb748465d3e52f7272d7dcf6b45df908f Mon Sep 17 00:00:00 2001
From: yuxianghui <3437689193@qq.com>
Date: Thu, 18 Jul 2024 16:33:41 +0800
Subject: [PATCH 5/5] =?UTF-8?q?1=E3=80=81cnc=E7=BC=96=E7=A8=8B=E5=8D=95tre?=
=?UTF-8?q?e=E8=A7=86=E5=9B=BE=E5=B1=95=E7=A4=BA=E5=88=80=E5=85=B7?=
=?UTF-8?q?=E7=8A=B6=E6=80=81=E5=AD=97=E6=AE=B5=EF=BC=9B2=E3=80=81?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=E5=88=B6=E9=80=A0=E8=AE=A2=E5=8D=95=E7=9A=84?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD=E5=88=80=E5=85=B7=E7=8A=B6=E6=80=81=E5=AD=97?=
=?UTF-8?q?=E6=AE=B5=E8=87=AA=E5=8A=A8=E6=9B=B4=E6=96=B0=E6=96=B9=E6=B3=95?=
=?UTF-8?q?=EF=BC=8C=E5=90=8C=E6=97=B6=E5=BD=93=E5=B7=A5=E5=8D=95=E5=88=80?=
=?UTF-8?q?=E5=85=B7=E7=8A=B6=E6=80=81=E5=8F=98=E5=8C=96=E6=97=B6=E5=8F=98?=
=?UTF-8?q?=E6=9B=B4=E7=BC=BA=E5=88=80=E5=A4=87=E6=B3=A8=E4=BF=A1=E6=81=AF?=
=?UTF-8?q?=EF=BC=8C=E6=B7=BB=E5=8A=A0=E7=8A=B6=E6=80=81=E4=B8=BA=E6=97=A0?=
=?UTF-8?q?=E6=95=88=E5=88=80=E7=9A=84=E5=A4=87=E6=B3=A8=E5=AD=97=E6=AE=B5?=
=?UTF-8?q?=EF=BC=9B3=E3=80=81=E4=BC=98=E5=8C=96=E5=BD=93=E5=8A=9F?=
=?UTF-8?q?=E8=83=BD=E5=88=80=E5=85=B7=E4=BB=8E=E3=80=90=E5=88=80=E5=85=B7?=
=?UTF-8?q?=E6=88=BF=E3=80=91=E5=88=B0=E3=80=90=E5=88=B6=E9=80=A0=E5=89=8D?=
=?UTF-8?q?=E3=80=91=E6=97=B6=E8=BF=9B=E8=A1=8C=E6=A0=A1=E9=AA=8C=EF=BC=8C?=
=?UTF-8?q?=E6=A0=A1=E9=AA=8C=E6=98=AF=E5=90=A6=E4=B8=BA=E5=88=B6=E9=80=A0?=
=?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=89=80=E7=BC=BA=E7=9A=84=E5=88=80=EF=BC=8C?=
=?UTF-8?q?=E5=A6=82=E6=9E=9C=E6=98=AF=E5=88=99=E4=BF=AE=E6=94=B9cnc?=
=?UTF-8?q?=E7=BC=96=E7=A8=8B=E5=8D=95=E5=88=80=E5=85=B7=E7=8A=B6=E6=80=81?=
=?UTF-8?q?=E4=B8=BA=E6=AD=A3=E5=B8=B8=EF=BC=9B4=E3=80=81=E4=BC=98?=
=?UTF-8?q?=E5=8C=96cnc=E7=94=A8=E5=88=80=E6=A0=A1=E9=AA=8C=EF=BC=9A?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=AF=B9=E6=97=A0=E6=95=88=E5=88=80=E7=9A=84?=
=?UTF-8?q?=E5=A4=84=E7=90=86(=E6=97=A0=E6=95=88=E5=88=80=E6=97=B6?=
=?UTF-8?q?=E8=A7=A6=E5=8F=91=E8=BF=94=E5=B7=A5=E6=B5=81=E7=A8=8B=EF=BC=8C?=
=?UTF-8?q?=E5=B9=B6=E7=94=9F=E6=88=90=E6=A3=80=E6=B5=8B=E7=BB=93=E6=9E=9C?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE)=EF=BC=8C=E4=BC=98=E5=8C=96=E7=94=9F?=
=?UTF-8?q?=E6=88=90=E7=9A=84=E5=BE=85=E5=A4=84=E7=90=86=E6=95=B0=E6=8D=AE?=
=?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E7=BB=93=E6=9E=84=EF=BC=9B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
sf_machine_connect/views/default_delivery.xml | 1 +
sf_manufacturing/models/mrp_production.py | 29 ++++++-
.../views/mrp_production_addional_change.xml | 1 +
sf_manufacturing/views/mrp_workorder_view.xml | 1 +
sf_tool_management/models/functional_tool.py | 16 ++--
sf_tool_management/models/mrp_workorder.py | 79 ++++++++++++++-----
sf_tool_management/models/stock.py | 37 +++++++++
7 files changed, 130 insertions(+), 34 deletions(-)
diff --git a/sf_machine_connect/views/default_delivery.xml b/sf_machine_connect/views/default_delivery.xml
index 0238c736..c9f3c07c 100644
--- a/sf_machine_connect/views/default_delivery.xml
+++ b/sf_machine_connect/views/default_delivery.xml
@@ -11,6 +11,7 @@
+
diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py
index b191e514..aabec83e 100644
--- a/sf_manufacturing/models/mrp_production.py
+++ b/sf_manufacturing/models/mrp_production.py
@@ -26,22 +26,43 @@ class MrpProduction(models.Model):
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
string='工单状态', default='未排')
-
detection_result_ids = fields.One2many('sf.detection.result', 'production_id', '检测报告')
tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='功能刀具状态', default='0',
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')
def _compute_tool_state(self):
for item in self:
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'
- 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_remark = tool_state_remark
+ item.tool_state_remark2 = ''
else:
item.tool_state = '0'
+ item.tool_state_remark = ''
+ item.tool_state_remark2 = ''
# state = fields.Selection(selection_add=[
# ('pending_scheduling', '待排程'),
diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml
index 8003eb4d..8d70027c 100644
--- a/sf_manufacturing/views/mrp_production_addional_change.xml
+++ b/sf_manufacturing/views/mrp_production_addional_change.xml
@@ -99,6 +99,7 @@
+
+
diff --git a/sf_tool_management/models/functional_tool.py b/sf_tool_management/models/functional_tool.py
index 4138bfe3..1e496985 100644
--- a/sf_tool_management/models/functional_tool.py
+++ b/sf_tool_management/models/functional_tool.py
@@ -115,8 +115,6 @@ class FunctionalCuttingToolEntity(models.Model):
# 新刀入库到线边
item.create_stock_move(pre_manufacturing_id, location_id)
item.current_shelf_location_id = location_id.id
- # 对该刀进行校验(校验是否为制造订单所缺的刀)
- item.cnc_function_tool_use_verify()
# 中控反馈该位置没有刀
else:
@@ -259,12 +257,13 @@ class FunctionalCuttingToolEntity(models.Model):
def cnc_function_tool_use_verify(self):
"""
- cnc程序用刀可用校验
+ cnc程序用刀可用校验(校验是否是制造订单所缺刀)
"""
- cnc_processing_ids = self.env['sf.cnc.processing'].search(
- [('tool_state', '=', '1'), ('cutting_tool_name', '=', self.tool_name_id.name)])
- if cnc_processing_ids:
- cnc_processing_ids.sudo().write({'tool_state': '0'})
+ if self.tool_name_id.name:
+ cnc_processing_ids = self.env['sf.cnc.processing'].search(
+ [('tool_state', '=', '1'), ('cutting_tool_name', '=', self.tool_name_id.name)])
+ if cnc_processing_ids:
+ cnc_processing_ids.sudo().write({'tool_state': '0'})
def tool_inventory_displacement_out(self):
"""
@@ -277,9 +276,6 @@ class FunctionalCuttingToolEntity(models.Model):
self.current_location_id = stock_location_id.id
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.functional_tool_name_id.id, '机床装刀', self.functional_tool_name_id,
# self.functional_tool_name_id.tool_groups_id)
diff --git a/sf_tool_management/models/mrp_workorder.py b/sf_tool_management/models/mrp_workorder.py
index f3476864..465d3ea6 100644
--- a/sf_tool_management/models/mrp_workorder.py
+++ b/sf_tool_management/models/mrp_workorder.py
@@ -35,24 +35,29 @@ class CNCprocessing(models.Model):
"""
cam_id = self.env['sf.cam.work.order.program.knife.plan']
production_ids = [] # 制造订单集
- datas = {} # 缺刀/无效刀集
+ datas = {'缺刀': {}, '无效刀': {}} # 缺刀/无效刀集
for cnc_processing in cnc_processing_ids:
+ # ======创建字典: {'缺刀': {'制造订单1': {'加工面1': [], ...}, ...}, '无效刀': {'制造订单1': {'加工面1': [], ...}, ...}}======
production_name = cnc_processing.production_id.name # 制造订单
processing_panel = cnc_processing.workorder_id.processing_panel # 加工面
- if not datas.get(production_name):
- datas.update({production_name: {}})
+ if production_name not in list(datas['缺刀'].keys()):
+ datas['缺刀'].update({production_name: {processing_panel: []}})
+ datas['无效刀'].update({production_name: {processing_panel: []}})
production_ids.append(cnc_processing.production_id)
- if not datas.get(production_name).get(processing_panel):
- datas.get(production_name).update({processing_panel: {'缺刀': [], '无效刀': []}})
+ else:
+ 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:
tool_name = cnc_processing.cutting_tool_name
# 检验CNC用刀是否是功能刀具清单中的刀具
tool_inventory_id = self.env['sf.tool.inventory'].sudo().search([('name', '=', tool_name)])
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'
- # todo 无效刀处理逻辑
-
+ logging.info(f'"无效刀":[{production_name}、{processing_panel}、{cnc_processing.cutting_tool_name}]')
# 跳过本次循环
continue
# 校验CNC用刀在系统是否存在
@@ -60,28 +65,62 @@ class CNCprocessing(models.Model):
[('tool_name_id', '=', tool_inventory_id.id), ('functional_tool_status', '=', '正常')])
# 判断线边、机内是否有满足条件的刀
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'
+ logging.info(f'"缺刀":[{production_name}、{processing_panel}、{cnc_processing.cutting_tool_name}]')
# 判断是否有满足条件的刀
if not functional_tools:
# 创建CAM申请装刀记录
cam_id.create_cam_work_plan(cnc_processing)
logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
+ logging.info(datas)
for production_id in production_ids:
if production_id:
- data = datas.get(production_id.name)
- tool_state_remark = ''
- # todo 对无效刀信息进行处理
-
+ data1 = datas['无效刀'].get(production_id.name) # data1: {'加工面1': [], ...}
+ data2 = datas['缺刀'].get(production_id.name) # data2: {'加工面1': [], ...}
+ 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_remark != '':
- tool_state_remark = f'{tool_state_remark}\n{key}缺刀:{data.get(key).get("缺刀")}'
- else:
- tool_state_remark = f'{key}缺刀:{data.get(key).get("缺刀")}'
- if production_id.tool_state == '1':
+ if tool_state_remark1 == '':
+ for key in data2:
+ if data2.get(key) and not data1.get(key):
+ if tool_state_remark2 != '':
+ tool_state_remark2 = f'{tool_state_remark2}\n{key}缺刀:{data2.get(key)}'
+ else:
+ tool_state_remark2 = f'{key}缺刀:{data2.get(key)}'
+ # 将备注信息存入制造订单功能刀具状态的备注字段
+ if production_id.tool_state_remark2 == '':
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
diff --git a/sf_tool_management/models/stock.py b/sf_tool_management/models/stock.py
index be0f2e45..a179c7d7 100644
--- a/sf_tool_management/models/stock.py
+++ b/sf_tool_management/models/stock.py
@@ -21,3 +21,40 @@ class ShelfLocation(models.Model):
continue
item.tool_rfid = ''
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