# -*- coding: utf-8 -*- import base64 import logging import os import json import hashlib import time import requests from datetime import datetime, timedelta from odoo.http import request from odoo import fields, models, api, _ from odoo.exceptions import ValidationError from odoo.exceptions import UserError from odoo.addons.sf_machine_connect.models import py2opcua, ftp_operate import shutil from io import BytesIO from zipfile import ZipFile from odoo.exceptions import MissingError _logger = logging.getLogger(__name__) # ---------------------------------------------------------- # Models for client # ---------------------------------------------------------- class FtpButton(models.Model): _inherit = 'sf.cnc.processing' user_permissions = fields.Boolean(string='权限', related='workorder_id.user_permissions') state = fields.Selection(string='状态', related='workorder_id.state') @api.onchange('users_ids') def get_user_permissions(self): uid = self.env.uid for workorder in self: if workorder.users_ids: list_user_id = [] for item in workorder.users_ids: list_user_id.append(item.id) if uid in list_user_id: workorder.user_permissions = True else: workorder.user_permissions = False else: workorder.user_permissions = False def up(self): """ 此函数用于将NC代码下发到机床 :return: """ # 点击下发按钮自动补偿三元检测偏差值 try: try: if self.sequence_number == '1': self.check_compensation_before_up() except Exception: raise UserError("补偿值写入执行超时,请检查机床状态或者写入状态") # host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC" host = self.workorder_id.workcenter_id.machine_tool_id.ftp_host port = self.workorder_id.workcenter_id.machine_tool_id.ftp_port username = self.workorder_id.workcenter_id.machine_tool_id.ftp_num pwd = self.workorder_id.workcenter_id.machine_tool_id.ftp_pwd remote_path = self.workorder_id.workcenter_id.machine_tool_id.ftp_remote_path print(host, port, username, pwd, remote_path) ftp = ftp_operate.FtpController(host, port, username, pwd) # ftp.delAllfile('C://Users//马广威//Desktop//ftp') a = self.cnc_id datas = base64.standard_b64decode(a.datas) # file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name) file_path_local = '{}/{}'.format('/nc2machine', a.display_name) # file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name) file_path_remote = '{}\{}'.format(remote_path, a.display_name) with open(file_path_local, mode='wb+') as file: file.write(datas) # 存在本地的文件下发到机床 ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local) _logger.info("======%s下发成功======" % a.display_name) ftp.close_ftp() up_time = str(datetime.now() + timedelta(hours=8)) self.env['delivery.record'].create({ 'workorder_id': self.workorder_id.id, 'delivery_type': '单个下发', 'delivery_time': up_time, 'influence_record': self.sequence_number, }) # self.workorder_id.delivery_records.sudo().create({ # 'delivery_type': '单个下发', # 'delivery_time': 'up_time', # 'influence_record': 'self.sequence_number', # }) except Exception as e: _logger.info("=====================================", e) raise UserError('NC下发执行超时, 请检查下发状态') # 补偿下发都执行完毕后,按钮标志位变为true self.button_state = True def check_compensation_before_up(self): """ 下发NC代码前自动补偿三元检测偏差值 :return: """ hongbianliang550 = self.workorder_id.workcenter_id.machine_tool_id.x_compensation_node hongbianliang551 = self.workorder_id.workcenter_id.machine_tool_id.y_compensation_node try: temp_dict = {} temp_dict[hongbianliang550] = self.workorder_id.compensation_value_x temp_dict[hongbianliang551] = self.workorder_id.compensation_value_y temp = py2opcua.Py2opcua() temp.write(temp_dict) except Exception as e: _logger.info("=====================================", e) raise UserError('补偿值获取失败,或机床未连接,请检查') class Machine_ftp(models.Model): """ 数据采集类 """ _inherit = 'sf.machine_tool' workorder_ids = fields.One2many('mrp.workorder', 'machine_tool_id', string='工单') # 机床配置项目 # ftp相关 ftp_num = fields.Char('ftp账号') ftp_pwd = fields.Char('ftp密码') ftp_host = fields.Char('ftp地址') ftp_port = fields.Integer('ftp端口') ftp_remote_path = fields.Char('机床ftp路径') # 补偿值写入相关 x_compensation_node = fields.Char('x补偿值节点') y_compensation_node = fields.Char('y补偿值节点') # 数采配置相关 machine_ip = fields.Char('机床IP') machine_signed = fields.Char('机床刷新间隔') machine_status = fields.Char('机床在线状态') machine_cnc_type = fields.Char('机床CNC型号') machine_axis_count = fields.Char('机床轴总数') machine_run_status = fields.Char('机床运行状态') machine_emg_status = fields.Char('机床急停状态') machine_cut_status = fields.Char('机床当前切削状态') machine_mode = fields.Char('机床当前操作模式') machine_spindle_load = fields.Char('机床主轴负载') machine_x_mach = fields.Char('机床X轴机械坐标') machine_x_abs_mach = fields.Char('机床X轴当前位置') machine_x_rel_mach = fields.Char('机床X轴相对工件坐标') machine_x_dis_mach = fields.Char('机床X轴目标距离') machine_x_axis_load = fields.Char('机床X轴伺服轴负载') machine_y_mach = fields.Char('机床Y轴机械坐标') machine_y_abs_mach = fields.Char('机床Y轴当前位置') machine_y_rel_mach = fields.Char('机床Y轴相对工件坐标') machine_y_dis_mach = fields.Char('机床Y轴目标距离') machine_y_axis_load = fields.Char('机床Y轴伺服轴负载') machine_z_mach = fields.Char('机床Z轴机械坐标') machine_z_abs_mach = fields.Char('机床Z轴当前位置') machine_z_rel_mach = fields.Char('机床Z轴相对工件坐标') machine_z_dis_mach = fields.Char('机床Z轴目标距离') machine_z_axis_load = fields.Char('机床Z轴伺服轴负载') machine_tool_num = fields.Char('机床当前刀位号') machine_program = fields.Char('机床主程序名称') machine_current_prg = fields.Char('机床当前执行指令') machine_prg_seq = fields.Char('机床当前执行语句号') machine_spindle_speed_set = fields.Char('机床设定主轴速度') machine_act_spindle_speed = fields.Char('机床实际主轴转速') machine_feed_speed_set = fields.Char('机床设定进给速度') machine_act_feed_speed = fields.Char('机床实际进给速度') machine_spindle_feed = fields.Char('机床主轴倍率') machine_feed_rate = fields.Char('机床进给倍率') machine_rapid_feed = fields.Char('机床快速移动倍率') machine_run_time = fields.Char('机床运行时间') machine_cut_time = fields.Char('机床切削时间') machine_keep_alive_time = fields.Char('机床上电时间') machine_circle_time = fields.Char('机床循环时间') machine_product_counts = fields.Char('机床加工件数') machine_system_date = fields.Char('机床系统日期') machine_system_time = fields.Char('机床系统时间') machine_alarm_msg = fields.Char('机床系统报警') # 刀位配置 tool_num1 = fields.Char('刀位1') tool_num2 = fields.Char('刀位2') tool_num3 = fields.Char('刀位3') tool_num4 = fields.Char('刀位4') tool_num5 = fields.Char('刀位5') tool_num6 = fields.Char('刀位6') tool_num7 = fields.Char('刀位7') tool_num8 = fields.Char('刀位8') tool_num9 = fields.Char('刀位9') tool_num10 = fields.Char('刀位10') tool_num11 = fields.Char('刀位11') tool_num12 = fields.Char('刀位12') tool_num13 = fields.Char('刀位13') tool_num14 = fields.Char('刀位14') tool_num15 = fields.Char('刀位15') tool_num16 = fields.Char('刀位16') tool_num17 = fields.Char('刀位17') tool_num18 = fields.Char('刀位18') tool_num19 = fields.Char('刀位19') tool_num20 = fields.Char('刀位20') tool_num21 = fields.Char('刀位21') tool_num22 = fields.Char('刀位22') tool_num23 = fields.Char('刀位23') tool_num24 = fields.Char('刀位24') # 机床采集项目 timestamp = fields.Datetime('时间戳', readonly=True) signed = fields.Integer('刷新间隔', readonly=True) status = fields.Boolean('在线状态', readonly=True) time_on = fields.Char('总在线时长', readonly=True) time_on_now = fields.Char('本次在线时长', readonly=True) tool_num = fields.Integer('当前刀具', readonly=True) program = fields.Char('当前程序', readonly=True) run_status = fields.Selection([('0', '空闲中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], string='运行状态', readonly=True, default='0') run_time = fields.Char('总运行时长', readonly=True) cut_time = fields.Char('总切削时长', readonly=True) cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')], string='切削状态', readonly=True, default='0') spindle_speed = fields.Char('主轴转速', readonly=True) tool_num_process_time1 = fields.Char('刀位1', readonly=True, default='0') tool_num_process_time2 = fields.Char('刀位2', readonly=True, default='0') tool_num_process_time3 = fields.Char('刀位3', readonly=True, default='0') tool_num_process_time4 = fields.Char('刀位4', readonly=True, default='0') tool_num_process_time5 = fields.Char('刀位5', readonly=True, default='0') tool_num_process_time6 = fields.Char('刀位6', readonly=True, default='0') tool_num_process_time7 = fields.Char('刀位7', readonly=True, default='0') tool_num_process_time8 = fields.Char('刀位8', readonly=True, default='0') tool_num_process_time9 = fields.Char('刀位9', readonly=True, default='0') tool_num_process_time10 = fields.Char('刀位10', readonly=True, default='0') tool_num_process_time11 = fields.Char('刀位11', readonly=True, default='0') tool_num_process_time12 = fields.Char('刀位12', readonly=True, default='0') tool_num_process_time13 = fields.Char('刀位13', readonly=True, default='0') tool_num_process_time14 = fields.Char('刀位14', readonly=True, default='0') tool_num_process_time15 = fields.Char('刀位15', readonly=True, default='0') tool_num_process_time16 = fields.Char('刀位16', readonly=True, default='0') tool_num_process_time17 = fields.Char('刀位17', readonly=True, default='0') tool_num_process_time18 = fields.Char('刀位18', readonly=True, default='0') tool_num_process_time19 = fields.Char('刀位19', readonly=True, default='0') tool_num_process_time20 = fields.Char('刀位20', readonly=True, default='0') tool_num_process_time21 = fields.Char('刀位21', readonly=True, default='0') tool_num_process_time22 = fields.Char('刀位22', readonly=True, default='0') tool_num_process_time23 = fields.Char('刀位23', readonly=True, default='0') tool_num_process_time24 = fields.Char('刀位24', readonly=True, default='0') class WorkCenterBarcode(models.Model): """ 扫码托盘码可查到制造订单,由制造订单查工单 """ _inherit = "mrp.workorder" # barcode = fields.Binary(string='条码', default='UP-ALL') compensation_value_x = fields.Float(string='X轴补偿值') compensation_value_y = fields.Float(string='Y轴补偿值') button_compensation_state = fields.Boolean(string='是否已经补偿', readonly=True) button_up_all_state = fields.Boolean(string='是否已经全部下发', readonly=True) machine_tool_id = fields.Many2one('sf.machine_tool', string='机床') machine_tool_name = fields.Char(string='机床名称', default='未知机床', compute='_run_info', readonly=True) machine_tool_type_id = fields.Char(string='机床型号', default='未知型号', compute='_run_info', readonly=True) machine_tool_status = fields.Boolean(string='在线状态', compute='_run_info', readonly=True) machine_tool_run_status = fields.Selection([('0', '关机中'), ('1', '加工中'), ('2', '加工中'), ('3', '加工中')], string='运行状态', compute='_run_info', readonly=True, default='0') machine_tool_timestamp = fields.Datetime('时间戳', compute='_run_info', readonly=True) machine_tool_time_on = fields.Char('总在线时长', compute='_run_info', readonly=True) machine_tool_time_on_now = fields.Char('本次在线时长', compute='_run_info', readonly=True) machine_tool_tool_num = fields.Integer('当前刀具', compute='_run_info', readonly=True) machine_tool_program = fields.Char('当前程序', compute='_run_info', readonly=True) machine_tool_machine_ip = fields.Char('机床IP', compute='_run_info', readonly=True) machine_tool_cut_status = fields.Selection([('0', '未切削'), ('1', '切削中'), ('2', '切削中'), ('3', '切削中')], string='切削状态', compute='_run_info', readonly=True, default='0') machine_tool_compensation_value_x = fields.Char('x补偿值', compute='_run_info', readonly=True) machine_tool_compensation_value_y = fields.Char('y补偿值', compute='_run_info', readonly=True) delivery_records = fields.One2many('delivery.record', 'workorder_id', string="下发记录") @api.depends('workcenter_id.machine_tool_id.timestamp') def _run_info(self): # self.machine_tool_name = '1号机床' self.machine_tool_name = self.workcenter_id.machine_tool_id.name self.machine_tool_type_id = self.workcenter_id.machine_tool_id.type_id.name self.machine_tool_status = self.workcenter_id.machine_tool_id.status self.machine_tool_run_status = self.workcenter_id.machine_tool_id.run_status self.machine_tool_timestamp = self.workcenter_id.machine_tool_id.timestamp self.machine_tool_time_on = self.workcenter_id.machine_tool_id.time_on self.machine_tool_time_on_now = self.workcenter_id.machine_tool_id.time_on_now self.machine_tool_tool_num = self.workcenter_id.machine_tool_id.tool_num self.machine_tool_program = self.workcenter_id.machine_tool_id.program self.machine_tool_machine_ip = self.workcenter_id.machine_tool_id.machine_ip self.machine_tool_cut_status = self.workcenter_id.machine_tool_id.cut_status self.machine_tool_compensation_value_x = self.compensation_value_x self.machine_tool_compensation_value_y = self.compensation_value_y def compensation(self): hongbianliang550 = self.workcenter_id.machine_tool_id.x_compensation_node hongbianliang551 = self.workcenter_id.machine_tool_id.y_compensation_node try: temp_dict = {} temp_dict[hongbianliang550] = self.compensation_value_x temp_dict[hongbianliang551] = self.compensation_value_y print("=================================") print(temp_dict) temp = py2opcua.Py2opcua() temp.write(temp_dict) except Exception as e: _logger.info("=====================================", e) raise UserError('补偿值获取失败,或机床未连接,请检查') # 补偿执行完毕后,按钮标志位变为true self.button_compensation_state = True def up_all(self): """ 此函数用于将NC代码全部下发到机床 :return: """ # 一键下发前删除机床上的全部程序 try: filepath = '/nc2machine' del_list = os.listdir(filepath) _logger.info("=====================================%s" % del_list) for f in del_list: file_path = os.path.join(filepath, f) if os.path.isfile(file_path): os.remove(file_path) except Exception as e: _logger.info("=====================================", e) raise UserError('程序删除失败,请重试') # host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC" try: self.compensation() except Exception: raise UserError("补偿值写入执行超时,请检查机床状态或者写入状态") sequence_collect = [] host = self.workcenter_id.machine_tool_id.ftp_host port = self.workcenter_id.machine_tool_id.ftp_port username = self.workcenter_id.machine_tool_id.ftp_num pwd = self.workcenter_id.machine_tool_id.ftp_pwd remote_path = self.workcenter_id.machine_tool_id.ftp_remote_path _logger.info("=====================1666666661111================%s,%s,%s,%s" % (host, port, username, pwd)) ftp = ftp_operate.FtpController(host, port, username, pwd) _logger.info("=====================1777777777111================") try: for item in self.cnc_ids: a = item.cnc_id sequence_collect.append(item.sequence_number) datas = base64.standard_b64decode(a.datas) # file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name) file_path_local = '{}/{}'.format('/nc2machine', a.display_name) # 本地测试一键下发 # file_path_local = '{}/{}'.format('D:\\jikimo', a.display_name) # file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name) file_path_remote = '{}\{}'.format(remote_path, a.display_name) with open(file_path_local, mode='wb+') as file: file.write(datas) # 存在本地的文件下发到机床 ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local) _logger.info("======%s下发成功======" % a.display_name) item.button_state = True ftp.close_ftp() # 增加一键下发记录 up_time = str(datetime.now() + timedelta(hours=8)) sequence_str = ','.join(sequence_collect) self.delivery_records.create({ 'delivery_type': '一键下发', 'delivery_time': up_time, 'influence_record': sequence_str, }) _logger.info("=====================22================") except Exception as e: _logger.info("=====================================", e) raise UserError('NC下发执行超时, 请检查下发状态') def up_merge_all(self): """ 此函数用于将NC代码一键合并下发到机床 :return: """ # 一键合并下发前删除机床上的全部程序 try: filepath = '/nc2machine' del_list = os.listdir(filepath) _logger.info("=====================================%s" % del_list) for f in del_list: file_path = os.path.join(filepath, f) if os.path.isfile(file_path): os.remove(file_path) except Exception as e: _logger.info("=====================================", e) raise UserError('程序删除失败,请重试') # host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC" try: self.compensation() except Exception: raise UserError("补偿值写入执行超时,请检查机床状态或者写入状态") sequence_collect = [] host = self.workcenter_id.machine_tool_id.ftp_host port = self.workcenter_id.machine_tool_id.ftp_port username = self.workcenter_id.machine_tool_id.ftp_num pwd = self.workcenter_id.machine_tool_id.ftp_pwd remote_path = self.workcenter_id.machine_tool_id.ftp_remote_path _logger.info("=====================1666666661111================%s,%s,%s,%s" % (host, port, username, pwd)) ftp = ftp_operate.FtpController(host, port, username, pwd) _logger.info("=====================1777777777111================") file_path_local = '' file_path_remote = '' try: # 给文件名 _logger.info('启动') begin_name1 = self.cnc_ids[0].cnc_id.display_name.split('-') _logger.info(begin_name1) temp_name1 = begin_name1[-1].split('.') final_name = '%s-ALL-MERGE.%s' % (begin_name1[0], temp_name1[-1]) _logger.info(final_name) for item in self.cnc_ids: a = item.cnc_id sequence_collect.append(item.sequence_number) datas = base64.standard_b64decode(a.datas) # file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name) file_path_local = '{}/{}'.format('/nc2machine', final_name) # 本地测试一键下发 # file_path_local = '{}/{}'.format('D:\\jikimo', a.display_name) # file_path_remote = '{}\{}'.format('//M80(192,168,2,142)//DS', a.display_name) file_path_remote = '{}\{}'.format(remote_path, final_name) # 合并文件 with open(file_path_local, mode='ab+') as file: file.write(datas) item.button_state = True _logger.info('========一键下发前合并成功===============') # 去除合并文件中间部分的头尾 with open(file_path_local, mode='rb+') as f: # _logger.info(f.read()) # content = f.read() # _logger.info(content) new_content = f.read().replace(b'\r\nM30\r\n%\r\n%\r\n', b'\r\n') # _logger.info(new_content) f.seek(0) f.truncate() f.write(new_content) _logger.info('========二次合并成功===============') # 存在本地的文件下发到机床 ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local) _logger.info("======%s一键合并下发成功======" % a.display_name) ftp.close_ftp() # 增加一键合并下发记录 up_time = str(datetime.now() + timedelta(hours=8)) sequence_str = ','.join(sequence_collect) self.delivery_records.create({ 'delivery_type': '一键合并下发', 'delivery_time': up_time, 'influence_record': sequence_str, }) _logger.info("=====================22================") except Exception as e: for item in self.cnc_ids: item.button_state = False _logger.info("=====================================", e) raise UserError('NC下发执行超时, 请检查下发状态') def get__state(self): pay_time = str(datetime.now()) json = { 'params': { 'model_name': 'jikimo.process.order', 'field_name': 'name', 'default_code': 'PO-2022-1207-0020', 'state': '待付款', # 'pay_time': pay_time, # 'get_order_sf': 21, }, } # res_str = json.dumps(vals) url = 'https://bfm.cs.jikimo.com/api/get/state' requests.post(url, json=json, data=None) def action_test(self, barcode=12345): workorder_obj = self.env['mrp.workorder'].sudo().search([('tray_code', '=', barcode)]) action = { 'name': '工单', # 'name': name, 'type': 'ir.actions.act_window', # 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mrp.workorder', 'view_id': self.env.ref('mrp.mrp_production_workorder_form_view_inherit').id, 'res_id': 1023, 'target': 'current', 'context': {'id': workorder_obj.id}, # 'flags': {'initial_mode': 'edit'}, } return action # result = request.env['ir.actions.act_window'].sudo().create(action).read()[0] # action = {'action': action} # return result @api.model def get_product_id_by_barcode(self, barcode, **kwargs): print(kwargs) print(barcode) print('111111111111111111111') workorder_obj_target = self.env['mrp.workorder'].sudo().search([('tray_code', '=', barcode)]) workorder_obj_current = self.env['mrp.workorder'].sudo().search([('id', '=', kwargs['current_id'])]) # workorder_cnc = self.env['mrp.workorder'].sudo().search(['&', ('production_id', '=', workorder_obj.production_id.id), ('name', '=', 'CNC加工')]) workorder_cnc = self.env['mrp.workorder'].sudo().search( ['&', ('production_id', '=', workorder_obj_target.production_id.id), ('name', '=', workorder_obj_current.name)]) print('222222222222222222222222') if workorder_obj_target: print(workorder_obj_target) print(workorder_obj_target.id) action = { 'name': '工单', 'type': 'ir.actions.act_window', # 'view_type': 'form', 'views': [[False, 'form']], 'view_mode': 'form', 'res_model': 'mrp.workorder', 'view_id': request.env.ref('mrp.mrp_production_workorder_form_view_inherit').id, 'res_id': workorder_cnc.id, 'target': 'current', 'context': {'id': workorder_obj_target.id, 'clear_breadcrumbs': True, }, # 'flags': {'initial_mode': 'edit'}, } action = {'result': action, 'error': '返回错误'} action1 = json.dumps(action) return action1 else: return False def cnc_file_download(self): """ 一个下载当前cnc所有nc文件为一个zip包的功能 """ self.ensure_one() # 如果没有附件,直接返回 if not self.cnc_ids: return # 处理第一个附件的文件名 first_attachment = self.cnc_ids[0].cnc_id file_name = first_attachment.display_name.split('-')[0] + '.zip' # 创建一个内存文件和一个zip文件 memory_file = BytesIO() with ZipFile(memory_file, 'w') as zipf: # 遍历需要下载的附件 for item in self.cnc_ids: a = item.cnc_id datas = base64.standard_b64decode(a.datas) # 将nc文件写入zip文件 zipf.writestr(a.display_name, datas) # 然后可以创建一个ir.attachment对象,将生成的zip文件保存为一个新的附件 memory_file.seek(0) output = base64.b64encode(memory_file.read()) memory_file.close() attachment_data = { 'name': file_name, 'type': 'binary', 'res_model': self._name, 'res_id': self.id, 'datas': output } attachment = self.env['ir.attachment'].create(attachment_data) # 返回附件的下载链接 download_url = '/web/content/%s?download=true' % attachment.id base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url') return { 'type': 'ir.actions.act_url', 'url': str(base_url) + download_url, 'target': 'self', } # class CuttingTimeToolType(models.Model): # _inherit = 'sf.cutting_tool.type' # total_cut_time = fields.Char(string='总切削时长') # predict_life_time = fields.Char(string='预估寿命') # # 只能看到未被占用的刀位,或者有提示说占没占用 # tool_position = fields.Char(string='选择刀位') # # cnc_ids = fields.One2many(string='选择机床') # is_connect_tool_position = fields.Boolean(string='是否已绑定刀位', default=False) # # def tool_connect_machine(self): # pass # # def tool_unconnect_machine(self): # pass class DeliveryRecord(models.Model): """ 扫码托盘码可查到制造订单,由制造订单查工单 """ _name = "delivery.record" _description = "Delivery Record" delivery_type = fields.Char(string='下发方式', readonly=True) delivery_time = fields.Char(string='下发时间', readonly=True) influence_record = fields.Char(string='影响记录', readonly=True) workorder_id = fields.Many2one('mrp.workorder', string='工单') sf_cnc_processing_id = fields.Many2one('sf.cnc.processing', string='NC') # @api.model # def create(self, values): # try: # values['order_code'] = self.env['ir.sequence'].next_by_code('sf_machine_connect.delivery.record') # stock = self.env['sunrise.u.stock'] # if 'order_items' in values.keys(): # for item in values['order_items']: # stock_commodity = stock.search([('commodity', '=', item[2]['commodity'])]) # stock_commodity.amount += item[2]['amount'] # return super().create(values) # except: # raise Exception('b_purchase_order.py:create()')