This commit is contained in:
gqh
2023-01-09 23:04:53 +08:00
parent d0497aa043
commit 311c7c723a
52 changed files with 1572 additions and 331 deletions

View File

@@ -359,7 +359,7 @@
<field name="arch" type="xml">
<form string="机床">
<header>
<button type="object" class="oe_highlight" name='enroll_machine_tool' string="机床注册" attrs="{'invisible': [('code','!=',False)]}"/>
<button type="object" class="oe_highlight" name='enroll_machine_tool' string="机床注册"/>
</header>
<group string="基本信息">
<group>

View File

@@ -49,6 +49,7 @@ class Sf_Bf_Connect(http.Controller):
logging.info('product:%s' % product)
bom_data = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).get_bom(product)
logging.info('bom_data:%s' % bom_data)
i += 1
if bom_data:
bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(product,
'normal',
@@ -60,7 +61,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')
order_id, 'self_machining', i)
# 创建胚料的bom
self_machining_bom = request.env['mrp.bom'].with_user(
request.env.ref("base.user_admin")).bom_create(
@@ -79,7 +80,8 @@ class Sf_Bf_Connect(http.Controller):
outsource_embryo = request.env['product.template'].sudo().no_bom_product_create(outsource_id,
item,
order_id,
'subcontract')
'subcontract',
i)
# 创建胚料的bom
outsource_bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(
outsource_embryo,
@@ -95,14 +97,13 @@ class Sf_Bf_Connect(http.Controller):
purchase_embryo = request.env['product.template'].sudo().no_bom_product_create(purchase_id,
item,
order_id,
'purchase')
'purchase', i)
# 产品配置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)
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)

View File

@@ -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': [

57
sf_dlm/data/tt.xml Normal file
View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data noupdate="1">
<record id="product_template_sf" model="product.product">
<field name="name">CNC加工产品模板</field>
<!-- <field name="categ_id" ref="product.product_category_5"/>-->
<field name="invoice_policy">delivery</field>
<field name="detailed_type">product</field>
<field name="purchase_ok">false</field>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="company_id" ref="base.main_company"/>
<field name="active">False</field>
</record>
<record id="product_category_embryo_sf" model="product.category">
<field name="name">胚料</field>
<field name="type">胚料</field>
</record>
<record id="product_embryo_sf_self_machining" model="product.product">
<field name="name">自加工</field>
<!-- <field name="categ_id" ref="product_category_embryo_sf"/>-->
<field name="invoice_policy">delivery</field>
<field name="detailed_type">product</field>
<field name="purchase_ok">false</field>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="company_id" ref="base.main_company"/>
<field name="active">False</field>
</record>
<record id="product_embryo_sf_outsource" model="product.product">
<field name="name">外协</field>
<!-- <field name="categ_id" ref="product_category_embryo_sf"/>-->
<field name="invoice_policy">delivery</field>
<field name="detailed_type">product</field>
<field name="purchase_ok">false</field>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="company_id" ref="base.main_company"/>
<field name="active">False</field>
</record>
<record id="product_embryo_sf_purchase" model="product.product">
<field name="name">采购</field>
<!-- <field name="categ_id" ref="product_category_embryo_sf"/>-->
<field name="invoice_policy">delivery</field>
<field name="detailed_type">product</field>
<field name="purchase_ok">false</field>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="company_id" ref="base.main_company"/>
<field name="active">False</field>
</record>
</data>
</odoo>

View File

@@ -3,9 +3,10 @@ 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'
@@ -34,6 +35,15 @@ 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('模型文件')
# 胚料的库存路线设置
@@ -72,16 +82,18 @@ class ResProductTemplate(models.Model):
item['model_height'] + model_type.embryo_tolerance),
'model_type_id': 1,
# 'model_machining_precision': item['model_machining_precision'],
'model_processing_panel': 'A',
'model_processing_panel': 'R',
'model_machining_precision': '±0.10mm',
'model_code': item['barcode'],
'length': item['model_long'],
'width': item['model_width'],
'height': item['model_height'],
'volume': item['model_long'] * item['model_width'] * item['model_height'],
'model_file': base64.b64decode(item['model_file']),
'model_file': '' if not item['model_file'] else 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(
@@ -94,18 +106,17 @@ 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)
print(len(copy_product_id.model_file))
product_id.product_tmpl_id.active = False
# 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',
'description': '模型文件',
'name': name
@@ -113,7 +124,7 @@ class ResProductTemplate(models.Model):
return attachment
# 创建胚料
def no_bom_product_create(self, product_id, item, order_id, route_type):
def no_bom_product_create(self, product_id, item, order_id, route_type, i):
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(
@@ -124,9 +135,10 @@ class ResProductTemplate(models.Model):
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' % (
order_id.name, materials_id.name, materials_type_id.name, item['model_long'], item['model_width'],
item['model_height']),
'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),
'length': item['model_long'] + model_type.embryo_tolerance,
'width': item['model_width'] + model_type.embryo_tolerance,
'height': item['model_height'] + model_type.embryo_tolerance,
@@ -158,32 +170,32 @@ class ResProductTemplate(models.Model):
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):
@@ -244,8 +256,6 @@ 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),
@@ -257,7 +267,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

View File

@@ -6,13 +6,13 @@
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="arch" type="xml">
<!-- <field name="image_1920" position="replace">-->
<!-- <field name="upload_model_file" required="True"-->
<!-- widget='many2many_binary'/>-->
<!-- </field>-->
<!-- <field name="image_1920" position="replace">-->
<!-- <field name="upload_model_file" required="True"-->
<!-- widget='many2many_binary'/>-->
<!-- </field>-->
<field name="invoice_policy" position="after">
<field name="model_file" required="True" widget="model_viewer"/>
<!-- <field name="model_file" required="True" widget="model_viewer"/>-->
<field name="materials_id" string="材料"/>
<field name="materials_type_id" string="型号"
domain="[('materials_id', '=', materials_id)]"/>
@@ -36,18 +36,31 @@
<xpath expr="//page[last()]" position="after">
<page string="加工参数">
<group string="模型">
<field name="model_long" string="长[mm]"/>
<field name="model_width" string="[mm]"/>
<field name="model_height" string="高[mm]"/>
<field name="model_volume" string="体积[m³]"/>
<field name="model_type_id" string="模型类型"/>
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"/>
<field name="model_machining_precision"/>
<field name="model_surface_process_id" string="表面工艺"/>
<field name="model_process_parameters_id" string="工艺参数"
domain="[('processing_order_ids', '=', model_surface_process_id)]"/>
<field name="model_remark" string="备注说明"/>
<group>
<group string="模型">
<label for="model_long" string="尺寸[mm]"/>
<div class="o_address_format">
<label for="model_long" string=""/>
<field name="model_long" class="o_address_zip"/>
<!-- <span>&amp;nbsp;</span>-->
<label for="model_width" string="宽"/>
<field name="model_width" class="o_address_zip"/>
<!-- <span>&amp;nbsp;</span>-->
<label for="model_height" string="高"/>
<field name="model_height" class="o_address_zip"/>
</div>
<!-- <field name="model_long" string="长[mm]"/>-->
<!-- <field name="model_width" string="宽[mm]"/>-->
<!-- <field name="model_height" string="高[mm]"/>-->
<field name="model_volume" string="体积[mm³]"/>
<field name="model_type_id" string="模型类型"/>
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"/>
<field name="model_machining_precision"/>
<field name="model_surface_process_id" string="表面工艺"/>
<field name="model_process_parameters_id" string="工艺参数"
domain="[('processing_order_ids', '=', model_surface_process_id)]"/>
<field name="model_remark" string="备注说明"/>
</group>
</group>
</page>
</xpath>

View File

@@ -0,0 +1 @@
from . import models

View File

@@ -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',
}

View File

@@ -0,0 +1,3 @@
from . import ftp_client
from . import ftp_operate
from . import py2opcua

View File

@@ -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="状态")

View File

@@ -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

View File

@@ -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) # 删除远程文件

View File

@@ -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()

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="iot_box_comp_rule" model="ir.rule">
<field name="name">IoT Box multi company rule</field>
<field name="model_id" ref="model_iot_box"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
<record id="iot_device_comp_rule" model="ir.rule">
<field name="name">IoT Device multi company rule</field>
<field name="model_id" ref="model_iot_device"/>
<field eval="True" name="global"/>
<field name="domain_force">['|',('company_id','=',False),('company_id', 'in', company_ids)]</field>
</record>
</data>
</odoo>

View File

@@ -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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_ftp_client ftp.client model_ftp_client base.group_user 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

@@ -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;
}
}
}
}
}

View File

@@ -0,0 +1,5 @@
.o_button_iot {
min-width: 120px;
min-height: 40px;
margin-left: 50px;
}

View File

@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="utf-8"?>
<templates xml:space="preserve">
<t t-name="sf_machine_connect.Barcode_Scan_template" t-inherit="web.Legacy.ControlPanel" t-inherit-mode="extension" owl="1">
<xpath expr="//div[hasclass('o_cp_pager')]" position="inside">
<button
style="float:left"
t-on-click="onBarcodeScanned"
type="button"
class="btn ms-3 o_barcode"
tabindex="-1"
draggable="false"
aria-label="Scan barcode"
title="Scan barcode"
data-tooltip="Scan barcode"
>扫码</button>
</xpath>
</t>
<!-- <t t-name="web.Many2OneField.CreateConfirmationDialog" owl="1">-->
<!-- <Dialog title="title" size="'md'">-->
<!-- <div>-->
<!-- Create <strong t-esc="props.value"/> as a new <t t-esc="props.name"/>?-->
<!-- </div>-->
<!-- <t t-set-slot="footer">-->
<!-- <button class="btn btn-primary" t-on-click="onCreate">Create</button>-->
<!-- <button class="btn" t-on-click="() => props.close()">Discard</button>-->
<!-- </t>-->
<!-- </Dialog>-->
<!-- </t>-->
<!-- <t t-name="web.Many2OneField" owl="1">-->
<!-- <t t-if="props.readonly">-->
<!-- <t t-if="!props.canOpen">-->
<!-- <span>-->
<!-- <span t-esc="displayName" />-->
<!-- <t t-foreach="extraLines" t-as="extraLine" t-key="extraLine_index">-->
<!-- <br />-->
<!-- <span t-esc="extraLine" />-->
<!-- </t>-->
<!-- </span>-->
<!-- </t>-->
<!-- <t t-else="">-->
<!-- <a-->
<!-- t-if="props.value"-->
<!-- class="o_form_uri"-->
<!-- t-att-href="props.value ? `#id=${props.value[0]}&amp;model=${relation}` : '#'"-->
<!-- t-on-click.prevent="onClick"-->
<!-- >-->
<!-- <span t-esc="displayName" />-->
<!-- <t t-foreach="extraLines" t-as="extraLine" t-key="extraLine_index">-->
<!-- <br />-->
<!-- <span t-esc="extraLine" />-->
<!-- </t>-->
<!-- </a>-->
<!-- </t>-->
<!-- </t>-->
<!-- <t t-else="">-->
<!-- <div class="o_field_many2one_selection">-->
<!-- <Many2XAutocomplete t-props="Many2XAutocompleteProps"/>-->
<!-- <t t-if="hasExternalButton">-->
<!-- <button-->
<!-- type="button"-->
<!-- class="btn btn-secondary fa o_external_button"-->
<!-- t-att-class="props.openTarget === 'current' ? 'fa-arrow-right' : 'fa-external-link'"-->
<!-- tabindex="-1"-->
<!-- draggable="false"-->
<!-- aria-label="Internal link"-->
<!-- data-tooltip="Internal link"-->
<!-- t-on-click="onExternalBtnClick"-->
<!-- />-->
<!-- </t>-->
<!-- <button-->
<!-- t-if="hasBarcodeButton"-->
<!-- t-on-click="onBarcodeBtnClick"-->
<!-- type="button"-->
<!-- class="btn ms-3 o_barcode"-->
<!-- tabindex="-1"-->
<!-- draggable="false"-->
<!-- aria-label="Scan barcode"-->
<!-- title="Scan barcode"-->
<!-- data-tooltip="Scan barcode"-->
<!-- />-->
<!-- </div>-->
<!-- <div class="o_field_many2one_extra">-->
<!-- <t t-foreach="extraLines" t-as="extraLine" t-key="extraLine_index">-->
<!-- <br t-if="!extraLine_first" />-->
<!-- <span t-esc="extraLine" />-->
<!-- </t>-->
<!-- </div>-->
<!-- </t>-->
<!-- </t>-->
</templates>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="owl_demo.PartnerOrderSummary2" owl="1">
<div class="row" style="padding-top: 20px;">
<p>
显示累加字符串aaaaaabbb
</p>
</div>
</t>
</templates>

View File

@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="owl_demo.MyComponent1" owl="1">
<div class="container">
<div class="jumbotron">
<h1>欢迎登陆页面!</h1>
<p>这是一个超大屏幕Jumbotron的实例。</p>
<p><a class="btn btn-primary btn-lg" role="button">
学习更多</a>
</p>
</div>
</div>
<!-- <div class="bg-info text-center p-2">-->
<!-- <i class="fa fa-arrow-left p-1 left"-->
<!-- style="cursor: pointer;"-->
<!-- t-on-click="onPrevious"> </i>-->
<!-- <b t-esc="messageList[Math.abs(-->
<!-- state.currentIndex%4)]"/>-->
<!-- <i class="fa fa-arrow-right p-1 right"-->
<!-- style="cursor: pointer;"-->
<!-- t-on-click="onNext"> </i>-->
<!-- <i class="fa fa-close p-1 float-right"-->
<!-- style="cursor: pointer;"-->
<!-- t-on-click="onRemove"> </i>-->
<!-- </div>-->
</t>
</templates>

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates>
</templates>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="sf_machine_connect.PartnerOrderSummary2" owl="1">
<!-- <div class="row" style="padding-top: 20px;">-->
<div style="padding-top: 20px;">
<button
t-on-click="onBarcodeBtnClick"
type="button"
class="btn ms-3 o_barcode"
tabindex="-1"
draggable="false"
aria-label="Scan barcode"
title="Scan barcode"
data-tooltip="Scan barcode"
>扫码</button>
<!-- <div class="o_barcode_mobile_container">-->
<!-- <a role="button" class="btn btn-primary o_mobile_barcode">-->
<!-- <i class="fa fa-camera fa-2x o_barcode_mobile_camera"/>-->
<!-- Tap to scan-->
<!-- </a>-->
<!--&lt;!&ndash; <img src="/barcodes/static/img/barcode.png" alt="Barcode"/>&ndash;&gt;-->
<!-- <span class="o_barcode_laser"/>-->
<!-- </div>-->
</div>
</t>
</templates>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="mobile_barcode_template">
<div class="o_barcode_mobile_container">
<a role="button" class="btn btn-primary o_mobile_barcode">
<i class="fa fa-camera fa-2x o_barcode_mobile_camera"/>
Tap to scan
</a>
<img src="/barcodes/static/img/barcode.png" alt="Barcode"/>
<span class="o_barcode_laser"/>
</div>
</t>
</templates>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<templates>
<div t-name="iot.scan_progress_template">
<h4>Range(s) to scan</h4>
<ul class="scan_ranges list-group mb-2"/>
<div class="input-group mb-4">
<input type="text" name="add_scan_range_ip" class="add_scan_range_ip form-control" placeholder="Scan another range, e.g.: 10.1.1.*"/>
<a role="button" class="add_scan_range btn btn-primary" tabindex="-1">Add</a>
</div>
<div class="mb-4">
<h4 class="scan_network"></h4>
<h4 class="iot_box_found"></h4>
<ul class="found_devices list-group"/>
</div>
</div>
</templates>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="web.Many2OneField" owl="1">
<button
t-on-click="onBarcodeBtnClick"
type="button"
class="btn ms-3 o_barcode"
tabindex="-1"
draggable="false"
aria-label="Scan barcode"
title="Scan barcode"
data-tooltip="Scan barcode"
/>
</t>
</templates>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" >
<t t-extend="stock_barcode_lines_template">
<t t-jquery="div[class='o_barcode_line list-group-item d-flex flex-row flex-nowrap']"
t-operation="append">
<div class="o_barcode_pic position-relative text-center mt-2 mb-1">
<i class="fa fa-5x mx-auto fa-exclamation-triangle text-white d-none"/>
<img class="o_barcode_icon" src="/stock_barcode/static/img/barcode.svg" alt="Barcode" height="40px"/>
<!-- <t t-if='widget.mobileMethods.scanBarcode'> -->
<div class="o_stock_mobile_barcode"/> <!-- Used to open the device scanner -->
<span> Tap to scan</span>
<!-- </t> -->
</div>
</t>
</t>
</templates>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0"?>
<odoo>
<record id="view_order_form_scan_barcode" model="ir.ui.view">
<field name="name">sale.order.form.scan.barcode</field>
<field name="model">sale.order</field>
<field name="inherit_id" ref="sale.view_order_form"/>
<field name="arch" type="xml">
<field name="partner_id" position="after">
<!-- invisible="1" -->
<field name="_barcode_scanned" widget="barcode_handler"/>
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<odoo>
<record id="sf_install_the_tray_workorder_form_view__scan_barcode" model="ir.ui.view">
<field name="name">sf.install.the.tray.workorder.form.scan.barcode</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml">
<xpath expr="//page//field[@name='tray_code']" position="before">
<!-- invisible="1" -->
<field name="_barcode_scanned" widget="barcode_handler"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0"?>
<odoo>
<record id="stock_picking_form_vieww_scan_barcode_search" model="ir.ui.view">
<field name="name">stock.picking.search</field>
<field name="model">stock.picking</field>
<field name="inherit_id" ref="stock.view_picking_internal_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='name']" position="before">
<!-- <field name="tray_code" filter_domain="[('production_id.tray_ids.code','=',self)]"/>-->
<field name="origin"/>
</xpath>
<!-- <xpath expr="//search//group//filter[@name='product']" position="before">-->
<!-- <filter string="Tray code" name="traycode" domain="[]" context="{'group_by': 'tray_code'}"/>-->
<!-- </xpath>-->
</field>
</record>
</odoo>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<odoo>
<record id="workcenter_form_vieww_scan_barcode_search" model="ir.ui.view">
<field name="name">work.order.search</field>
<!-- <field name="model">mrp.workcenter</field>-->
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="mrp.view_mrp_production_work_order_search"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='production_id']" position="before">
<!-- <field name="name" filter_domain="['|', '|', ('明确的字段内容', 'ilike', self), ('shortdesc', 'ilike', self), ('name', 'ilike', self)]" string="Theme"/>-->
<field name="tray_code" filter_domain="[('production_id.tray_ids.code','=',self)]"/>
<!-- <field name="production_id"/>-->
</xpath>
<!-- <xpath expr="//search//group//filter[@name='product']" position="before">-->
<!-- <filter string="Tray code" name="traycode" domain="[]" context="{'group_by': 'tray_code'}"/>-->
<!-- </xpath>-->
</field>
</record>
</odoo>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0"?>
<odoo>
<record id="compensation_view" model="ir.ui.view">
<field name="name">compensation</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml">
<xpath expr="//page//field[@name='cnc_ids']" position="before">
<group>
<field name="compensation_value_x"/>
<field name="compensation_value_y"/>
</group>
<div>
<button string="一键补偿" name="compensation" type="object" confirm="是否确认下发补偿" class="btn-primary"/>
</div>
</xpath>
<!-- attrs='{"invisible": [("routing_type","!=","CNC加工")]}'-->
</field>
</record>
</odoo>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="flush">
&lt;!DOCTYPE html&gt;
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<title>World Map</title>
<script type="text/javascript">
$(function () {
setInterval(function () {
$("#map").load(location.href + " #map>*", "");//注意后面DIV的ID前面的空格跟 id 后的>*,很重要!
}, 1000);//8秒自动刷新
})
</script>
</head>
<body>
</body>
</html>
</template>
</odoo>

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sf_install_the_tray_workorder_form_view_inherit" model="ir.ui.view">
<field name="name">sale.order.inherit</field>
<field name="model">mrp.workorder</field>
<!-- <field name="model">cnc.processing</field>-->
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='remark']" position="after">
<button string="测试按钮" name="pri" type="object" class="btn-primary"/>
<button string="下发按钮" name="up" type="object" confirm="是否确认下发此程序" class="btn-primary"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_tree_mrs_machine_tool_inherited" model="ir.ui.view">
<field name="name">sf_base_extension</field>
<field name="model">sf.machine_tool</field>
<field name="inherit_id" ref="sf_base.sf_machine_tool_form"/>
<!-- <field name="inherit_id" ref="sf_base.form_mrs_machine_tool_type"/>-->
<field eval="20" name="priority"/>
<field name="arch" type="xml">
<!-- <xpath expr="//field[@name='knife_type']" position="before">-->
<xpath expr="//form//notebook//page[1]" position="inside">
<!-- <xpath expr="//page[@name='other']" position="before">-->
<!-- <page string="监控页面">-->
<group string="监控">
<field name="timestamp"/>
<field name="signed"/>
<field name="status"/>
<!-- <field name="tool_num"/>-->
<field name="program"/>
</group>
<!-- </page>-->
</xpath>
</field>
</record>
</odoo>
<!--&lt;!&ndash;继承了本模块的视图&ndash;&gt;-->
<!--<?xml version="1.0" encoding="utf-8"?>-->
<!--<odoo>-->
<!-- <record id="view_tree_mrs_machine_tool_inherited" model="ir.ui.view">-->
<!-- <field name="name">sf_base_extension</field>-->
<!-- <field name="model">ftp.client</field>-->
<!-- <field name="inherit_id" ref="ftp_form"/>-->
<!-- <field eval="20" name="priority"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="//field[@name='name']" position="before">-->
<!-- <field name="count_books"/>-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
<!--</odoo>-->

View File

@@ -0,0 +1,25 @@
<record id="view_purchase_order_barcode_inherit_form" model="ir.ui.view">
<field name="name">purchase.order.form</field>
<field name="model">purchase.order</field>
<field name="inherit_id" ref="purchase.purchase_order_form"/>
<field name="priority" eval="8"/>
<field name="arch" type="xml">
<form position="inside">
<field name="_barcode_scanned" widget="purchaseorder_barcode_handler"/>
</form>
<xpath expr="//field[@name='order_line']/tree" position="inside">
<field name="product_barcode" invisible="1"/>
</xpath>
<xpath expr="//field[@name='order_line']/kanban" position="inside">
<field name="product_barcode" invisible="1"/>
</xpath>
<xpath expr="//field[@name='order_line']//field[@name='product_qty']" position="attributes">
<attribute name="options">{'barcode_events': True}</attribute>
<attribute name="widget">field_float_scannable</attribute>
</xpath>
<xpath expr="//button[@name='button_confirm']" position="attributes">
<attribute name="barcode_trigger">validate</attribute>
</xpath>
</field>
</record>

View File

@@ -0,0 +1,176 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Menus -->
<menuitem
id="ftp_menu_root"
name="sf2machine"
web_icon="iot,static/description/icon.png"
groups="base.group_system"
/>
IoT Boxes
<record model="ir.ui.view" id="data_list">
<field name="model">ftp.client</field>
<field name="arch" type="xml">
<!-- <div id="map">-->
<tree string="目标">
<field name="name"/>
<field name="mobile"/>
<field name="description"/>
</tree>
<!-- </div>-->
</field>
</record>
<record model="ir.ui.view" id="barcode_list">
<field name="model">mrp.production</field>
<field name="arch" type="xml">
<!-- <div id="map">-->
<tree string="目标">
<field name="_barcode_scanned" widget="barcode_handler"/>
<field name="aa"/>
</tree>
<!-- </div>-->
</field>
</record>
<record model="ir.ui.view" id="ftp_form">
<field name="model">ftp.client</field>
<field name="arch" type="xml">
<form string="数据采集">
<group string="基本信息">
<group>
<field name="name"/>
<field name="mobile"/>
<field name="description"/>
<field name="_barcode_scanned" widget="barcode_handler"/>
<!-- <button string="测试按钮" name="pri" type="object"/>-->
<button string="下发程序" name="up" type="object" data-hotkey="enter"/>
<button string="扫码" name="on_barcode_scanned" type="object"/>
<!-- <button string="删除程序" name="delete" type="object"/>-->
<templates xml:space="preserve">
<t t-name="web.Many2OneField" owl="1">
<button t-on-click="onBarcodeBtnClick"
type="button"
class="btn ms-3 o_barcode"
tabindex="-1"
draggable="false"
aria-label="Scan barcode"
title="Scan barcode"
data-tooltip="Scan barcode"
>saomiao</button>
</t>
</templates>
</group>
</group>
</form>
</field>
</record>
<record model="ir.ui.view" id="barcode_form">
<field name="model">mrp.production</field>
<field name="arch" type="xml">
<form string="扫码">
<group string="基本信息">
<field name="_barcode_scanned" widget="barcode_handler"/>
<field name="aa"/>
</group>
</form>
</field>
</record>
<record id="ftp_action" model="ir.actions.act_window">
<field name="name">数据采集</field>
<field name="res_model">ftp.client</field>
<field name="view_mode">list,form,kanban</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
这是我们的数据采集与程序管理页面!
</p>
</field>
</record>
<record id="barcode_action" model="ir.actions.act_window">
<field name="name">扫码</field>
<field name="res_model">mrp.production</field>
<field name="view_mode">list,form,kanban</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
这是我们的扫码页面!
</p>
</field>
</record>
<menuitem
id="ftp_data_menu_action"
name="数据采集"
action="ftp_action"
parent="ftp_menu_root"
sequence="1"/>
<menuitem
id="ftp_cnc_data_menu_action"
name="CNC"
action="ftp_action"
parent="ftp_data_menu_action"
sequence="1"/>
<!-- <menuitem-->
<!-- id="ftp_mit_cnc_data_menu_action"-->
<!-- name="三菱CNC"-->
<!-- action="ftp_action"-->
<!-- parent="ftp_cnc_data_menu_action"-->
<!-- sequence="1"/>-->
<!-- <menuitem-->
<!-- id="ftp_sim_cnc_data_menu_action"-->
<!-- name="西门子CNC"-->
<!-- action="ftp_action"-->
<!-- parent="ftp_cnc_data_menu_action"-->
<!-- sequence="1"/>-->
<!-- <menuitem-->
<!-- id="ftp_fan_cnc_data_menu_action"-->
<!-- name="发那科CNC"-->
<!-- action="ftp_action"-->
<!-- parent="ftp_cnc_data_menu_action"-->
<!-- sequence="1"/>-->
<menuitem
id="ftp_plc_data_menu_action"
name="PLC"
action="ftp_action"
parent="ftp_data_menu_action"
sequence="3"/>
<menuitem
id="ftp_instrument_data_menu_action"
name="仪器仪表"
action="ftp_action"
parent="ftp_data_menu_action"
sequence="9"/>
<menuitem
id="ftp_procedure_menu_action"
name="程序管理"
action="barcode_action"
parent="ftp_menu_root"
sequence="2"/>
<menuitem
id="ftp_up_menu_action"
name="本地代码"
action="ftp_action"
parent="ftp_procedure_menu_action"
sequence="2"/>
<menuitem
id="ftp_down_menu_action"
name="机床代码"
action="ftp_action"
parent="ftp_procedure_menu_action"
sequence="6"/>
</odoo>

View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sale_order_form_inherit" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">sf.machine_tool</field>
<field name="inherit_id" ref="sf_base.sf_machine_tool_form"/>
<field name="arch" type="xml">
<xpath expr="//form//notebook//page[1]" position="inside">
<group string="监控">
<field name="timestamp"/>
<field name="signed"/>
<field name="signed16"/>
<field name="pulse2"/>
<field name="tool_num"/>
<field name="program"/>
</group>
<!-- </page>-->
<div class="o_partner_order_summary" colspan="2"/>
</xpath>
<!-- <field name="payment_term_id" position="after">-->
<!-- <field name="create_date" widget="show_units" options="{'units':'UTC'}"/>-->
<!-- -->
<!-- </field>-->
</field>
</record>
</odoo>
<!--<?xml version="1.0" encoding="utf-8"?>-->
<!--<odoo>-->
<!-- <record id="sale_order_form_inherit" model="ir.ui.view">-->
<!-- <field name="name">sale.order.form.inherit</field>-->
<!-- <field name="model">sale.order</field>-->
<!-- <field name="inherit_id" ref="sale.view_order_form"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <field name="payment_term_id" position="after">-->
<!-- <field name="create_date" widget="show_units" options="{'units':'UTC'}"/>-->
<!-- <div class="o_partner_order_summary" colspan="2"/>-->
<!-- </field>-->
<!-- </field>-->
<!-- </record>-->
<!--</odoo>-->

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sf_install_the_tray_workorder_form_view_inherit" model="ir.ui.view">
<field name="name">sale.order.form.inherit</field>
<field name="model">mrp.workorder</field>
<field name="inherit_id" ref="sf_manufacturing.view_mrp_production_workorder_tray_form_inherit_sf"/>
<field name="arch" type="xml">
<field name="tray_code" position="before">
<!-- <field name="create_date" widget="show_units" options="{'units':'UTC'}"/>-->
<div class="o_partner_order_summary" colspan="2"/>
<!-- <field name="aa"/>-->
</field>
</field>
</record>
</odoo>

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mrp_workcenter_view_kanban_inherit_workorder_inherit" model="ir.ui.view">
<field name="name">mrp.workcenter.view.kanban.inherit.mrpworkorder</field>
<field name="model">mrp.workcenter</field>
<!-- <field name="model">cnc.processing</field>-->
<field name="inherit_id" ref="mrp.mrp_workcenter_kanban"/>
<field name="arch" type="xml">
<xpath expr="//button[@name='action_work_order']" position="after">
<!-- <field name="aaaa"/>-->
<button string="扫码查询" name="search_order" type="object" class="btn-primary"/>
</xpath>
</field>
</record>
</odoo>

View File

@@ -10,7 +10,7 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['mrp', 'sf_base', 'maintenance'],
'depends': ['mrp', 'sf_base', 'maintenance', 'sf_mrs_connect'],
'data': [
'security/group_security.xml',
'security/ir.model.access.csv',

View File

@@ -2,10 +2,12 @@
from odoo import api, fields, models,_
class resProduct(models.Model):
class ResProducTemplate_Production(models.Model):
_inherit = 'product.template'
model_file = fields.Binary('模型文件')
class MrpProduction(models.Model):
_inherit = 'mrp.production'
_description = "制造订单"

View File

@@ -13,6 +13,12 @@ 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")

View File

@@ -4,6 +4,7 @@ import math
import requests
import logging
import base64
import hashlib
# import subprocess
from datetime import datetime
from dateutil.relativedelta import relativedelta
@@ -47,9 +48,12 @@ 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)
@@ -85,50 +89,48 @@ 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):
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("参数计算有误")
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
# 将补偿值写入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, '', {
@@ -138,6 +140,7 @@ 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,
@@ -164,9 +167,8 @@ 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)])
@@ -181,11 +183,10 @@ class ResMrpWorkOrder(models.Model):
'production_id': self.production_id,
'state': '占用',
})
self.tray_id = values
else:
raise UserError('该托盘编码已失效')
else:
raise UserError('托盘码不能为空')
return ""
def gettray_auto(self, barcode):
if barcode != False:
@@ -204,45 +205,15 @@ class ResMrpWorkOrder(models.Model):
else:
raise UserError('该托盘编码已失效')
else:
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)],
}
return ""
# 解除托盘绑定
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 {
# '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'
# }
return ""
def recreateManufacturingOrWorkerOrder(self):
"""
@@ -285,45 +256,74 @@ class ResMrpWorkOrder(models.Model):
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
productions._create_workorder2(self.processing_panel)
else:
return True
return {
'name': _("工单"),
'view_mode': 'form',
'res_model': 'mrp.workorder',
'res_id': self.id,
'type': 'ir.actions.act_window',
}
# def fetchCNCing(self):
# return None
# cnc程序获取
# cnc程序获取
def fetchCNC(self):
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})
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('行业资源库解析失败')
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'
# }
def json_workorder_str1(self, k, production, route):
workorders_values_str = [0, '', {
@@ -333,6 +333,7 @@ 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,
@@ -411,26 +412,52 @@ class CNCprocessing(models.Model):
workorder_id = fields.Many2one('mrp.workorder', string="工单")
# mrs下发编程单创建CNC加工
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)
def cnc_processing_create(self, cnc_workorder, 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)
cnc_workorder.state = 'done'
cnc_workorder.work_state = '已编程'
cnc_workorder.programming_state = '已编程'
cnc_workorder.time_ids.date_end = datetime.now()
def get_cnc_processing_file(self, folder_name, cnc_processing):
logging.info('folder_name:%s' % folder_name)
serverdir = os.path.join('/', folder_name, 'return', cnc_processing.processing_panel)
logging.info('serverdir:%s' % serverdir)
for root, dirs, files in os.walk(server_dir):
for f in files:
logging.info('f:%s' % f)
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_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(server_dir, root, f)
logging.info('cnc_file_path:%s' % cnc_file_path)
cnc_processing.with_user(request.env.ref("base.user_admin")).write_file(cnc_file_path,
cnc_processing)
# 创建附件(nc文件)
def attachment_create(self, name, data):
@@ -443,38 +470,26 @@ class CNCprocessing(models.Model):
return attachment
# 将FTP的nc文件下载到临时目录
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
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
# 将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 + '.NC', data_bytes)
cnc.write({'cnc_id': attachment.id})
file.close()
attachment = self.attachment_create(cnc.program_name, 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):
"""

View File

@@ -3,7 +3,7 @@
import base64
from io import BytesIO
from odoo import api, fields, models, SUPERUSER_ID, _
from pystrich.code128 import Code128Encoder
#from pystrich.code128 import Code128Encoder
class Tray(models.Model):
@@ -20,41 +20,6 @@ class Tray(models.Model):
def updateTrayState(self):
if self.workorder_id != False:
self.state = '占用'
else:
self.state = '空闲'

View File

@@ -107,7 +107,7 @@
</xpath>
<xpath expr="//field[@name='alternative_workcenter_ids']" position="after">
<field name="machine_tool_id"/>
<field name="machine_tool_id" domain="[('is_binding', '=', False)]"/>
</xpath>
</field>
</record>

View File

@@ -12,32 +12,21 @@
<field name="name" position="after">
<field name="processing_panel"/>
</field>
<field name="state" position="after">
<field name="work_state"/>
</field>
<xpath expr="//button[@name='button_start']" position="attributes">
<attribute name="attrs">{'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done',
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
('is_user_working', '!=', False),("user_permissions","=",False)]}
</attribute>
</xpath>
<xpath expr="//button[@name='%(mrp.act_mrp_block_workcenter_wo)d']" position="attributes">
<attribute name="attrs">{'invisible': [("user_permissions","=",False)]} </attribute>
<attribute name="string">停工</attribute>
</xpath>
<xpath expr="//button[@name='action_open_wizard']" position="attributes">
<attribute name="invisible">1</attribute>
</xpath>
<!-- <button name="button_start" type="object" string="Start" class="btn-success"-->
<!-- attrs="{'invisible': ['|', '|', '|', ('production_state','in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')), ('is_user_working', '!=', False)]}"/>-->
<!-- <button name="button_pending" type="object" string="Pause" class="btn-warning"-->
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>-->
<!-- <button name="button_finish" type="object" string="Done" class="btn-success"-->
<!-- attrs="{'invisible': ['|', '|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked'), ('is_user_working', '=', False)]}"/>-->
<!-- <button name="%(mrp.act_mrp_block_workcenter_wo)d" type="action" string="Block" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"-->
<!-- attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '=', 'blocked')]}"/>-->
<!-- <button name="button_unblock" type="object" string="Unblock" context="{'default_workcenter_id': workcenter_id}" class="btn-danger"-->
<!-- attrs="{'invisible': ['|', ('production_state', 'in', ('draft', 'done', 'cancel')), ('working_state', '!=', 'blocked')]}"/>-->
<!-- <button name="action_open_wizard" type="object" icon="fa-external-link" class="oe_edit_only"-->
<!-- title="Open Work Order"/>-->
<tree position="attributes">
<attribute name="multi_edit"></attribute>
<attribute name="editable"></attribute>
@@ -95,11 +84,20 @@
<xpath expr="//page[last()]" position="after">
<page string="获取CNC加工程序" attrs='{"invisible": [("routing_type","!=","获取CNC加工程序")]}'>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="fetchCNC" string="获取CNC程序代码"
attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
</div>
<group>
<field name="programming_no" readonly="1"
attrs='{"invisible": [("programming_no","=",False)]}'/>
<field name="programming_state" readonly="1"
attrs='{"invisible": [("programming_no","=",False)]}'/>
</group>
<group>
<div class="col-12 col-lg-6 o_setting_box" style="white-space: nowrap">
<button type="object" class="oe_highlight" name="fetchCNC" string="获取CNC程序代码"
attrs='{"invisible": [("user_permissions","=",False)]}'/>
<button type="object" class="oe_highlight disabled" name="fetchCNC" string="获取CNC程序代码"
attrs='{"invisible": ["|",("programming_no","=",False),("programming_no","=",False)]}'/>
</div>
</group>
</page>
</xpath>
@@ -109,13 +107,11 @@
<field name="routing_type" invisible="1"/>
<field name="processing_panel" readonly="1"/>
<field name="tray_code"/>
<field name="tray_id" readonly="1"/>
</group>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="gettray" string="绑定托盘"
attrs='{"invisible": ["|","|",("tray_id","!=",False),("state","!=","progress"),("production_id","=",False)]}'/>
attrs='{"invisible": [("production_id","=",False)]}'/>
</div>
</page>
@@ -226,7 +222,7 @@
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="getcenter" string="计算定位"
attrs='{"invisible": ["|","|",("material_center_point","!=",False),("state","!=","progress"),("user_permissions","=",False)]}'/>
attrs='{"invisible": [("user_permissions","=",False)]}'/>
</div>
<group>
@@ -268,7 +264,7 @@
</group>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="recreateManufacturingOrWorkerOrder"
string="检测确认" attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
string="检测确认" attrs='{"invisible": [("user_permissions","=",False)]}'/>
</div>
</page>
</xpath>
@@ -277,11 +273,11 @@
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="unbindtray" string="解除装夹"
attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
attrs='{"invisible": [("user_permissions","=",False)]}'/>
</div>
<div class="col-12 col-lg-6 o_setting_box">
<button type="action" class="oe_highlight" name="sf_manufacturing.label_sf_tray_code1"
string="打印标签" attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
string="打印标签" attrs='{"invisible": [("user_permissions","=",False)]}'/>
</div>
</page>

View File

@@ -20,44 +20,55 @@ 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 = self.env['mrp.workorder'].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)
logging.info('download_state:%s' % download_state)
# i += 1
if download_state == False:
res = {'status': -2, 'message': 'cnc文件拉取失败'}
return json.JSONEncoder().encode(res)
request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).cnc_processing_create(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)
@http.route('/api/cnc_processing/update_state', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
cors="*")
def get_cnc_processing_state(self, **kw):
"""
获取mrs下发的编程单的状态
:param kw:
:return:
"""
logging.info('get_cnc_processing_state:%s' % kw)
try:
res = {'status': 1, 'message': '成功'}
datas = request.httprequest.data
ret = json.loads(datas)
ret = json.loads(ret['result'])
cnc_processing = request.env['sf.cnc.processing'].with_user(
request.env.ref("base.user_admin")).cnc_processing_create(ret['programming_list'],
ret['production_order_no'])
except Exception as e:
res = {'status': -1, 'message': '系统解析失败'}
logging.info('get_cnc_processing_create error:%s' % e)
return json.JSONEncoder().encode(res)

View File

@@ -15,7 +15,7 @@ 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)
@@ -34,7 +34,7 @@ class FtpController():
if file.find(".") != -1:
self.download_file(server, file)
else:
return
return False
# 下载指定目录下的指定文件
def download_file(self, serverfile, remotefile):

View File

@@ -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 "")

View File

@@ -14,22 +14,49 @@
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="token"/>
<field name="token" />
<label for="sf_url"/>
<field name="sf_url"/>
</div>
<div class="text-muted">
<label for="token" string="Token"/>
<field name="token"/>
</div>
<div class="text-muted">
<label for="sf_secret_key"/>
<field name="sf_secret_key"/>
</div>
<div class="text-muted">
<label for="sf_url"/>
<field name="sf_url"/>
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="sf_all_sync"
string="同步资源库基础数据"
/>
</div>
</div>
</div>
</div>
</div>
<div>
<h2>FTP参数配置</h2>
<div class="row mt16 o_settings_container" id="pay_api">
<div class="col-12 col-lg-6 o_setting_box">
<button type="object" class="oe_highlight" name="sf_all_sync" string="同步资源库所有基础数据"
/>
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<div class="text-muted">
<label for="ftp_host" string="访问地址"/>
<field name="ftp_host"/>
</div>
<div class="text-muted">
<label for="ftp_port" string="端口"/>
<field name="ftp_port"/>
</div>
<div class="text-muted">
<label for="ftp_user" string="用户"/>
<field name="ftp_user"/>
</div>
<div class="text-muted">
<label for="ftp_password" string="密码"/>
<field name="ftp_password" password="True"/>
</div>
</div>
</div>
</div>
</div>

View File

@@ -44,7 +44,6 @@ class ReSaleOrder(models.Model):
product.model_machining_precision,
product.materials_id.name),
'price_unit': product.list_price,
'route_id': product.route_ids,
'product_uom_qty': item['number']
}
return self.env['sale.order.line'].create(vals)