sf1.0
This commit is contained in:
@@ -359,7 +359,7 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<form string="机床">
|
<form string="机床">
|
||||||
<header>
|
<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>
|
</header>
|
||||||
<group string="基本信息">
|
<group string="基本信息">
|
||||||
<group>
|
<group>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ class Sf_Bf_Connect(http.Controller):
|
|||||||
logging.info('product:%s' % product)
|
logging.info('product:%s' % product)
|
||||||
bom_data = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).get_bom(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)
|
logging.info('bom_data:%s' % bom_data)
|
||||||
|
i += 1
|
||||||
if bom_data:
|
if bom_data:
|
||||||
bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(product,
|
bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(product,
|
||||||
'normal',
|
'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_embryo = request.env['product.template'].sudo().no_bom_product_create(
|
||||||
self_machining_id,
|
self_machining_id,
|
||||||
item,
|
item,
|
||||||
order_id, 'self_machining')
|
order_id, 'self_machining', i)
|
||||||
# 创建胚料的bom
|
# 创建胚料的bom
|
||||||
self_machining_bom = request.env['mrp.bom'].with_user(
|
self_machining_bom = request.env['mrp.bom'].with_user(
|
||||||
request.env.ref("base.user_admin")).bom_create(
|
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,
|
outsource_embryo = request.env['product.template'].sudo().no_bom_product_create(outsource_id,
|
||||||
item,
|
item,
|
||||||
order_id,
|
order_id,
|
||||||
'subcontract')
|
'subcontract',
|
||||||
|
i)
|
||||||
# 创建胚料的bom
|
# 创建胚料的bom
|
||||||
outsource_bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(
|
outsource_bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(
|
||||||
outsource_embryo,
|
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,
|
purchase_embryo = request.env['product.template'].sudo().no_bom_product_create(purchase_id,
|
||||||
item,
|
item,
|
||||||
order_id,
|
order_id,
|
||||||
'purchase')
|
'purchase', i)
|
||||||
# 产品配置bom
|
# 产品配置bom
|
||||||
product_bom_purchase = request.env['mrp.bom'].with_user(
|
product_bom_purchase = request.env['mrp.bom'].with_user(
|
||||||
request.env.ref("base.user_admin")).bom_create(product, 'normal', False)
|
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(
|
product_bom_purchase.with_user(request.env.ref("base.user_admin")).bom_create_line_has(
|
||||||
purchase_embryo)
|
purchase_embryo)
|
||||||
order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item)
|
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
|
res['factory_order_no'] = order_id.name
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.info('get_bfm_process_order_list error:%s' % e)
|
logging.info('get_bfm_process_order_list error:%s' % e)
|
||||||
|
|||||||
@@ -10,9 +10,10 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['mrp', 'base', 'sf_manufacturing'],
|
'depends': ['mrp', 'base', 'sf_manufacturing', 'purchase', 'mrp_subcontracting', 'uom'],
|
||||||
'data': [
|
'data': [
|
||||||
'data/product_data.xml',
|
'data/product_data.xml',
|
||||||
|
'data/uom_data.xml',
|
||||||
'views/product_template_view.xml'
|
'views/product_template_view.xml'
|
||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
|
|||||||
57
sf_dlm/data/tt.xml
Normal file
57
sf_dlm/data/tt.xml
Normal 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>
|
||||||
@@ -3,9 +3,10 @@ from odoo.exceptions import ValidationError
|
|||||||
import logging
|
import logging
|
||||||
import base64
|
import base64
|
||||||
import os
|
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
|
from odoo.modules import get_resource_path
|
||||||
|
|
||||||
|
|
||||||
class ResProductTemplate(models.Model):
|
class ResProductTemplate(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = 'product.template'
|
||||||
|
|
||||||
@@ -34,6 +35,15 @@ class ResProductTemplate(models.Model):
|
|||||||
materials_type_id = fields.Many2one('sf.materials.model', string='材料型号')
|
materials_type_id = fields.Many2one('sf.materials.model', string='材料型号')
|
||||||
single_manufacturing = fields.Boolean(string="单个制造")
|
single_manufacturing = fields.Boolean(string="单个制造")
|
||||||
upload_model_file = fields.Many2many('ir.attachment', 'upload_model_file_attachment_ref', 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('模型文件')
|
# model_file = fields.Binary('模型文件')
|
||||||
|
|
||||||
# 胚料的库存路线设置
|
# 胚料的库存路线设置
|
||||||
@@ -72,16 +82,18 @@ class ResProductTemplate(models.Model):
|
|||||||
item['model_height'] + model_type.embryo_tolerance),
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
'model_type_id': 1,
|
'model_type_id': 1,
|
||||||
# 'model_machining_precision': item['model_machining_precision'],
|
# 'model_machining_precision': item['model_machining_precision'],
|
||||||
'model_processing_panel': 'A',
|
'model_processing_panel': 'R',
|
||||||
'model_machining_precision': '±0.10mm',
|
'model_machining_precision': '±0.10mm',
|
||||||
|
'model_code': item['barcode'],
|
||||||
'length': item['model_long'],
|
'length': item['model_long'],
|
||||||
'width': item['model_width'],
|
'width': item['model_width'],
|
||||||
'height': item['model_height'],
|
'height': item['model_height'],
|
||||||
'volume': item['model_long'] * item['model_width'] * 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,
|
'model_name': attachment.name,
|
||||||
'upload_model_file': [(6, 0, [attachment.id])],
|
'upload_model_file': [(6, 0, [attachment.id])],
|
||||||
# 'single_manufacturing': True,
|
# 'single_manufacturing': True,
|
||||||
|
'tracking': 'serial',
|
||||||
'list_price': item['price'],
|
'list_price': item['price'],
|
||||||
# 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id,
|
# 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id,
|
||||||
'materials_id': self.env['sf.production.materials'].search(
|
'materials_id': self.env['sf.production.materials'].search(
|
||||||
@@ -99,8 +111,7 @@ class ResProductTemplate(models.Model):
|
|||||||
# 'route_ids': self._get_routes('')
|
# 'route_ids': self._get_routes('')
|
||||||
}
|
}
|
||||||
copy_product_id.sudo().write(vals)
|
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
|
return copy_product_id
|
||||||
|
|
||||||
def attachment_create(self, name, data):
|
def attachment_create(self, name, data):
|
||||||
@@ -113,7 +124,7 @@ class ResProductTemplate(models.Model):
|
|||||||
return attachment
|
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_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||||
no_bom_copy_product_id.product_tmpl_id.active = True
|
no_bom_copy_product_id.product_tmpl_id.active = True
|
||||||
materials_id = self.env['sf.production.materials'].search(
|
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)
|
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
||||||
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
||||||
vals = {
|
vals = {
|
||||||
'name': '%s %s %s %s * %s * %s' % (
|
'name': '%s-%s %s %s %s * %s * %s' % (
|
||||||
order_id.name, materials_id.name, materials_type_id.name, item['model_long'], item['model_width'],
|
order_id.name, i, materials_id.name, materials_type_id.name,
|
||||||
item['model_height']),
|
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,
|
'length': item['model_long'] + model_type.embryo_tolerance,
|
||||||
'width': item['model_width'] + model_type.embryo_tolerance,
|
'width': item['model_width'] + model_type.embryo_tolerance,
|
||||||
'height': item['model_height'] + 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)
|
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)
|
no_bom_copy_product_id.write(vals)
|
||||||
logging.info('no_bom_copy_product_id-vals:%s' % 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
|
return no_bom_copy_product_id
|
||||||
|
|
||||||
@api.onchange('upload_model_file')
|
# @api.onchange('upload_model_file')
|
||||||
def onchange_model_file(self):
|
# def onchange_model_file(self):
|
||||||
for item in self:
|
# for item in self:
|
||||||
if len(item.upload_model_file) > 1:
|
# if len(item.upload_model_file) > 1:
|
||||||
raise ValidationError('只允许上传一个文件')
|
# raise ValidationError('只允许上传一个文件')
|
||||||
if item.upload_model_file:
|
# if item.upload_model_file:
|
||||||
file_attachment_id = item.upload_model_file[0]
|
# file_attachment_id = item.upload_model_file[0]
|
||||||
item.model_name = file_attachment_id.name
|
# item.model_name = file_attachment_id.name
|
||||||
# 附件路径
|
# # 附件路径
|
||||||
report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
|
# report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
|
||||||
shapes = read_step_file(report_path)
|
# shapes = read_step_file(report_path)
|
||||||
output_file = get_resource_path('sf_dlm', 'static/file', 'out.stl')
|
# output_file = get_resource_path('sf_dlm', 'static/file', 'out.stl')
|
||||||
write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
|
# write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
|
||||||
# 转化为glb
|
# # 转化为glb
|
||||||
output_glb_file = get_resource_path('sf_dlm', 'static/file', 'out.glb')
|
# output_glb_file = get_resource_path('sf_dlm', 'static/file', 'out.glb')
|
||||||
util_path = get_resource_path('sf_dlm', 'static/util')
|
# util_path = get_resource_path('sf_dlm', 'static/util')
|
||||||
cmd = 'python %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
|
# cmd = 'python %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
|
||||||
os.system(cmd)
|
# os.system(cmd)
|
||||||
# 转base64
|
# # 转base64
|
||||||
with open(output_glb_file, 'rb') as fileObj:
|
# with open(output_glb_file, 'rb') as fileObj:
|
||||||
image_data = fileObj.read()
|
# image_data = fileObj.read()
|
||||||
base64_data = base64.b64encode(image_data)
|
# base64_data = base64.b64encode(image_data)
|
||||||
item.model_file = base64_data
|
# item.model_file = base64_data
|
||||||
|
|
||||||
|
|
||||||
class ResMrpBom(models.Model):
|
class ResMrpBom(models.Model):
|
||||||
@@ -244,8 +256,6 @@ class ResMrpBom(models.Model):
|
|||||||
|
|
||||||
# 匹配bom
|
# 匹配bom
|
||||||
def get_bom(self, product):
|
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(
|
embryo_has = self.env['product.product'].search(
|
||||||
[('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id),
|
[('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id),
|
||||||
('length', '>', product.length), ('width', '>', product.width),
|
('length', '>', product.length), ('width', '>', product.width),
|
||||||
@@ -257,7 +267,7 @@ class ResMrpBom(models.Model):
|
|||||||
logging.info('get_bom-vals:%s' % embryo_has)
|
logging.info('get_bom-vals:%s' % embryo_has)
|
||||||
if embryo_has:
|
if embryo_has:
|
||||||
rate_of_waste = ((embryo_has.volume - product.model_volume) % embryo_has.volume) * 100
|
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
|
return embryo_has
|
||||||
else:
|
else:
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<!-- </field>-->
|
<!-- </field>-->
|
||||||
|
|
||||||
<field name="invoice_policy" position="after">
|
<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_id" string="材料"/>
|
||||||
<field name="materials_type_id" string="型号"
|
<field name="materials_type_id" string="型号"
|
||||||
domain="[('materials_id', '=', materials_id)]"/>
|
domain="[('materials_id', '=', materials_id)]"/>
|
||||||
@@ -36,11 +36,23 @@
|
|||||||
|
|
||||||
<xpath expr="//page[last()]" position="after">
|
<xpath expr="//page[last()]" position="after">
|
||||||
<page string="加工参数">
|
<page string="加工参数">
|
||||||
|
<group>
|
||||||
<group string="模型">
|
<group string="模型">
|
||||||
<field name="model_long" string="长[mm]"/>
|
<label for="model_long" string="尺寸[mm]"/>
|
||||||
<field name="model_width" string="宽[mm]"/>
|
<div class="o_address_format">
|
||||||
<field name="model_height" string="高[mm]"/>
|
<label for="model_long" string="长"/>
|
||||||
<field name="model_volume" string="体积[m³]"/>
|
<field name="model_long" class="o_address_zip"/>
|
||||||
|
<!-- <span>&nbsp;</span>-->
|
||||||
|
<label for="model_width" string="宽"/>
|
||||||
|
<field name="model_width" class="o_address_zip"/>
|
||||||
|
<!-- <span>&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_type_id" string="模型类型"/>
|
||||||
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"/>
|
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"/>
|
||||||
<field name="model_machining_precision"/>
|
<field name="model_machining_precision"/>
|
||||||
@@ -49,6 +61,7 @@
|
|||||||
domain="[('processing_order_ids', '=', model_surface_process_id)]"/>
|
domain="[('processing_order_ids', '=', model_surface_process_id)]"/>
|
||||||
<field name="model_remark" string="备注说明"/>
|
<field name="model_remark" string="备注说明"/>
|
||||||
</group>
|
</group>
|
||||||
|
</group>
|
||||||
</page>
|
</page>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
1
sf_machine_connect/__init__.py
Normal file
1
sf_machine_connect/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
from . import models
|
||||||
30
sf_machine_connect/__manifest__.py
Normal file
30
sf_machine_connect/__manifest__.py
Normal 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',
|
||||||
|
}
|
||||||
3
sf_machine_connect/models/__init__.py
Normal file
3
sf_machine_connect/models/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
from . import ftp_client
|
||||||
|
from . import ftp_operate
|
||||||
|
from . import py2opcua
|
||||||
44
sf_machine_connect/models/data_collection.py
Normal file
44
sf_machine_connect/models/data_collection.py
Normal 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="状态")
|
||||||
153
sf_machine_connect/models/ftp_client.py
Normal file
153
sf_machine_connect/models/ftp_client.py
Normal 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
|
||||||
118
sf_machine_connect/models/ftp_operate.py
Normal file
118
sf_machine_connect/models/ftp_operate.py
Normal 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) # 删除远程文件
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
32
sf_machine_connect/models/py2opcua.py
Normal file
32
sf_machine_connect/models/py2opcua.py
Normal 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()
|
||||||
20
sf_machine_connect/security/iot_security.xml
Normal file
20
sf_machine_connect/security/iot_security.xml
Normal 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>
|
||||||
2
sf_machine_connect/security/ir.model.access.csv
Normal file
2
sf_machine_connect/security/ir.model.access.csv
Normal 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
|
||||||
|
BIN
sf_machine_connect/static/description/icon.png
Normal file
BIN
sf_machine_connect/static/description/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.5 KiB |
30
sf_machine_connect/static/src/css/MyWidget.css
Normal file
30
sf_machine_connect/static/src/css/MyWidget.css
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
5
sf_machine_connect/static/src/css/iot.css
Normal file
5
sf_machine_connect/static/src/css/iot.css
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.o_button_iot {
|
||||||
|
min-width: 120px;
|
||||||
|
min-height: 40px;
|
||||||
|
margin-left: 50px;
|
||||||
|
}
|
||||||
94
sf_machine_connect/static/src/xml/Barcode_Scan_template.xml
Normal file
94
sf_machine_connect/static/src/xml/Barcode_Scan_template.xml
Normal 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]}&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>
|
||||||
10
sf_machine_connect/static/src/xml/Flush.xml
Normal file
10
sf_machine_connect/static/src/xml/Flush.xml
Normal 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>
|
||||||
27
sf_machine_connect/static/src/xml/MyComponent.xml
Normal file
27
sf_machine_connect/static/src/xml/MyComponent.xml
Normal 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>
|
||||||
4
sf_machine_connect/static/src/xml/MyWidget.xml
Normal file
4
sf_machine_connect/static/src/xml/MyWidget.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<templates>
|
||||||
|
|
||||||
|
</templates>
|
||||||
32
sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml
Normal file
32
sf_machine_connect/static/src/xml/PartnerOrderSummary2.xml
Normal 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>-->
|
||||||
|
<!--<!– <img src="/barcodes/static/img/barcode.png" alt="Barcode"/>–>-->
|
||||||
|
<!-- <span class="o_barcode_laser"/>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</t>
|
||||||
|
</templates>
|
||||||
15
sf_machine_connect/static/src/xml/barcodes.xml
Normal file
15
sf_machine_connect/static/src/xml/barcodes.xml
Normal 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>
|
||||||
@@ -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>
|
||||||
17
sf_machine_connect/static/src/xml/many2one_field.xml
Normal file
17
sf_machine_connect/static/src/xml/many2one_field.xml
Normal 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>
|
||||||
17
sf_machine_connect/static/src/xml/stack.xml
Normal file
17
sf_machine_connect/static/src/xml/stack.xml
Normal 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>
|
||||||
14
sf_machine_connect/views/Barcode_Scan.xml
Normal file
14
sf_machine_connect/views/Barcode_Scan.xml
Normal 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>
|
||||||
15
sf_machine_connect/views/SfWorkOrderBarcodes.xml
Normal file
15
sf_machine_connect/views/SfWorkOrderBarcodes.xml
Normal 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>
|
||||||
18
sf_machine_connect/views/Stock_picking_Barcodes.xml
Normal file
18
sf_machine_connect/views/Stock_picking_Barcodes.xml
Normal 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>
|
||||||
20
sf_machine_connect/views/WorkCenterBarcodes.xml
Normal file
20
sf_machine_connect/views/WorkCenterBarcodes.xml
Normal 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>
|
||||||
23
sf_machine_connect/views/compensation.xml
Normal file
23
sf_machine_connect/views/compensation.xml
Normal 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>
|
||||||
23
sf_machine_connect/views/flush_template.xml
Normal file
23
sf_machine_connect/views/flush_template.xml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<template id="flush">
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<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>
|
||||||
19
sf_machine_connect/views/ftp_button.xml
Normal file
19
sf_machine_connect/views/ftp_button.xml
Normal 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>
|
||||||
|
|
||||||
43
sf_machine_connect/views/machine_monitor.xml
Normal file
43
sf_machine_connect/views/machine_monitor.xml
Normal 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>
|
||||||
|
|
||||||
|
<!--<!–继承了本模块的视图–>-->
|
||||||
|
<!--<?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>-->
|
||||||
25
sf_machine_connect/views/purchase_barcode.xml
Normal file
25
sf_machine_connect/views/purchase_barcode.xml
Normal 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>
|
||||||
176
sf_machine_connect/views/sf_machine_connnect.xml
Normal file
176
sf_machine_connect/views/sf_machine_connnect.xml
Normal 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>
|
||||||
|
|
||||||
|
|
||||||
45
sf_machine_connect/views/views.xml
Normal file
45
sf_machine_connect/views/views.xml
Normal 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>-->
|
||||||
15
sf_machine_connect/views/views_test_barcode.xml
Normal file
15
sf_machine_connect/views/views_test_barcode.xml
Normal 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>
|
||||||
18
sf_machine_connect/views/workorder_button.xml
Normal file
18
sf_machine_connect/views/workorder_button.xml
Normal 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>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['mrp', 'sf_base', 'maintenance'],
|
'depends': ['mrp', 'sf_base', 'maintenance', 'sf_mrs_connect'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/group_security.xml',
|
'security/group_security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
from odoo import api, fields, models,_
|
from odoo import api, fields, models,_
|
||||||
|
|
||||||
|
|
||||||
class resProduct(models.Model):
|
class ResProducTemplate_Production(models.Model):
|
||||||
_inherit = 'product.template'
|
_inherit = 'product.template'
|
||||||
|
|
||||||
model_file = fields.Binary('模型文件')
|
model_file = fields.Binary('模型文件')
|
||||||
|
|
||||||
|
|
||||||
class MrpProduction(models.Model):
|
class MrpProduction(models.Model):
|
||||||
_inherit = 'mrp.production'
|
_inherit = 'mrp.production'
|
||||||
_description = "制造订单"
|
_description = "制造订单"
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ class ResWorkcenter(models.Model):
|
|||||||
'maintenance.equipment', 'workcenter_id', string="Maintenance Equipment",
|
'maintenance.equipment', 'workcenter_id', string="Maintenance Equipment",
|
||||||
check_company=True)
|
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):
|
def action_work_order(self):
|
||||||
if not self.env.context.get('desktop_list_view', False):
|
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")
|
action = self.env["ir.actions.actions"]._for_xml_id("sf_manufacturing.mrp_workorder_action_tablet")
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import math
|
|||||||
import requests
|
import requests
|
||||||
import logging
|
import logging
|
||||||
import base64
|
import base64
|
||||||
|
import hashlib
|
||||||
# import subprocess
|
# import subprocess
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
@@ -47,9 +48,12 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
workorder.user_permissions = False
|
workorder.user_permissions = False
|
||||||
|
|
||||||
user_permissions = fields.Boolean('用户权限', compute='get_user_permissions')
|
user_permissions = fields.Boolean('用户权限', compute='get_user_permissions')
|
||||||
|
programming_no = fields.Char('编程单号')
|
||||||
|
work_state = fields.Char('业务状态')
|
||||||
|
programming_state = fields.Char('编程状态')
|
||||||
cnc_worksheet = fields.Binary(
|
cnc_worksheet = fields.Binary(
|
||||||
'工作指令', readonly=True)
|
'工作指令', readonly=True)
|
||||||
material_center_point = fields.Char(string='胚料中心点')
|
material_center_point = fields.Char(string='配料中心点')
|
||||||
X1_axis = fields.Float(default=0)
|
X1_axis = fields.Float(default=0)
|
||||||
Y1_axis = fields.Float(default=0)
|
Y1_axis = fields.Float(default=0)
|
||||||
Z1_axis = fields.Float(default=0)
|
Z1_axis = fields.Float(default=0)
|
||||||
@@ -85,12 +89,9 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
string="检测结果")
|
string="检测结果")
|
||||||
cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工")
|
cnc_ids = fields.One2many("sf.cnc.processing", 'workorder_id', string="CNC加工")
|
||||||
tray_code = fields.Char(string="托盘")
|
tray_code = fields.Char(string="托盘")
|
||||||
programming_no = fields.Char('编程单号')
|
|
||||||
is_programming = fields.Boolean('是否编程', default=False)
|
|
||||||
|
|
||||||
# 计算配料中心点和与x轴倾斜度方法
|
# 计算配料中心点和与x轴倾斜度方法
|
||||||
def getcenter(self):
|
def getcenter(self):
|
||||||
try:
|
|
||||||
x1 = self.X1_axis
|
x1 = self.X1_axis
|
||||||
x2 = self.X2_axis
|
x2 = self.X2_axis
|
||||||
x3 = self.X3_axis
|
x3 = self.X3_axis
|
||||||
@@ -125,10 +126,11 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
print("(%.2f,%.2f)" % (x, y))
|
print("(%.2f,%.2f)" % (x, y))
|
||||||
self.material_center_point = ("(%.2f,%.2f,%.2f)" % (x, y, z))
|
self.material_center_point = ("(%.2f,%.2f,%.2f)" % (x, y, z))
|
||||||
self.X_deviation_angle = jdz
|
self.X_deviation_angle = jdz
|
||||||
return self.material_center_point
|
# 将补偿值写入CNC加工工单
|
||||||
except:
|
workorder = self.env['mrp.workorder'].browse(self.ids)
|
||||||
raise UserError("参数计算有误")
|
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):
|
def json_workorder_str(self, k, production, route):
|
||||||
workorders_values_str = [0, '', {
|
workorders_values_str = [0, '', {
|
||||||
@@ -138,6 +140,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
'name': route.route_workcenter_id.name,
|
'name': route.route_workcenter_id.name,
|
||||||
'processing_panel': k,
|
'processing_panel': k,
|
||||||
'routing_type': route.routing_type,
|
'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),
|
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids),
|
||||||
'date_planned_start': False,
|
'date_planned_start': False,
|
||||||
'date_planned_finished': False,
|
'date_planned_finished': False,
|
||||||
@@ -164,9 +167,8 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
'target': 'new',
|
'target': 'new',
|
||||||
'domain': [('workorder_id', '=', self.id)]
|
'domain': [('workorder_id', '=', self.id)]
|
||||||
}
|
}
|
||||||
tray_id = fields.Many2one('sf.tray', string="托盘信息")
|
|
||||||
# 扫码绑定托盘方法
|
|
||||||
|
|
||||||
|
# 扫码绑定托盘方法
|
||||||
def gettray(self):
|
def gettray(self):
|
||||||
if self.tray_code != False:
|
if self.tray_code != False:
|
||||||
values = self.env['sf.tray'].search([("code", "=", self.tray_code)])
|
values = self.env['sf.tray'].search([("code", "=", self.tray_code)])
|
||||||
@@ -181,11 +183,10 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
'production_id': self.production_id,
|
'production_id': self.production_id,
|
||||||
'state': '占用',
|
'state': '占用',
|
||||||
})
|
})
|
||||||
self.tray_id = values
|
|
||||||
else:
|
else:
|
||||||
raise UserError('该托盘编码已失效')
|
raise UserError('该托盘编码已失效')
|
||||||
else:
|
else:
|
||||||
raise UserError('托盘码不能为空')
|
return ""
|
||||||
|
|
||||||
def gettray_auto(self, barcode):
|
def gettray_auto(self, barcode):
|
||||||
if barcode != False:
|
if barcode != False:
|
||||||
@@ -204,45 +205,15 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
else:
|
else:
|
||||||
raise UserError('该托盘编码已失效')
|
raise UserError('该托盘编码已失效')
|
||||||
else:
|
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):
|
def unbindtray(self):
|
||||||
tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)])
|
tray = self.env['sf.tray'].search([("production_id", "=", self.production_id.id)])
|
||||||
if tray:
|
if tray:
|
||||||
tray.unclamp()
|
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):
|
def recreateManufacturingOrWorkerOrder(self):
|
||||||
"""
|
"""
|
||||||
@@ -285,26 +256,38 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
self.env['stock.move'].sudo().create(productions._get_moves_finished_values())
|
||||||
productions._create_workorder2(self.processing_panel)
|
productions._create_workorder2(self.processing_panel)
|
||||||
else:
|
else:
|
||||||
|
return True
|
||||||
|
|
||||||
return {
|
# def fetchCNCing(self):
|
||||||
'name': _("工单"),
|
# return None
|
||||||
'view_mode': 'form',
|
|
||||||
'res_model': 'mrp.workorder',
|
|
||||||
'res_id': self.id,
|
|
||||||
'type': 'ir.actions.act_window',
|
|
||||||
}
|
|
||||||
|
|
||||||
# cnc程序获取
|
|
||||||
# cnc程序获取
|
# cnc程序获取
|
||||||
def fetchCNC(self):
|
def fetchCNC(self):
|
||||||
|
try:
|
||||||
cnc = self.env['mrp.workorder'].search(
|
cnc = self.env['mrp.workorder'].search(
|
||||||
[('routing_type', '=', 'CNC加工'), ('production_id', '=', self.production_id.id)], limit=1)
|
[('routing_type', '=', 'CNC加工'), ('production_id', '=', self.production_id.id)], limit=1)
|
||||||
res = {'model_code': cnc.product_id.barcode, 'production_no': self.production_id.name,
|
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,
|
'machine_tool_code': cnc.workcenter_id.machine_tool_id.code,
|
||||||
'material_code': cnc.env['sf.production.materials'].search(
|
'material_code': cnc.env['sf.production.materials'].search(
|
||||||
[('id', '=', cnc.product_id.materials_id.id)]).materials_no,
|
[('id', '=', cnc.product_id.materials_id.id)]).materials_no,
|
||||||
'material_type_code': cnc.env['sf.materials.model'].search(
|
'material_type_code': cnc.env['sf.materials.model'].search(
|
||||||
[('id', '=', cnc.product_id.materials_type_id.id)]).materials_no,
|
[('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,
|
'machining_precision': cnc.product_id.model_machining_precision,
|
||||||
'embryo_long': cnc.product_id.bom_ids.bom_line_ids.product_id.length,
|
'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_height': cnc.product_id.bom_ids.bom_line_ids.product_id.height,
|
||||||
@@ -322,8 +305,25 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
# res_str = json.dumps(res)
|
# res_str = json.dumps(res)
|
||||||
ret = requests.post(config_url, json={}, data=res, headers=config_header)
|
ret = requests.post(config_url, json={}, data=res, headers=config_header)
|
||||||
ret = ret.json()
|
ret = ret.json()
|
||||||
|
logging.info('fetchCNC-ret:%s' % ret)
|
||||||
if ret['status'] == 1:
|
if ret['status'] == 1:
|
||||||
return self.write({'programming_no': ret['programming_no'], 'is_programming': True})
|
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):
|
def json_workorder_str1(self, k, production, route):
|
||||||
workorders_values_str = [0, '', {
|
workorders_values_str = [0, '', {
|
||||||
@@ -333,6 +333,7 @@ class ResMrpWorkOrder(models.Model):
|
|||||||
'name': route.route_workcenter_id.name,
|
'name': route.route_workcenter_id.name,
|
||||||
'processing_panel': k,
|
'processing_panel': k,
|
||||||
'routing_type': route.routing_type,
|
'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),
|
'workcenter_id': self.env['mrp.routing.workcenter'].get_workcenter(route.workcenter_ids.ids),
|
||||||
'date_planned_start': False,
|
'date_planned_start': False,
|
||||||
'date_planned_finished': False,
|
'date_planned_finished': False,
|
||||||
@@ -411,11 +412,12 @@ class CNCprocessing(models.Model):
|
|||||||
workorder_id = fields.Many2one('mrp.workorder', string="工单")
|
workorder_id = fields.Many2one('mrp.workorder', string="工单")
|
||||||
|
|
||||||
# mrs下发编程单创建CNC加工
|
# mrs下发编程单创建CNC加工
|
||||||
def cnc_processing_create(self, obj):
|
def cnc_processing_create(self, cnc_workorder, ret):
|
||||||
workorder = self.env['mrp.workorder'].search([('production_id.name', '=', obj['production_order_no']),
|
for obj in ret['programming_list']:
|
||||||
|
workorder = self.env['mrp.workorder'].search([('production_id.name', '=', ret['production_order_no']),
|
||||||
('processing_panel', '=', obj['processing_panel']),
|
('processing_panel', '=', obj['processing_panel']),
|
||||||
('routing_type', '=', 'CNC加工')])
|
('routing_type', '=', 'CNC加工')])
|
||||||
vals = {
|
cnc_processing = self.env['sf.cnc.processing'].create({
|
||||||
'workorder_id': workorder.id,
|
'workorder_id': workorder.id,
|
||||||
'sequence_number': obj['sequence_number'],
|
'sequence_number': obj['sequence_number'],
|
||||||
'program_name': obj['program_name'],
|
'program_name': obj['program_name'],
|
||||||
@@ -429,8 +431,33 @@ class CNCprocessing(models.Model):
|
|||||||
'cutting_tool_handle_type': obj['cutting_tool_handle_type'],
|
'cutting_tool_handle_type': obj['cutting_tool_handle_type'],
|
||||||
'estimated_processing_time': obj['estimated_processing_time'],
|
'estimated_processing_time': obj['estimated_processing_time'],
|
||||||
'remark': obj['remark']
|
'remark': obj['remark']
|
||||||
}
|
})
|
||||||
return self.env['sf.cnc.processing'].create(vals)
|
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文件)
|
# 创建附件(nc文件)
|
||||||
def attachment_create(self, name, data):
|
def attachment_create(self, name, data):
|
||||||
@@ -443,38 +470,26 @@ class CNCprocessing(models.Model):
|
|||||||
return attachment
|
return attachment
|
||||||
|
|
||||||
# 将FTP的nc文件下载到临时目录
|
# 将FTP的nc文件下载到临时目录
|
||||||
def download_file_tmp(self, model_code, processing_panel):
|
def download_file_tmp(self, production_no, processing_panel):
|
||||||
remotepath = os.path.join('/', model_code, 'return', processing_panel)
|
remotepath = os.path.join('/', production_no, 'return', processing_panel)
|
||||||
serverdir = os.path.join('/tmp', model_code, 'return', processing_panel)
|
serverdir = os.path.join('/tmp', production_no, 'return', processing_panel)
|
||||||
ftp = FtpController()
|
ftp_resconfig = self.env['res.config.settings'].get_values()
|
||||||
ftp.download_file_tree(remotepath, serverdir)
|
ftp = FtpController(str(ftp_resconfig['ftp_host']), int(ftp_resconfig['ftp_port']), ftp_resconfig['ftp_user'],
|
||||||
return serverdir
|
ftp_resconfig['ftp_password'])
|
||||||
|
download_state = ftp.download_file_tree(remotepath, serverdir)
|
||||||
|
return download_state
|
||||||
|
|
||||||
# 将nc文件存到attach的datas里
|
# 将nc文件存到attach的datas里
|
||||||
def write_file(self, nc_file_path, cnc):
|
def write_file(self, nc_file_path, cnc):
|
||||||
if os.path.exists(nc_file_path):
|
if os.path.exists(nc_file_path):
|
||||||
with open(nc_file_path, 'rb') as file:
|
with open(nc_file_path, 'rb') as file:
|
||||||
data_bytes = file.read()
|
data_bytes = file.read()
|
||||||
attachment = self.attachment_create(cnc.program_name + '.NC', data_bytes)
|
attachment = self.attachment_create(cnc.program_name, data_bytes)
|
||||||
cnc.write({'cnc_id': attachment.id})
|
cnc.write({'cnc_id': attachment.id})
|
||||||
file.close()
|
file.close()
|
||||||
else:
|
else:
|
||||||
return False
|
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):
|
class SfWorkOrderBarcodes(models.Model):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import base64
|
import base64
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
from odoo import api, fields, models, SUPERUSER_ID, _
|
from odoo import api, fields, models, SUPERUSER_ID, _
|
||||||
from pystrich.code128 import Code128Encoder
|
#from pystrich.code128 import Code128Encoder
|
||||||
|
|
||||||
|
|
||||||
class Tray(models.Model):
|
class Tray(models.Model):
|
||||||
@@ -20,41 +20,6 @@ class Tray(models.Model):
|
|||||||
def updateTrayState(self):
|
def updateTrayState(self):
|
||||||
|
|
||||||
if self.workorder_id != False:
|
if self.workorder_id != False:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.state = '占用'
|
self.state = '占用'
|
||||||
else:
|
else:
|
||||||
self.state = '空闲'
|
self.state = '空闲'
|
||||||
|
|||||||
@@ -107,7 +107,7 @@
|
|||||||
</xpath>
|
</xpath>
|
||||||
|
|
||||||
<xpath expr="//field[@name='alternative_workcenter_ids']" position="after">
|
<xpath expr="//field[@name='alternative_workcenter_ids']" position="after">
|
||||||
<field name="machine_tool_id"/>
|
<field name="machine_tool_id" domain="[('is_binding', '=', False)]"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -12,32 +12,21 @@
|
|||||||
<field name="name" position="after">
|
<field name="name" position="after">
|
||||||
<field name="processing_panel"/>
|
<field name="processing_panel"/>
|
||||||
</field>
|
</field>
|
||||||
|
<field name="state" position="after">
|
||||||
|
<field name="work_state"/>
|
||||||
|
</field>
|
||||||
<xpath expr="//button[@name='button_start']" position="attributes">
|
<xpath expr="//button[@name='button_start']" position="attributes">
|
||||||
<attribute name="attrs">{'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done',
|
<attribute name="attrs">{'invisible': ['|', '|', '|','|', ('production_state','in', ('draft', 'done',
|
||||||
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
|
'cancel')), ('working_state', '=', 'blocked'), ('state', 'in', ('done', 'cancel')),
|
||||||
('is_user_working', '!=', False),("user_permissions","=",False)]}
|
('is_user_working', '!=', False),("user_permissions","=",False)]}
|
||||||
</attribute>
|
</attribute>
|
||||||
</xpath>
|
</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"-->
|
<!-- <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)]}"/>-->
|
<!-- 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"-->
|
<!-- <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)]}"/>-->
|
<!-- 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"-->
|
<!-- <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)]}"/>-->
|
<!-- 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">
|
<tree position="attributes">
|
||||||
<attribute name="multi_edit"></attribute>
|
<attribute name="multi_edit"></attribute>
|
||||||
<attribute name="editable"></attribute>
|
<attribute name="editable"></attribute>
|
||||||
@@ -95,11 +84,20 @@
|
|||||||
|
|
||||||
<xpath expr="//page[last()]" position="after">
|
<xpath expr="//page[last()]" position="after">
|
||||||
<page string="获取CNC加工程序" attrs='{"invisible": [("routing_type","!=","获取CNC加工程序")]}'>
|
<page string="获取CNC加工程序" attrs='{"invisible": [("routing_type","!=","获取CNC加工程序")]}'>
|
||||||
|
<group>
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<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程序代码"
|
<button type="object" class="oe_highlight" name="fetchCNC" string="获取CNC程序代码"
|
||||||
attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
|
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>
|
</div>
|
||||||
|
</group>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
</xpath>
|
</xpath>
|
||||||
@@ -109,13 +107,11 @@
|
|||||||
<field name="routing_type" invisible="1"/>
|
<field name="routing_type" invisible="1"/>
|
||||||
<field name="processing_panel" readonly="1"/>
|
<field name="processing_panel" readonly="1"/>
|
||||||
<field name="tray_code"/>
|
<field name="tray_code"/>
|
||||||
<field name="tray_id" readonly="1"/>
|
|
||||||
|
|
||||||
</group>
|
</group>
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<div class="col-12 col-lg-6 o_setting_box">
|
||||||
<button type="object" class="oe_highlight" name="gettray" string="绑定托盘"
|
<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>
|
</div>
|
||||||
</page>
|
</page>
|
||||||
|
|
||||||
@@ -226,7 +222,7 @@
|
|||||||
|
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<div class="col-12 col-lg-6 o_setting_box">
|
||||||
<button type="object" class="oe_highlight" name="getcenter" string="计算定位"
|
<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>
|
</div>
|
||||||
|
|
||||||
<group>
|
<group>
|
||||||
@@ -268,7 +264,7 @@
|
|||||||
</group>
|
</group>
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<div class="col-12 col-lg-6 o_setting_box">
|
||||||
<button type="object" class="oe_highlight" name="recreateManufacturingOrWorkerOrder"
|
<button type="object" class="oe_highlight" name="recreateManufacturingOrWorkerOrder"
|
||||||
string="检测确认" attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
|
string="检测确认" attrs='{"invisible": [("user_permissions","=",False)]}'/>
|
||||||
</div>
|
</div>
|
||||||
</page>
|
</page>
|
||||||
</xpath>
|
</xpath>
|
||||||
@@ -277,11 +273,11 @@
|
|||||||
|
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<div class="col-12 col-lg-6 o_setting_box">
|
||||||
<button type="object" class="oe_highlight" name="unbindtray" string="解除装夹"
|
<button type="object" class="oe_highlight" name="unbindtray" string="解除装夹"
|
||||||
attrs='{"invisible": ["|",("state","!=","progress"),("user_permissions","=",False)]}'/>
|
attrs='{"invisible": [("user_permissions","=",False)]}'/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<div class="col-12 col-lg-6 o_setting_box">
|
||||||
<button type="action" class="oe_highlight" name="sf_manufacturing.label_sf_tray_code1"
|
<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>
|
</div>
|
||||||
|
|
||||||
</page>
|
</page>
|
||||||
|
|||||||
@@ -20,44 +20,55 @@ class Sf_Mrs_Connect(http.Controller):
|
|||||||
"""
|
"""
|
||||||
logging.info('get_cnc_processing_create:%s' % kw)
|
logging.info('get_cnc_processing_create:%s' % kw)
|
||||||
try:
|
try:
|
||||||
|
res = {'status': 1, 'message': '成功'}
|
||||||
datas = request.httprequest.data
|
datas = request.httprequest.data
|
||||||
ret = json.loads(datas)
|
ret = json.loads(datas)
|
||||||
ret = json.loads(ret['result'])
|
ret = json.loads(ret['result'])
|
||||||
for obj in ret:
|
# 查询状态为进行中且类型为获取CNC加工程序的工单
|
||||||
cnc = request.env['sf.cnc.processing'].with_user(
|
cnc_workorder = self.env['mrp.workorder'].search([('production_id.name', '=', ret['production_order_no']),
|
||||||
request.env.ref("base.user_admin")).cnc_processing_create(obj)
|
('routing_type', '=', '获取CNC加工程序')])
|
||||||
# # 从ftp拉取对应的文件
|
if cnc_workorder:
|
||||||
model_code = cnc.workorder_id.product_id.barcode
|
# 拉取所有加工面的程序文件
|
||||||
processing_panel = cnc.workorder_id.processing_panel
|
# i = 1
|
||||||
logging.info('model_code:%s' % model_code)
|
for r in ret['processing_panel']:
|
||||||
server_dir = cnc.with_user(request.env.ref("base.user_admin")).download_file_tmp(model_code,
|
download_state = request.env['sf.cnc.processing'].with_user(
|
||||||
processing_panel)
|
request.env.ref("base.user_admin")).download_file_tmp(
|
||||||
# cnc_file_path = os.path.join('/', server_dir, cnc.program_name + '.nc')
|
ret['folder_name'], r)
|
||||||
# logging.info('cnc_file_path:%s' % cnc_file_path)
|
logging.info('download_state:%s' % download_state)
|
||||||
# cnc.with_user(request.env.ref("base.user_admin")).write_file(cnc_file_path, cnc)
|
# i += 1
|
||||||
logging.info('server_dir:%s' % server_dir)
|
if download_state == False:
|
||||||
for root, dirs, files in os.walk(server_dir):
|
res = {'status': -2, 'message': 'cnc文件拉取失败'}
|
||||||
for f in files:
|
return json.JSONEncoder().encode(res)
|
||||||
logging.info('f:%s' % f)
|
request.env['sf.cnc.processing'].with_user(
|
||||||
logging.info('f[0]:%s' % f.split('.')[0])
|
request.env.ref("base.user_admin")).cnc_processing_create(ret)
|
||||||
if os.path.splitext(f)[1] == ".pdf":
|
return json.JSONEncoder().encode(res)
|
||||||
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:
|
else:
|
||||||
logging.info('break:%s' % 'break')
|
res = {'status': 0, 'message': '该制造订单暂未开始'}
|
||||||
continue
|
return json.JSONEncoder().encode(res)
|
||||||
else:
|
except Exception as e:
|
||||||
logging.info('cnc.program_name:%s' % cnc.program_name)
|
res = {'status': -1, 'message': '系统解析失败'}
|
||||||
if cnc.program_name == f.split('.')[0]:
|
logging.info('get_cnc_processing_create error:%s' % e)
|
||||||
logging.info('f[0]:%s' % f[0])
|
return json.JSONEncoder().encode(res)
|
||||||
cnc_file_path = os.path.join(server_dir, root, f)
|
|
||||||
logging.info('cnc_file_path:%s' % cnc_file_path)
|
@http.route('/api/cnc_processing/update_state', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False,
|
||||||
cnc.with_user(request.env.ref("base.user_admin")).write_file(cnc_file_path, cnc)
|
cors="*")
|
||||||
else:
|
def get_cnc_processing_state(self, **kw):
|
||||||
continue
|
"""
|
||||||
|
获取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:
|
except Exception as e:
|
||||||
|
res = {'status': -1, 'message': '系统解析失败'}
|
||||||
logging.info('get_cnc_processing_create error:%s' % e)
|
logging.info('get_cnc_processing_create error:%s' % e)
|
||||||
|
return json.JSONEncoder().encode(res)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class FtpController():
|
|||||||
|
|
||||||
ftp = FTP()
|
ftp = FTP()
|
||||||
|
|
||||||
def __init__(self, host="192.168.50.202", port=21, username="ftpuser", password="123456"):
|
def __init__(self, host, port, username, password):
|
||||||
try:
|
try:
|
||||||
self.ftp.connect(host, port)
|
self.ftp.connect(host, port)
|
||||||
self.ftp.login(username, password)
|
self.ftp.login(username, password)
|
||||||
@@ -34,7 +34,7 @@ class FtpController():
|
|||||||
if file.find(".") != -1:
|
if file.find(".") != -1:
|
||||||
self.download_file(server, file)
|
self.download_file(server, file)
|
||||||
else:
|
else:
|
||||||
return
|
return False
|
||||||
|
|
||||||
# 下载指定目录下的指定文件
|
# 下载指定目录下的指定文件
|
||||||
def download_file(self, serverfile, remotefile):
|
def download_file(self, serverfile, remotefile):
|
||||||
|
|||||||
@@ -14,6 +14,10 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
token = fields.Char(string='TOKEN', default='b811ac06-3f00-11ed-9aed-0242ac110003')
|
token = fields.Char(string='TOKEN', default='b811ac06-3f00-11ed-9aed-0242ac110003')
|
||||||
sf_secret_key = fields.Char(string='密钥', default='wBmxej38OkErKhD6')
|
sf_secret_key = fields.Char(string='密钥', default='wBmxej38OkErKhD6')
|
||||||
sf_url = fields.Char(string='访问地址', default='https://sf.cs.jikimo.com')
|
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):
|
def sf_all_sync(self):
|
||||||
self.env['sf.production.materials'].sync_all_production_materials()
|
self.env['sf.production.materials'].sync_all_production_materials()
|
||||||
@@ -40,8 +44,6 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
_logger.info("同步资源库刀具")
|
_logger.info("同步资源库刀具")
|
||||||
# self.env['sf.processing.order'].sync_all_processing_order()
|
# self.env['sf.processing.order'].sync_all_processing_order()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def get_values(self):
|
def get_values(self):
|
||||||
"""
|
"""
|
||||||
@@ -53,11 +55,19 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
token = config.get_param('token', default='')
|
token = config.get_param('token', default='')
|
||||||
sf_secret_key = config.get_param('sf_secret_key', default='')
|
sf_secret_key = config.get_param('sf_secret_key', default='')
|
||||||
sf_url = config.get_param('sf_url', 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(
|
values.update(
|
||||||
token=token,
|
token=token,
|
||||||
sf_secret_key=sf_secret_key,
|
sf_secret_key=sf_secret_key,
|
||||||
sf_url=sf_url,
|
sf_url=sf_url,
|
||||||
|
ftp_host=ftp_host,
|
||||||
|
ftp_port=ftp_port,
|
||||||
|
ftp_user=ftp_user,
|
||||||
|
ftp_password=ftp_password
|
||||||
)
|
)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
@@ -67,4 +77,7 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
ir_config.set_param("token", self.token or "")
|
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_secret_key", self.sf_secret_key or "")
|
||||||
ir_config.set_param("sf_url", self.sf_url 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 "")
|
||||||
|
|||||||
@@ -14,25 +14,52 @@
|
|||||||
<div class="o_setting_left_pane"/>
|
<div class="o_setting_left_pane"/>
|
||||||
<div class="o_setting_right_pane">
|
<div class="o_setting_right_pane">
|
||||||
<div class="text-muted">
|
<div class="text-muted">
|
||||||
<label for="token"/>
|
<label for="sf_url"/>
|
||||||
|
<field name="sf_url"/>
|
||||||
|
</div>
|
||||||
|
<div class="text-muted">
|
||||||
|
<label for="token" string="Token"/>
|
||||||
<field name="token"/>
|
<field name="token"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-muted">
|
<div class="text-muted">
|
||||||
<label for="sf_secret_key"/>
|
<label for="sf_secret_key"/>
|
||||||
<field name="sf_secret_key"/>
|
<field name="sf_secret_key"/>
|
||||||
</div>
|
|
||||||
<div class="text-muted">
|
|
||||||
<label for="sf_url"/>
|
|
||||||
<field name="sf_url"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 col-lg-6 o_setting_box">
|
<div class="col-12 col-lg-6 o_setting_box">
|
||||||
<button type="object" class="oe_highlight" name="sf_all_sync" string="同步资源库所有基础数据"
|
<button type="object" class="oe_highlight" name="sf_all_sync"
|
||||||
|
string="同步资源库基础数据"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</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">
|
||||||
|
<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>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ class ReSaleOrder(models.Model):
|
|||||||
product.model_machining_precision,
|
product.model_machining_precision,
|
||||||
product.materials_id.name),
|
product.materials_id.name),
|
||||||
'price_unit': product.list_price,
|
'price_unit': product.list_price,
|
||||||
'route_id': product.route_ids,
|
|
||||||
'product_uom_qty': item['number']
|
'product_uom_qty': item['number']
|
||||||
}
|
}
|
||||||
return self.env['sale.order.line'].create(vals)
|
return self.env['sale.order.line'].create(vals)
|
||||||
|
|||||||
Reference in New Issue
Block a user