From 612906e01da2f50126d62c9aed345a0cc017696a Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Fri, 21 Jun 2024 16:00:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=B9=E6=8D=AE=E5=A4=9A?= =?UTF-8?q?=E9=9D=A2=E7=94=9F=E6=88=90=E5=B7=A5=E5=8D=95=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 46 ++++++ sf_manufacturing/models/mrp_workorder.py | 58 +++---- sf_manufacturing/models/stock.py | 46 ------ sf_manufacturing/security/ir.model.access.csv | 3 +- sf_mrs_connect/controllers/controllers.py | 146 +++++++----------- sf_plan/models/custom_plan.py | 45 +++--- 6 files changed, 161 insertions(+), 183 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 7c5c37bc..aa1ffae0 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -391,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() diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index cd704eb0..248e49ce 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -505,7 +505,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,7 +516,7 @@ class ResMrpWorkOrder(models.Model): 'duration': 0, 'cnc_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cnc.processing']._json_cnc_processing( k, item), - 'cmc_ids': False if route.routing_type != 'CNC加工' else self.env['sf.cmm.program']._json_cmm_program(k, + '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) @@ -1098,7 +1098,7 @@ class CNCprocessing(models.Model): _rec_name = 'program_name' _order = 'sequence_number,id' - # cnc_id = fields.Many2one('ir.attachment') + cnc_id = fields.Many2one('ir.attachment') sequence_number = fields.Integer('序号') program_name = fields.Char('程序名') functional_tool_type_id = fields.Many2one('sf.functional.cutting.tool.model', string='功能刀具类型') @@ -1116,6 +1116,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,22 +1152,23 @@ class CNCprocessing(models.Model): def _json_cnc_processing(self, panel, ret): cnc_processing = [] for item in ret['programming_list']: - if item['processing_panel'] == panel: - cnc_processing.append(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'], - 'remark': obj['remark'] - }) + 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进行匹配 @@ -1197,14 +1199,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 @@ -1619,11 +1621,11 @@ class CMMprogram(models.Model): def _json_cmm_program(self, panel, ret): cmm_program = [] for item in ret['programming_list']: - if item['processing_panel'] == panel: - cmm_program.append(0, 0, { - 'sequence_number': obj['sequence_number'], - 'program_name': obj['program_name'], - 'program_path': obj['program_path'], - 'program_create_date': obj['program_create_date'] - }) + 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 diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 6d6d8158..6d83c011 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -238,52 +238,6 @@ class StockRule(models.Model): ( p.move_dest_ids.procure_method != 'make_to_order' and not p.move_raw_ids and not p.workorder_ids)).action_confirm() - 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 - 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 production in productions: ''' diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index 3b75f102..72c211ea 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -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,0 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 diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py index 0208b779..35e9a32c 100644 --- a/sf_mrs_connect/controllers/controllers.py +++ b/sf_mrs_connect/controllers/controllers.py @@ -24,95 +24,69 @@ class Sf_Mrs_Connect(http.Controller): ret = json.loads(datas) ret = json.loads(ret['result']) logging.info('下发编程单:%s' % ret) - all_production = None 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: # 拉取所有加工面的程序文件 - # for r in ret['processing_panel'].split(','): - # if is_delete_file is True: - # 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) - # 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工单') - cnc_processing_arr = [] - cmm_program_arr = [] - for panel in ret['processing_panel'].split(','): - program_path_tmp = os.path.join('/tmp', ret['folder_name'], 'return', panel) - # 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): - productions = request.env['mrp.production'].with_user( - request.env.ref("base.user_admin")).search( - [('programming_no', '=', cnc_production.programming_no)]) - if productions: - if not productions.workorder_ids: - productions.product_id.model_processing_panel = ret['processing_panel'] - productions._create_workorder(ret) - # cnc_workorder = productions.workorder_ids.filtered(lambda g: g.routing_type == '装夹预调') - # 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}) + for r in ret['processing_panel'].split(','): + if is_delete_file is True: + 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) + 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 is_delete_file is True: + 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('/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': '该制造订单暂未开始'} diff --git a/sf_plan/models/custom_plan.py b/sf_plan/models/custom_plan.py index fd1e231a..fcfb8020 100644 --- a/sf_plan/models/custom_plan.py +++ b/sf_plan/models/custom_plan.py @@ -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 {