Merge branch 'feature/CNC功能刀具用刀校验' into feature/销售订单、工单优化
This commit is contained in:
@@ -24,6 +24,21 @@ class MrpProduction(models.Model):
|
|||||||
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
|
work_order_state = fields.Selection([('未排', '未排'), ('已排', '已排'), ('已完成', '已完成')],
|
||||||
string='工单状态', default='未排')
|
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' and a.state not in ('rework', '返工')):
|
||||||
|
item.tool_state = '2'
|
||||||
|
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'
|
||||||
|
|
||||||
# state = fields.Selection(selection_add=[
|
# state = fields.Selection(selection_add=[
|
||||||
# ('pending_scheduling', '待排程'),
|
# ('pending_scheduling', '待排程'),
|
||||||
# ('pending_processing', '待加工'),
|
# ('pending_processing', '待加工'),
|
||||||
@@ -524,70 +539,90 @@ class MrpProduction(models.Model):
|
|||||||
|
|
||||||
def _reset_work_order_sequence(self):
|
def _reset_work_order_sequence(self):
|
||||||
for rec in 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_type_id = rec.product_id.product_model_type_id
|
||||||
# 产品加工面板
|
# 产品加工面板
|
||||||
model_processing_panel = rec.product_id.model_processing_panel
|
model_processing_panel = rec.product_id.model_processing_panel
|
||||||
if model_type_id:
|
if not workorder_ids:
|
||||||
if model_processing_panel:
|
sequence_list = {}
|
||||||
tmpl_num = 1
|
if model_type_id:
|
||||||
panel_list = model_processing_panel.split(',')
|
if model_processing_panel:
|
||||||
for panel in panel_list:
|
tmpl_num = 1
|
||||||
panel_sequence_list = {}
|
panel_list = model_processing_panel.split(',')
|
||||||
# 成品工序
|
for panel in panel_list:
|
||||||
product_routing_tmpl_ids = model_type_id.product_routing_tmpl_ids
|
panel_sequence_list = {}
|
||||||
if product_routing_tmpl_ids:
|
# 成品工序
|
||||||
for tmpl_id in product_routing_tmpl_ids:
|
product_routing_tmpl_ids = model_type_id.product_routing_tmpl_ids
|
||||||
panel_sequence_list.update({tmpl_id.route_workcenter_id.name: tmpl_num})
|
if product_routing_tmpl_ids:
|
||||||
tmpl_num += 1
|
for tmpl_id in product_routing_tmpl_ids:
|
||||||
sequence_list.update({panel: panel_sequence_list})
|
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
|
surface_tmpl_ids = model_type_id.surface_technics_routing_tmpl_ids
|
||||||
process_dict = {}
|
# 产品选择的表面工艺
|
||||||
if model_process_parameters_ids:
|
model_process_parameters_ids = rec.product_id.model_process_parameters_ids
|
||||||
for process_parameters_id in model_process_parameters_ids:
|
process_dict = {}
|
||||||
process_id = process_parameters_id.process_id
|
if model_process_parameters_ids:
|
||||||
for surface_tmpl_id in surface_tmpl_ids:
|
for process_parameters_id in model_process_parameters_ids:
|
||||||
if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
|
process_id = process_parameters_id.process_id
|
||||||
surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
|
for surface_tmpl_id in surface_tmpl_ids:
|
||||||
process_dict.update({int(process_id.category_id.code): '%s-%s' % (
|
if process_id == surface_tmpl_id.route_workcenter_id.surface_technics_id:
|
||||||
surface_tmpl_name, process_parameters_id.name)})
|
surface_tmpl_name = surface_tmpl_id.route_workcenter_id.name
|
||||||
process_list = sorted(process_dict.keys())
|
process_dict.update({int(process_id.category_id.code): '%s-%s' % (
|
||||||
for process_num in process_list:
|
surface_tmpl_name, process_parameters_id.name)})
|
||||||
sequence_list.update({process_dict.get(process_num): tmpl_num})
|
process_list = sorted(process_dict.keys())
|
||||||
tmpl_num += 1
|
for process_num in process_list:
|
||||||
# 坯料工序
|
sequence_list.update({process_dict.get(process_num): tmpl_num})
|
||||||
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
|
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:
|
else:
|
||||||
raise ValidationError('该产品【加工面板】为空!')
|
raise ValidationError('该产品没有选择【模版类型】!')
|
||||||
|
|
||||||
else:
|
for work in rec.workorder_ids:
|
||||||
raise ValidationError('该产品没有选择【模版类型】!')
|
if sequence_list.get(work.name):
|
||||||
|
work.sequence = sequence_list[work.name]
|
||||||
for work in rec.workorder_ids:
|
elif sequence_list.get(work.processing_panel):
|
||||||
if sequence_list.get(work.name):
|
processing_panel = sequence_list.get(work.processing_panel)
|
||||||
work.sequence = sequence_list[work.name]
|
if processing_panel.get(work.name):
|
||||||
elif sequence_list.get(work.processing_panel):
|
work.sequence = processing_panel[work.name]
|
||||||
processing_panel = sequence_list.get(work.processing_panel)
|
else:
|
||||||
if processing_panel.get(work.name):
|
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
||||||
work.sequence = processing_panel[work.name]
|
|
||||||
else:
|
else:
|
||||||
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
||||||
else:
|
# 当单个面触发返工时,将新生成的工单插入到返工工单下方,并且后面的所以工单工序重排
|
||||||
raise ValidationError('工序【%s】在产品选择的模版类型中不存在!' % work.name)
|
elif rec.workorder_ids.filtered(lambda item: item.sequence == 0):
|
||||||
# if work.name == '获取CNC加工程序':
|
# 获取新增的返工工单
|
||||||
# work.button_start()
|
work_ids = rec.workorder_ids.filtered(lambda item: item.sequence == 0)
|
||||||
# #work.fetchCNC()
|
# 获取当前返工面最后一个工单工序
|
||||||
# work.button_finish()
|
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):
|
def _create_workorder(self, item):
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ from dateutil.relativedelta import relativedelta
|
|||||||
# import subprocess
|
# import subprocess
|
||||||
from odoo import api, fields, models, SUPERUSER_ID, _
|
from odoo import api, fields, models, SUPERUSER_ID, _
|
||||||
from odoo.addons.sf_base.commons.common import Common
|
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
|
from odoo.addons.sf_mrs_connect.models.ftp_operate import FtpController
|
||||||
|
|
||||||
|
|
||||||
@@ -158,6 +158,21 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# 加工图纸
|
# 加工图纸
|
||||||
processing_drawing = fields.Binary(string='加工图纸')
|
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')
|
@api.depends('production_id')
|
||||||
def _compute_save_name(self):
|
def _compute_save_name(self):
|
||||||
"""
|
"""
|
||||||
@@ -1004,13 +1019,15 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
if workorder.state != 'done':
|
if workorder.state != 'done':
|
||||||
is_production_id = False
|
is_production_id = False
|
||||||
if record.routing_type == '解除装夹':
|
if record.routing_type == '解除装夹':
|
||||||
for workorder in record.production_id.workorder_ids:
|
for workorder in record.production_id.workorder_ids.filtered(
|
||||||
if workorder.processing_panel == record.processing_panel:
|
lambda a: a.processing_panel == record.processing_panel):
|
||||||
rfid_code = workorder.rfid_code
|
rfid_code = workorder.rfid_code
|
||||||
workorder.write({'rfid_code_old': rfid_code,
|
workorder.write({'rfid_code_old': rfid_code,
|
||||||
'rfid_code': False})
|
'rfid_code': False})
|
||||||
workorder.rfid_code_old = rfid_code
|
if workorder.rfid_code:
|
||||||
workorder.rfid_code = False
|
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 ['解除装夹', '表面工艺']:
|
if is_production_id is True and record.routing_type in ['解除装夹', '表面工艺']:
|
||||||
logging.info('product_qty:%s' % record.production_id.product_qty)
|
logging.info('product_qty:%s' % record.production_id.product_qty)
|
||||||
for move_raw_id in record.production_id.move_raw_ids:
|
for move_raw_id in record.production_id.move_raw_ids:
|
||||||
@@ -1130,6 +1147,8 @@ class CNCprocessing(models.Model):
|
|||||||
program_path = fields.Char('程序文件路径')
|
program_path = fields.Char('程序文件路径')
|
||||||
program_create_date = fields.Datetime('程序创建日期')
|
program_create_date = fields.Datetime('程序创建日期')
|
||||||
|
|
||||||
|
tool_state = fields.Selection([('0', '正常'), ('1', '缺刀'), ('2', '无效刀')], string='刀具状态', default='0')
|
||||||
|
|
||||||
# mrs下发编程单创建CNC加工
|
# mrs下发编程单创建CNC加工
|
||||||
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
|
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
|
||||||
cnc_processing = None
|
cnc_processing = None
|
||||||
|
|||||||
@@ -87,9 +87,11 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='user_id']" position="after">
|
<xpath expr="//field[@name='user_id']" position="after">
|
||||||
<field name="production_line_id" readonly="1"/>
|
<field name="production_line_id" readonly="1"/>
|
||||||
<!-- <field name="production_line_state" readonly="1"/>-->
|
<!-- <field name="production_line_state" readonly="1"/>-->
|
||||||
<field name="part_number" string="成品的零件图号"/>
|
<field name="part_number" string="成品的零件图号"/>
|
||||||
<field name="part_drawing"/>
|
<field name="part_drawing"/>
|
||||||
|
<field name="tool_state"/>
|
||||||
|
<field name="tool_state_remark" string="备注" attrs="{'invisible': [('tool_state', '!=', '1')]}"/>
|
||||||
</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"
|
||||||
@@ -365,7 +367,9 @@
|
|||||||
<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="取消" groups="sf_base.group_sf_mrp_user"/>
|
<button name="action_cancel" type="object" string="取消" groups="sf_base.group_sf_mrp_user"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
<xpath expr="//field[@name='state']" position="after">
|
||||||
|
<field name="tool_state" invisible="1"/>
|
||||||
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
</field>
|
</field>
|
||||||
<field name="state" position="after">
|
<field name="state" position="after">
|
||||||
<field name="work_state" optional="hide"/>
|
<field name="work_state" optional="hide"/>
|
||||||
|
<field name="tool_state" invisible="1"/>
|
||||||
<field name="product_tmpl_name" invisible="1"/>
|
<field name="product_tmpl_name" invisible="1"/>
|
||||||
</field>
|
</field>
|
||||||
<field name="duration" position="replace">
|
<field name="duration" position="replace">
|
||||||
@@ -121,6 +122,7 @@
|
|||||||
</button>
|
</button>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='state']" position="before">
|
<xpath expr="//field[@name='state']" position="before">
|
||||||
|
<field name='tool_state' invisible="1"/>
|
||||||
<field name='user_permissions' invisible="1"/>
|
<field name='user_permissions' invisible="1"/>
|
||||||
<field name='name' invisible="1"/>
|
<field name='name' invisible="1"/>
|
||||||
<field name='is_delivery' invisible="1"/>
|
<field name='is_delivery' invisible="1"/>
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ class ReSaleOrder(models.Model):
|
|||||||
'price_unit': product.list_price,
|
'price_unit': product.list_price,
|
||||||
'product_uom_qty': item['number'],
|
'product_uom_qty': item['number'],
|
||||||
'model_glb_file': base64.b64decode(item['model_file']),
|
'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)
|
return self.env['sale.order.line'].with_context(skip_procurement=True).create(vals)
|
||||||
|
|
||||||
|
|||||||
@@ -313,42 +313,27 @@ class CAMWorkOrderProgramKnifePlan(models.Model):
|
|||||||
'applicant': None,
|
'applicant': None,
|
||||||
'sf_functional_tool_assembly_id': 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工单程序用刀计划
|
根据传入的工单信息,查询是否有需要的功能刀具,如果没有则生成CAM工单程序用刀计划
|
||||||
"""
|
"""
|
||||||
for cnc_processing in cnc_processing_ids:
|
knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
|
||||||
status = False
|
'name': cnc_processing.workorder_id.production_id.name,
|
||||||
if cnc_processing.cutting_tool_name:
|
'cam_procedure_code': cnc_processing.program_name,
|
||||||
functional_tools = self.env['sf.real.time.distribution.of.functional.tools'].sudo().search(
|
'filename': cnc_processing.cnc_id.name,
|
||||||
[('name', '=', cnc_processing.cutting_tool_name)])
|
'functional_tool_name': cnc_processing.cutting_tool_name,
|
||||||
if functional_tools:
|
'cam_cutter_spacing_code': cnc_processing.cutting_tool_no,
|
||||||
for functional_tool in functional_tools:
|
'process_type': cnc_processing.processing_type,
|
||||||
if functional_tool.on_tool_stock_num == 0:
|
'margin_x_y': float(cnc_processing.margin_x_y),
|
||||||
if functional_tool.tool_stock_num == 0 and functional_tool.side_shelf_num == 0:
|
'margin_z': float(cnc_processing.margin_z),
|
||||||
status = True
|
'finish_depth': float(cnc_processing.depth_of_processing_z),
|
||||||
else:
|
'extension_length': float(cnc_processing.cutting_tool_extension_length),
|
||||||
status = True
|
'shank_model': cnc_processing.cutting_tool_handle_type,
|
||||||
if status:
|
'estimated_processing_time': cnc_processing.estimated_processing_time,
|
||||||
knife_plan = self.env['sf.cam.work.order.program.knife.plan'].sudo().create({
|
})
|
||||||
'name': cnc_processing.workorder_id.production_id.name,
|
logging.info('CAM工单程序用刀计划创建成功!!!')
|
||||||
'cam_procedure_code': cnc_processing.program_name,
|
# 创建装刀请求
|
||||||
'filename': cnc_processing.cnc_id.name,
|
knife_plan.apply_for_tooling()
|
||||||
'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)
|
|
||||||
|
|
||||||
def unlink_cam_plan(self, production):
|
def unlink_cam_plan(self, production):
|
||||||
for item in 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',
|
integral_lot_id = fields.Many2one('stock.lot', string='整体式刀具批次', compute='_compute_functional_tool_num',
|
||||||
store=True)
|
store=True)
|
||||||
integral_freight_id = fields.Many2one('sf.shelf.location', '整体式刀具目标货位',
|
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',
|
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_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_lot_id = fields.Many2one('stock.lot', string='刀片批次', compute='_compute_functional_tool_num', store=True)
|
||||||
blade_freight_id = fields.Many2one('sf.shelf.location', '刀片目标货位',
|
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',
|
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_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_lot_id = fields.Many2one('stock.lot', string='刀杆批次', compute='_compute_functional_tool_num', store=True)
|
||||||
bar_freight_id = fields.Many2one('sf.shelf.location', '刀杆目标货位',
|
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',
|
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_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_lot_id = fields.Many2one('stock.lot', string='刀盘批次', compute='_compute_functional_tool_num', store=True)
|
||||||
pad_freight_id = fields.Many2one('sf.shelf.location', '刀盘目标货位',
|
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',
|
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_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_lot_id = fields.Many2one('stock.lot', string='夹头批次', compute='_compute_functional_tool_num', store=True)
|
||||||
chuck_freight_id = fields.Many2one('sf.shelf.location', '夹头目标货位',
|
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')
|
@api.onchange('functional_tool_id')
|
||||||
def _onchange_freight(self):
|
def _onchange_freight(self):
|
||||||
|
|||||||
@@ -115,6 +115,8 @@ 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:
|
||||||
@@ -255,6 +257,15 @@ class FunctionalCuttingToolEntity(models.Model):
|
|||||||
result['domain'] = [('id', '=', self.safe_inventory_id.id)]
|
result['domain'] = [('id', '=', self.safe_inventory_id.id)]
|
||||||
return result
|
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):
|
def tool_inventory_displacement_out(self):
|
||||||
"""
|
"""
|
||||||
机床当前刀库实时信息接口,功能刀具出库
|
机床当前刀库实时信息接口,功能刀具出库
|
||||||
@@ -265,6 +276,10 @@ class FunctionalCuttingToolEntity(models.Model):
|
|||||||
self.create_stock_move(stock_location_id, False)
|
self.create_stock_move(stock_location_id, False)
|
||||||
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)
|
||||||
|
|||||||
@@ -29,13 +29,66 @@ class CNCprocessing(models.Model):
|
|||||||
# else:
|
# else:
|
||||||
# raise ValidationError("MES装刀指令发送失败")
|
# 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
|
@api.model_create_multi
|
||||||
def create(self, vals):
|
def create(self, vals):
|
||||||
obj = super(CNCprocessing, self).create(vals)
|
obj = super(CNCprocessing, self).create(vals)
|
||||||
for item in obj:
|
# 调用CAM工单程序用刀计划创建方法
|
||||||
# 调用CAM工单程序用刀计划创建方法
|
self.cnc_tool_checkout(obj)
|
||||||
self.env['sf.cam.work.order.program.knife.plan'].create_cam_work_plan(item)
|
|
||||||
logging.info('成功调用CAM工单程序用刀计划创建方法!!!')
|
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user