Merge branch 'develop' of https://e.coding.net/jikimo-hn/jikimo_sfs/jikimo_sf into feature/刀具管理加粗字段调整及界面布局优化
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['account', 'base', 'mrp_workorder'],
|
'depends': ['account', 'base', 'mrp_workorder','sale'],
|
||||||
'data': [
|
'data': [
|
||||||
'security/group_security.xml',
|
'security/group_security.xml',
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
|
|||||||
@@ -7,3 +7,5 @@ from . import functional_fixture
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -312,6 +312,7 @@ class MachineToolType(models.Model):
|
|||||||
machine_tool_type_ids = []
|
machine_tool_type_ids = []
|
||||||
for item in machine_tool_type_code:
|
for item in machine_tool_type_code:
|
||||||
machine_tool_type = self.search([('code', '=', item)])
|
machine_tool_type = self.search([('code', '=', item)])
|
||||||
|
if machine_tool_type:
|
||||||
machine_tool_type_ids.append(machine_tool_type.id)
|
machine_tool_type_ids.append(machine_tool_type.id)
|
||||||
return [(6, 0, machine_tool_type_ids)]
|
return [(6, 0, machine_tool_type_ids)]
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ class FixtureModel(models.Model):
|
|||||||
_name = 'sf.fixture.model'
|
_name = 'sf.fixture.model'
|
||||||
_description = "夹具型号"
|
_description = "夹具型号"
|
||||||
|
|
||||||
code = fields.Char(string='编码')
|
|
||||||
name = fields.Char(string="名称", size=15)
|
name = fields.Char(string="名称", size=15)
|
||||||
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", )
|
fixture_material_id = fields.Many2one('sf.fixture.material', string="夹具物料", )
|
||||||
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name', store=True)
|
fixture_material_type = fields.Char(string="夹具物料类型", related='fixture_material_id.name', store=True)
|
||||||
@@ -53,10 +52,38 @@ class FixtureModel(models.Model):
|
|||||||
screw_size = fields.Integer(string="螺牙大小[mm]", size=6)
|
screw_size = fields.Integer(string="螺牙大小[mm]", size=6)
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
# @api.model
|
def _get_code(self, fixture_model_type_code):
|
||||||
# def create(self, vals):
|
fixture_model = self.env['sf.fixture.model'].sudo().search(
|
||||||
# obj = super(FixtureModel, self).create(vals)
|
[('code', 'ilike', fixture_model_type_code)],
|
||||||
# return obj
|
limit=1,
|
||||||
|
order="id desc")
|
||||||
|
if not fixture_model:
|
||||||
|
num = "%03d" % 1
|
||||||
|
else:
|
||||||
|
m = int(fixture_model.code[-3:]) + 1
|
||||||
|
num = "%03d" % m
|
||||||
|
return "%s%s" % (fixture_model_type_code, num)
|
||||||
|
|
||||||
|
code = fields.Char(string='编码', readonly=True)
|
||||||
|
|
||||||
|
def _onchange_fixture_material_id(self, fixture_material_id):
|
||||||
|
if fixture_material_id:
|
||||||
|
if fixture_material_id.name == "气动夹具":
|
||||||
|
code = self._get_code("JKM-C-JJWL-QDJJ-")
|
||||||
|
elif fixture_material_id.name == "转接板(锁板)夹具":
|
||||||
|
code = self._get_code("JKM-C-JJWL-ZJBJJ-")
|
||||||
|
elif fixture_material_id.name == "磁吸夹具":
|
||||||
|
code = self._get_code("JKM-C-JJWL-CXJJ-")
|
||||||
|
elif fixture_material_id.name == "虎钳夹具":
|
||||||
|
code = self._get_code("JKM-C-JJWL-HQJJ-")
|
||||||
|
else:
|
||||||
|
code = self._get_code("JKM-C-JJWL-LDKP-")
|
||||||
|
return code
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
obj = super(FixtureModel, self).create(vals)
|
||||||
|
if obj.fixture_material_id:
|
||||||
|
code = self._onchange_fixture_material_id(obj.fixture_material_id)
|
||||||
|
obj.code = code
|
||||||
|
return obj
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from odoo import fields, models, api
|
from odoo import fields, models, api
|
||||||
|
|
||||||
|
|
||||||
# from datetime import datetime
|
# from datetime import datetime
|
||||||
# from odoo.exceptions import ValidationError
|
# from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
@@ -95,7 +97,6 @@ class CuttingToolModel(models.Model):
|
|||||||
_description = '刀具型号'
|
_description = '刀具型号'
|
||||||
|
|
||||||
name = fields.Char('名称')
|
name = fields.Char('名称')
|
||||||
code = fields.Char('编码')
|
|
||||||
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', string='刀具物料')
|
cutting_tool_material_id = fields.Many2one('sf.cutting.tool.material', string='刀具物料')
|
||||||
cutting_tool_type = fields.Char(string="刀具物料类型", related='cutting_tool_material_id.name', store=True)
|
cutting_tool_type = fields.Char(string="刀具物料类型", related='cutting_tool_material_id.name', store=True)
|
||||||
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', string='刀具类型',
|
cutting_tool_type_id = fields.Many2one('sf.cutting.tool.type', string='刀具类型',
|
||||||
@@ -177,12 +178,43 @@ class CuttingToolModel(models.Model):
|
|||||||
)
|
)
|
||||||
active = fields.Boolean('有效', default=True)
|
active = fields.Boolean('有效', default=True)
|
||||||
|
|
||||||
# @api.model
|
def _get_code(self, cutting_tool_type_code):
|
||||||
# def create(self, vals):
|
cutting_tool_model = self.search(
|
||||||
# if vals.get('name', '/') == '/' or vals.get('name', '/') is False:
|
[('code', 'ilike', cutting_tool_type_code)],
|
||||||
# vals['name'] = '/'
|
limit=1,
|
||||||
# obj = super(CuttingToolModel, self).create(vals)
|
order="id desc")
|
||||||
# return obj
|
if not cutting_tool_model:
|
||||||
|
num = "%03d" % 1
|
||||||
|
else:
|
||||||
|
m = int(cutting_tool_model.code[-3:]) + 1
|
||||||
|
num = "%03d" % m
|
||||||
|
return "%s%s" % (cutting_tool_type_code, num)
|
||||||
|
|
||||||
|
code = fields.Char(string='编码', readonly=True)
|
||||||
|
|
||||||
|
def _onchange_cutting_tool_material_id(self, cutting_tool_material_id):
|
||||||
|
if cutting_tool_material_id:
|
||||||
|
if cutting_tool_material_id.name == "整体式刀具":
|
||||||
|
code = self._get_code("JKM-T-DJWL-ZTDJ-")
|
||||||
|
elif cutting_tool_material_id.name == "刀片":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DPIA-")
|
||||||
|
elif cutting_tool_material_id.name == "刀杆":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DGAN-")
|
||||||
|
elif cutting_tool_material_id.name == "刀盘":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DPAN-")
|
||||||
|
elif cutting_tool_material_id.name == "夹头":
|
||||||
|
code = self._get_code("JKM-T-DJWL-DJIA-")
|
||||||
|
else:
|
||||||
|
code = self._get_code("JKM-T-DJWL-DBIN-")
|
||||||
|
return code
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
obj = super(CuttingToolModel, self).create(vals)
|
||||||
|
if obj.cutting_tool_material_id:
|
||||||
|
code = self._onchange_cutting_tool_material_id(obj.cutting_tool_material_id)
|
||||||
|
obj.code = code
|
||||||
|
return obj
|
||||||
|
|
||||||
|
|
||||||
# 刀具类型
|
# 刀具类型
|
||||||
|
|||||||
@@ -15,20 +15,27 @@ div:has(.o_required_modifier)>label::before {
|
|||||||
vertical-align: top !important;
|
vertical-align: top !important;
|
||||||
font-size: 1.5rem !important;
|
font-size: 1.5rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.my-image div {
|
.my-image div {
|
||||||
width: 100px !important;
|
width: 110px !important;
|
||||||
height: 130px !important;
|
height: 110px !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.add_flex {
|
.add_flex {
|
||||||
|
padding: 5px 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
.maintenance_name {
|
.maintenance_name {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.o_kanban_renderer .o_kanban_record .o_kanban_record_has_image_fill .o_kanban_image_fill_left {
|
.o_kanban_renderer .o_kanban_record .o_kanban_record_has_image_fill .o_kanban_image_fill_left {
|
||||||
flex: unset !important;
|
flex: unset !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.o_kanban_renderer .o_kanban_record .o_kanban_record_bottom {
|
.o_kanban_renderer .o_kanban_record .o_kanban_record_bottom {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
display: inline !important;
|
display: inline !important;
|
||||||
@@ -37,3 +44,79 @@ div:has(.o_required_modifier)>label::before {
|
|||||||
td.o_required_modifier {
|
td.o_required_modifier {
|
||||||
display: table-cell !important;
|
display: table-cell !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.show_state {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
right: 8px;
|
||||||
|
margin: auto;
|
||||||
|
height: 34px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show_state > div {
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
border: 1px solid #000
|
||||||
|
}
|
||||||
|
|
||||||
|
.show_state > div:nth-child(2) {
|
||||||
|
border-top: none;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oe_kanban_card.kanban_color_2 {
|
||||||
|
background-color: #FF4343 !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oe_kanban_card.kanban_color_1 {
|
||||||
|
background-color: #27FEA9 !important;
|
||||||
|
opacity: 0.7;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.oe_kanban_card.kanban_color_3 {
|
||||||
|
background-color: rgb(255, 150, 0) !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.my-image img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color_1 {
|
||||||
|
background-color: #27FEA9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color_2 {
|
||||||
|
background-color: #FF4343;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color_3 {
|
||||||
|
background-color: rgb(255, 150, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.font_color_1 {
|
||||||
|
color: rgb(0, 183, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.font_color_2 {
|
||||||
|
color: #FF4343;
|
||||||
|
}
|
||||||
|
|
||||||
|
.font_color_3 {
|
||||||
|
color: rgb(255, 150, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_kanban_card_header_title {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.o_kanban_record_bottom {
|
||||||
|
font-family: '华文中宋';
|
||||||
|
//font-weight: bold;
|
||||||
|
}
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
<field name="code"/>
|
<field name="code"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="tag_ids" widget="many2many_tags" optional="hide"/>
|
<field name="tag_ids" widget="many2many_tags" optional="hide"/>
|
||||||
<field name="remark"/>
|
|
||||||
<field name="image_brand" widget="image"/>
|
<field name="image_brand" widget="image"/>
|
||||||
|
<field name="remark"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
@@ -95,8 +95,8 @@
|
|||||||
<field name="name" string="名称"/>
|
<field name="name" string="名称"/>
|
||||||
<field name="machine_tool_category"/>
|
<field name="machine_tool_category"/>
|
||||||
<field name="brand_id"/>
|
<field name="brand_id"/>
|
||||||
<field name="remark"/>
|
|
||||||
<field name="machine_tool_picture" widget="image"/>
|
<field name="machine_tool_picture" widget="image"/>
|
||||||
|
<field name="remark"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -229,7 +229,8 @@
|
|||||||
attrs='{"invisible": [("fixture_material_type","!=",("转接板(锁板)夹具"))]}'/>
|
attrs='{"invisible": [("fixture_material_type","!=",("转接板(锁板)夹具"))]}'/>
|
||||||
<field name="driving_way"
|
<field name="driving_way"
|
||||||
attrs='{"invisible": [("fixture_material_type","not in",("虎钳夹具","零点卡盘"))]}'/>
|
attrs='{"invisible": [("fixture_material_type","not in",("虎钳夹具","零点卡盘"))]}'/>
|
||||||
<field name="apply_machine_tool_type_ids" widget="many2many_tags" options="{'no_create': True}"
|
<field name="apply_machine_tool_type_ids" widget="many2many_tags"
|
||||||
|
options="{'no_create': True}"
|
||||||
attrs='{"invisible": [("fixture_material_type","!=",("零点卡盘"))]}'/>
|
attrs='{"invisible": [("fixture_material_type","!=",("零点卡盘"))]}'/>
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
|
|||||||
@@ -32,10 +32,10 @@
|
|||||||
name="功能夹具类型"
|
name="功能夹具类型"
|
||||||
sequence="3"
|
sequence="3"
|
||||||
/>
|
/>
|
||||||
<menuitem id="menu_sf_functional_fixture"
|
<!-- <menuitem id="menu_sf_functional_fixture"-->
|
||||||
parent="menu_sf_fixture"
|
<!-- parent="menu_sf_fixture"-->
|
||||||
action="sf_functional_fixture_view_act"
|
<!-- action="sf_functional_fixture_view_act"-->
|
||||||
name="功能夹具"
|
<!-- name="功能夹具"-->
|
||||||
sequence="4"
|
sequence="4"
|
||||||
/>
|
/>
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -109,13 +109,13 @@
|
|||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- 功能刀具 -->
|
<!-- 功能刀具 -->
|
||||||
<menuitem
|
<!-- <menuitem-->
|
||||||
id="menu_sf_functional_cutting_tool"
|
<!-- id="menu_sf_functional_cutting_tool"-->
|
||||||
parent="menu_sf_base"
|
<!-- parent="menu_sf_base"-->
|
||||||
name="功能刀具"
|
<!-- name="功能刀具"-->
|
||||||
sequence="3"
|
<!-- sequence="3"-->
|
||||||
action="action_sf_functional_cutting_tool"
|
<!-- action="action_sf_functional_cutting_tool"-->
|
||||||
/>
|
<!-- />-->
|
||||||
<!-- 刀具物料 -->
|
<!-- 刀具物料 -->
|
||||||
<menuitem
|
<menuitem
|
||||||
id="menu_sf_cutting_tool_material"
|
id="menu_sf_cutting_tool_material"
|
||||||
|
|||||||
@@ -70,13 +70,13 @@
|
|||||||
action="action_sf_cutting_tool"
|
action="action_sf_cutting_tool"
|
||||||
/>
|
/>
|
||||||
<!-- 功能刀具 -->
|
<!-- 功能刀具 -->
|
||||||
<menuitem
|
<!-- <menuitem-->
|
||||||
id="menu_sf_functional_cutting_tool"
|
<!-- id="menu_sf_functional_cutting_tool"-->
|
||||||
parent="menu_sf_cutting_tool"
|
<!-- parent="menu_sf_cutting_tool"-->
|
||||||
name="功能刀具"
|
<!-- name="功能刀具"-->
|
||||||
sequence="5"
|
<!-- sequence="5"-->
|
||||||
action="action_sf_functional_cutting_tool"
|
<!-- action="action_sf_functional_cutting_tool"-->
|
||||||
/>
|
<!-- />-->
|
||||||
<!-- 功能刀具类型 -->
|
<!-- 功能刀具类型 -->
|
||||||
<menuitem
|
<menuitem
|
||||||
id="menu_sf_functional_cutting_tool_model_type"
|
id="menu_sf_functional_cutting_tool_model_type"
|
||||||
@@ -85,5 +85,6 @@
|
|||||||
sequence="4"
|
sequence="4"
|
||||||
action="action_sf_functional_cutting_tool_model_type"
|
action="action_sf_functional_cutting_tool_model_type"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ class Http(models.AbstractModel):
|
|||||||
timestamp_str = int(time.time())
|
timestamp_str = int(time.time())
|
||||||
# 设置API接口请求时间,不能超过5秒
|
# 设置API接口请求时间,不能超过5秒
|
||||||
deltime = datetime.timedelta(seconds=5)
|
deltime = datetime.timedelta(seconds=5)
|
||||||
if abs(int(datas['HTTP_TIMESTAMP'])-timestamp_str) > deltime.seconds:
|
# if abs(int(datas['HTTP_TIMESTAMP'])-timestamp_str) > deltime.seconds:
|
||||||
raise AuthenticationError('请求已过期')
|
# raise AuthenticationError('请求已过期')
|
||||||
# 获得sha1_str加密字符串
|
# 获得sha1_str加密字符串
|
||||||
post_time = int(datas['HTTP_TIMESTAMP'])
|
post_time = int(datas['HTTP_TIMESTAMP'])
|
||||||
check_str = '%s%s%s' % (datas['HTTP_TOKEN'], post_time, factory_secret.sf_secret_key)
|
check_str = '%s%s%s' % (datas['HTTP_TOKEN'], post_time, factory_secret.sf_secret_key)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from . import product_template
|
# from . import product_template
|
||||||
from . import product_supplierinfo
|
from . import product_supplierinfo
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import hashlib
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
class ResProduct(models.Model):
|
# class ResProduct(models.Model):
|
||||||
_inherit = 'product.template'
|
# _inherit = 'product.template'
|
||||||
|
|
||||||
# image_1920 = fields.Image(related='cutting_tool_parameter_image', store=True,
|
# image_1920 = fields.Image(related='cutting_tool_parameter_image', store=True,
|
||||||
# domain=[('cutting_tool_parameter_image', '!=', False)])
|
# domain=[('cutting_tool_parameter_image', '!=', False)])
|
||||||
@@ -184,194 +184,6 @@ class ResProduct(models.Model):
|
|||||||
# if self.cutting_tool_parameter_nut <= 0:
|
# if self.cutting_tool_parameter_nut <= 0:
|
||||||
# raise ValueError('该产品中配对螺母不能为零,请确认并重新输入!')
|
# raise ValueError('该产品中配对螺母不能为零,请确认并重新输入!')
|
||||||
|
|
||||||
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')
|
|
||||||
|
|
||||||
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
|
|
||||||
def product_create(self, product_id, item, order_id, order_number, i):
|
|
||||||
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
|
||||||
copy_product_id.product_tmpl_id.active = True
|
|
||||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
|
||||||
attachment = self.attachment_create(item['model_name'], item['model_data'])
|
|
||||||
vals = {
|
|
||||||
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
|
||||||
'model_long': item['model_long'] + model_type.embryo_tolerance,
|
|
||||||
'model_width': item['model_width'] + model_type.embryo_tolerance,
|
|
||||||
'model_height': item['model_height'] + model_type.embryo_tolerance,
|
|
||||||
'model_volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
|
||||||
item['model_width'] + model_type.embryo_tolerance) * (
|
|
||||||
item['model_height'] + model_type.embryo_tolerance),
|
|
||||||
'product_model_type_id': model_type.id,
|
|
||||||
'model_processing_panel': 'R',
|
|
||||||
'model_machining_precision': item['model_machining_precision'],
|
|
||||||
'model_code': item['barcode'],
|
|
||||||
'length': item['model_long'],
|
|
||||||
'width': item['model_width'],
|
|
||||||
'height': item['model_height'],
|
|
||||||
'volume': item['model_long'] * item['model_width'] * item['model_height'],
|
|
||||||
'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
|
|
||||||
'model_name': attachment.name,
|
|
||||||
'upload_model_file': [(6, 0, [attachment.id])],
|
|
||||||
# 'tag_ids': [(6, 0, [t.id for t in account_template.tag_ids])],
|
|
||||||
# 'single_manufacturing': True,
|
|
||||||
# 'tracking': 'serial',
|
|
||||||
'list_price': item['price'],
|
|
||||||
# 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id,
|
|
||||||
'materials_id': self.env['sf.production.materials'].search(
|
|
||||||
[('materials_no', '=', item['texture_code'])]).id,
|
|
||||||
'materials_type_id': self.env['sf.materials.model'].search(
|
|
||||||
[('materials_no', '=', item['texture_type_code'])]).id,
|
|
||||||
# 'model_surface_process_ids': self.get_production_process_id(item['surface_process_code']),
|
|
||||||
'model_process_parameters_ids': self.get_process_parameters_id(item['process_parameters_code']),
|
|
||||||
'model_remark': item['remark'],
|
|
||||||
'default_code': '%s-%s' % (order_number, i),
|
|
||||||
# 'barcode': item['barcode'],
|
|
||||||
'active': True,
|
|
||||||
# 'route_ids': self._get_routes('')
|
|
||||||
}
|
|
||||||
copy_product_id.sudo().write(vals)
|
|
||||||
# product_id.product_tmpl_id.active = False
|
|
||||||
return copy_product_id
|
|
||||||
|
|
||||||
def _get_ids(self, param):
|
|
||||||
type_ids = []
|
|
||||||
if not param:
|
|
||||||
return []
|
|
||||||
for item in param:
|
|
||||||
type_ids.append(item.id)
|
|
||||||
return [(6, 0, type_ids)]
|
|
||||||
|
|
||||||
def get_process_parameters_id(self, process_parameters_code):
|
|
||||||
process_parameters_ids = []
|
|
||||||
for item in process_parameters_code:
|
|
||||||
process_parameters = self.env['sf.production.process.parameter'].search([('code', '=', item)])
|
|
||||||
process_parameters_ids.append(process_parameters.id)
|
|
||||||
return [(6, 0, process_parameters_ids)]
|
|
||||||
|
|
||||||
def attachment_create(self, name, data):
|
|
||||||
attachment = self.env['ir.attachment'].create({
|
|
||||||
'datas': base64.b64decode(data),
|
|
||||||
'type': 'binary',
|
|
||||||
'public': True,
|
|
||||||
'description': '模型文件',
|
|
||||||
'name': name
|
|
||||||
})
|
|
||||||
return attachment
|
|
||||||
|
|
||||||
# 创建坯料
|
|
||||||
def no_bom_product_create(self, product_id, item, order_id, route_type, i):
|
|
||||||
no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
|
||||||
no_bom_copy_product_id.product_tmpl_id.active = True
|
|
||||||
materials_id = self.env['sf.production.materials'].search(
|
|
||||||
[('materials_no', '=', item['texture_code'])])
|
|
||||||
materials_type_id = self.env['sf.materials.model'].search(
|
|
||||||
[('materials_no', '=', item['texture_type_code'])])
|
|
||||||
model_type = self.env['sf.model.type'].search([], limit=1)
|
|
||||||
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
|
||||||
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
|
||||||
vals = {
|
|
||||||
'name': '%s-%s-%s [%s %s-%s * %s * %s]' % ('R',
|
|
||||||
order_id.name, i, materials_id.name, materials_type_id.name,
|
|
||||||
item['model_long'] + model_type.embryo_tolerance,
|
|
||||||
item['model_width'] + model_type.embryo_tolerance,
|
|
||||||
item['model_height'] + model_type.embryo_tolerance),
|
|
||||||
'length': item['model_long'] + model_type.embryo_tolerance,
|
|
||||||
'width': item['model_width'] + model_type.embryo_tolerance,
|
|
||||||
'height': item['model_height'] + model_type.embryo_tolerance,
|
|
||||||
'volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
|
||||||
item['model_width'] + model_type.embryo_tolerance) * (
|
|
||||||
item['model_height'] + model_type.embryo_tolerance),
|
|
||||||
'embryo_model_type_id': model_type.id,
|
|
||||||
'list_price': item['price'],
|
|
||||||
'materials_id': materials_id.id,
|
|
||||||
'materials_type_id': materials_type_id.id,
|
|
||||||
'is_bfm': True,
|
|
||||||
# 'route_ids': self._get_routes(route_type),
|
|
||||||
# 'categ_id': self.env.ref('sf_dlm.product_category_embryo_sf').id,
|
|
||||||
# 'model_surface_process_id': self.env['sf.production.process'].search(
|
|
||||||
# [('process_encode', '=', item['surface_process_code'])]).id,
|
|
||||||
# 'model_process_parameters_id': self.env['sf.processing.technology'].search(
|
|
||||||
# [('process_encode', '=', item['process_parameters_code'])]).id,
|
|
||||||
'active': True
|
|
||||||
}
|
|
||||||
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
|
||||||
if route_type == 'subcontract' or route_type == 'purchase':
|
|
||||||
no_bom_copy_product_id.purchase_ok = True
|
|
||||||
no_bom_copy_product_id.seller_ids = [
|
|
||||||
(0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0})]
|
|
||||||
if route_type == 'subcontract':
|
|
||||||
partner = self.env['res.partner'].search([('id', '=', supplier.partner_id.id)])
|
|
||||||
partner.is_subcontractor = True
|
|
||||||
no_bom_copy_product_id.write(vals)
|
|
||||||
logging.info('no_bom_copy_product_id-vals:%s' % vals)
|
|
||||||
# product_id.product_tmpl_id.active = False
|
|
||||||
return no_bom_copy_product_id
|
|
||||||
|
|
||||||
@api.model_create_multi
|
|
||||||
def create(self, vals_list):
|
|
||||||
for vals in vals_list:
|
|
||||||
if vals.get('upload_model_file'):
|
|
||||||
if vals.get('is_bfm') is False and vals.get('categ_type') == '成品':
|
|
||||||
for item in vals['upload_model_file']:
|
|
||||||
logging.info('create-attachment:%s' % int(item[2][0]))
|
|
||||||
attachment = self.env['ir.attachment'].sudo().search([('id', '=', int(item[2][0]))])
|
|
||||||
base64_data = base64.b64encode(attachment.datas)
|
|
||||||
base64_datas = base64_data.decode('utf-8')
|
|
||||||
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
|
||||||
report_path = attachment._full_path(attachment.store_fname)
|
|
||||||
vals['model_file'] = self.transition_glb_file(report_path, model_code)
|
|
||||||
logging.info('create-model_file:%s' % len(vals['model_file']))
|
|
||||||
self._sanitize_vals(vals)
|
|
||||||
templates = super(ResProduct, self).create(vals_list)
|
|
||||||
if "create_product_product" not in self._context:
|
|
||||||
templates._create_variant_ids()
|
|
||||||
|
|
||||||
# This is needed to set given values to first variant after creation
|
|
||||||
for template, vals in zip(templates, vals_list):
|
|
||||||
related_vals = {}
|
|
||||||
for field_name in self._get_related_fields_variant_template():
|
|
||||||
if vals.get(field_name):
|
|
||||||
related_vals[field_name] = vals[field_name]
|
|
||||||
if related_vals:
|
|
||||||
template.write(related_vals)
|
|
||||||
return templates
|
|
||||||
|
|
||||||
@api.onchange('upload_model_file')
|
|
||||||
def onchange_model_file(self):
|
|
||||||
for item in self:
|
|
||||||
if item.upload_model_file:
|
|
||||||
if len(item.upload_model_file) > 1:
|
|
||||||
raise ValidationError('只允许上传一个文件')
|
|
||||||
manufacturing_order = self.env['mrp.production'].search([('product_id', '=', self.id)])
|
|
||||||
if manufacturing_order:
|
|
||||||
raise ValidationError('该产品已生成制造订单,无法进行修改')
|
|
||||||
file_attachment_id = item.upload_model_file[0]
|
|
||||||
# 附件路径
|
|
||||||
report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
|
|
||||||
base64_data = base64.b64encode(file_attachment_id.datas)
|
|
||||||
base64_datas = base64_data.decode('utf-8')
|
|
||||||
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
|
||||||
item.model_file = self.transition_glb_file(report_path, model_code)
|
|
||||||
|
|
||||||
# 将attach的datas内容转为glb文件
|
|
||||||
def transition_glb_file(self, report_path, code):
|
|
||||||
shapes = read_step_file(report_path)
|
|
||||||
output_file = os.path.join('/tmp', str(code) + '.stl')
|
|
||||||
write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
|
|
||||||
# 转化为glb
|
|
||||||
output_glb_file = os.path.join('/tmp', str(code) + '.glb')
|
|
||||||
util_path = get_resource_path('sf_dlm', 'static/util')
|
|
||||||
cmd = 'python3 %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
|
|
||||||
os.system(cmd)
|
|
||||||
# 转base64
|
|
||||||
with open(output_glb_file, 'rb') as fileObj:
|
|
||||||
image_data = fileObj.read()
|
|
||||||
base64_data = base64.b64encode(image_data)
|
|
||||||
return base64_data
|
|
||||||
|
|
||||||
# @api.onchange('cutting_tool_material_id')
|
# @api.onchange('cutting_tool_material_id')
|
||||||
# def _get_cutting_tool_material_info(self):
|
# def _get_cutting_tool_material_info(self):
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<field name="model">product.template</field>
|
<field name="model">product.template</field>
|
||||||
<field name="inherit_id" ref="sale.product_template_form_view"/>
|
<field name="inherit_id" ref="sale.product_template_form_view"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<field name="detailed_type" position="before">
|
<field name="list_price" position="before">
|
||||||
<field name='categ_type' invisible="1"/>
|
<field name='categ_type' invisible="1"/>
|
||||||
<field name="upload_model_file"
|
<field name="upload_model_file"
|
||||||
widget="many2many_binary"
|
widget="many2many_binary"
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
attrs="{'invisible': ['|','|', ('categ_type', '!=', '成品'),('categ_type', '=', False),('model_file', '=', False)]}"/>
|
attrs="{'invisible': ['|','|', ('categ_type', '!=', '成品'),('categ_type', '=', False),('model_file', '=', False)]}"/>
|
||||||
</field>
|
</field>
|
||||||
<field name="invoice_policy" position="after">
|
<field name="invoice_policy" position="after">
|
||||||
|
<!-- <field name='categ_id'/>-->
|
||||||
<field name='cutting_tool_type' invisible="1"/>
|
<field name='cutting_tool_type' invisible="1"/>
|
||||||
<field name="fixture_material_type" invisible="1"/>
|
<field name="fixture_material_type" invisible="1"/>
|
||||||
<field name="embryo_model_type_id" string="模型类型"
|
<field name="embryo_model_type_id" string="模型类型"
|
||||||
@@ -29,13 +30,18 @@
|
|||||||
attrs="{'invisible': ['|',('categ_type', '!=', '表面工艺'),('categ_type', '=', False)]}"/>
|
attrs="{'invisible': ['|',('categ_type', '!=', '表面工艺'),('categ_type', '=', False)]}"/>
|
||||||
<field name="cutting_tool_material_id" attrs="{'invisible': [('categ_type', '!=', '刀具')]}"/>
|
<field name="cutting_tool_material_id" attrs="{'invisible': [('categ_type', '!=', '刀具')]}"/>
|
||||||
<field name="cutting_tool_model_id"
|
<field name="cutting_tool_model_id"
|
||||||
|
context="{'default_cutting_tool_material_id': cutting_tool_material_id,'default_cutting_tool_type_id': cutting_tool_type_id}"
|
||||||
attrs="{'invisible': [('categ_type', '!=', '刀具')]}"
|
attrs="{'invisible': [('categ_type', '!=', '刀具')]}"
|
||||||
domain="[('cutting_tool_material_id','=',cutting_tool_material_id)]"/>
|
domain="[('cutting_tool_material_id','=',cutting_tool_material_id)]"/>
|
||||||
<field name="fixture_material_id" attrs="{'invisible': [('categ_type', '!=', '夹具')]}"/>
|
<field name="fixture_material_id" attrs="{'invisible': [('categ_type', '!=', '夹具')]}"/>
|
||||||
<field name="fixture_model_id" string="型号"
|
<field name="fixture_model_id" string="型号"
|
||||||
|
context="{'default_fixture_material_id': fixture_material_id,'default_multi_mounting_type_id': fixture_multi_mounting_type_id}"
|
||||||
attrs="{'invisible': [('categ_type', '!=', '夹具')]}"
|
attrs="{'invisible': [('categ_type', '!=', '夹具')]}"
|
||||||
domain="[('fixture_material_id','=',fixture_material_id)]"/>
|
domain="[('fixture_material_id','=',fixture_material_id)]"/>
|
||||||
</field>
|
</field>
|
||||||
|
<!-- <field name="categ_id" position="replace">-->
|
||||||
|
<!-- <field name='categ_id' invisible="1"/>-->
|
||||||
|
<!-- </field>-->
|
||||||
<xpath expr="//label[@for='volume']" position="before">
|
<xpath expr="//label[@for='volume']" position="before">
|
||||||
<label for="length" string="尺寸"
|
<label for="length" string="尺寸"
|
||||||
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
|
attrs="{'invisible':[('product_variant_count', '>', 1), ('is_product_variant', '=', False)]}"/>
|
||||||
|
|||||||
@@ -58,6 +58,14 @@ class SfSaintenanceStandards(models.Model):
|
|||||||
maintenance_standards = fields.Char('维保标准')
|
maintenance_standards = fields.Char('维保标准')
|
||||||
equipment_maintenance_standards_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准')
|
equipment_maintenance_standards_id = fields.Many2one('equipment.maintenance.standards', string='设备维保标准')
|
||||||
maintenance_request_id = fields.Many2one('maintenance.request', string='设备维保计划')
|
maintenance_request_id = fields.Many2one('maintenance.request', string='设备维保计划')
|
||||||
|
images = fields.One2many('maintenance.standard.image', 'standard_id', string='反馈图片')
|
||||||
|
|
||||||
|
|
||||||
|
class MaintenanceStandardImage(models.Model):
|
||||||
|
_name = 'maintenance.standard.image'
|
||||||
|
|
||||||
|
image = fields.Binary(string='维保图片')
|
||||||
|
standard_id = fields.Many2one('maintenance.standards', string='Standard')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ access_equipment_maintenance_standards,equipment_maintenance_standards,model_equ
|
|||||||
access_sf_maintenance_logs,sf_maintenance_logs,model_sf_maintenance_logs,base.group_user,1,1,1,1
|
access_sf_maintenance_logs,sf_maintenance_logs,model_sf_maintenance_logs,base.group_user,1,1,1,1
|
||||||
access_maintenance_equipment,maintenance_equipment,model_maintenance_equipment,base.group_user,1,1,1,1
|
access_maintenance_equipment,maintenance_equipment,model_maintenance_equipment,base.group_user,1,1,1,1
|
||||||
access_maintenance_standards,maintenance_standards,model_maintenance_standards,base.group_user,1,1,1,1
|
access_maintenance_standards,maintenance_standards,model_maintenance_standards,base.group_user,1,1,1,1
|
||||||
|
access_maintenance_standard_image,maintenance_standard_image,model_maintenance_standard_image,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
|
@@ -8,8 +8,10 @@
|
|||||||
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_form"/>
|
<field name="inherit_id" ref="maintenance.hr_equipment_request_view_form"/>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//button[@name='archive_equipment_request']" position="before">
|
<xpath expr="//button[@name='archive_equipment_request']" position="before">
|
||||||
<button name="confirm_maintenance" string="确认维保计划" type="object" class="btn-primary" attrs="{'invisible': [('stage_id', '!=', 1)]}" />
|
<button name="confirm_maintenance" string="确认维保计划" type="object" class="btn-primary"
|
||||||
<button name="confirm_maintenance_done" string="标记已完成" type="object" class="btn-primary" attrs="{'invisible': [('stage_id', '!=', 2)]}" />
|
attrs="{'invisible': [('stage_id', '!=', 1)]}"/>
|
||||||
|
<button name="confirm_maintenance_done" string="标记已完成" type="object" class="btn-primary"
|
||||||
|
attrs="{'invisible': [('stage_id', '!=', 2)]}"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='maintenance_type']" position="replace">
|
<xpath expr="//field[@name='maintenance_type']" position="replace">
|
||||||
<field name="sf_maintenance_type" widget="radio"/>
|
<field name="sf_maintenance_type" widget="radio"/>
|
||||||
@@ -21,9 +23,10 @@
|
|||||||
<notebook>
|
<notebook>
|
||||||
<page string="维保标准" attrs="{'invisible': [('equipment_maintenance_id', '=', False)]}">
|
<page string="维保标准" attrs="{'invisible': [('equipment_maintenance_id', '=', False)]}">
|
||||||
<field name="maintenance_standards" widget="ony2many">
|
<field name="maintenance_standards" widget="ony2many">
|
||||||
<tree editable="bottom">
|
<tree>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="maintenance_standards"/>
|
<field name="maintenance_standards"/>
|
||||||
|
<field name="images"/>
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|
||||||
@@ -66,5 +69,32 @@
|
|||||||
<field name="active" eval="False"/>
|
<field name="active" eval="False"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<!-- 维保项目表单视图-->
|
||||||
|
|
||||||
|
<record id="view_maintenance_standards_form" model="ir.ui.view">
|
||||||
|
<field name="name">maintenance.standards.form</field>
|
||||||
|
<field name="model">maintenance.standards</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="设备维保项目">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="maintenance_standards"/>
|
||||||
|
</group>
|
||||||
|
<notebook>
|
||||||
|
<page string="上传图片">
|
||||||
|
<field name="images" widget="one2many">
|
||||||
|
<tree editable="bottom">
|
||||||
|
<field name="image" widget="image" options="{'size': [100, 100], 'click enlarge': True}"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
@@ -284,12 +284,11 @@
|
|||||||
<field name="machine_tool_picture"/>
|
<field name="machine_tool_picture"/>
|
||||||
|
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
||||||
|
|
||||||
<xpath expr="//templates" position="inside">
|
<xpath expr="//templates" position="inside">
|
||||||
<t t-name="kanban-box">
|
<t t-name="kanban-box">
|
||||||
<div t-attf-class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record oe_kanban_card oe_kanban_global_click
|
<div t-attf-class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record oe_kanban_card oe_kanban_global_click">
|
||||||
#{record.state.raw_value == '正常' ? 'kanban_color_1' : ''}
|
|
||||||
#{record.state.raw_value == '故障' ? 'kanban_color_2' : ''}
|
|
||||||
#{record.state.raw_value == '不可用' ? 'kanban_color_3' : ''}">
|
|
||||||
|
|
||||||
<field name="machine_tool_picture" class="o_kanban_image_fill_left d-block my-image"
|
<field name="machine_tool_picture" class="o_kanban_image_fill_left d-block my-image"
|
||||||
preview_image="image_128" widget="image"/>
|
preview_image="image_128" widget="image"/>
|
||||||
@@ -305,6 +304,12 @@
|
|||||||
<field name="state_zc"/>
|
<field name="state_zc"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="o_kanban_record_bottom state_zc">
|
<div class="o_kanban_record_bottom state_zc">
|
||||||
|
<field name="technician_user_id"/>
|
||||||
|
</div>
|
||||||
|
<div class="o_kanban_record_bottom state_zc"
|
||||||
|
t-attf-class="#{record.state.raw_value == '正常' ? 'font_color_1' : ''}
|
||||||
|
#{record.state.raw_value == '故障' ? 'font_color_2' : ''}
|
||||||
|
#{record.state.raw_value == '不可用' ? 'font_color_3' : ''}">
|
||||||
<field name="state"/>
|
<field name="state"/>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="o_kanban_record_bottom">-->
|
<!-- <div class="o_kanban_record_bottom">-->
|
||||||
@@ -313,7 +318,12 @@
|
|||||||
<!-- <field name="supplier_id"/>-->
|
<!-- <field name="supplier_id"/>-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
</div>
|
</div>
|
||||||
|
<div class="show_state" t-attf-class="oe_kanban_global_click o_kanban_record_has_image_fill o_hr_kanban_record oe_kanban_card oe_kanban_global_click
|
||||||
|
">
|
||||||
|
<div t-attf-class="#{record.state.raw_value == '正常' ? 'color_1' : ''}"></div>
|
||||||
|
<div t-attf-class="#{record.state.raw_value == '故障' ? 'color_2' : ''}"></div>
|
||||||
|
<div t-attf-class="#{record.state.raw_value == '不可用' ? 'color_3' : ''}"></div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</t>
|
</t>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ class ResWorkcenter(models.Model):
|
|||||||
|
|
||||||
# 生产线显示
|
# 生产线显示
|
||||||
production_line_show = fields.Char(string='生产线')
|
production_line_show = fields.Char(string='生产线')
|
||||||
equipment_id = fields.Many2one('maintenance.equipment', string='设备')
|
|
||||||
machine_tool_id = fields.Many2one('sf.machine_tool', string='机床')
|
machine_tool_id = fields.Many2one('sf.machine_tool', string='机床')
|
||||||
production_line_id = fields.Many2one('sf.production.line', string='生产线')
|
production_line_id = fields.Many2one('sf.production.line', string='生产线')
|
||||||
is_process_outsourcing = fields.Boolean('工艺外协')
|
is_process_outsourcing = fields.Boolean('工艺外协')
|
||||||
@@ -19,6 +18,12 @@ class ResWorkcenter(models.Model):
|
|||||||
'maintenance.equipment', string="设备",
|
'maintenance.equipment', string="设备",
|
||||||
check_company=True)
|
check_company=True)
|
||||||
|
|
||||||
|
equipment_status = fields.Selection(
|
||||||
|
[("正常", "正常"), ("故障", "故障"), ("不可用", "不可用")],
|
||||||
|
string="设备状态", related='equipment_id.state')
|
||||||
|
|
||||||
|
equipment_image = fields.Binary('设备图片', related='equipment_id.machine_tool_picture')
|
||||||
|
|
||||||
# 查询工艺外协加工中心
|
# 查询工艺外协加工中心
|
||||||
def get_process_outsourcing_workcenter(self):
|
def get_process_outsourcing_workcenter(self):
|
||||||
outsourcing_workcenter = self.env['mrp.workcenter'].search([('is_process_outsourcing', '=', True)])
|
outsourcing_workcenter = self.env['mrp.workcenter'].search([('is_process_outsourcing', '=', True)])
|
||||||
|
|||||||
@@ -1,4 +1,12 @@
|
|||||||
from odoo import models, fields, api
|
from odoo import models, fields, api
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from odoo.modules import get_resource_path
|
||||||
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
|
import logging
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
class ResProductMo(models.Model):
|
class ResProductMo(models.Model):
|
||||||
@@ -318,8 +326,276 @@ class ResProductMo(models.Model):
|
|||||||
item.cutting_tool_blade_ids = False
|
item.cutting_tool_blade_ids = False
|
||||||
item.cutting_tool_handle_ids = False
|
item.cutting_tool_handle_ids = False
|
||||||
|
|
||||||
|
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')
|
||||||
|
|
||||||
|
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
|
||||||
|
def product_create(self, product_id, item, order_id, order_number, i):
|
||||||
|
copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||||
|
copy_product_id.product_tmpl_id.active = True
|
||||||
|
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||||
|
attachment = self.attachment_create(item['model_name'], item['model_data'])
|
||||||
|
vals = {
|
||||||
|
'name': '%s-%s-%s' % ('P', order_id.name, i),
|
||||||
|
'model_long': item['model_long'] + model_type.embryo_tolerance,
|
||||||
|
'model_width': item['model_width'] + model_type.embryo_tolerance,
|
||||||
|
'model_height': item['model_height'] + model_type.embryo_tolerance,
|
||||||
|
'model_volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||||
|
item['model_width'] + model_type.embryo_tolerance) * (
|
||||||
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
|
'product_model_type_id': model_type.id,
|
||||||
|
'model_processing_panel': 'R',
|
||||||
|
'model_machining_precision': item['model_machining_precision'],
|
||||||
|
'model_code': item['barcode'],
|
||||||
|
'length': item['model_long'],
|
||||||
|
'width': item['model_width'],
|
||||||
|
'height': item['model_height'],
|
||||||
|
'volume': item['model_long'] * item['model_width'] * item['model_height'],
|
||||||
|
'model_file': '' if not item['model_file'] else base64.b64decode(item['model_file']),
|
||||||
|
'model_name': attachment.name,
|
||||||
|
'upload_model_file': [(6, 0, [attachment.id])],
|
||||||
|
# 'tag_ids': [(6, 0, [t.id for t in account_template.tag_ids])],
|
||||||
|
# 'single_manufacturing': True,
|
||||||
|
# 'tracking': 'serial',
|
||||||
|
'list_price': item['price'],
|
||||||
|
# 'categ_id': self.env.ref('sf_dlm.product_category_finished_sf').id,
|
||||||
|
'materials_id': self.env['sf.production.materials'].search(
|
||||||
|
[('materials_no', '=', item['texture_code'])]).id,
|
||||||
|
'materials_type_id': self.env['sf.materials.model'].search(
|
||||||
|
[('materials_no', '=', item['texture_type_code'])]).id,
|
||||||
|
# 'model_surface_process_ids': self.get_production_process_id(item['surface_process_code']),
|
||||||
|
'model_process_parameters_ids': [(6, 0, [])] if not item.get('process_parameters_code') else self.get_process_parameters_id(item['process_parameters_code']),
|
||||||
|
'model_remark': item['remark'],
|
||||||
|
'default_code': '%s-%s' % (order_number, i),
|
||||||
|
# 'barcode': item['barcode'],
|
||||||
|
'active': True,
|
||||||
|
# 'route_ids': self._get_routes('')
|
||||||
|
}
|
||||||
|
copy_product_id.sudo().write(vals)
|
||||||
|
# product_id.product_tmpl_id.active = False
|
||||||
|
return copy_product_id
|
||||||
|
|
||||||
|
def _get_ids(self, param):
|
||||||
|
type_ids = []
|
||||||
|
if not param:
|
||||||
|
return []
|
||||||
|
for item in param:
|
||||||
|
type_ids.append(item.id)
|
||||||
|
return [(6, 0, type_ids)]
|
||||||
|
|
||||||
|
def get_process_parameters_id(self, process_parameters_code):
|
||||||
|
process_parameters_ids = []
|
||||||
|
for item in process_parameters_code:
|
||||||
|
process_parameters = self.env['sf.production.process.parameter'].search([('code', '=', item)])
|
||||||
|
process_parameters_ids.append(process_parameters.id)
|
||||||
|
return [(6, 0, process_parameters_ids)]
|
||||||
|
|
||||||
|
def attachment_create(self, name, data):
|
||||||
|
attachment = self.env['ir.attachment'].create({
|
||||||
|
'datas': base64.b64decode(data),
|
||||||
|
'type': 'binary',
|
||||||
|
'public': True,
|
||||||
|
'description': '模型文件',
|
||||||
|
'name': name
|
||||||
|
})
|
||||||
|
return attachment
|
||||||
|
|
||||||
|
# 创建坯料
|
||||||
|
def no_bom_product_create(self, product_id, item, order_id, route_type, i):
|
||||||
|
no_bom_copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy()
|
||||||
|
no_bom_copy_product_id.product_tmpl_id.active = True
|
||||||
|
materials_id = self.env['sf.production.materials'].search(
|
||||||
|
[('materials_no', '=', item['texture_code'])])
|
||||||
|
materials_type_id = self.env['sf.materials.model'].search(
|
||||||
|
[('materials_no', '=', item['texture_type_code'])])
|
||||||
|
model_type = self.env['sf.model.type'].search([], limit=1)
|
||||||
|
supplier = self.env['mrp.bom'].get_supplier(materials_type_id)
|
||||||
|
logging.info('no_bom_copy_product_supplier-vals:%s' % supplier)
|
||||||
|
vals = {
|
||||||
|
'name': '%s-%s-%s [%s %s-%s * %s * %s]' % ('R',
|
||||||
|
order_id.name, i, materials_id.name, materials_type_id.name,
|
||||||
|
item['model_long'] + model_type.embryo_tolerance,
|
||||||
|
item['model_width'] + model_type.embryo_tolerance,
|
||||||
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
|
'length': item['model_long'] + model_type.embryo_tolerance,
|
||||||
|
'width': item['model_width'] + model_type.embryo_tolerance,
|
||||||
|
'height': item['model_height'] + model_type.embryo_tolerance,
|
||||||
|
'volume': (item['model_long'] + model_type.embryo_tolerance) * (
|
||||||
|
item['model_width'] + model_type.embryo_tolerance) * (
|
||||||
|
item['model_height'] + model_type.embryo_tolerance),
|
||||||
|
'embryo_model_type_id': model_type.id,
|
||||||
|
'list_price': item['price'],
|
||||||
|
'materials_id': materials_id.id,
|
||||||
|
'materials_type_id': materials_type_id.id,
|
||||||
|
'is_bfm': True,
|
||||||
|
# 'route_ids': self._get_routes(route_type),
|
||||||
|
# 'categ_id': self.env.ref('sf_dlm.product_category_embryo_sf').id,
|
||||||
|
# 'model_surface_process_id': self.env['sf.production.process'].search(
|
||||||
|
# [('process_encode', '=', item['surface_process_code'])]).id,
|
||||||
|
# 'model_process_parameters_id': self.env['sf.processing.technology'].search(
|
||||||
|
# [('process_encode', '=', item['process_parameters_code'])]).id,
|
||||||
|
'active': True
|
||||||
|
}
|
||||||
|
# 外协和采购生成的坯料需要根据材料型号绑定供应商
|
||||||
|
if route_type == 'subcontract' or route_type == 'purchase':
|
||||||
|
no_bom_copy_product_id.purchase_ok = True
|
||||||
|
no_bom_copy_product_id.seller_ids = [
|
||||||
|
(0, 0, {'partner_id': supplier.partner_id.id, 'delay': 1.0})]
|
||||||
|
if route_type == 'subcontract':
|
||||||
|
partner = self.env['res.partner'].search([('id', '=', supplier.partner_id.id)])
|
||||||
|
partner.is_subcontractor = True
|
||||||
|
no_bom_copy_product_id.write(vals)
|
||||||
|
logging.info('no_bom_copy_product_id-vals:%s' % vals)
|
||||||
|
# product_id.product_tmpl_id.active = False
|
||||||
|
return no_bom_copy_product_id
|
||||||
|
|
||||||
|
@api.model_create_multi
|
||||||
|
def create(self, vals_list):
|
||||||
|
for vals in vals_list:
|
||||||
|
if vals.get('upload_model_file'):
|
||||||
|
if vals.get('is_bfm') is False and vals.get('categ_type') == '成品':
|
||||||
|
for item in vals['upload_model_file']:
|
||||||
|
logging.info('create-attachment:%s' % int(item[2][0]))
|
||||||
|
attachment = self.env['ir.attachment'].sudo().search([('id', '=', int(item[2][0]))])
|
||||||
|
base64_data = base64.b64encode(attachment.datas)
|
||||||
|
base64_datas = base64_data.decode('utf-8')
|
||||||
|
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
||||||
|
report_path = attachment._full_path(attachment.store_fname)
|
||||||
|
vals['model_file'] = self.transition_glb_file(report_path, model_code)
|
||||||
|
logging.info('create-model_file:%s' % len(vals['model_file']))
|
||||||
|
self._sanitize_vals(vals)
|
||||||
|
templates = super(ResProductMo, self).create(vals_list)
|
||||||
|
if "create_product_product" not in self._context:
|
||||||
|
templates._create_variant_ids()
|
||||||
|
|
||||||
|
# This is needed to set given values to first variant after creation
|
||||||
|
for template, vals in zip(templates, vals_list):
|
||||||
|
related_vals = {}
|
||||||
|
for field_name in self._get_related_fields_variant_template():
|
||||||
|
if vals.get(field_name):
|
||||||
|
related_vals[field_name] = vals[field_name]
|
||||||
|
if related_vals:
|
||||||
|
template.write(related_vals)
|
||||||
|
return templates
|
||||||
|
|
||||||
|
@api.onchange('upload_model_file')
|
||||||
|
def onchange_model_file(self):
|
||||||
|
for item in self:
|
||||||
|
if item.upload_model_file:
|
||||||
|
if len(item.upload_model_file) > 1:
|
||||||
|
raise ValidationError('只允许上传一个文件')
|
||||||
|
manufacturing_order = self.env['mrp.production'].search([('product_id', '=', self.id)])
|
||||||
|
if manufacturing_order:
|
||||||
|
raise ValidationError('该产品已生成制造订单,无法进行修改')
|
||||||
|
file_attachment_id = item.upload_model_file[0]
|
||||||
|
# 附件路径
|
||||||
|
report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
|
||||||
|
base64_data = base64.b64encode(file_attachment_id.datas)
|
||||||
|
base64_datas = base64_data.decode('utf-8')
|
||||||
|
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
||||||
|
item.model_file = self.transition_glb_file(report_path, model_code)
|
||||||
|
|
||||||
|
# 将attach的datas内容转为glb文件
|
||||||
|
def transition_glb_file(self, report_path, code):
|
||||||
|
shapes = read_step_file(report_path)
|
||||||
|
output_file = os.path.join('/tmp', str(code) + '.stl')
|
||||||
|
write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
|
||||||
|
# 转化为glb
|
||||||
|
output_glb_file = os.path.join('/tmp', str(code) + '.glb')
|
||||||
|
util_path = get_resource_path('sf_dlm', 'static/util')
|
||||||
|
cmd = 'python3 %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
|
||||||
|
os.system(cmd)
|
||||||
|
# 转base64
|
||||||
|
with open(output_glb_file, 'rb') as fileObj:
|
||||||
|
image_data = fileObj.read()
|
||||||
|
base64_data = base64.b64encode(image_data)
|
||||||
|
return base64_data
|
||||||
|
|
||||||
|
|
||||||
class ResMrpBomMo(models.Model):
|
class ResMrpBomMo(models.Model):
|
||||||
_inherit = 'mrp.bom'
|
_inherit = 'mrp.bom'
|
||||||
|
|
||||||
subcontractor_id = fields.Many2one('res.partner', string='外包商')
|
subcontractor_id = fields.Many2one('res.partner', string='外包商')
|
||||||
|
|
||||||
|
def bom_create_line_has(self, embryo):
|
||||||
|
vals = {
|
||||||
|
'bom_id': self.id,
|
||||||
|
'product_id': embryo.id,
|
||||||
|
'product_tmpl_id': embryo.product_tmpl_id.id,
|
||||||
|
'product_qty': 1,
|
||||||
|
'product_uom_id': 1
|
||||||
|
}
|
||||||
|
return self.env['mrp.bom.line'].create(vals)
|
||||||
|
|
||||||
|
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom
|
||||||
|
|
||||||
|
def bom_create(self, product, bom_type, product_type):
|
||||||
|
bom_id = self.env['mrp.bom'].create({
|
||||||
|
'product_tmpl_id': product.product_tmpl_id.id,
|
||||||
|
'type': bom_type,
|
||||||
|
# 'subcontractor_id': '' or subcontract.partner_id.id,
|
||||||
|
'product_qty': 1,
|
||||||
|
'product_uom_id': 1
|
||||||
|
})
|
||||||
|
if bom_type == 'subcontract' and product_type is not False:
|
||||||
|
subcontract = self.get_supplier(product.materials_type_id)
|
||||||
|
bom_id.subcontractor_id = subcontract.partner_id.id
|
||||||
|
return bom_id
|
||||||
|
|
||||||
|
# 坯料BOM组件:选取当前坯料原材料,
|
||||||
|
# 然后根据当前的坯料的体积得出需要的原材料重量(立方米m³) *材料密度 * 1000 = 所需原材料重量KG(公斤)
|
||||||
|
# 坯料所需原材料公式:当前的坯料的体积(立方米m³) *材料密度 * 1000 = 所需原材料重量KG(公斤)
|
||||||
|
|
||||||
|
def bom_create_line(self, embryo):
|
||||||
|
# 选取当前坯料原材料
|
||||||
|
raw_bom_line = self.get_raw_bom(embryo)
|
||||||
|
if raw_bom_line:
|
||||||
|
bom_line = self.env['mrp.bom.line'].create({
|
||||||
|
'bom_id': self.id,
|
||||||
|
'product_id': raw_bom_line.id,
|
||||||
|
'product_tmpl_id': raw_bom_line.product_tmpl_id.id,
|
||||||
|
'product_qty': round(embryo.volume * raw_bom_line.materials_type_id.density / 1000000),
|
||||||
|
'product_uom_id': raw_bom_line.uom_id.id,
|
||||||
|
})
|
||||||
|
return bom_line
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 查询材料型号默认排第一的供应商
|
||||||
|
|
||||||
|
def get_supplier(self, materials_type):
|
||||||
|
seller_id = self.env['sf.supplier.sort'].search(
|
||||||
|
[('materials_model_id', '=', materials_type.id)],
|
||||||
|
limit=1,
|
||||||
|
order='sequence asc')
|
||||||
|
return seller_id
|
||||||
|
|
||||||
|
# 匹配bom
|
||||||
|
|
||||||
|
def get_bom(self, product):
|
||||||
|
embryo_has = self.env['product.product'].search(
|
||||||
|
[('categ_id.type', '=', '坯料'), ('materials_type_id', '=', product.materials_type_id.id),
|
||||||
|
('length', '>', product.length), ('width', '>', product.width),
|
||||||
|
('height', '>', product.height), ('is_bfm', '=', False)
|
||||||
|
],
|
||||||
|
limit=1,
|
||||||
|
order='volume desc'
|
||||||
|
)
|
||||||
|
logging.info('get_bom-vals:%s' % embryo_has)
|
||||||
|
if embryo_has:
|
||||||
|
rate_of_waste = ((embryo_has.volume - product.model_volume) % embryo_has.volume) * 100
|
||||||
|
if rate_of_waste <= 20:
|
||||||
|
return embryo_has
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
# 查bom的原材料
|
||||||
|
|
||||||
|
def get_raw_bom(self, product):
|
||||||
|
raw_bom = self.env['product.product'].search(
|
||||||
|
[('categ_id.type', '=', '原材料'), ('materials_type_id', '=', product.materials_type_id.id)])
|
||||||
|
return raw_bom
|
||||||
|
|||||||
@@ -24,19 +24,28 @@
|
|||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
<!-- <record id="mrp_workcenter_view_kanban_inherit_workorder" model="ir.ui.view">-->
|
<record id="mrp_workcenter_view_kanban_inherit_workorder" model="ir.ui.view">
|
||||||
<!-- <field name="name">mrp.workcenter.view.kanban.inherit.mrp.workorder</field>-->
|
<field name="name">mrp.workcenter.view.kanban.inherit.mrp.workorder</field>
|
||||||
<!-- <field name="model">mrp.workcenter</field>-->
|
<field name="model">mrp.workcenter</field>
|
||||||
<!-- <field name="inherit_id" ref="mrp.mrp_workcenter_kanban"/>-->
|
<field name="inherit_id" ref="mrp.mrp_workcenter_kanban"/>
|
||||||
<!-- <field name="arch" type="xml">-->
|
<field name="arch" type="xml">
|
||||||
<!-- <!– Desktop view –>-->
|
<!-- Desktop view -->
|
||||||
<!-- <xpath expr="//div[@name='o_wo']" position="inside">-->
|
<xpath expr='(//field[@name="name"])[1]' position="after">
|
||||||
<!-- <button class="btn btn-secondary fa fa-desktop" name="action_work_order" type="object"-->
|
|
||||||
<!-- context="{'search_default_ready': 1, 'search_default_progress': 1, 'search_default_pending': 1, 'desktop_list_view': 1, 'search_default_workcenter_id': active_id}"-->
|
<field name="equipment_status" />
|
||||||
<!-- title="Work orders" aria-label="Work orders"/>-->
|
<field name="equipment_image" />
|
||||||
<!-- </xpath>-->
|
|
||||||
<!-- </field>-->
|
|
||||||
<!-- </record>-->
|
</xpath>
|
||||||
|
<xpath expr='(//field[@name="name"])[2]' position="after">
|
||||||
|
|
||||||
|
<field name="equipment_status" />
|
||||||
|
<field name="equipment_image" widget="image" />
|
||||||
|
|
||||||
|
|
||||||
|
</xpath>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
<!-- override to change the no content image -->
|
<!-- override to change the no content image -->
|
||||||
<record id="mrp.action_work_orders" model="ir.actions.act_window">
|
<record id="mrp.action_work_orders" model="ir.actions.act_window">
|
||||||
@@ -90,6 +99,7 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<xpath expr="//field[@name='company_id']" position="after">
|
<xpath expr="//field[@name='company_id']" position="after">
|
||||||
<field name="users_ids" widget="many2many_tags" string="可操作用户"/>
|
<field name="users_ids" widget="many2many_tags" string="可操作用户"/>
|
||||||
|
<field name="equipment_status"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
<xpath expr="//field[@name='alternative_workcenter_ids']" position="after">
|
<xpath expr="//field[@name='alternative_workcenter_ids']" position="after">
|
||||||
<field name="production_line_id"/>
|
<field name="production_line_id"/>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ 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')
|
||||||
|
bfm_url = fields.Char(string='业务平台后端访问地址', default='https://bfm.jikimo.com')
|
||||||
ftp_host = fields.Char(string='FTP的ip')
|
ftp_host = fields.Char(string='FTP的ip')
|
||||||
ftp_port = fields.Char(string='FTP端口')
|
ftp_port = fields.Char(string='FTP端口')
|
||||||
ftp_user = fields.Char(string='FTP用户')
|
ftp_user = fields.Char(string='FTP用户')
|
||||||
@@ -81,6 +82,7 @@ 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='')
|
||||||
|
bfm_url = config.get_param('bfm_url', default='')
|
||||||
ftp_host = config.get_param('ftp_host', default='')
|
ftp_host = config.get_param('ftp_host', default='')
|
||||||
ftp_port = config.get_param('ftp_port', default='')
|
ftp_port = config.get_param('ftp_port', default='')
|
||||||
ftp_user = config.get_param('ftp_user', default='')
|
ftp_user = config.get_param('ftp_user', default='')
|
||||||
@@ -90,6 +92,7 @@ class ResConfigSettings(models.TransientModel):
|
|||||||
token=token,
|
token=token,
|
||||||
sf_secret_key=sf_secret_key,
|
sf_secret_key=sf_secret_key,
|
||||||
sf_url=sf_url,
|
sf_url=sf_url,
|
||||||
|
bfm_url=bfm_url,
|
||||||
ftp_host=ftp_host,
|
ftp_host=ftp_host,
|
||||||
ftp_port=ftp_port,
|
ftp_port=ftp_port,
|
||||||
ftp_user=ftp_user,
|
ftp_user=ftp_user,
|
||||||
@@ -103,6 +106,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("bfm_url", self.bfm_url or "")
|
||||||
ir_config.set_param("ftp_host", self.ftp_host 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_port", self.ftp_port or "")
|
||||||
ir_config.set_param("ftp_user", self.ftp_user or "")
|
ir_config.set_param("ftp_user", self.ftp_user or "")
|
||||||
|
|||||||
@@ -1525,7 +1525,7 @@ class SyncFixtureModel(models.Model):
|
|||||||
[('materials_no', '=', item['materials_model_code'])]).id,
|
[('materials_no', '=', item['materials_model_code'])]).id,
|
||||||
"driving_way": item['driving_way'],
|
"driving_way": item['driving_way'],
|
||||||
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
||||||
item['apply_machine_tool_type_code']).id,
|
item['apply_machine_tool_type_code']),
|
||||||
"through_hole_size": item['through_hole_size'],
|
"through_hole_size": item['through_hole_size'],
|
||||||
"screw_size": item['screw_size'],
|
"screw_size": item['screw_size'],
|
||||||
"active": item['active'],
|
"active": item['active'],
|
||||||
@@ -1555,7 +1555,7 @@ class SyncFixtureModel(models.Model):
|
|||||||
[('materials_no', '=', item['materials_model_code'])]).id,
|
[('materials_no', '=', item['materials_model_code'])]).id,
|
||||||
"driving_way": item['driving_way'],
|
"driving_way": item['driving_way'],
|
||||||
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
||||||
item['apply_machine_tool_type_code']).id,
|
item['apply_machine_tool_type_code']),
|
||||||
"through_hole_size": item['through_hole_size'],
|
"through_hole_size": item['through_hole_size'],
|
||||||
"screw_size": item['screw_size'],
|
"screw_size": item['screw_size'],
|
||||||
"active": item['active'],
|
"active": item['active'],
|
||||||
@@ -1607,7 +1607,7 @@ class SyncFixtureModel(models.Model):
|
|||||||
[('materials_no', '=', item['materials_model_code'])]).id,
|
[('materials_no', '=', item['materials_model_code'])]).id,
|
||||||
"driving_way": item['driving_way'],
|
"driving_way": item['driving_way'],
|
||||||
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
||||||
item['apply_machine_tool_type_code']).id,
|
item['apply_machine_tool_type_code']),
|
||||||
"through_hole_size": item['through_hole_size'],
|
"through_hole_size": item['through_hole_size'],
|
||||||
"screw_size": item['screw_size'],
|
"screw_size": item['screw_size'],
|
||||||
"active": item['active'],
|
"active": item['active'],
|
||||||
@@ -1637,7 +1637,7 @@ class SyncFixtureModel(models.Model):
|
|||||||
[('materials_no', '=', item['materials_model_code'])]).id,
|
[('materials_no', '=', item['materials_model_code'])]).id,
|
||||||
"driving_way": item['driving_way'],
|
"driving_way": item['driving_way'],
|
||||||
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
"apply_machine_tool_type_ids": self.env['sf.machine_tool.type'].sudo()._get_ids(
|
||||||
item['apply_machine_tool_type_code']).id,
|
item['apply_machine_tool_type_code']),
|
||||||
"through_hole_size": item['through_hole_size'],
|
"through_hole_size": item['through_hole_size'],
|
||||||
"screw_size": item['screw_size'],
|
"screw_size": item['screw_size'],
|
||||||
"active": item['active'],
|
"active": item['active'],
|
||||||
|
|||||||
@@ -60,6 +60,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<h2>业务平台参数配置</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="bfm_url" string="访问地址"/>
|
||||||
|
<field name="bfm_url"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</xpath>
|
</xpath>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
|
|||||||
@@ -10,9 +10,12 @@
|
|||||||
""",
|
""",
|
||||||
'category': 'sf',
|
'category': 'sf',
|
||||||
'website': 'https://www.sf.jikimo.com',
|
'website': 'https://www.sf.jikimo.com',
|
||||||
'depends': ['sale', 'sale_management', 'web_widget_model_viewer'],
|
'depends': ['sale_management', 'web_widget_model_viewer',],
|
||||||
'data': [
|
'data': [
|
||||||
'views/sale_order_view.xml'
|
'security/group_security.xml',
|
||||||
|
'security/ir.model.access.csv',
|
||||||
|
'views/sale_order_view.xml',
|
||||||
|
'views/quick_easy_order_view.xml'
|
||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
from . import sale_order
|
from . import sale_order
|
||||||
|
from . import quick_easy_order
|
||||||
|
from . import auto_quatotion_common
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
37
sf_sale/models/auto_quatotion_common.py
Normal file
37
sf_sale/models/auto_quatotion_common.py
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import logging
|
||||||
|
from odoo.modules import get_resource_path
|
||||||
|
from odoo import fields, models, api
|
||||||
|
from quatotion import readSql, feature_recognize, auto_quatotion
|
||||||
|
|
||||||
|
__author__ = 'jinling.yang'
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AutoQuatotion(models.Model):
|
||||||
|
_name = 'sf.auto_quatotion.common'
|
||||||
|
_description = u'自动报价公用类'
|
||||||
|
|
||||||
|
# 获取feature.sqlite的地址
|
||||||
|
def get_feature_full_path(self):
|
||||||
|
return get_resource_path('sf_sale', 'models', 'feature.sqlite')
|
||||||
|
|
||||||
|
# 获取price.sqlite的地址
|
||||||
|
def get_price_full_path(self):
|
||||||
|
return get_resource_path('sf_sale', 'models', 'price.sqlite')
|
||||||
|
|
||||||
|
# 获取price.sqlite的地址
|
||||||
|
def get_process_time_db_path(self):
|
||||||
|
return get_resource_path('sf_sale', 'models', 'process_time.db')
|
||||||
|
|
||||||
|
def get_auto_quatotion(self, stp_url, feature_full_path, process_time_db_path, model_code):
|
||||||
|
'''
|
||||||
|
通过打包好的.so库,
|
||||||
|
以调用autoQuatotion库中Quatotion类,
|
||||||
|
初始化后调用类的analyseShape方法对模型文件进行价格预测
|
||||||
|
'''
|
||||||
|
# 初始化自动报价类(输入特征数据库和加工时间数据库)
|
||||||
|
reader = auto_quatotion.Quatotion(feature_full_path, process_time_db_path)
|
||||||
|
# 获取价格、加工时间、尺寸、XYZ、翻面次数
|
||||||
|
feature_info = reader.analyseShape(stp_url, InfoJson={})
|
||||||
|
return feature_info
|
||||||
BIN
sf_sale/models/feature.sqlite
Normal file
BIN
sf_sale/models/feature.sqlite
Normal file
Binary file not shown.
BIN
sf_sale/models/price.sqlite
Normal file
BIN
sf_sale/models/price.sqlite
Normal file
Binary file not shown.
BIN
sf_sale/models/process_time.db
Normal file
BIN
sf_sale/models/process_time.db
Normal file
Binary file not shown.
280
sf_sale/models/quick_easy_order.py
Normal file
280
sf_sale/models/quick_easy_order.py
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
from odoo import models, fields, api
|
||||||
|
from odoo.modules import get_resource_path
|
||||||
|
from OCC.Extend.DataExchange import read_step_file
|
||||||
|
from OCC.Extend.DataExchange import write_stl_file
|
||||||
|
from odoo.exceptions import ValidationError, UserError
|
||||||
|
from odoo.addons.sf_base.commons.common import Common
|
||||||
|
from datetime import datetime
|
||||||
|
import logging
|
||||||
|
import base64
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
|
||||||
|
class QuickEasyOrder(models.Model):
|
||||||
|
_name = 'quick.easy.order'
|
||||||
|
_description = '简易下单'
|
||||||
|
|
||||||
|
name = fields.Char('订单编号', default=lambda self: self.env['ir.sequence'].next_by_code('quick.easy.order'))
|
||||||
|
model_length = fields.Float('长(mm)', digits=(16, 3))
|
||||||
|
model_width = fields.Float('宽(mm)', digits=(16, 3))
|
||||||
|
model_height = fields.Float('高(mm)', digits=(16, 3))
|
||||||
|
model_volume = fields.Float('体积(mm³)', digits=(16, 3))
|
||||||
|
model_processing_side = fields.Char('加工面', default='A')
|
||||||
|
model_feature = fields.Char('特征')
|
||||||
|
machining_precision = fields.Selection([
|
||||||
|
('0.10', '±0.10mm'),
|
||||||
|
('0.05', '±0.05mm'),
|
||||||
|
('0.03', '±0.03mm'),
|
||||||
|
('0.02', '±0.02mm'),
|
||||||
|
('0.01', '±0.01mm')], string='加工精度', default='0.10')
|
||||||
|
material_id = fields.Many2one('sf.production.materials', '材料', compute='_compute_material_model', store=True)
|
||||||
|
material_model_id = fields.Many2one('sf.materials.model', '型号', compute='_compute_material_model', store=True)
|
||||||
|
process_id = fields.Many2one('sf.production.process', string='表面工艺')
|
||||||
|
parameter_ids = fields.One2many('sf.production.process.parameter', 'process_id', string='可选参数')
|
||||||
|
quantity = fields.Integer('数量', default=1)
|
||||||
|
unit_price = fields.Float('单价')
|
||||||
|
price = fields.Float('总价')
|
||||||
|
model_file = fields.Binary('模型文件')
|
||||||
|
upload_model_file = fields.Many2many('ir.attachment', 'upload_qf_model_file_attachment_ref', string='模型文件')
|
||||||
|
delivery_time = fields.Date('交货日期')
|
||||||
|
customer_id = fields.Many2one('res.partner', string='客户', default=lambda self: self.env.user.partner_id.id)
|
||||||
|
state = fields.Selection([('草稿', '草稿'), ('待付款', '待付款'), ('待派单', '待派单'),
|
||||||
|
('待接单', '待接单'), ('加工中', '加工中'),
|
||||||
|
('物流中', '物流中'), ('已交付', '已交付')], string='订单状态', default='草稿',
|
||||||
|
readonly=True)
|
||||||
|
model_color_state = fields.Selection([
|
||||||
|
('success', '成功'),
|
||||||
|
('fail', '失败')], string='模型上色状态')
|
||||||
|
|
||||||
|
@api.depends('material_id', 'material_model_id')
|
||||||
|
def _compute_material_model(self):
|
||||||
|
for item in self:
|
||||||
|
materials = self.env['sf.production.materials'].search([], limit=1, order='id desc')
|
||||||
|
item.material_id = materials.id
|
||||||
|
item.material_model_id = self.env['sf.materials.model'].search(
|
||||||
|
[('materials_id', '=', materials.id)],
|
||||||
|
limit=1, order='id desc')
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
if vals.get('upload_model_file'):
|
||||||
|
logging.info('create-attachment:%s' % vals['upload_model_file'][0])
|
||||||
|
for item in vals['upload_model_file']:
|
||||||
|
print(len(item[2]))
|
||||||
|
if len(item[2]) > 0:
|
||||||
|
logging.info('create-attachment:%s' % int(item[2][0]))
|
||||||
|
attachment = self.env['ir.attachment'].sudo().search([('id', '=', int(item[2][0]))])
|
||||||
|
base64_data = base64.b64encode(attachment.datas)
|
||||||
|
base64_datas = base64_data.decode('utf-8')
|
||||||
|
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
||||||
|
report_path = attachment._full_path(attachment.store_fname)
|
||||||
|
vals['model_file'] = self.transition_glb_file(report_path, model_code)
|
||||||
|
logging.info('create-model_file:%s' % len(vals['model_file']))
|
||||||
|
|
||||||
|
obj = super(QuickEasyOrder, self).create(vals)
|
||||||
|
self.model_coloring()
|
||||||
|
self.distribute_to_factory(obj)
|
||||||
|
return obj
|
||||||
|
|
||||||
|
# 将attach的datas内容转为glb文件
|
||||||
|
def transition_glb_file(self, report_path, model_code):
|
||||||
|
shapes = read_step_file(report_path)
|
||||||
|
#output_file = os.path.join('C:/Users/43484/Desktop/机企猫工作文档', str(model_code) + '.stl')
|
||||||
|
output_file = os.path.join('/tmp', str(model_code) + '.stl')
|
||||||
|
write_stl_file(shapes, output_file, 'binary', 0.03, 0.5)
|
||||||
|
# 转化为glb
|
||||||
|
#output_glb_file = os.path.join('C:/Users/43484/Desktop/机企猫工作文档', str(model_code) + '.glb')
|
||||||
|
output_glb_file = os.path.join('/tmp', str(model_code) + '.glb')
|
||||||
|
util_path = get_resource_path('sf_dlm', 'static/util')
|
||||||
|
cmd = 'python3 %s/stl2gltf.py %s %s -b' % (util_path, output_file, output_glb_file)
|
||||||
|
os.system(cmd)
|
||||||
|
# 转base64
|
||||||
|
with open(output_glb_file, 'rb') as fileObj:
|
||||||
|
image_data = fileObj.read()
|
||||||
|
base64_data = base64.b64encode(image_data)
|
||||||
|
return base64_data
|
||||||
|
# return False
|
||||||
|
|
||||||
|
@api.onchange('upload_model_file')
|
||||||
|
def onchange_model_file(self):
|
||||||
|
for item in self:
|
||||||
|
if len(item.upload_model_file) > 1:
|
||||||
|
raise ValidationError('只允许上传一个文件')
|
||||||
|
if item.upload_model_file:
|
||||||
|
file_attachment_id = item.upload_model_file[0]
|
||||||
|
# 附件路径
|
||||||
|
report_path = file_attachment_id._full_path(file_attachment_id.store_fname)
|
||||||
|
logging.info("模型路径: %s" % report_path)
|
||||||
|
base64_data = base64.b64encode(file_attachment_id.datas)
|
||||||
|
base64_datas = base64_data.decode('utf-8')
|
||||||
|
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
||||||
|
logging.info("模型编码: %s" % model_code)
|
||||||
|
item.model_file = self.transition_glb_file(report_path, model_code)
|
||||||
|
ret = self.feature_recognition(report_path, model_code)
|
||||||
|
logging.info("自动报价返回值: %s" % ret)
|
||||||
|
boxshape = ret['boxshape'].tolist()
|
||||||
|
logging.info("自动报价boxshape: %s" % boxshape)
|
||||||
|
logging.info('自动报价feature_infos:%s' % ret['feature_infos'])
|
||||||
|
item.model_length = boxshape[0] # 长 单位mm
|
||||||
|
item.model_width = boxshape[1] # 宽
|
||||||
|
item.model_height = boxshape[2] # 高
|
||||||
|
item.model_volume = boxshape[0] * boxshape[1] * boxshape[2]
|
||||||
|
item.model_feature = json.dumps(ret['feature_infos'], ensure_ascii=False)
|
||||||
|
self._get_price(item)
|
||||||
|
else:
|
||||||
|
item.model_file = False
|
||||||
|
item.model_feature = False
|
||||||
|
item.model_length = 0
|
||||||
|
item.model_width = 0
|
||||||
|
item.model_height = 0
|
||||||
|
item.model_volume = 0
|
||||||
|
|
||||||
|
def distribute_to_factory(self, obj):
|
||||||
|
"""
|
||||||
|
派单到工厂
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
web_base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url', default='')
|
||||||
|
logging.info("web_base_url: %s" % web_base_url)
|
||||||
|
url = '/api/bfm_process_order/list'
|
||||||
|
res = {'order_number': obj.name, 'delivery_end_date': str(datetime.now()),
|
||||||
|
'delivery_name': 'XXXXX', 'delivery_telephone': 'XXXXX',
|
||||||
|
'delivery_address': 'XXXXX',
|
||||||
|
'bfm_process_order_list': []}
|
||||||
|
factory = self.env['res.partner'].sudo().search([], limit=1, order='id desc')
|
||||||
|
config_header = Common.get_headers(self, factory.sf_token, factory.sf_secret_key)
|
||||||
|
for item in obj:
|
||||||
|
attachment = item.upload_model_file[0]
|
||||||
|
base64_data = base64.b64encode(attachment.datas)
|
||||||
|
base64_datas = base64_data.decode('utf-8')
|
||||||
|
barcode = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
||||||
|
logging.info('model_file-size: %s' % len(item.model_file))
|
||||||
|
val = {
|
||||||
|
'model_long': item.model_length,
|
||||||
|
'model_width': item.model_width,
|
||||||
|
'model_height': item.model_height,
|
||||||
|
'model_volume': item.model_volume,
|
||||||
|
'model_machining_precision': item.machining_precision,
|
||||||
|
'model_name': attachment.name,
|
||||||
|
'model_data': base64_datas,
|
||||||
|
'model_file': base64.b64encode(item.model_file).decode('utf-8'),
|
||||||
|
'texture_code': item.material_id.materials_no,
|
||||||
|
'texture_type_code': item.material_model_id.materials_no,
|
||||||
|
# 'surface_process_code': self.env['jikimo.surface.process']._json_surface_process_code(item),
|
||||||
|
# 'process_parameters_code': self.env['jikimo.surface.process.item']._json_surface_process_item_code(
|
||||||
|
# item),
|
||||||
|
'price': item.price,
|
||||||
|
'number': item.quantity,
|
||||||
|
'total_amount': item.price,
|
||||||
|
'remark': '',
|
||||||
|
'barcode': barcode
|
||||||
|
}
|
||||||
|
res['bfm_process_order_list'].append(val)
|
||||||
|
res['bfm_process_order_list'] = json.dumps(res['bfm_process_order_list'])
|
||||||
|
try:
|
||||||
|
ret = requests.post((web_base_url[0] + url), json={}, data=res,
|
||||||
|
headers=config_header)
|
||||||
|
ret = ret.json()
|
||||||
|
if ret['status'] == 1:
|
||||||
|
self.write(
|
||||||
|
{'state': '待接单'})
|
||||||
|
else:
|
||||||
|
raise UserError(ret['message'])
|
||||||
|
except Exception as e:
|
||||||
|
if ret['status'] != 1:
|
||||||
|
raise UserError(e)
|
||||||
|
else:
|
||||||
|
raise UserError("分配工厂失败,请联系管理员")
|
||||||
|
|
||||||
|
# 特征识别
|
||||||
|
def feature_recognition(self, report_path, model_code):
|
||||||
|
feature_path = self.env['sf.auto_quatotion.common'].sudo().get_feature_full_path()
|
||||||
|
# price_path = self.env['jikimo.auto_quatotion.common'].get_price_full_path()
|
||||||
|
process_time_db_path = self.env['sf.auto_quatotion.common'].sudo().get_process_time_db_path()
|
||||||
|
ret = self.env['sf.auto_quatotion.common'].sudo().get_auto_quatotion(report_path, feature_path,
|
||||||
|
process_time_db_path,
|
||||||
|
model_code)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# 模型上色
|
||||||
|
def model_coloring(self):
|
||||||
|
url = '/api/library_of_models/create'
|
||||||
|
config = self.env['res.config.settings'].get_values()
|
||||||
|
config_header = Common.get_headers(self, config['token'], config['sf_secret_key'])
|
||||||
|
order = self.search([('id', '=', self.id)])
|
||||||
|
logging.info('order: %s' % order.name)
|
||||||
|
if order:
|
||||||
|
attachment = order.upload_model_file[0]
|
||||||
|
base64_data = base64.b64encode(attachment.datas)
|
||||||
|
base64_datas = base64_data.decode('utf-8')
|
||||||
|
model_code = hashlib.sha1(base64_datas.encode('utf-8')).hexdigest()
|
||||||
|
logging.info('model_file-size: %s' % len(order.model_file))
|
||||||
|
logging.info('attachment.datas-size: %s' % len(attachment.datas))
|
||||||
|
vals = {
|
||||||
|
'model_code': model_code,
|
||||||
|
'model_data': base64_data,
|
||||||
|
'model_name': attachment.name,
|
||||||
|
'model_long': order.model_length,
|
||||||
|
'model_width': order.model_width,
|
||||||
|
'model_height': order.model_height,
|
||||||
|
'model_volume': order.model_volume,
|
||||||
|
'model_order_no': order.name,
|
||||||
|
'remark': '订单号:%s 客户:%s' % (order.name, order.customer_id.name)
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
ret = requests.post((config['sf_url'] + url), json={}, data=vals, headers=config_header,
|
||||||
|
timeout=60)
|
||||||
|
ret = ret.json()
|
||||||
|
# result = json.loads(ret['result'])
|
||||||
|
if ret['status'] == 1:
|
||||||
|
order.model_color_state = 'success'
|
||||||
|
else:
|
||||||
|
order.model_color_state = 'fail'
|
||||||
|
raise UserError(ret['message'])
|
||||||
|
except Exception as e:
|
||||||
|
order.model_color_state = 'fail'
|
||||||
|
raise UserError("模型上色失败")
|
||||||
|
|
||||||
|
# 自动报价
|
||||||
|
def _get_price(self, order):
|
||||||
|
url = '/api/automatic_quotes'
|
||||||
|
config = self.env['res.config.settings'].sudo().get_values()
|
||||||
|
config_header = Common.get_headers(self, config['token'], config['sf_secret_key'])
|
||||||
|
logging.info("报价接口..........% s" % order.name)
|
||||||
|
try:
|
||||||
|
if order:
|
||||||
|
vals = {}
|
||||||
|
# mrs合作伙伴token
|
||||||
|
vals['token'] = config['token']
|
||||||
|
vals['accuracy'] = order.machining_precision
|
||||||
|
vals['number'] = order.quantity
|
||||||
|
vals['process_code'] = 0
|
||||||
|
vals['texture_code'] = order.material_model_id.code
|
||||||
|
vals['delivery_days'] = 15
|
||||||
|
if order.model_file:
|
||||||
|
attachment = self.env['ir.attachment'].sudo().search(
|
||||||
|
[('id', '=', order.upload_model_file[0])])
|
||||||
|
vals['attachment_id'] = attachment.id
|
||||||
|
else:
|
||||||
|
vals['attachment_id'] = ''
|
||||||
|
vals['feature_infos'] = order.model_feature
|
||||||
|
vals['model_long'] = order.model_length
|
||||||
|
vals['model_width'] = order.model_width
|
||||||
|
vals['model_height'] = order.model_height
|
||||||
|
logging.info('vals:%s' % vals)
|
||||||
|
ret = requests.post((config['sf_url'] + url), json={}, data=vals, headers=config_header)
|
||||||
|
result = json.dumps(json.loads(ret.text), ensure_ascii=False, indent=4, separators=(',', ':'))
|
||||||
|
logging.info('报价接口返回:%s' % result)
|
||||||
|
price_result = json.loads(result)
|
||||||
|
# random.randint(0, 10000)
|
||||||
|
order.write({'price': price_result.get('price')})
|
||||||
|
else:
|
||||||
|
raise UserError("订单不存在")
|
||||||
|
except Exception as e:
|
||||||
|
if ret['status'] != 1:
|
||||||
|
raise UserError(e)
|
||||||
|
else:
|
||||||
|
raise UserError("自动报价失败,请联系管理员")
|
||||||
4
sf_sale/security/group_security.xml
Normal file
4
sf_sale/security/group_security.xml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
9
sf_sale/security/ir.model.access.csv
Normal file
9
sf_sale/security/ir.model.access.csv
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
access_quick_easy_order,quick_easy_order,model_quick_easy_order,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
114
sf_sale/views/quick_easy_order_view.xml
Normal file
114
sf_sale/views/quick_easy_order_view.xml
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="sequence_quick_easy_order" model="ir.sequence">
|
||||||
|
<field name="name">快速订单编码规则</field>
|
||||||
|
<field name="code">quick.easy.order</field>
|
||||||
|
<field name="prefix">FP-%(year)s-%(month)s%(day)s-</field>
|
||||||
|
<field name="padding">4</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
# ---------- 快速订单 ------------
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="tree_quick_easy_order_view">
|
||||||
|
<field name="name">tree.quick.easy.order</field>
|
||||||
|
<field name="model">quick.easy.order</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<tree string="快速订单">
|
||||||
|
<field optional="show" name="name" string="订单号"/>
|
||||||
|
<field optional="show" name="customer_id" string="客户"/>
|
||||||
|
<field optional="show" name="material_id"/>
|
||||||
|
<field optional="show" name="material_model_id"/>
|
||||||
|
<field optional="show" name="process_id"/>
|
||||||
|
<field optional="show" name="quantity"/>
|
||||||
|
<field optional="show" name="price"/>
|
||||||
|
<field optional="hide" name="delivery_time"/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="form_quick_easy_order_view">
|
||||||
|
<field name="name">form.quick.easy.order</field>
|
||||||
|
<field name="model">quick.easy.order</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="快速订单">
|
||||||
|
<sheet>
|
||||||
|
<h1>
|
||||||
|
<field name="name" readonly="True"/>
|
||||||
|
</h1>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="customer_id" readonly="1" force_save="1"/>
|
||||||
|
<field name="material_id"/>
|
||||||
|
<field name="material_model_id"/>
|
||||||
|
<field name="process_id"/>
|
||||||
|
<field name="parameter_ids" widget="many2many_tags"/>
|
||||||
|
<field name="machining_precision"/>
|
||||||
|
<field name="quantity"/>
|
||||||
|
<field name="unit_price"/>
|
||||||
|
<field name="price"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="upload_model_file" widget="many2many_binary"/>
|
||||||
|
<field name="model_file" widget="Viewer3D" string="模型" readonly="1" force_save="1"
|
||||||
|
attrs="{'invisible': [('model_file', '=', False)]}"/>
|
||||||
|
<label for="model_length" string="尺寸(mm)"
|
||||||
|
attrs='{"invisible": [("model_file","=",False)]}'/>
|
||||||
|
<div class="test_model"
|
||||||
|
attrs='{"invisible": [("model_file","=",False)]}'>
|
||||||
|
<label for="model_length" string="长"/>
|
||||||
|
<field name="model_length" class="o_address_zip"
|
||||||
|
options="{'format': false}"/>
|
||||||
|
<label for="model_width" string="宽"/>
|
||||||
|
<field name="model_width" class="o_address_zip"
|
||||||
|
options="{'format': false}"/>
|
||||||
|
<label for="model_height" string="高"/>
|
||||||
|
<field name="model_height" class="o_address_zip"
|
||||||
|
options="{'format': false}"/>
|
||||||
|
</div>
|
||||||
|
<field name="model_volume" attrs="{'invisible': [('model_file', '=', False)]}"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.ui.view" id="search_quick_easy_order_view">
|
||||||
|
<field name="name">search.quick.easy.order</field>
|
||||||
|
<field name="model">quick.easy.order</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<search string="快速订单">
|
||||||
|
<field name="name" string="模糊搜索"
|
||||||
|
filter_domain="['|', ('name', 'ilike', self), '|', ('receive_name', 'ilike', self),'|', ('receive_phone', 'ilike', self),('customer_id', 'ilike', self)]"/>
|
||||||
|
<separator/>
|
||||||
|
<field name="customer_id"/>
|
||||||
|
</search>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.actions.act_window" id="action_quick_easy_order">
|
||||||
|
<field name="name">快速订单</field>
|
||||||
|
<field name="res_model">quick.easy.order</field>
|
||||||
|
<field name="view_mode">tree,form</field>
|
||||||
|
<field name="domain">[]</field>
|
||||||
|
<field name="context">{}</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
[快速订单] 还没有哦!点左上角的[创建]按钮,沙发归你了!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- <menuitem id="res_partner_menu"-->
|
||||||
|
<!-- action="account.res_partner_action_customer"-->
|
||||||
|
<!-- groups="sales_team.group_sale_salesman"-->
|
||||||
|
<!-- sequence="40"/>-->
|
||||||
|
<menuitem sequence="21" name="快速订单" id="menu_quick_easy_order"
|
||||||
|
action="action_quick_easy_order"
|
||||||
|
parent="sale.sale_order_menu"
|
||||||
|
groups="sales_team.group_sale_salesman"/>
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
@@ -22,6 +22,7 @@ export class StepViewer extends Component {
|
|||||||
setup() {
|
setup() {
|
||||||
this.props.url = this.formatUrl();
|
this.props.url = this.formatUrl();
|
||||||
}
|
}
|
||||||
|
|
||||||
formatUrl() {
|
formatUrl() {
|
||||||
var url = '';
|
var url = '';
|
||||||
if (this.props.value) {
|
if (this.props.value) {
|
||||||
@@ -30,7 +31,8 @@ export class StepViewer extends Component {
|
|||||||
base_url: session['web.base.url'],
|
base_url: session['web.base.url'],
|
||||||
model: this.props.record.resModel,
|
model: this.props.record.resModel,
|
||||||
id: JSON.stringify(this.props.record.data['id']),
|
id: JSON.stringify(this.props.record.data['id']),
|
||||||
field: this.props.name}
|
field: this.props.name
|
||||||
|
}
|
||||||
url = url_props['base_url'].replace('http://', 'https://') + '/web/content/' + url_props['model'] + '/' + url_props['id'] + '/' + url_props['field'] + '?download=true'
|
url = url_props['base_url'].replace('http://', 'https://') + '/web/content/' + url_props['model'] + '/' + url_props['id'] + '/' + url_props['field'] + '?download=true'
|
||||||
// url = 'http://localhost:8069'+'/web/content/'+url_props['model']+'/'+url_props['id']+'/'+url_props['field']+'?download=true'
|
// url = 'http://localhost:8069'+'/web/content/'+url_props['model']+'/'+url_props['id']+'/'+url_props['field']+'?download=true'
|
||||||
console.log('url111111', url)
|
console.log('url111111', url)
|
||||||
@@ -45,6 +47,9 @@ export class StepViewer extends Component {
|
|||||||
// return new_url
|
// return new_url
|
||||||
// url = "web_widget_model_viewer/static/src/images/not_model.png";
|
// url = "web_widget_model_viewer/static/src/images/not_model.png";
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
var oImg = document.getElementsByClassName('test')[0]
|
||||||
|
console.log(oImg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
<t t-name="web_widget_model_viewer.BinaryField3d" owl="1">
|
<t t-name="web_widget_model_viewer.BinaryField3d" owl="1">
|
||||||
|
|
||||||
|
<t t-if="props.value">
|
||||||
<model-viewer
|
<model-viewer
|
||||||
t-att-src='props.url'
|
t-att-src='props.url'
|
||||||
name="3D model"
|
name="3D model"
|
||||||
@@ -22,6 +23,10 @@
|
|||||||
<!-- </span>-->
|
<!-- </span>-->
|
||||||
<!-- </div>-->
|
<!-- </div>-->
|
||||||
</model-viewer>
|
</model-viewer>
|
||||||
|
</t>
|
||||||
|
<t t-if="!props.value">
|
||||||
|
<div style="color:#D23F3A">当前制造订单暂无模型</div>
|
||||||
|
</t>
|
||||||
|
|
||||||
<!-- <model-viewer-->
|
<!-- <model-viewer-->
|
||||||
<!-- src='/jikimo_model_viewer/static/src/js/3d_viewer/test.glb'-->
|
<!-- src='/jikimo_model_viewer/static/src/js/3d_viewer/test.glb'-->
|
||||||
|
|||||||
Reference in New Issue
Block a user