diff --git a/sf_base/views/base_view.xml b/sf_base/views/base_view.xml index 7d4854d3..ff85bfda 100644 --- a/sf_base/views/base_view.xml +++ b/sf_base/views/base_view.xml @@ -359,7 +359,7 @@
-
diff --git a/sf_dlm/__manifest__.py b/sf_dlm/__manifest__.py index da6dba4b..32d84919 100644 --- a/sf_dlm/__manifest__.py +++ b/sf_dlm/__manifest__.py @@ -10,9 +10,10 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['mrp', 'base', 'sf_manufacturing'], + 'depends': ['mrp', 'base', 'sf_manufacturing', 'purchase', 'mrp_subcontracting', 'uom'], 'data': [ 'data/product_data.xml', + 'data/uom_data.xml', 'views/product_template_view.xml' ], 'demo': [ diff --git a/sf_dlm/data/tt.xml b/sf_dlm/data/tt.xml new file mode 100644 index 00000000..847e6a80 --- /dev/null +++ b/sf_dlm/data/tt.xml @@ -0,0 +1,57 @@ + + + + + CNC加工产品模板 + + delivery + product + false + + + + False + + + + 胚料 + 胚料 + + + + 自加工 + + delivery + product + false + + + + False + + + + 外协 + + delivery + product + false + + + + False + + + + 采购 + + delivery + product + false + + + + False + + + \ No newline at end of file diff --git a/sf_dlm/models/product_template.py b/sf_dlm/models/product_template.py index 13321df6..471fad79 100644 --- a/sf_dlm/models/product_template.py +++ b/sf_dlm/models/product_template.py @@ -17,11 +17,11 @@ class ResProductTemplate(models.Model): model_height = fields.Float('模型高[mm]', digits=(16, 3)) model_volume = fields.Float('模型体积[m³]') model_machining_precision = fields.Selection([ - ('±0.10mm', '±0.10mm'), - ('±0.05mm', '±0.05mm'), - ('±0.03mm', '±0.03mm'), - ('±0.02mm', '±0.02mm'), - ('±0.01mm', '±0.01mm')], string='加工精度') + ('0.10', '±0.10mm'), + ('0.05', '±0.05mm'), + ('0.03', '±0.03mm'), + ('0.02', '±0.02mm'), + ('0.01', '±0.01mm')], string='加工精度') model_type_id = fields.Many2one('sf.model.type', string='模型类型') model_processing_panel = fields.Char('模型加工面板') model_surface_process_id = fields.Many2one('sf.production.process', string='表面工艺') @@ -80,10 +80,9 @@ class ResProductTemplate(models.Model): 'model_volume': (item['model_long'] + model_type.embryo_tolerance) * ( item['model_width'] + model_type.embryo_tolerance) * ( item['model_height'] + model_type.embryo_tolerance), - 'model_type_id': 1, - # 'model_machining_precision': item['model_machining_precision'], + 'model_type_id': model_type.id, 'model_processing_panel': 'R', - 'model_machining_precision': '±0.10mm', + 'model_machining_precision': item['model_machining_precision'], 'model_code': item['barcode'], 'length': item['model_long'], 'width': item['model_width'], @@ -118,6 +117,7 @@ class ResProductTemplate(models.Model): attachment = self.env['ir.attachment'].create({ 'datas': base64.b64decode(data), 'type': 'binary', + 'public': True, 'description': '模型文件', 'name': name }) @@ -131,7 +131,6 @@ class ResProductTemplate(models.Model): [('materials_no', '=', item['texture_code'])]) materials_type_id = self.env['sf.materials.model'].search( [('materials_no', '=', item['texture_type_code'])]) - model_type = self.env['sf.model.type'].search([], limit=1) supplier = self.env['mrp.bom'].get_supplier(materials_type_id) logging.info('no_bom_copy_product_supplier-vals:%s' % supplier) vals = { @@ -162,12 +161,10 @@ class ResProductTemplate(models.Model): no_bom_copy_product_id.purchase_ok = True no_bom_copy_product_id.seller_ids = [ (0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0, 'is_subcontractor': True})] - logging.info('no_bom_copy_product_id-seller_ids-vals:%s' % no_bom_copy_product_id.seller_ids) elif route_type == 'purchase': no_bom_copy_product_id.purchase_ok = True no_bom_copy_product_id.seller_ids = [ (0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0})] - logging.info('no_bom_copy_product_id-seller_ids-vals:%s' % no_bom_copy_product_id.seller_ids) no_bom_copy_product_id.write(vals) logging.info('no_bom_copy_product_id-vals:%s' % vals) # product_id.product_tmpl_id.active = False diff --git a/sf_dlm/views/product_template_view.xml b/sf_dlm/views/product_template_view.xml index c563f728..652b05a3 100644 --- a/sf_dlm/views/product_template_view.xml +++ b/sf_dlm/views/product_template_view.xml @@ -6,13 +6,13 @@ product.template - - - - + + + + - + @@ -36,18 +36,31 @@ - - - - - - - - - - - + + + diff --git a/sf_machine_connect/__init__.py b/sf_machine_connect/__init__.py new file mode 100644 index 00000000..9a7e03ed --- /dev/null +++ b/sf_machine_connect/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/sf_machine_connect/__manifest__.py b/sf_machine_connect/__manifest__.py new file mode 100644 index 00000000..b74437dc --- /dev/null +++ b/sf_machine_connect/__manifest__.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +{ + 'name': 'sf_machine_connect', + 'version': '1.0', + 'summary': '智能工厂机床连接模块', + 'sequence': 10, + 'description': """ +这是一个模块 +==================== + """, + 'category': 'Tools', + 'depends': ['sf_base', 'sf_manufacturing', 'barcodes', ], + 'data': [ + # 定义权限组放在最上面 + # 权限组 + "security/ir.model.access.csv", + 'views/compensation.xml', + 'views/ftp_button.xml', + 'views/SfWorkOrderBarcodes.xml', + 'views/WorkCenterBarcodes.xml', + 'views/Stock_picking_Barcodes.xml', + 'views/machine_monitor.xml', + ], + + 'installable': True, + 'application': True, + # 'auto_install': False, + 'license': 'LGPL-3', +} diff --git a/sf_machine_connect/models/__init__.py b/sf_machine_connect/models/__init__.py new file mode 100644 index 00000000..30087503 --- /dev/null +++ b/sf_machine_connect/models/__init__.py @@ -0,0 +1,3 @@ +from . import ftp_client +from . import ftp_operate +from . import py2opcua diff --git a/sf_machine_connect/models/data_collection.py b/sf_machine_connect/models/data_collection.py new file mode 100644 index 00000000..8f860c37 --- /dev/null +++ b/sf_machine_connect/models/data_collection.py @@ -0,0 +1,44 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import api, fields, models + +# ---------------------------------------------------------- +# Models for Simulation +# ---------------------------------------------------------- +class Simulation(models.Model): + _name = 'simulation' + _description = 'SIMULATION' + + name = fields.Char('Name', size=50, readonly=True) + place_value = fields.Boolean(String="位值") + place_value_random = fields.Boolean(String="位值随机") + place_value_ai = fields.Boolean(String="位值自增") + place_value_list = fields.Boolean(String="位值列表") + + unsigned_integer_8_DO = fields.Integer(Sting="无符号8位整数D0") + unsigned_integer_8_D1 = fields.Integer(Sting="无符号8位整数D1") + unsigned_integer_8_random = fields.Integer(Sting="无符号8位整数随机") + unsigned_integer_8_ai = fields.Integer(Sting="无符号8位整数自增") + unsigned_integer_8_list = fields.Integer(Sting="无符号8位整数列表") + + integer_8 = fields.Integer(String="有符号8位整数") + integer_8_random = fields.Integer(String="有符号8位整数随机") + integer_8_ai = fields.Integer(String="有符号8位整数自增") + integer_8_ad = fields.Integer(String="有符号8位整数自减") + integer_16 = fields.Integer(String="有符号16位整数") + integer_16_random = fields.Integer(String="有符号16位整数随机") + integer_16_list = fields.Integer(String="有符号16位整数列表") + + + + +# ---------------------------------------------------------- +# Models for Mitsubishi +# ---------------------------------------------------------- +class MitsuCnc(models.Model): + _name = 'mitsu.cnc' + _description = 'Mitsubishi CNC' + + name = fields.Char('Name', size=50, readonly=True) + status = fields.Boolean(string="状态") diff --git a/sf_machine_connect/models/ftp_client.py b/sf_machine_connect/models/ftp_client.py new file mode 100644 index 00000000..9f943dca --- /dev/null +++ b/sf_machine_connect/models/ftp_client.py @@ -0,0 +1,153 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. +import base64 + +import psycopg2 +import os +import logging +from zeep.exceptions import ValidationError + +from odoo import http +from ftplib import FTP +from odoo.http import request +from odoo import api, fields, models +from odoo.addons.sf_machine_connect.models import py2opcua, ftp_operate +# from .ftp_operate import FtpController +# from .py2opcua import Py2opcua + +_logger = logging.getLogger(__name__) + +# ---------------------------------------------------------- +# Models for client +# ---------------------------------------------------------- + +class FtpButton(models.Model): + _inherit = 'sf.cnc.processing' + + def pri(self): + print('11111111111111111') + s = self.cnc_id + s1 = self.cnc_id._filestore() + print(s1) + v = self.cnc_id.display_name + a = self.cnc_id.datas + print(v) + print(a) + ftp_operate.FtpController.prin(self) + + def up(self): + # self.env['mrp.workorder'].check_compensation_before_up() + ftp = ftp_operate.FtpController() + # ftp.delAllfile('C://Users//马广威//Desktop//ftp') + a = self.cnc_id + print(a.display_name) + _logger.info(a.display_name) + datas = base64.standard_b64decode(a.datas) + # file_path = '{}\{}\{}'.format(a._filestore(), a.store_fname.split('/'[0]), a.display_name) + + # 此方法不走ftp,直接文件写入,暂不确定能否写入ftp服务器,但可以转成ftp方法,只是要把文件暂存到本地,再上传 + # file_path_local = '{}\{}'.format('C://Users//马广威//Desktop//ftp', a.display_name) + file_path_local = '{}/{}'.format('/nc2machine', a.display_name) + file_path_remote = '{}\{}'.format('//(192,168,2,141)//DS', a.display_name) + + + with open(file_path_local, mode='wb+') as file: + file.write(datas) + + # file = open(file_path_local, 'wb+') + # file.write(datas) + # file.close() + + # 存在本地的文件下发到机床 + ftp.upload_file(remotepath=file_path_remote, localpath=file_path_local) + + +class FtpClient(models.Model): + _name = "ftp.client" + _description = 'Ftp Client' + + name = fields.Char('Name', size=50, readonly=True) + description = fields.Char(size=50) + mobile = fields.Char(size=50) + + def up(self): + ftp = ftp_operate.FtpController() + # FtpController.__init__(self, host="127.0.0.1", port=2121, username="admin", password="123456") + ftp.upload_file(remotepath='/(192,168,199,2)/DS/02-222.NC', localpath='D:/ftp/up/02-222.NC') + + # def delete(self): + # ftp = FtpController() + # ftp.del_file() + + # + # def _compute_ip_url(self): + # for box in self: + # if not box.ip: + # box.ip_url = False + # else: + # url = 'https://%s' if box.get_base_url()[:5] == 'https' else 'http://%s:8069' + # box.ip_url = url % box.ip + # + # def _compute_device_count(self): + # for box in self: + # box.device_count = len(box.device_ids) + + +class Machine_ftp(models.Model): + # _name = 'data.collection' + _inherit = 'sf.machine_tool' + + timestamp = fields.Datetime('时间戳', readonly=True) + signed = fields.Integer('刷新间隔', readonly=True) + status = fields.Boolean('在线状态', readonly=True) + tool_num = fields.Integer('当前刀具', readonly=True) + program = fields.Char('当前程序', readonly=True) + + +class WorkCenterBarcode(models.Model): + """ + 扫码托盘码可查到制造订单,由制造订单查工单 + """ + _inherit = "mrp.workorder" + compensation_value_x = fields.Float(string='X轴补偿值') + compensation_value_y = fields.Float(string='Y轴补偿值') + + def compensation(self): + ''' + 将节点与其值放入字典,字典作为参数传入 + :return: + ''' + temp_dict = {} + temp_dict['ns=1;s=Project_Default.Group1.Mitsubishi_NC.hongbianliang520'] = self.compensation_value_x + temp_dict['ns=1;s=Project_Default.Group1.Mitsubishi_NC.hongbianliang521'] = self.compensation_value_y + print("测试补偿能够执行") + temp = py2opcua.Py2opcua() + _logger.info(temp) + temp.connect() + temp.write(temp_dict) + temp.disconnect() + + def check_compensation_before_up(self): + temp_value = self.env['mrp.workorder'].getcenter() + _logger.info("====================================================================================") + _logger.info(temp_value) + if temp_value[0] == 0 or temp_value[1] != 0: + temp_dict = {} + # temp_dict['ns=1;s=Project_Default.Group1.Mitsubishi_NC.hongbianliang520'] = temp_value[0] + temp_dict['ns=1;s=Project_Default.Group1.Mitsubishi_NC.hongbianliang520'] = 111 + temp_dict['ns=1;s=Project_Default.Group1.Mitsubishi_NC.hongbianliang521'] = 111 + # temp_dict['ns=1;s=Project_Default.Group1.Mitsubishi_NC.hongbianliang521'] = temp_value[1] + print("测试补偿能够执行") + temp = py2opcua.Py2opcua() + _logger.info(temp) + temp.connect() + temp.write(temp_dict) + temp.disconnect() + + + + + def test(self, barcode): + # 托盘对象 + tray = self.env('sf.tray').search("code", "=", barcode) + product = tray.product_id \ No newline at end of file diff --git a/sf_machine_connect/models/ftp_operate.py b/sf_machine_connect/models/ftp_operate.py new file mode 100644 index 00000000..052c6e1c --- /dev/null +++ b/sf_machine_connect/models/ftp_operate.py @@ -0,0 +1,118 @@ +# -*- coding: utf-8 -*- +import os +from ftplib import FTP + +class FTP_P(FTP): + def dirs(self, *args): + '''List a directory in long form. + By default list current directory to stdout. + Optional last argument is callback function; all + non-empty arguments before it are concatenated to the + LIST command. (This *should* only be used for a pathname.)''' + cmd = 'LIST' + templist = [] + tempdic = {} + func = None + if args[-1:] and type(args[-1]) != type(''): + args, func = args[:-1], args[-1] + for arg in args: + if arg: + cmd = cmd + (' ' + arg) + self.retrlines(cmd, templist.append) + # print(templist) + # 处理返回结果,只需要目录名称 + r_files = [file.split(" ")[-1] for file in templist] + tempdic['name'] = [file for file in r_files if file != "." and file != ".."] + # 去除. .. + return tempdic + # return [file for file in r_files if file != "." and file != ".."] + +# FTP接口类 +class FtpController(): + + ''' + 这是ftp接口类,在类初始化的时候就连接了ftp服务器,能否成功连接有反馈。 + 类中定义了两个接口:上传接口和删除接口 + ''' + # 三菱机床连接 + def __init__(self, host="192.168.2.158", port=8080, username="MITSUBISHI", password="CNC"): + self.host = host + self.port = port + self.username = username + self.password = password + ftp = FTP_P() + # self.ftp.set_debuglevel(2) #打开调试级别2,显示详细信息 + ftp.set_pasv(0) #0主动模式 1 #被动模式 + try: + ftp.connect(self.host, self.port) + ftp.login(self.username, self.password) + print("连接成功") + self.ftp = ftp + except: + print("连接失败") + + # 试验接口 + def prin(self): + print("这是试验接口") + + # 试验ftp服务器连接 + # def connect(self, host="127.0.0.1", port=2121, username="admin", password="123456"): + # ftp = FTP_P() + # try: + # ftp.connect(host, port) + # ftp.login(username, password) + # print("连接成功") + # ftp1 = ftp + # return ftp1 + # except: + # print("连接失败") + + + # 三菱代码下发 + def upload_file(self, remotepath='/(192,168,199,2)/DS/Z4.5.NC', localpath='D:/ftp/up/Z4.5.NC'): + ''' + 第一个是要上传到ftp服务器路径下的文件,第二个是本地要上传的的路径文件 + :param remotepath: 上传和下载都需要设置工作目录,注意只能使用文件名,不能有路径中的冒号 + :param localpath: + :return: + ''' + bufsize = 1024 + fp = open(localpath, 'rb') + self.ftp.storbinary('STOR ' + remotepath, fp, bufsize) + fp.close() + # return "上传成功" + + def delAllfile(self, ftppath): + dir_res = [] + try: + print(ftppath) + try: + self.ftp.cwd(ftppath) + except Exception as e: + print("进入ftp目录失败" + str(e)) + self.ftp.dir('.', dir_res.append) # 对当前目录进行dir(),将结果放入列表 + print(dir_res) + # for i in dir_res: + # if i.startswith("d"): + # dirName = i.split(" ")[-1] + # print("开始删除" + dirName + "文件夹") + # delAllfile(ftp, ftp.pwd() + "/" + dirName) + # ftp.cwd('..') + # print(ftppath + "/" + dirName) + # ftp.rmd(ftppath + '/' + dirName) + # else: + # filelist = ftp.getfiles(ftppath) + # for f in filelist: + # print("删除FTP目录:" + ftppath + "下存在文件:" + f) + # ftp.delete(f) + except Exception as e: + raise e + + # 删除远端ftp文件 + # 出现550 not found file是路径不对 + # def del_file(self, delpath='./YIN.NC'): + def del_file(self, delpath='/(192,168,199,2)/DS/Z4.5.NC'): + self.ftp.delete(delpath) # 删除远程文件 + + + diff --git a/sf_machine_connect/models/py2opcua.py b/sf_machine_connect/models/py2opcua.py new file mode 100644 index 00000000..992f3f72 --- /dev/null +++ b/sf_machine_connect/models/py2opcua.py @@ -0,0 +1,32 @@ +from opcua import ua, Client + + +class Py2opcua: + + def __init__(self, url='opc.tcp://192.168.2.99:4840'): + self.client = Client(url) + + def connect(self): + + try: + # 连接客户端 + self.client.connect() + print("opcua服务器连接成功,可以写入") + return self.client + except: + print("opcua服务器连接失败,请检查") + + def write(self, temp_dict): + temp_dict = temp_dict + temp_list = list(temp_dict.items()) + for i in range(len(temp_list)): + # 寻找节点上的变量 + var = self.client.get_node(temp_list[i][0]) + # var.set_value(ua.Variant(1.234, ua.VariantType.Float)) + # 通过set_value写值 + var.set_value(ua.Variant(temp_list[i][1], ua.VariantType.Double)) + print("%s 已写入" % var.get_value()) + + def disconnect(self): + # 断开连接 + self.client.disconnect() diff --git a/sf_machine_connect/security/iot_security.xml b/sf_machine_connect/security/iot_security.xml new file mode 100644 index 00000000..c673200b --- /dev/null +++ b/sf_machine_connect/security/iot_security.xml @@ -0,0 +1,20 @@ + + + + + + IoT Box multi company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + + IoT Device multi company rule + + + ['|',('company_id','=',False),('company_id', 'in', company_ids)] + + + + diff --git a/sf_machine_connect/security/ir.model.access.csv b/sf_machine_connect/security/ir.model.access.csv new file mode 100644 index 00000000..53d13813 --- /dev/null +++ b/sf_machine_connect/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_ftp_client,ftp.client,model_ftp_client,base.group_user,1,1,1,1 diff --git a/sf_machine_connect/static/description/icon.png b/sf_machine_connect/static/description/icon.png new file mode 100644 index 00000000..d5c71478 Binary files /dev/null and b/sf_machine_connect/static/description/icon.png differ diff --git a/sf_machine_connect/static/src/css/MyWidget.css b/sf_machine_connect/static/src/css/MyWidget.css new file mode 100644 index 00000000..12e077c3 --- /dev/null +++ b/sf_machine_connect/static/src/css/MyWidget.css @@ -0,0 +1,30 @@ +.o_int_colorpicker { + .o_color_pill { + display: inline-block; + height: 25px; + width: 25px; + margin: 4px; + border-radius: 25px; + position: relative; + @for $size from 1 through length($o-colors) { + &.o_color_#{$size - 1} { + background-color: nth($o-colors, $size); + &:not(.readonly):hover { + transform: scale(1.2); + transition: 0.3s; + cursor: pointer; + } + &.active:after{ + content: "\f00c"; + display: inline-block; + font: normal normal normal 14px/1 FontAwesome; + font-size: inherit; + color: #fff; + position: absolute; + padding: 4px; + font-size: 16px; + } + } + } + } +} \ No newline at end of file diff --git a/sf_machine_connect/static/src/css/iot.css b/sf_machine_connect/static/src/css/iot.css new file mode 100644 index 00000000..2aab2fe1 --- /dev/null +++ b/sf_machine_connect/static/src/css/iot.css @@ -0,0 +1,5 @@ +.o_button_iot { + min-width: 120px; + min-height: 40px; + margin-left: 50px; +} diff --git a/sf_machine_connect/static/src/xml/Barcode_Scan_template.xml b/sf_machine_connect/static/src/xml/Barcode_Scan_template.xml new file mode 100644 index 00000000..0b5dec78 --- /dev/null +++ b/sf_machine_connect/static/src/xml/Barcode_Scan_template.xml @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sf_machine_connect/static/src/xml/Flush.xml b/sf_machine_connect/static/src/xml/Flush.xml new file mode 100644 index 00000000..8fab7c9e --- /dev/null +++ b/sf_machine_connect/static/src/xml/Flush.xml @@ -0,0 +1,10 @@ + + + +
+

+ 显示累加字符串:aaaaaabbb +

+
+
+
\ No newline at end of file diff --git a/sf_machine_connect/static/src/xml/MyComponent.xml b/sf_machine_connect/static/src/xml/MyComponent.xml new file mode 100644 index 00000000..ae289933 --- /dev/null +++ b/sf_machine_connect/static/src/xml/MyComponent.xml @@ -0,0 +1,27 @@ + + + +
+
+

欢迎登陆页面!

+

这是一个超大屏幕(Jumbotron)的实例。

+

+ 学习更多 +

+
+
+ + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/sf_machine_connect/static/src/xml/MyWidget.xml b/sf_machine_connect/static/src/xml/MyWidget.xml new file mode 100644 index 00000000..00a6b92c --- /dev/null +++ b/sf_machine_connect/static/src/xml/MyWidget.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml b/sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml new file mode 100644 index 00000000..dc9b67a0 --- /dev/null +++ b/sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml @@ -0,0 +1,32 @@ + + + + +
+ + + + + + + + + + + + + + +
+ +
+
\ No newline at end of file diff --git a/sf_machine_connect/static/src/xml/barcodes.xml b/sf_machine_connect/static/src/xml/barcodes.xml new file mode 100644 index 00000000..4336852b --- /dev/null +++ b/sf_machine_connect/static/src/xml/barcodes.xml @@ -0,0 +1,15 @@ + + + + + + + + diff --git a/sf_machine_connect/static/src/xml/iot_scan_progress_template.xml b/sf_machine_connect/static/src/xml/iot_scan_progress_template.xml new file mode 100644 index 00000000..9360c22b --- /dev/null +++ b/sf_machine_connect/static/src/xml/iot_scan_progress_template.xml @@ -0,0 +1,17 @@ + + +
+

Range(s) to scan

+
    +
    + + Add +
    + +
    +

    +

    +
      +
    +
+
diff --git a/sf_machine_connect/static/src/xml/many2one_field.xml b/sf_machine_connect/static/src/xml/many2one_field.xml new file mode 100644 index 00000000..8ed9b397 --- /dev/null +++ b/sf_machine_connect/static/src/xml/many2one_field.xml @@ -0,0 +1,17 @@ + + + + + + + + +
+
+ + + +
+ + + + mrp.production + +
+ + + + + + +
+
+
+ + + 数据采集 + ftp.client + list,form,kanban + +

+ 这是我们的数据采集与程序管理页面! +

+
+
+ + 扫码 + mrp.production + list,form,kanban + +

+ 这是我们的扫码页面! +

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/sf_machine_connect/views/views.xml b/sf_machine_connect/views/views.xml new file mode 100644 index 00000000..6b4e447d --- /dev/null +++ b/sf_machine_connect/views/views.xml @@ -0,0 +1,45 @@ + + + + sale.order.form.inherit + sf.machine_tool + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf_machine_connect/views/views_test_barcode.xml b/sf_machine_connect/views/views_test_barcode.xml new file mode 100644 index 00000000..c346ae36 --- /dev/null +++ b/sf_machine_connect/views/views_test_barcode.xml @@ -0,0 +1,15 @@ + + + + sale.order.form.inherit + mrp.workorder + + + + +
+ + + + + \ No newline at end of file diff --git a/sf_machine_connect/views/workorder_button.xml b/sf_machine_connect/views/workorder_button.xml new file mode 100644 index 00000000..5e4c0d9d --- /dev/null +++ b/sf_machine_connect/views/workorder_button.xml @@ -0,0 +1,18 @@ + + + + + + mrp.workcenter.view.kanban.inherit.mrpworkorder + mrp.workcenter + + + + + +
-
+ -
@@ -110,16 +104,12 @@ - -
-
@@ -227,7 +217,7 @@
@@ -269,7 +259,7 @@
@@ -278,11 +268,11 @@
diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py index 76fc34c5..e37983e2 100644 --- a/sf_mrs_connect/controllers/controllers.py +++ b/sf_mrs_connect/controllers/controllers.py @@ -20,44 +20,32 @@ class Sf_Mrs_Connect(http.Controller): """ logging.info('get_cnc_processing_create:%s' % kw) try: + res = {'status': 1, 'message': '成功'} datas = request.httprequest.data ret = json.loads(datas) ret = json.loads(ret['result']) - for obj in ret: - cnc = request.env['sf.cnc.processing'].with_user( - request.env.ref("base.user_admin")).cnc_processing_create(obj) - # # 从ftp拉取对应的文件 - model_code = cnc.workorder_id.product_id.barcode - processing_panel = cnc.workorder_id.processing_panel - logging.info('model_code:%s' % model_code) - server_dir = cnc.with_user(request.env.ref("base.user_admin")).download_file_tmp(model_code, - processing_panel) - # cnc_file_path = os.path.join('/', server_dir, cnc.program_name + '.nc') - # logging.info('cnc_file_path:%s' % cnc_file_path) - # cnc.with_user(request.env.ref("base.user_admin")).write_file(cnc_file_path, cnc) - logging.info('server_dir:%s' % server_dir) - for root, dirs, files in os.walk(server_dir): - for f in files: - logging.info('f:%s' % f) - logging.info('f[0]:%s' % f.split('.')[0]) - if os.path.splitext(f)[1] == ".pdf": - full_path = os.path.join(server_dir, root, f) - logging.info('pdf:%s' % full_path) - if full_path != False: - if not cnc.workorder_id.cnc_worksheet: - cnc.workorder_id.cnc_worksheet = base64.b64encode(open(full_path, 'rb').read()) - else: - logging.info('break:%s' % 'break') - continue - else: - logging.info('cnc.program_name:%s' % cnc.program_name) - if cnc.program_name == f.split('.')[0]: - logging.info('f[0]:%s' % f[0]) - cnc_file_path = os.path.join(server_dir, root, f) - logging.info('cnc_file_path:%s' % cnc_file_path) - cnc.with_user(request.env.ref("base.user_admin")).write_file(cnc_file_path, cnc) - else: - continue - + # 查询状态为进行中且类型为获取CNC加工程序的工单 + cnc_workorder = request.env['mrp.workorder'].with_user( + request.env.ref("base.user_admin")).search([('production_id.name', '=', ret['production_order_no']), + ('routing_type', '=', '获取CNC加工程序')]) + if cnc_workorder: + # 拉取所有加工面的程序文件 + # i = 1 + 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 == False: + res['status'] = -2 + res['message'] = '制造订单号为%s的CNC程序文件从FTP拉取失败' % (cnc_workorder.production_id.name) + return json.JSONEncoder().encode(res) + request.env['sf.cnc.processing'].with_user( + request.env.ref("base.user_admin")).cnc_processing_create(cnc_workorder, ret) + return json.JSONEncoder().encode(res) + else: + res = {'status': 0, 'message': '该制造订单暂未开始'} + return json.JSONEncoder().encode(res) except Exception as e: + res = {'status': -1, 'message': '系统解析失败'} logging.info('get_cnc_processing_create error:%s' % e) + return json.JSONEncoder().encode(res) diff --git a/sf_mrs_connect/models/ftp_operate.py b/sf_mrs_connect/models/ftp_operate.py index 655c50e6..07bf5690 100644 --- a/sf_mrs_connect/models/ftp_operate.py +++ b/sf_mrs_connect/models/ftp_operate.py @@ -15,26 +15,31 @@ class FtpController(): ftp = FTP() - def __init__(self, host="192.168.50.202", port=21, username="ftpuser", password="123456"): + def __init__(self, host, port, username, password): try: self.ftp.connect(host, port) self.ftp.login(username, password) - logging.info("连接成功: ") + logging.info("ftp连接成功") except: - logging.info("连接失败: ") + logging.info("ftp连接失败") + return False # 下载目录下的文件 def download_file_tree(self, target_dir, serverdir): if not os.path.exists(serverdir): os.makedirs(serverdir) + try: + logging.info("进入FTP目录 ") self.ftp.cwd(target_dir) # 切换工作路径 + logging.info('FTP目录:%s' % target_dir) remotenames = self.ftp.nlst() + logging.info('FTP目录文件:%s' % remotenames) for file in remotenames: server = os.path.join(serverdir, file) if file.find(".") != -1: self.download_file(server, file) - else: - return + except: + return False # 下载指定目录下的指定文件 def download_file(self, serverfile, remotefile): diff --git a/sf_mrs_connect/models/res_config_setting.py b/sf_mrs_connect/models/res_config_setting.py index fec87d75..dadb7de5 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -12,8 +12,12 @@ class ResConfigSettings(models.TransientModel): _inherit = 'res.config.settings' token = fields.Char(string='TOKEN', default='b811ac06-3f00-11ed-9aed-0242ac110003') - sf_secret_key = fields.Char(string='密钥', default= 'wBmxej38OkErKhD6') - sf_url = fields.Char(string='访问地址', default= 'https://sf.cs.jikimo.com') + sf_secret_key = fields.Char(string='密钥', default='wBmxej38OkErKhD6') + sf_url = fields.Char(string='访问地址', default='https://sf.cs.jikimo.com') + ftp_host = fields.Char(string='FTP的ip') + ftp_port = fields.Char(string='FTP端口') + ftp_user = fields.Char(string='FTP用户') + ftp_password = fields.Char(string='FTP密码') def sf_all_sync(self): self.env['sf.production.materials'].sync_all_production_materials() @@ -40,8 +44,6 @@ class ResConfigSettings(models.TransientModel): _logger.info("同步资源库刀具") # self.env['sf.processing.order'].sync_all_processing_order() - - @api.model def get_values(self): """ @@ -53,11 +55,19 @@ class ResConfigSettings(models.TransientModel): token = config.get_param('token', default='') sf_secret_key = config.get_param('sf_secret_key', default='') sf_url = config.get_param('sf_url', default='') + ftp_host = config.get_param('ftp_host', default='') + ftp_port = config.get_param('ftp_port', default='') + ftp_user = config.get_param('ftp_user', default='') + ftp_password = config.get_param('ftp_password', default='') values.update( token=token, sf_secret_key=sf_secret_key, sf_url=sf_url, + ftp_host=ftp_host, + ftp_port=ftp_port, + ftp_user=ftp_user, + ftp_password=ftp_password ) return values @@ -67,4 +77,7 @@ class ResConfigSettings(models.TransientModel): ir_config.set_param("token", self.token or "") ir_config.set_param("sf_secret_key", self.sf_secret_key or "") ir_config.set_param("sf_url", self.sf_url or "") - + ir_config.set_param("ftp_host", self.ftp_host or "") + ir_config.set_param("ftp_port", self.ftp_port or "") + ir_config.set_param("ftp_user", self.ftp_user or "") + ir_config.set_param("ftp_password", self.ftp_password or "") diff --git a/sf_mrs_connect/views/res_config_settings_views.xml b/sf_mrs_connect/views/res_config_settings_views.xml index d650d0f3..7bc7f2ad 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -14,22 +14,49 @@
-
+
+
-
-
+
+ +
+

FTP参数配置

+
-