From eb162cb416f03efb44a4c82c794004efcb6585ce Mon Sep 17 00:00:00 2001 From: gqh Date: Wed, 11 Jan 2023 11:13:52 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=B7=A5=E5=8D=95=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/views/base_view.xml | 2 +- sf_bf_connect/controllers/controllers.py | 9 +- sf_dlm/__manifest__.py | 3 +- sf_dlm/models/product_template.py | 105 +++--- sf_dlm/views/product_template_view.xml | 47 +-- sf_manufacturing/__manifest__.py | 2 +- sf_manufacturing/models/mrp_production.py | 4 +- sf_manufacturing/models/mrp_workcenter.py | 6 - sf_manufacturing/models/mrp_workorder.py | 327 +++++++++--------- sf_manufacturing/models/tray.py | 35 ++ .../views/mrp_workcenter_views.xml | 2 +- sf_manufacturing/views/mrp_workorder_view.xml | 53 +-- sf_mrs_connect/controllers/controllers.py | 60 ++-- sf_mrs_connect/models/ftp_operate.py | 15 +- sf_mrs_connect/models/res_config_setting.py | 23 +- .../views/res_config_settings_views.xml | 41 +-- sf_sale/models/sale_order.py | 2 +- 17 files changed, 350 insertions(+), 386 deletions(-) diff --git a/sf_base/views/base_view.xml b/sf_base/views/base_view.xml index ff85bfda..7d4854d3 100644 --- a/sf_base/views/base_view.xml +++ b/sf_base/views/base_view.xml @@ -359,7 +359,7 @@
-
diff --git a/sf_bf_connect/controllers/controllers.py b/sf_bf_connect/controllers/controllers.py index 87b48468..5227592f 100644 --- a/sf_bf_connect/controllers/controllers.py +++ b/sf_bf_connect/controllers/controllers.py @@ -60,7 +60,7 @@ class Sf_Bf_Connect(http.Controller): self_machining_embryo = request.env['product.template'].sudo().no_bom_product_create( self_machining_id, item, - order_id, 'self_machining', i) + order_id, 'self_machining') # 创建胚料的bom self_machining_bom = request.env['mrp.bom'].with_user( request.env.ref("base.user_admin")).bom_create( @@ -79,8 +79,7 @@ class Sf_Bf_Connect(http.Controller): outsource_embryo = request.env['product.template'].sudo().no_bom_product_create(outsource_id, item, order_id, - 'subcontract', - i) + 'subcontract') # 创建胚料的bom outsource_bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create( outsource_embryo, @@ -96,14 +95,14 @@ class Sf_Bf_Connect(http.Controller): purchase_embryo = request.env['product.template'].sudo().no_bom_product_create(purchase_id, item, order_id, - 'purchase', i) + 'purchase') # 产品配置bom product_bom_purchase = request.env['mrp.bom'].with_user( request.env.ref("base.user_admin")).bom_create(product, 'normal', False) product_bom_purchase.with_user(request.env.ref("base.user_admin")).bom_create_line_has( purchase_embryo) - i += 1 order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item) + i += 1 res['factory_order_no'] = order_id.name except Exception as e: logging.info('get_bfm_process_order_list error:%s' % e) diff --git a/sf_dlm/__manifest__.py b/sf_dlm/__manifest__.py index 32d84919..da6dba4b 100644 --- a/sf_dlm/__manifest__.py +++ b/sf_dlm/__manifest__.py @@ -10,10 +10,9 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['mrp', 'base', 'sf_manufacturing', 'purchase', 'mrp_subcontracting', 'uom'], + 'depends': ['mrp', 'base', 'sf_manufacturing'], 'data': [ 'data/product_data.xml', - 'data/uom_data.xml', 'views/product_template_view.xml' ], 'demo': [ diff --git a/sf_dlm/models/product_template.py b/sf_dlm/models/product_template.py index 471fad79..f80f0437 100644 --- a/sf_dlm/models/product_template.py +++ b/sf_dlm/models/product_template.py @@ -3,10 +3,9 @@ from odoo.exceptions import ValidationError import logging import base64 import os -# from OCC.Extend.DataExchange import read_step_file, write_stl_file +from OCC.Extend.DataExchange import read_step_file, write_stl_file from odoo.modules import get_resource_path - class ResProductTemplate(models.Model): _inherit = 'product.template' @@ -17,11 +16,11 @@ class ResProductTemplate(models.Model): model_height = fields.Float('模型高[mm]', digits=(16, 3)) model_volume = fields.Float('模型体积[m³]') model_machining_precision = fields.Selection([ - ('0.10', '±0.10mm'), - ('0.05', '±0.05mm'), - ('0.03', '±0.03mm'), - ('0.02', '±0.02mm'), - ('0.01', '±0.01mm')], string='加工精度') + ('±0.10mm', '±0.10mm'), + ('±0.05mm', '±0.05mm'), + ('±0.03mm', '±0.03mm'), + ('±0.02mm', '±0.02mm'), + ('±0.01mm', '±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='表面工艺') @@ -35,15 +34,6 @@ class ResProductTemplate(models.Model): materials_type_id = fields.Many2one('sf.materials.model', string='材料型号') single_manufacturing = fields.Boolean(string="单个制造") upload_model_file = fields.Many2many('ir.attachment', 'upload_model_file_attachment_ref', string='上传模型文件') - model_code = fields.Char('模型编码') - - def _get_volume_uom_id_from_ir_config_parameter(self): - product_length_in_feet_param = self.env['ir.config_parameter'].sudo().get_param('product.volume_in_cubic_feet') - if product_length_in_feet_param == '1': - return self.env.ref('uom.product_uom_cubic_foot') - else: - return self.env.ref('sf_dlm.product_uom_cubic_millimeter') - # model_file = fields.Binary('模型文件') # 胚料的库存路线设置 @@ -80,19 +70,18 @@ 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': model_type.id, - 'model_processing_panel': 'R', - 'model_machining_precision': item['model_machining_precision'], - 'model_code': item['barcode'], + 'model_type_id': 1, + # 'model_machining_precision': item['model_machining_precision'], + 'model_processing_panel': 'A', + 'model_machining_precision': '±0.10mm', 'length': item['model_long'], 'width': item['model_width'], 'height': item['model_height'], 'volume': item['model_long'] * item['model_width'] * item['model_height'], - 'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']), + 'model_file': base64.b64decode(item['model_file']), 'model_name': attachment.name, 'upload_model_file': [(6, 0, [attachment.id])], # 'single_manufacturing': True, - 'tracking': 'serial', 'list_price': item['price'], # 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id, 'materials_id': self.env['sf.production.materials'].search( @@ -105,39 +94,39 @@ class ResProductTemplate(models.Model): # [('process_encode', '=', item['process_parameters_code'])]).id, 'model_remark': item['remark'], 'default_code': '%s-%s' % (order_number, i), - # 'barcode': item['barcode'], + #'barcode': item['barcode'], 'active': True, # 'route_ids': self._get_routes('') } copy_product_id.sudo().write(vals) - # product_id.product_tmpl_id.active = False + print(len(copy_product_id.model_file)) + product_id.product_tmpl_id.active = False return copy_product_id def attachment_create(self, name, data): attachment = self.env['ir.attachment'].create({ - 'datas': base64.b64decode(data), + 'datas': base64.b64decode(data), 'type': 'binary', - 'public': True, 'description': '模型文件', 'name': name }) return attachment # 创建胚料 - def no_bom_product_create(self, product_id, item, order_id, route_type, i): + def no_bom_product_create(self, product_id, item, order_id, route_type): no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy() no_bom_copy_product_id.product_tmpl_id.active = True materials_id = self.env['sf.production.materials'].search( [('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 = { - 'name': '%s-%s %s %s %s * %s * %s' % ( - order_id.name, i, materials_id.name, materials_type_id.name, - item['model_long'] + model_type.embryo_tolerance, item['model_width'] + model_type.embryo_tolerance, - item['model_height'] + model_type.embryo_tolerance), + 'name': '%s %s %s %s * %s * %s' % ( + order_id.name, materials_id.name, materials_type_id.name, item['model_long'], item['model_width'], + item['model_height']), 'length': item['model_long'] + model_type.embryo_tolerance, 'width': item['model_width'] + model_type.embryo_tolerance, 'height': item['model_height'] + model_type.embryo_tolerance, @@ -161,38 +150,40 @@ 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 + product_id.product_tmpl_id.active = False return no_bom_copy_product_id - # @api.onchange('upload_model_file') - # def onchange_model_file(self): - # for item in self: - # if len(item.upload_model_file) > 1: - # raise ValidationError('只允许上传一个文件') - # if item.upload_model_file: - # file_attachment_id = item.upload_model_file[0] - # item.model_name = file_attachment_id.name - # # 附件路径 - # report_path = file_attachment_id._full_path(file_attachment_id.store_fname) - # shapes = read_step_file(report_path) - # output_file = get_resource_path('sf_dlm', 'static/file', 'out.stl') - # write_stl_file(shapes, output_file, 'binary', 0.03, 0.5) - # # 转化为glb - # output_glb_file = get_resource_path('sf_dlm', 'static/file', 'out.glb') - # util_path = get_resource_path('sf_dlm', 'static/util') - # cmd = 'python %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file) - # os.system(cmd) - # # 转base64 - # with open(output_glb_file, 'rb') as fileObj: - # image_data = fileObj.read() - # base64_data = base64.b64encode(image_data) - # item.model_file = base64_data + @api.onchange('upload_model_file') + def onchange_model_file(self): + for item in self: + if len(item.upload_model_file) > 1: + raise ValidationError('只允许上传一个文件') + if item.upload_model_file: + file_attachment_id = item.upload_model_file[0] + item.model_name = file_attachment_id.name + # 附件路径 + report_path = file_attachment_id._full_path(file_attachment_id.store_fname) + shapes = read_step_file(report_path) + output_file = get_resource_path('sf_dlm', 'static/file', 'out.stl') + write_stl_file(shapes, output_file, 'binary', 0.03, 0.5) + # 转化为glb + output_glb_file = get_resource_path('sf_dlm', 'static/file', 'out.glb') + util_path = get_resource_path('sf_dlm', 'static/util') + cmd = 'python %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file) + os.system(cmd) + # 转base64 + with open(output_glb_file, 'rb') as fileObj: + image_data = fileObj.read() + base64_data = base64.b64encode(image_data) + item.model_file = base64_data class ResMrpBom(models.Model): @@ -253,6 +244,8 @@ class ResMrpBom(models.Model): # 匹配bom def get_bom(self, product): + logging.info('get_bom-product:%s' % product) + logging.info('get_bom-product:%s' % product.materials_type_id.id) embryo_has = self.env['product.product'].search( [('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id), ('length', '>', product.length), ('width', '>', product.width), @@ -264,7 +257,7 @@ class ResMrpBom(models.Model): logging.info('get_bom-vals:%s' % embryo_has) if embryo_has: rate_of_waste = ((embryo_has.volume - product.model_volume) % embryo_has.volume) * 100 - if rate_of_waste <= 20: + if rate_of_waste >= 20: return embryo_has else: return diff --git a/sf_dlm/views/product_template_view.xml b/sf_dlm/views/product_template_view.xml index 652b05a3..c563f728 100644 --- a/sf_dlm/views/product_template_view.xml +++ b/sf_dlm/views/product_template_view.xml @@ -6,13 +6,13 @@ product.template - - - - + + + + - + @@ -36,31 +36,18 @@ - - - + + + + + + + + + + + diff --git a/sf_manufacturing/__manifest__.py b/sf_manufacturing/__manifest__.py index e51cc99c..a133d6f6 100644 --- a/sf_manufacturing/__manifest__.py +++ b/sf_manufacturing/__manifest__.py @@ -10,7 +10,7 @@ """, 'category': 'sf', 'website': 'https://www.sf.jikimo.com', - 'depends': ['mrp', 'sf_base', 'maintenance', 'sf_mrs_connect'], + 'depends': ['mrp', 'sf_base', 'maintenance'], 'data': [ 'security/group_security.xml', 'security/ir.model.access.csv', diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index c1a252f2..5046e128 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -2,12 +2,10 @@ from odoo import api, fields, models,_ -class ResProducTemplate_Production(models.Model): +class resProduct(models.Model): _inherit = 'product.template' - model_file = fields.Binary('模型文件') - class MrpProduction(models.Model): _inherit = 'mrp.production' _description = "制造订单" diff --git a/sf_manufacturing/models/mrp_workcenter.py b/sf_manufacturing/models/mrp_workcenter.py index e0daea8f..e853ab3f 100644 --- a/sf_manufacturing/models/mrp_workcenter.py +++ b/sf_manufacturing/models/mrp_workcenter.py @@ -13,12 +13,6 @@ class ResWorkcenter(models.Model): 'maintenance.equipment', 'workcenter_id', string="Maintenance Equipment", check_company=True) - # @api.onchange('machine_tool_id') - # def update_machine_tool_is_binding(self): - # self.machine_tool_id.is_binding = True - - - def action_work_order(self): if not self.env.context.get('desktop_list_view', False): action = self.env["ir.actions.actions"]._for_xml_id("sf_manufacturing.mrp_workorder_action_tablet") diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 62cdf236..ac29bfaf 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -4,7 +4,6 @@ import math import requests import logging import base64 -import hashlib # import subprocess from datetime import datetime from dateutil.relativedelta import relativedelta @@ -48,12 +47,9 @@ class ResMrpWorkOrder(models.Model): workorder.user_permissions = False user_permissions = fields.Boolean('用户权限', compute='get_user_permissions') - programming_no = fields.Char('编程单号') - work_state = fields.Char('业务状态') - programming_state = fields.Char('编程状态') cnc_worksheet = fields.Binary( '工作指令', readonly=True) - material_center_point = fields.Char(string='配料中心点') + material_center_point = fields.Char(string='胚料中心点') X1_axis = fields.Float(default=0) Y1_axis = fields.Float(default=0) Z1_axis = fields.Float(default=0) @@ -89,48 +85,50 @@ class ResMrpWorkOrder(models.Model): string="检测结果") cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工") tray_code = fields.Char(string="托盘") + programming_no = fields.Char('编程单号') + is_programming = fields.Boolean('是否编程', default=False) # 计算配料中心点和与x轴倾斜度方法 def getcenter(self): - x1 = self.X1_axis - x2 = self.X2_axis - x3 = self.X3_axis - x4 = self.X4_axis - x5 = self.X5_axis - x6 = self.X6_axis - x7 = self.X7_axis - x8 = self.X8_axis - y1 = self.Y1_axis - y2 = self.Y2_axis - y3 = self.Y3_axis - y4 = self.Y4_axis - y5 = self.Y5_axis - y6 = self.Y6_axis - y7 = self.Y7_axis - y8 = self.Y8_axis - z1 = self.Z9_axis - x0 = ((x3 - x4) * (x2 * y1 - x1 * y2) - (x1 - x2) * (x4 * y3 - x3 * y4)) / ( - (x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)) - y0 = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / ( - (y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4)) - x1 = ((x7 - x8) * (x6 * y5 - x5 * y6) - (x5 - x6) * (x8 * y7 - x7 * y8)) / ( - (x7 - x8) * (y5 - y6) - (x5 - x6) * (y7 - y8)); - y1 = ((y7 - y8) * (y6 * x5 - y5 * x6) - (y5 - y6) * (y8 * x7 - y7 * x8)) / ( - (y7 - y8) * (x5 - x6) - (y5 - y6) * (x7 - x8)) - x = (x0 + x1) / 2 - y = (y0 + y1) / 2 - z = z1 / 2 + try: + x1 = self.X1_axis + x2 = self.X2_axis + x3 = self.X3_axis + x4 = self.X4_axis + x5 = self.X5_axis + x6 = self.X6_axis + x7 = self.X7_axis + x8 = self.X8_axis + y1 = self.Y1_axis + y2 = self.Y2_axis + y3 = self.Y3_axis + y4 = self.Y4_axis + y5 = self.Y5_axis + y6 = self.Y6_axis + y7 = self.Y7_axis + y8 = self.Y8_axis + z1 = self.Z9_axis + x0 = ((x3 - x4) * (x2 * y1 - x1 * y2) - (x1 - x2) * (x4 * y3 - x3 * y4)) / ( + (x3 - x4) * (y1 - y2) - (x1 - x2) * (y3 - y4)) + y0 = ((y3 - y4) * (y2 * x1 - y1 * x2) - (y1 - y2) * (y4 * x3 - y3 * x4)) / ( + (y3 - y4) * (x1 - x2) - (y1 - y2) * (x3 - x4)) + x1 = ((x7 - x8) * (x6 * y5 - x5 * y6) - (x5 - x6) * (x8 * y7 - x7 * y8)) / ( + (x7 - x8) * (y5 - y6) - (x5 - x6) * (y7 - y8)); + y1 = ((y7 - y8) * (y6 * x5 - y5 * x6) - (y5 - y6) * (y8 * x7 - y7 * x8)) / ( + (y7 - y8) * (x5 - x6) - (y5 - y6) * (x7 - x8)) + x = (x0 + x1) / 2 + y = (y0 + y1) / 2 + z = z1 / 2 + + jd = math.atan2((x5 - x6), (y5 - y6)) + jdz = jd * 180 / math.pi + print("(%.2f,%.2f)" % (x, y)) + self.material_center_point = ("(%.2f,%.2f,%.2f)" % (x, y, z)) + self.X_deviation_angle = jdz + return self.material_center_point + except: + raise UserError("参数计算有误") - jd = math.atan2((x5 - x6), (y5 - y6)) - jdz = jd * 180 / math.pi - print("(%.2f,%.2f)" % (x, y)) - self.material_center_point = ("(%.2f,%.2f,%.2f)" % (x, y, z)) - self.X_deviation_angle = jdz - # 将补偿值写入CNC加工工单 - workorder = self.env['mrp.workorder'].browse(self.ids) - work = workorder.production_id.workorder_ids - work.compensation_value_x = eval(self.material_center_point)[0] - work.compensation_value_y = eval(self.material_center_point)[1] def json_workorder_str(self, k, production, route): workorders_values_str = [0, '', { @@ -140,7 +138,6 @@ class ResMrpWorkOrder(models.Model): 'name': route.route_workcenter_id.name, 'processing_panel': k, 'routing_type': route.routing_type, - 'work_state': '' if not route.routing_type == '获取CNC加工程序' else '待发起', 'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids), 'date_planned_start': False, 'date_planned_finished': False, @@ -167,8 +164,9 @@ class ResMrpWorkOrder(models.Model): 'target': 'new', 'domain': [('workorder_id', '=', self.id)] } - + tray_id = fields.Many2one('sf.tray', string="托盘信息") # 扫码绑定托盘方法 + def gettray(self): if self.tray_code != False: values = self.env['sf.tray'].search([("code", "=", self.tray_code)]) @@ -183,10 +181,11 @@ class ResMrpWorkOrder(models.Model): 'production_id': self.production_id, 'state': '占用', }) + self.tray_id = values else: raise UserError('该托盘编码已失效') else: - return "" + raise UserError('托盘码不能为空') def gettray_auto(self, barcode): if barcode != False: @@ -205,15 +204,45 @@ class ResMrpWorkOrder(models.Model): else: raise UserError('该托盘编码已失效') else: - return "" + return { + 'name': _('New Maintenance Request'), + 'view_mode': 'form', + 'res_model': 'maintenance.request', + 'type': 'ir.actions.act_window', + 'context': { + 'default_company_id': self.company_id.id, + 'default_production_id': self.id, + }, + 'domain': [('production_id', '=', self.id)], + } # 解除托盘绑定 def unbindtray(self): tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)]) if tray: tray.unclamp() + return { + 'name': _("工单"), + 'view_mode': 'form', + 'res_model': 'mrp.workorder', + 'res_id': self.id, + 'type': 'ir.actions.act_window', + 'target': 'new' + } - return "" + # return { + # 'name': _('New Maintenance Request'), + # 'view_mode': 'form', + # 'res_model': 'maintenance.request', + # 'res_id':self.id, + # 'type': 'ir.actions.act_window', + # 'context': { + # 'default_company_id': self.company_id.id, + # 'default_production_id': self.id, + # }, + # 'domain': [('production_id', '=', self.id)], + # 'target':'new' + # } def recreateManufacturingOrWorkerOrder(self): """ @@ -256,74 +285,45 @@ class ResMrpWorkOrder(models.Model): self.env['stock.move'].sudo().create(productions._get_moves_finished_values()) productions._create_workorder2(self.processing_panel) else: - return True - # def fetchCNCing(self): - # return None + return { + 'name': _("工单"), + 'view_mode': 'form', + 'res_model': 'mrp.workorder', + 'res_id': self.id, + 'type': 'ir.actions.act_window', + } + # cnc程序获取 # cnc程序获取 def fetchCNC(self): - try: - cnc = self.env['mrp.workorder'].search( - [('routing_type', '=', 'CNC加工'), ('production_id', '=', self.production_id.id)], limit=1) - logging.info('fetchCNC-cnc:%s' % cnc) - # if cnc.product_id.upload_model_file: - # logging.info('fetchCNC-upload_model_file:%s' % cnc.product_id.upload_model_file) - # attachments = cnc.product_id.upload_model_file[0] - # logging.info('fetchCNC-attachment1:%s' % attachments) - # logging.info('fetchCNC-attachment1:%s' % cnc.product_id.upload_model_file[0]) - # logging.info('fetchCNC-attachment2:%s' % cnc.product_id.upload_model_file[0].datas) - # logging.info('fetchCNC-attachment:%s' % attachments.datas) - # base64_data = base64.b64encode(attachments.datas) - # logging.info('fetchCNC-attachment1:%s' % attachments) - # base64_datas = base64_data.decode('utf-8') - # model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest() - # logging.info('fetchCNC-model_code:%s' % model_code) - logging.info('fetchCNC-model_code1:%s' % cnc.product_id.model_code) - res = {'model_code': '' if not cnc.product_id.model_code else cnc.product_id.model_code, - 'production_no': self.production_id.name, - 'machine_tool_code': cnc.workcenter_id.machine_tool_id.code, - 'material_code': cnc.env['sf.production.materials'].search( - [('id', '=', cnc.product_id.materials_id.id)]).materials_no, - 'material_type_code': cnc.env['sf.materials.model'].search( - [('id', '=', cnc.product_id.materials_type_id.id)]).materials_no, - 'machining_processing_panel': cnc.product_id.model_processing_panel, - # 'machining_precision': cnc.product_id.model_machining_precision, - 'embryo_long': cnc.product_id.bom_ids.bom_line_ids.product_id.length, - 'embryo_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height, - 'embryo_width': cnc.product_id.bom_ids.bom_line_ids.product_id.width, - 'order_no': cnc.production_id.origin, - 'user': self.env.user.name, - 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( - cnc.product_id.model_file).decode('utf-8') - } - logging.info('res:%s' % res) - configsettings = self.env['res.config.settings'].get_values() - config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key']) - url = '/api/intelligent_programming/create' - config_url = configsettings['sf_url'] + url - # res_str = json.dumps(res) - ret = requests.post(config_url, json={}, data=res, headers=config_header) - ret = ret.json() - logging.info('fetchCNC-ret:%s' % ret) - if ret['status'] == 1: - self.write( - {'programming_no': ret['programming_no'], 'programming_state': '编程中', 'work_state': '编程中'}) - else: - logging.info('fetchCNC-error:%s' % cnc) - raise UserError(ret['message']) - except Exception as e: - logging.info('fetchCNC error:%s' % e) - raise UserError(e) - - # return { - # 'name': _("工单"), - # 'view_mode': 'form', - # 'res_model': 'mrp.workorder', - # 'res_id': self.id, - # 'type': 'ir.actions.act_window', - # 'target': 'new' - # } + cnc = self.env['mrp.workorder'].search( + [('routing_type', '=', 'CNC加工'), ('production_id', '=', self.production_id.id)], limit=1) + res = {'model_code': cnc.product_id.barcode, 'production_no': self.production_id.name, + 'machine_tool_code': cnc.workcenter_id.machine_tool_id.code, + 'material_code': cnc.env['sf.production.materials'].search( + [('id', '=', cnc.product_id.materials_id.id)]).materials_no, + 'material_type_code': cnc.env['sf.materials.model'].search( + [('id', '=', cnc.product_id.materials_type_id.id)]).materials_no, + 'machining_precision': cnc.product_id.model_machining_precision, + 'embryo_long': cnc.product_id.bom_ids.bom_line_ids.product_id.length, + 'embryo_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height, + 'embryo_width': cnc.product_id.bom_ids.bom_line_ids.product_id.width, + 'order_no': cnc.production_id.origin, + 'user': self.env.user.name, + 'model_file': '' if not cnc.product_id.model_file else base64.b64encode( + cnc.product_id.model_file).decode('utf-8') + } + logging.info('res:%s' % res) + configsettings = self.env['res.config.settings'].get_values() + config_header = Common.get_headers(self, configsettings['token'], configsettings['sf_secret_key']) + url = '/api/intelligent_programming/create' + config_url = configsettings['sf_url'] + url + # res_str = json.dumps(res) + ret = requests.post(config_url, json={}, data=res, headers=config_header) + ret = ret.json() + if ret['status'] == 1: + return self.write({'programming_no': ret['programming_no'], 'is_programming': True}) def json_workorder_str1(self, k, production, route): workorders_values_str = [0, '', { @@ -333,7 +333,6 @@ class ResMrpWorkOrder(models.Model): 'name': route.route_workcenter_id.name, 'processing_panel': k, 'routing_type': route.routing_type, - 'work_state': '' if not route.routing_type == '获取CNC加工程序' else '待发起', 'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids), 'date_planned_start': False, 'date_planned_finished': False, @@ -412,86 +411,70 @@ class CNCprocessing(models.Model): workorder_id = fields.Many2one('mrp.workorder', string="工单") # mrs下发编程单创建CNC加工 - def cnc_processing_create(self, cnc_workorder, ret): - logging.info('ret:%s' % ret) - for obj in ret['programming_list']: - workorder = self.env['mrp.workorder'].search([('production_id.name', '=', ret['production_order_no']), - ('processing_panel', '=', obj['processing_panel']), - ('routing_type', '=', 'CNC加工')]) - cnc_processing = self.env['sf.cnc.processing'].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'] - }) - self.get_cnc_processing_file(ret['folder_name'], cnc_processing, workorder.processing_panel) - cnc_workorder.state = 'done' - cnc_workorder.work_state = '已编程' - cnc_workorder.programming_state = '已编程' - cnc_workorder.time_ids.date_end = datetime.now() - cnc_workorder.button_finish() - - def get_cnc_processing_file(self, folder_name, cnc_processing, processing_panel): - logging.info('folder_name:%s' % folder_name) - serverdir = os.path.join('/tmp', folder_name, 'return', processing_panel) - logging.info('serverdir:%s' % serverdir) - for root, dirs, files in os.walk(serverdir): - for f in files: - logging.info('f:%s' % f) - if os.path.splitext(f)[1] == ".pdf": - full_path = os.path.join(serverdir, root, f) - logging.info('pdf:%s' % full_path) - if full_path != False: - if not cnc_processing.workorder_id.cnc_worksheet: - cnc_processing.workorder_id.cnc_worksheet = base64.b64encode( - open(full_path, 'rb').read()) - else: - if cnc_processing.program_name == f.split('.')[0]: - cnc_file_path = os.path.join(serverdir, root, f) - logging.info('cnc_file_path:%s' % cnc_file_path) - self.write_file(cnc_file_path, cnc_processing) + def cnc_processing_create(self, obj): + workorder = self.env['mrp.workorder'].search([('production_id.name', '=', obj['production_order_no']), + ('processing_panel', '=', obj['processing_panel']), + ('routing_type', '=', 'CNC加工')]) + vals = { + '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'] + } + return self.env['sf.cnc.processing'].create(vals) # 创建附件(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 # 将FTP的nc文件下载到临时目录 - def download_file_tmp(self, production_no, processing_panel): - remotepath = os.path.join('/', 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) - return download_state + def download_file_tmp(self, model_code, processing_panel): + remotepath = os.path.join('/', model_code, 'return', processing_panel) + serverdir = os.path.join('/tmp', model_code, 'return', processing_panel) + ftp = FtpController() + ftp.download_file_tree(remotepath, serverdir) + return serverdir # 将nc文件存到attach的datas里 def write_file(self, nc_file_path, cnc): if os.path.exists(nc_file_path): with open(nc_file_path, 'rb') as file: data_bytes = file.read() - attachment = self.attachment_create(cnc.program_name, data_bytes) - cnc.write({'cnc_id': attachment.id}) - file.close() + attachment = self.attachment_create(cnc.program_name + '.NC', data_bytes) + cnc.write({'cnc_id': attachment.id}) + file.close() else: return False + # 将nc文件对应的excel清单转为pdf + # def to_pdf(self, excel_path, pdf_path): + # """ + # 需要在linux中下载好libreoffice + # """ + # logging.info('pdf_path:%s' % pdf_path) + # logging.info('pdf_path:%s' % excel_path) + # # 注意cmd中的libreoffice要和linux中安装的一致 + # cmd = 'soffice --headless --convert-to pdf'.split() + [excel_path] + ['--outdir'] + [pdf_path] + # p = subprocess.Popen(cmd, stderr=subprocess.PIPE, stdout=subprocess.PIPE, bufsize=1) + # # p.wait(timeout=30) # 停顿30秒等待转化 + # # stdout, stderr = p.communicate() + # p.communicate() + class SfWorkOrderBarcodes(models.Model): """ diff --git a/sf_manufacturing/models/tray.py b/sf_manufacturing/models/tray.py index 08906217..a572f52c 100644 --- a/sf_manufacturing/models/tray.py +++ b/sf_manufacturing/models/tray.py @@ -20,6 +20,41 @@ class Tray(models.Model): def updateTrayState(self): if self.workorder_id != False: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + self.state = '占用' else: self.state = '空闲' diff --git a/sf_manufacturing/views/mrp_workcenter_views.xml b/sf_manufacturing/views/mrp_workcenter_views.xml index 6c6e73e6..186dce3c 100644 --- a/sf_manufacturing/views/mrp_workcenter_views.xml +++ b/sf_manufacturing/views/mrp_workcenter_views.xml @@ -107,7 +107,7 @@ - + diff --git a/sf_manufacturing/views/mrp_workorder_view.xml b/sf_manufacturing/views/mrp_workorder_view.xml index 493640c3..5c0adf7f 100644 --- a/sf_manufacturing/views/mrp_workorder_view.xml +++ b/sf_manufacturing/views/mrp_workorder_view.xml @@ -12,21 +12,32 @@ - - - {'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False),("user_permissions","=",False)]} + + {'invisible': [("user_permissions","=",False)]} + 停工 + + + 1 + + + + + + + + @@ -80,23 +91,17 @@ + + - - - - - -
-
-
+ +
+
+
@@ -104,12 +109,16 @@ + +
+ @@ -217,7 +226,7 @@
@@ -259,7 +268,7 @@
@@ -268,11 +277,11 @@
diff --git a/sf_mrs_connect/controllers/controllers.py b/sf_mrs_connect/controllers/controllers.py index e37983e2..76fc34c5 100644 --- a/sf_mrs_connect/controllers/controllers.py +++ b/sf_mrs_connect/controllers/controllers.py @@ -20,32 +20,44 @@ 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']) - # 查询状态为进行中且类型为获取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) + 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 + 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 07bf5690..655c50e6 100644 --- a/sf_mrs_connect/models/ftp_operate.py +++ b/sf_mrs_connect/models/ftp_operate.py @@ -15,31 +15,26 @@ class FtpController(): ftp = FTP() - def __init__(self, host, port, username, password): + def __init__(self, host="192.168.50.202", port=21, username="ftpuser", password="123456"): try: self.ftp.connect(host, port) self.ftp.login(username, password) - logging.info("ftp连接成功") + logging.info("连接成功: ") except: - logging.info("ftp连接失败") - return False + logging.info("连接失败: ") # 下载目录下的文件 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) - except: - return False + else: + return # 下载指定目录下的指定文件 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 dadb7de5..fec87d75 100644 --- a/sf_mrs_connect/models/res_config_setting.py +++ b/sf_mrs_connect/models/res_config_setting.py @@ -12,12 +12,8 @@ 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') - 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密码') + sf_secret_key = fields.Char(string='密钥', default= 'wBmxej38OkErKhD6') + sf_url = fields.Char(string='访问地址', default= 'https://sf.cs.jikimo.com') def sf_all_sync(self): self.env['sf.production.materials'].sync_all_production_materials() @@ -44,6 +40,8 @@ class ResConfigSettings(models.TransientModel): _logger.info("同步资源库刀具") # self.env['sf.processing.order'].sync_all_processing_order() + + @api.model def get_values(self): """ @@ -55,19 +53,11 @@ 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 @@ -77,7 +67,4 @@ 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 7bc7f2ad..d650d0f3 100644 --- a/sf_mrs_connect/views/res_config_settings_views.xml +++ b/sf_mrs_connect/views/res_config_settings_views.xml @@ -14,49 +14,22 @@
-
-
-
-
-
-
- -
-

FTP参数配置

-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 8d5fafe5..899e2126 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -44,7 +44,7 @@ class ReSaleOrder(models.Model): product.model_machining_precision, product.materials_id.name), 'price_unit': product.list_price, - # 'route_id': product.route_ids, + 'route_id': product.route_ids, 'product_uom_qty': item['number'] } return self.env['sale.order.line'].create(vals)