Accept Merge Request #1087: (feature/优化工单(cnc和cmc)涉及多个加工面 -> develop)

Merge Request: 优化工单(cnc和cmc)涉及多个加工面

Created By: @杨金灵
Reviewed By: @马广威
Approved By: @马广威 
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/1087
This commit is contained in:
杨金灵
2024-06-24 14:55:49 +08:00
committed by Coding
9 changed files with 234 additions and 292 deletions

View File

@@ -5,10 +5,10 @@
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml">
<xpath expr="//header" position="inside">
<button string="程序下载" name="cnc_file_download" type="object" class="oe_highlight" attrs='{"invisible": ["|",
("user_permissions","=",False),("routing_type","!=","CNC加工")]}'/>
</xpath>
<!-- <xpath expr="//header" position="inside">-->
<!-- <button string="程序下载" name="cnc_file_download" type="object" class="oe_highlight" attrs='{"invisible": ["|",-->
<!-- ("user_permissions","=",False),("routing_type","!=","CNC加工")]}'/>-->
<!-- </xpath>-->
<xpath expr="//page//field[@name='cnc_ids']" position="before">
<group>
<group>
@@ -19,21 +19,21 @@
<div>
<field name="button_compensation_state" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"
class="btn-primary" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<span>&#32;</span>
<button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<span>&#32;</span>
<button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"
type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<span>&#32;</span>
<button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"
class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",
("state","!=","progress"),("user_permissions","=",False)]}'/>
<!-- <button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿"-->
<!-- class="btn-primary" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button string="一键下发" name="up_all" type="object" style="text-align: right;" confirm="是否确认一键下发"-->
<!-- class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button string="合并下发" id="action_up_select" name="%(sf_machine_connect.action_up_select)d"-->
<!-- type="action" class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
<!-- <span>&#32;</span>-->
<!-- <button string="一键合并下发" name="up_merge_all" type="object" style="text-align: right;" confirm="是否确认一键合并下发"-->
<!-- class="btn-primary" context="{'default_workorder_id': id}" attrs='{"invisible": ["|",-->
<!-- ("state","!=","progress"),("user_permissions","=",False)]}'/>-->
</div>
</div>
</group>

View File

@@ -9,7 +9,6 @@
<tree>
<field name="sequence_number"/>
<field name="program_name"/>
<field name="cnc_id" string="文件"/>
<field name="functional_tool_type_id"/>
<field name="cutting_tool_name"/>
<field name="cutting_tool_no"/>

View File

@@ -292,7 +292,7 @@ class MrpProduction(models.Model):
# 则根据设备找到工作中心;否则采用前面描述的工作中心分配机制;
# 其他规则限制: 默认只分配给工作中心状态为非故障的工作中心;
def _create_workorder3(self):
def _create_workorder3(self, item):
# 根据product_id对self进行分组
grouped_product_ids = {k: list(g) for k, g in groupby(self, key=lambda x: x.product_id.id)}
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
@@ -328,19 +328,6 @@ class MrpProduction(models.Model):
'state': 'pending',
}]
if production.product_id.categ_id.type == '成品':
if production.product_id.id in product_id_to_production_names:
# # 同一个产品多个制造订单对应一个编程单和模型库
# # 只调用一次fetchCNC并将所有生产订单的名称作为字符串传递
if not production.programming_no:
production_programming = self.search(
[('product_id.id', '=', production.product_id.id), ('origin', '=', production.origin)],
limit=1, order='id asc')
if not production_programming.programming_no:
production.fetchCNC(', '.join(product_id_to_production_names[production.product_id.id]))
else:
production.write({'programming_no': production_programming.programming_no,
'programming_state': '编程中'})
# # 根据加工面板的面数及对应的工序模板生成工单
i = 0
processing_panel_len = len(production.product_id.model_processing_panel.split(','))
@@ -353,10 +340,10 @@ class MrpProduction(models.Model):
for route in product_routing_workcenter:
if route.is_repeat is True:
workorders_values.append(
self.env['mrp.workorder'].json_workorder_str(k, production, route))
if i == processing_panel_len and route.routing_type == '解除装夹':
workorders_values.append(
self.env['mrp.workorder'].json_workorder_str(k, production, route))
self.env['mrp.workorder'].json_workorder_str(k, production, route, item))
# if i == processing_panel_len and route.routing_type == '解除装夹':
# workorders_values.append(
# self.env['mrp.workorder'].json_workorder_str(k, production, route))
# 表面工艺工序
# 获取表面工艺id
if production.product_id.model_process_parameters_ids:
@@ -404,6 +391,52 @@ class MrpProduction(models.Model):
workorders_values.append(
self.env['mrp.workorder'].json_workorder_str('', production, route))
production.workorder_ids = workorders_values
# for production_item in productions:
process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production.id),
('is_subcontract', '=', True)])
if process_parameter_workorder:
is_pick = False
consecutive_workorders = []
m = 0
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
for i in range(len(sorted_workorders) - 1):
if m == 0:
is_pick = False
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
if sorted_workorders[i] not in consecutive_workorders:
consecutive_workorders.append(sorted_workorders[i])
consecutive_workorders.append(sorted_workorders[i + 1])
m += 1
continue
else:
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
production_item)
if sorted_workorders[i] in consecutive_workorders:
is_pick = True
consecutive_workorders = []
m = 0
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
if is_pick is False:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
production_item)
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
production_item)
if sorted_workorders[i] in consecutive_workorders:
is_pick = True
consecutive_workorders = []
m = 0
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item)
if is_pick is False and m == 0:
if len(sorted_workorders) == 1:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
else:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item)
for workorder in production.workorder_ids:
workorder.duration_expected = workorder._get_duration_expected()
@@ -546,8 +579,8 @@ class MrpProduction(models.Model):
# work.button_finish()
# 创建工单并进行排序
def _create_workorder(self):
self._create_workorder3()
def _create_workorder(self, item):
self._create_workorder3(item)
self._reset_work_order_sequence()
return True

View File

@@ -474,7 +474,7 @@ class ResMrpWorkOrder(models.Model):
raise UserError(_("该工单暂未完成,无法进行工件配送"))
# 拼接工单对象属性值
def json_workorder_str(self, k, production, route):
def json_workorder_str(self, k, production, route, item):
# 计算预计时长duration_expected
if route.routing_type == '切割':
duration_expected = self.env['mrp.routing.workcenter'].sudo().search(
@@ -507,7 +507,7 @@ class ResMrpWorkOrder(models.Model):
'processing_panel': k,
'quality_point_ids': route.route_workcenter_id.quality_point_ids,
'routing_type': route.routing_type,
'work_state': '待发起',
# 'work_state': '待发起',
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids,
route.routing_type,
production.product_id),
@@ -516,6 +516,10 @@ class ResMrpWorkOrder(models.Model):
'date_planned_finished': datetime.now() + timedelta(days=1),
'duration_expected': duration_expected,
'duration': 0,
'cnc_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cnc.processing']._json_cnc_processing(
k, item),
'cmm_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cmm.program']._json_cmm_program(k,
item),
'workpiece_delivery_ids': False if not route.routing_type == '装夹预调' else self._json_workpiece_delivery_list(
production)
}]
@@ -1119,6 +1123,7 @@ class CNCprocessing(models.Model):
production_id = fields.Many2one('mrp.production', string="制造订单")
button_state = fields.Boolean(string='是否已经下发')
program_path = fields.Char('程序文件路径')
program_create_date = fields.Datetime('程序创建日期')
# mrs下发编程单创建CNC加工
def cnc_processing_create(self, cnc_workorder, ret, program_path, program_path_tmp):
@@ -1151,24 +1156,27 @@ class CNCprocessing(models.Model):
cnc_workorder.write({'programming_state': '已编程', 'work_state': '已编程'})
return cnc_processing
def _json_cnc_processing(self, obj):
cnc_processing_str = (0, 0, {
'sequence_number': obj['sequence_number'],
'program_name': obj['program_name'],
'cutting_tool_name': obj['cutting_tool_name'],
'cutting_tool_no': obj['cutting_tool_no'],
'processing_type': obj['processing_type'],
'margin_x_y': obj['margin_x_y'],
'margin_z': obj['margin_z'],
'depth_of_processing_z': obj['depth_of_processing_z'],
'cutting_tool_extension_length': obj['cutting_tool_extension_length'],
'cutting_tool_handle_type': obj['cutting_tool_handle_type'],
'estimated_processing_time': obj['estimated_processing_time'],
'program_path': obj['program_path'],
'cnc_id': obj['cnc_id'].id,
'remark': obj['remark']
})
return cnc_processing_str
def _json_cnc_processing(self, panel, ret):
cnc_processing = []
for item in ret['programming_list']:
if item['processing_panel'] == panel and item['ftp_path'].find('.dmi') == -1:
cnc_processing.append((0, 0, {
'sequence_number': item['sequence_number'],
'program_name': item['program_name'],
'cutting_tool_name': item['cutting_tool_name'],
'cutting_tool_no': item['cutting_tool_no'],
'processing_type': item['processing_type'],
'margin_x_y': item['margin_x_y'],
'margin_z': item['margin_z'],
'depth_of_processing_z': item['depth_of_processing_z'],
'cutting_tool_extension_length': item['cutting_tool_extension_length'],
'cutting_tool_handle_type': item['cutting_tool_handle_type'],
'estimated_processing_time': item['estimated_processing_time'],
'program_path': item['ftp_path'],
'program_create_date': datetime.strptime(item['program_create_date'], '%Y-%m-%d %H:%M:%S'),
'remark': item['remark']
}))
return cnc_processing
# 根据程序名和加工面匹配到ftp里对应的Nc程序名,可优化为根据cnc_processing.program_path进行匹配
def get_cnc_processing_file(self, serverdir, cnc_processing, program_path):
@@ -1198,14 +1206,14 @@ class CNCprocessing(models.Model):
})
return attachment
# 将FTP的nc文件下载到临时目录
# 将FTP的多面的程序单文件下载到临时目录
def download_file_tmp(self, production_no, processing_panel):
remotepath = os.path.join('/NC', production_no, 'return', processing_panel)
serverdir = os.path.join('/tmp', production_no, 'return', processing_panel)
ftp_resconfig = self.env['res.config.settings'].get_values()
ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), ftp_resconfig['ftp_user'],
ftp_resconfig['ftp_password'])
download_state = ftp.download_file_tree(remotepath, serverdir)
download_state = ftp.download_program_file(remotepath, serverdir)
logging.info('download_state:%s' % download_state)
return download_state
@@ -1610,80 +1618,22 @@ class CMMprogram(models.Model):
_name = 'sf.cmm.program'
_description = "CMM程序"
cmm_id = fields.Many2one('ir.attachment')
sequence_number = fields.Integer('序号')
program_name = fields.Char('程序名')
cutting_tool_name = fields.Char('刀具名称')
cutting_tool_no = fields.Char('刀号')
processing_type = fields.Char('加工类型')
margin_x_y = fields.Char('余量_X/Y')
margin_z = fields.Char('余量_Z')
depth_of_processing_z = fields.Char('加工深度(Z)')
cutting_tool_extension_length = fields.Char('刀具伸出长度')
cutting_tool_handle_type = fields.Char('刀柄型号')
estimated_processing_time = fields.Char('预计加工时间')
remark = fields.Text('备注')
workorder_id = fields.Many2one('mrp.workorder', string="工单")
production_id = fields.Many2one('mrp.production', string="制造订单")
program_path = fields.Char('程序文件路径')
program_create_date = fields.Datetime('程序创建日期')
def cmm_program_create(self, ret, program_path, program_path_tmp):
cmm_program = None
for obj in ret['programming_list']:
workorder = self.env['mrp.workorder'].search(
[('production_id.name', '=', ret['production_order_no'].split(',')[0]),
('processing_panel', '=', obj['processing_panel']),
('routing_type', '=', 'CNC加工')])
if obj['program_name'] in program_path:
logging.info('obj:%s' % obj['program_name'])
cmm_program = self.sudo().create({
'workorder_id': workorder.id,
'sequence_number': obj['sequence_number'],
'program_name': obj['program_name'],
'cutting_tool_name': obj['cutting_tool_name'],
'cutting_tool_no': obj['cutting_tool_no'],
'processing_type': obj['processing_type'],
'margin_x_y': obj['margin_x_y'],
'margin_z': obj['margin_z'],
'depth_of_processing_z': obj['depth_of_processing_z'],
'cutting_tool_extension_length': obj['cutting_tool_extension_length'],
'cutting_tool_handle_type': obj['cutting_tool_handle_type'],
'estimated_processing_time': obj['estimated_processing_time'],
'remark': obj['remark'],
'program_path': program_path.replace('/tmp', '')
})
cmm_program.get_cmm_program_file(program_path_tmp, cmm_program, program_path)
def _json_cmm_program(self, panel, ret):
cmm_program = []
for item in ret['programming_list']:
if item['processing_panel'] == panel and item['ftp_path'].find('.dmi') != -1:
cmm_program.append((0, 0, {
'sequence_number': 1,
'program_name': item['program_name'],
'program_path': item['ftp_path'],
'program_create_date': datetime.strptime(item['program_create_date'], '%Y-%m-%d %H:%M:%S'),
}))
return cmm_program
# 根据程序名和加工面匹配到ftp里对应的cmm程序名
def get_cmm_program_file(self, serverdir, cmm_program, program_path):
logging.info('cmm-serverdir:%s' % serverdir)
for root, dirs, files in os.walk(serverdir):
for f in files:
if f in program_path:
cmm_program_file_path = os.path.join(serverdir, root, f)
self.write_file_cmm(cmm_program_file_path, cmm_program)
# 创建附件(nc文件)
def attachment_create(self, name, data):
attachment = self.env['ir.attachment'].create({
'datas': base64.b64encode(data),
'type': 'binary',
'public': True,
'description': '程序文件',
'name': name
})
return attachment
# 将cmm文件存到attach的datas里
def write_file_cmm(self, cmm_file_path, cnc):
cmm_file_name = cmm_file_path.split('/')
logging.info('cmm_file_name:%s' % cmm_file_name[-1])
if os.path.exists(cmm_file_path):
with open(cmm_file_path, 'rb') as file:
data_bytes = file.read()
attachment = self.attachment_create(cnc.program_name + cmm_file_name[-1], data_bytes)
cnc.write({'cmm_id': attachment.id})
file.close()
else:
return False

View File

@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
import base64
import qrcode
from itertools import groupby
from collections import defaultdict, namedtuple
import logging
import io
@@ -205,61 +206,37 @@ class StockRule(models.Model):
# self.env['stock.move'].sudo().create(productions._get_moves_raw_values())
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
'''
创建工单
'''
productions._create_workorder()
productions.filtered(lambda p: (not p.orderpoint_id and p.move_raw_ids) or \
(
p.move_dest_ids.procure_method != 'make_to_order' and not
p.move_raw_ids and not p.workorder_ids)).action_confirm()
'''
创建工单
'''
# productions._create_workorder()
#
grouped_product_ids = {k: list(g) for k, g in groupby(productions, key=lambda x: x.product_id.id)}
# 初始化一个字典来存储每个product_id对应的生产订单名称列表
product_id_to_production_names = {}
# 对于每个product_id获取其所有生产订单的名称
for product_id, productions in grouped_product_ids.items():
# 为同一个product_id创建一个生产订单名称列表
product_id_to_production_names[product_id] = [production.name for production in productions]
for production_item in productions:
process_parameter_workorder = self.env['mrp.workorder'].search(
[('surface_technics_parameters_id', '!=', False), ('production_id', '=', production_item.id),
('is_subcontract', '=', True)])
if process_parameter_workorder:
is_pick = False
consecutive_workorders = []
m = 0
sorted_workorders = sorted(process_parameter_workorder, key=lambda w: w.id)
for i in range(len(sorted_workorders) - 1):
if m == 0:
is_pick = False
if sorted_workorders[i].supplier_id.id == sorted_workorders[i + 1].supplier_id.id and \
sorted_workorders[i].is_subcontract == sorted_workorders[i + 1].is_subcontract and \
sorted_workorders[i].id == sorted_workorders[i + 1].id - 1:
if sorted_workorders[i] not in consecutive_workorders:
consecutive_workorders.append(sorted_workorders[i])
consecutive_workorders.append(sorted_workorders[i + 1])
m += 1
continue
if production_item.product_id.id in product_id_to_production_names:
# # 同一个产品多个制造订单对应一个编程单和模型库
# # 只调用一次fetchCNC并将所有生产订单的名称作为字符串传递
if not production_item.programming_no:
production_programming = self.env['mrp.production'].search(
[('product_id.id', '=', production_item.product_id.id),
('origin', '=', production_item.origin)],
limit=1, order='id asc')
if not production_programming.programming_no:
production_item.fetchCNC(
', '.join(product_id_to_production_names[production_item.product_id.id]))
else:
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
production_item)
if sorted_workorders[i] in consecutive_workorders:
is_pick = True
consecutive_workorders = []
m = 0
# 当前面的连续工序生成对应的外协出入库单再生成当前工序的外协出入库单
if is_pick is False:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i],
production_item)
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders,
production_item)
if sorted_workorders[i] in consecutive_workorders:
is_pick = True
consecutive_workorders = []
m = 0
if m == len(consecutive_workorders) - 1 and m != 0:
self.env['stock.picking'].create_outcontract_picking(consecutive_workorders, production_item)
if is_pick is False and m == 0:
if len(sorted_workorders) == 1:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders, production_item)
else:
self.env['stock.picking'].create_outcontract_picking(sorted_workorders[i], production_item)
production_item.write({'programming_no': production_programming.programming_no,
'programming_state': '编程中'})
for production in productions:
'''

View File

@@ -1,8 +1,9 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_cnc_processing_group_sf_mrp_user,sf_cnc_processing,model_sf_cnc_processing,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_cnc_processing_manager,sf_cnc_processing,model_sf_cnc_processing,sf_base.group_sf_mrp_manager,1,1,1,0
access_sf_cmm_program_group_sf_mrp_user_group_sf_mrp_user,sf_cmm_program_group_sf_mrp_user,model_sf_cmm_program,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_cmm_program_group_sf_mrp_user,sf_cmm_program_group_sf_mrp_user,model_sf_cmm_program,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_cmm_program_group_sf_mrp_manager,sf_cmm_program_group_sf_mrp_manager,model_sf_cmm_program,sf_base.group_sf_mrp_manager,1,0,0,0
access_sf_cmm_program_admin,sf_cmm_program_admin,model_sf_cmm_program,base.group_system,1,1,1,1
access_sf_model_type_group_sf_mrp_user,sf_model_type,model_sf_model_type,sf_base.group_sf_mrp_user,1,0,0,0
access_sf_model_type_admin,sf_model_type_admin,model_sf_model_type,base.group_system,1,1,1,0
access_sf_model_type_manager,sf_model_type,model_sf_model_type,sf_base.group_sf_mrp_manager,1,1,1,0
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_cnc_processing_group_sf_mrp_user sf_cnc_processing model_sf_cnc_processing sf_base.group_sf_mrp_user 1 0 0 0
3 access_sf_cnc_processing_manager sf_cnc_processing model_sf_cnc_processing sf_base.group_sf_mrp_manager 1 1 1 0
4 access_sf_cmm_program_group_sf_mrp_user_group_sf_mrp_user access_sf_cmm_program_group_sf_mrp_user sf_cmm_program_group_sf_mrp_user model_sf_cmm_program sf_base.group_sf_mrp_user 1 0 0 0
5 access_sf_cmm_program_group_sf_mrp_manager sf_cmm_program_group_sf_mrp_manager model_sf_cmm_program sf_base.group_sf_mrp_manager 1 0 0 0
6 access_sf_cmm_program_admin sf_cmm_program_admin model_sf_cmm_program base.group_system 1 1 1 1
7 access_sf_model_type_group_sf_mrp_user sf_model_type model_sf_model_type sf_base.group_sf_mrp_user 1 0 0 0
8 access_sf_model_type_admin sf_model_type_admin model_sf_model_type base.group_system 1 1 1 0
9 access_sf_model_type_manager sf_model_type model_sf_model_type sf_base.group_sf_mrp_manager 1 1 1 0

View File

@@ -219,9 +219,6 @@
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
<field name="functional_fixture_type_id"
attrs='{"invisible": [("routing_type","!=","装夹预调")]}'/>
<field name="rfid_code" force_save="1" readonly="1" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
</group>
<!-- <group>-->
<!-- <div>-->
@@ -507,11 +504,11 @@
</xpath>
<xpath expr="//page[1]" position="before">
<page string="CNC程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<field name="cnc_ids" widget="one2many" string="工作程序" default_order="sequence_number,id">
<tree decoration-success="button_state" decoration-bf="button_state">
<field name="cnc_ids" widget="one2many" string="工作程序" default_order="sequence_number,id"
readonly="1">
<tree>
<field name="sequence_number"/>
<field name="program_name"/>
<field name="cnc_id" string="文件"/>
<field name="cutting_tool_name"/>
<field name="cutting_tool_no"/>
<field name="processing_type"/>
@@ -521,8 +518,10 @@
<field name="cutting_tool_extension_length"/>
<field name="cutting_tool_handle_type"/>
<field name="estimated_processing_time"/>
<field name="program_path"/>
<field name="program_create_date"/>
<field name="remark"/>
<field name="button_state" invisible="1"/>
<!-- <field name="button_state" invisible="1"/>-->
</tree>
</field>
<group>
@@ -530,20 +529,12 @@
</group>
</page>
<page string="CMM程序" attrs='{"invisible": [("routing_type","!=","CNC加工")]}'>
<field name="cmm_ids" widget="one2many" string="CMM程序">
<field name="cmm_ids" widget="one2many" string="CMM程序" readonly="1">
<tree>
<field name="sequence_number"/>
<field name="program_name"/>
<field name="cmm_id" string="文件"/>
<field name="cutting_tool_name"/>
<field name="cutting_tool_no"/>
<field name="processing_type"/>
<field name="margin_x_y"/>
<field name="margin_z"/>
<field name="depth_of_processing_z"/>
<field name="cutting_tool_extension_length"/>
<field name="cutting_tool_handle_type"/>
<field name="estimated_processing_time"/>
<field name="program_path"/>
<field name="program_create_date"/>
<field name="remark"/>
</tree>
</field>
@@ -574,8 +565,8 @@
</xpath>
<xpath expr="//form//sheet//group//group//div[3]" position="after">
<field name="is_ok"/>
<field name="processing_user_id"/>
<field name="inspection_user_id"/>
<!-- <field name="processing_user_id"/>-->
<!-- <field name="inspection_user_id"/>-->
<field name="save_name" widget="CopyClipboardChar"
attrs="{'invisible':[('routing_type','!=','装夹预调')]}"/>
<label for="material_length" string="物料尺寸"/>
@@ -590,6 +581,9 @@
<field name="material_height" class="o_address_zip"/>
</div>
<field name="part_number" string="成品的零件图号"/>
<field name="rfid_code" force_save="1" readonly="1" cache="True"
attrs="{'invisible': [('rfid_code_old', '!=', False)]}"/>
<field name="rfid_code_old" readonly="1" attrs="{'invisible': [('rfid_code_old', '=', False)]}"/>
</xpath>
</field>
</record>

View File

@@ -24,82 +24,69 @@ class Sf_Mrs_Connect(http.Controller):
ret = json.loads(datas)
ret = json.loads(ret['result'])
logging.info('下发编程单:%s' % ret)
is_delete_file = False
# 查询状态为进行中且类型为获取CNC加工程序的工单
cnc_production = request.env['mrp.production'].with_user(
request.env.ref("base.user_admin")).search([('name', '=', ret['production_order_no'].split(',')[0])])
cnc_program = request.env['mrp.production'].with_user(
productions = request.env['mrp.production'].with_user(
request.env.ref("base.user_admin")).search(
[('programming_no', '=', cnc_production.programming_no), ('id', '!=', cnc_production.id)])
if cnc_production.workorder_ids.filtered(lambda a: a.routing_type == 'CNC加工').cnc_ids:
is_delete_file = True
cnc_production.workorder_ids.filtered(
lambda a1: a1.routing_type == 'CNC加工').cnc_ids.sudo().unlink()
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(cnc_production)
if cnc_program.workorder_ids.filtered(lambda c: c.routing_type == 'CNC加工').cnc_ids:
cnc_program.workorder_ids.filtered(
lambda c1: c1.routing_type == 'CNC加工').cnc_ids.sudo().unlink()
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(cnc_program)
# cnc_program = request.env['mrp.production'].with_user(
# request.env.ref("base.user_admin")).search([('programming_no', '=', cnc_production.programming_no)])
logging.info('制造订单号:%s' % cnc_production.name)
if cnc_production:
# if ret['glb_file']:
# cnc_production.glb_file = base64.b64encode(ret['glb_file'])
[('programming_no', '=', ret['programming_no'])])
if productions:
# 拉取所有加工面的程序文件
if is_delete_file is True:
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', 'R')
for r in ret['processing_panel'].split(','):
program_path_tmp_r = os.path.join('/tmp', ret['folder_name'], 'return', r)
files_r = os.listdir(program_path_tmp_r)
if files_r:
for file_name in files_r:
file_path = os.path.join(program_path_tmp_r, file_name)
os.remove(file_path)
for r in ret['processing_panel']:
download_state = request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).download_file_tmp(
ret['folder_name'], r)
if download_state == 0:
res['status'] = -2
res['message'] = '制造订单号为%s的CNC程序文件从FTP拉取失败' % (cnc_production.name)
return json.JSONEncoder().encode(res)
logging.info('创建cnc工单')
program_path_tmp = os.path.join('/tmp', ret['folder_name'], 'return', r)
# program_path_tmp = "C://Users//43484//Desktop//机企猫工作文档//其他//model_analysis"
files = os.listdir(program_path_tmp)
cnc_processing_arr = []
for f in files:
program_path = os.path.join(program_path_tmp, f)
logging.info('cnc程序路径 :%s' % program_path)
if f.endswith(".doc"):
# 插入cmm程序数据
cmm_program = request.env['sf.cmm.program'].with_user(
request.env.ref("base.user_admin")).cmm_program_create(ret, program_path, program_path_tmp)
cnc_processing = request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).cnc_processing_create(cnc_production, ret, program_path,
program_path_tmp)
logging.info('cnc_processing111:%s' % cnc_processing)
if cnc_processing:
cnc_processing_arr.append(cnc_processing._json_cnc_processing(cnc_processing))
if (cnc_program and cnc_processing_arr) or (not cnc_program and cnc_processing_arr):
cnc_production.workorder_ids.filtered(lambda g: g.routing_type == '装夹预调').write(
{'processing_drawing': cnc_production.workorder_ids.filtered(
lambda g1: g1.routing_type == 'CNC加工').cnc_worksheet})
if cnc_program and cnc_processing_arr:
cnc_program.write({'programming_state': '已编程', 'work_state': '已编程'})
cnc_program.workorder_ids.filtered(lambda d: d.routing_type == '装夹预调').write(
{'processing_drawing': cnc_production.workorder_ids.filtered(
lambda d1: d1.routing_type == 'CNC加工').cnc_worksheet})
cnc_program.workorder_ids.filtered(lambda b: b.routing_type == 'CNC加工').write(
{'cnc_ids': cnc_processing_arr, 'cnc_worksheet': cnc_production.workorder_ids.filtered(
lambda b1: b1.routing_type == 'CNC加工').cnc_worksheet})
cnc_program |= cnc_production
if not cnc_program and cnc_processing_arr:
cnc_program = cnc_production
cnc_program_ids = [item.id for item in cnc_program]
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[('production_id', 'in', cnc_program_ids)])
if workpiece_delivery:
workpiece_delivery.write({'is_cnc_program_down': True})
download_state = request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).download_file_tmp(
ret['folder_name'], r)
if download_state == 0:
res['status'] = -2
res['message'] = '制造订单号为%s的CNC程序文件从FTP拉取失败' % (cnc_production.name)
return json.JSONEncoder().encode(res)
for production in productions:
if not production.workorder_ids:
production.product_id.model_processing_panel = ret['processing_panel']
production._create_workorder(ret)
else:
for panel in ret['processing_panel'].split(','):
# 查询状态为进行中且工序类型为CNC加工的工单
cnc_workorder = production.workorder_ids.filtered(
lambda ac: ac.routing_type == 'CNC加工' and ac.state not in ['progress', 'done',
'cancel'] and ac.processing_panel == panel)
if cnc_workorder:
if cnc_workorder.cnc_ids:
cnc_workorder.cmm_ids.sudo().unlink()
cnc_workorder.cnc_ids.sudo().unlink()
request.env['sf.cam.work.order.program.knife.plan'].sudo().unlink_cam_plan(
production)
# program_path_tmp_panel = os.path.join('C://Users//43484//Desktop//fsdownload//test',
# panel)
program_path_tmp_panel = os.path.join('/tmp', ret['folder_name'], 'return', panel)
logging.info('program_path_tmp_panel:%s' % program_path_tmp_panel)
files_panel = os.listdir(program_path_tmp_panel)
if files_panel:
for file in files_panel:
file_extension = os.path.splitext(file)[1]
logging.info('file_extension:%s' % file_extension)
if file_extension.lower() == '.pdf':
panel_file_path = os.path.join(program_path_tmp_panel, file)
logging.info('panel_file_path:%s' % panel_file_path)
cnc_workorder.write(
{'cnc_ids': cnc_workorder.cnc_ids.sudo()._json_cnc_processing(panel, ret),
'cmm_ids': cnc_workorder.cmm_ids.sudo()._json_cmm_program(panel, ret),
'cnc_worksheet': base64.b64encode(open(panel_file_path, 'rb').read())})
pre_workorder = production.workorder_ids.filtered(
lambda ap: ap.routing_type == '装夹预调' and ap.state not in ['done',
'cancel'] and ap.processing_panel == panel)
if pre_workorder:
pre_workorder.write(
{'processing_drawing': base64.b64encode(open(panel_file_path, 'rb').read())})
productions.write({'programming_state': '已编程', 'work_state': '已编程'})
cnc_program_ids = [item.id for item in productions]
workpiece_delivery = request.env['sf.workpiece.delivery'].sudo().search(
[('production_id', 'in', cnc_program_ids)])
if workpiece_delivery:
workpiece_delivery.write({'is_cnc_program_down': True})
return json.JSONEncoder().encode(res)
else:
res = {'status': 0, 'message': '该制造订单暂未开始'}

View File

@@ -200,22 +200,23 @@ class sf_production_plan(models.Model):
raise ValidationError("未选择生产线")
else:
workorder_id_list = record.production_id.workorder_ids.ids
if record.production_id.workorder_ids:
for item in record.production_id.workorder_ids:
if item.name == 'CNC加工':
item.date_planned_finished = datetime.now() + timedelta(days=100)
# item.date_planned_start = record.date_planned_start
item.date_planned_start = self.date_planned_start if self.date_planned_start else datetime.now()
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
item.date_planned_finished = item.date_planned_start + timedelta(
minutes=record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle)
item.duration_expected = record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
record.calculate_plan_time_before(item, workorder_id_list)
record.calculate_plan_time_after(item, workorder_id_list)
record.date_planned_start, record.date_planned_finished = \
item.date_planned_start, item.date_planned_finished
if record.production_id:
if record.production_id.workorder_ids:
for item in record.production_id.workorder_ids:
if item.name == 'CNC加工':
item.date_planned_finished = datetime.now() + timedelta(days=100)
# item.date_planned_start = record.date_planned_start
item.date_planned_start = self.date_planned_start if self.date_planned_start else datetime.now()
record.sudo().production_id.plan_start_processing_time = item.date_planned_start
item.date_planned_finished = item.date_planned_start + timedelta(
minutes=record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle)
item.duration_expected = record.env['mrp.routing.workcenter'].sudo().search(
[('name', '=', 'CNC加工')]).time_cycle
record.calculate_plan_time_before(item, workorder_id_list)
record.calculate_plan_time_after(item, workorder_id_list)
record.date_planned_start, record.date_planned_finished = \
item.date_planned_start, item.date_planned_finished
record.state = 'done'
# record.production_id.schedule_state = '已排'
record.sudo().production_id.schedule_state = '已排'
@@ -231,12 +232,12 @@ class sf_production_plan(models.Model):
# record.production_id.date_planned_start = record.date_planned_start
# record.production_id.date_planned_finished = record.date_planned_finished
record.sudo().production_id.production_line_id = record.production_line_id.id
record.sudo().production_id.workorder_ids.filtered(
lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
{'production_line_id': record.production_line_id.id,
'plan_start_processing_time': record.date_planned_start})
else:
raise ValidationError("未找到工单")
if record.production_id.workorder_ids:
record.sudo().production_id.workorder_ids.filtered(
lambda b: b.routing_type == "装夹预调").workpiece_delivery_ids.write(
{'production_line_id': record.production_line_id.id,
'plan_start_processing_time': record.date_planned_start})
# record.date_planned_finished = record.date_planned_start + timedelta(days=3)
# record.state = 'done'
return {