Accept Merge Request #200: (feature/刀具基础信息生成产品模板 -> develop)

Merge Request: 刀具基础信息生成产品模板

Created By: @杨金灵
Accepted By: @杨金灵
URL: https://jikimo-hn.coding.net/p/jikimo_sfs/d/jikimo_sf/git/merge/200?initial=true
This commit is contained in:
杨金灵
2023-06-15 16:18:04 +08:00
17 changed files with 931 additions and 773 deletions

View File

@@ -304,33 +304,6 @@ class MachineToolType(models.Model):
code = fields.Char('编码')
# 刀具
class CuttingTool(models.Model):
_name = 'sf.cutting_tool.category'
_description = '刀具类别'
code = fields.Char('编码')
name = fields.Char('名称')
remark = fields.Text('备注')
active = fields.Boolean('有效', default=True)
class CuttingToolType(models.Model):
_name = 'sf.cutting_tool.type'
_description = '刀具型号'
code = fields.Char('编码')
name = fields.Char('名称')
diameter = fields.Integer('直径')
long_blade = fields.Integer('避空长/刃长')
cone_angle_pitch = fields.Integer('锥角/节距')
shank_diameter = fields.Integer('柄径')
taper_shank_length = fields.Integer('锥柄长')
tool_length = fields.Integer('刀具总长')
blade_number = fields.Integer('刃数')
category_id = fields.Many2one('sf.cutting_tool.category', string='刀具类别')
brand_id = fields.Many2one('sf.machine.brand', string='品牌')
remark = fields.Text('备注')
active = fields.Boolean('有效', default=True)
class MachineToolCategory(models.Model):
_name = 'sf.machine_tool.category'
_description = '机床类型'

View File

@@ -1,8 +1,6 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sf_machine_tool,sf_machine_tool,model_sf_machine_tool,base.group_user,1,1,1,1
access_sf_cutting_tool_category,sf_cutting_tool_category,model_sf_cutting_tool_category,base.group_user,1,1,1,1
access_sf_machine_tool_type,sf_machine_tool_type,model_sf_machine_tool_type,base.group_user,1,1,1,1
access_sf_cutting_tool_type,sf_cutting_tool_type,model_sf_cutting_tool_type,base.group_user,1,1,1,1
access_sf_machine_brand,sf_machine_brand,model_sf_machine_brand,base.group_user,1,1,1,1
access_sf_machine_brand_tags,sf_machine_brand_tags,model_sf_machine_brand_tags,base.group_user,1,1,1,1
access_sf_machine_control_system,sf_machine_control_system,model_sf_machine_control_system,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sf_machine_tool sf_machine_tool model_sf_machine_tool base.group_user 1 1 1 1
access_sf_cutting_tool_category sf_cutting_tool_category model_sf_cutting_tool_category base.group_user 1 1 1 1
3 access_sf_machine_tool_type sf_machine_tool_type model_sf_machine_tool_type base.group_user 1 1 1 1
access_sf_cutting_tool_type sf_cutting_tool_type model_sf_cutting_tool_type base.group_user 1 1 1 1
4 access_sf_machine_brand sf_machine_brand model_sf_machine_brand base.group_user 1 1 1 1
5 access_sf_machine_brand_tags sf_machine_brand_tags model_sf_machine_brand_tags base.group_user 1 1 1 1
6 access_sf_machine_control_system sf_machine_control_system model_sf_machine_control_system base.group_user 1 1 1 1

View File

@@ -255,156 +255,6 @@
</p>
</field>
</record>
#------------------刀具型号------------------
<record model="ir.ui.view" id="search_sf_cutting_tool_type_view">
<field name="name">search.sf.cutting_tool.type</field>
<field name="model">sf.cutting_tool.type</field>
<field name="arch" type="xml">
<search string="刀具型号">
<field name="name" string="模糊搜索"
filter_domain="['|',('name', 'ilike', self),('code', 'ilike', self)]"/>
</search>
</field>
</record>
<record model="ir.ui.view" id="tree_cutting_tool_type_view">
<field name="name">tree.sf.cutting_tool.type</field>
<field name="model">sf.cutting_tool.type</field>
<field name="arch" type="xml">
<tree string="刀具型号">
<field name="code"/>
<field name="name"/>
<field name="remark"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="form_sf_cutting_tool_type">
<field name="name">form.sf.cutting_tool.type</field>
<field name="model">sf.cutting_tool.type</field>
<field name="arch" type="xml">
<form string="刀具型号">
<group string="基本信息">
<group>
<field name="code" force_save="1" readonly="1"/>
<field name="category_id" string="类别" required="1"/>
</group>
<group>
<field name="name" required="1"/>
<field name="brand_id" required="1"
domain="[('tag_ids', '=', '机床')]"/>
</group>
</group>
<group string="刀具参数">
<group>
<field name="taper_shank_length" required="1" options="{'format': false}"/>
<field name="long_blade" required="1" options="{'format': false}"/>
<field name="tool_length" required="1" options="{'format': false}"/>
</group>
<group>
<field name="diameter" required="1" options="{'format': false}"/>
<field name="shank_diameter" required="1" options="{'format': false}"/>
<field name="cone_angle_pitch" required="1" options="{'format': false}"/>
<field name="blade_number" required="1" options="{'format': false}"/>
</group>
</group>
<group string="其它">
<field name="remark"/>
</group>
</form>
</field>
</record>
<record id="action_sf_cutting_tool_type" model="ir.actions.act_window">
<field name="name">刀具型号</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.cutting_tool.type</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
[刀具型号] 还没有哦!点左上角的[创建]按钮,沙发归你了!
</p>
<p>
</p>
</field>
</record>
#------------------刀具类别------------------
<record model="ir.ui.view" id="search_sf_cutting_tool_category_view">
<field name="name">search.sf.cutting_tool.category</field>
<field name="model">sf.cutting_tool.category</field>
<field name="arch" type="xml">
<search string="刀具类别">
<field name="name" string="模糊搜索"
filter_domain="['|',('name', 'ilike', self),('remark', 'ilike', self)]"/>
</search>
</field>
</record>
<record model="ir.ui.view" id="tree_sf_cutting_tool_category_view">
<field name="name">tree.sf.cutting_tool.category</field>
<field name="model">sf.cutting_tool.category</field>
<field name="arch" type="xml">
<tree string="刀具类别">
<field name="code"/>
<field name="name"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="sf_cutting_tool_category_form">
<field name="name">form.sf.cutting_tool.category</field>
<field name="model">sf.cutting_tool.category</field>
<field name="arch" type="xml">
<form string="刀具类别">
<group string="基本信息">
<group>
<field name="code" readonly="1"/>
</group>
<group>
<field name="name" required="1"/>
</group>
</group>
<!-- <group string="参数">-->
<!-- <field name="type_ids" string="刀具型号">-->
<!-- <tree editable="bottom">-->
<!-- <field name="category_id" invisible="True"/>-->
<!-- <field name="code" string="编码" required="True"/>-->
<!-- <field name="name" string="名称" required="True"/>-->
<!-- <field name="diameter" string="直径" required="True"/>-->
<!-- <field name="long_blade" string="避空长/刃长" required="True"/>-->
<!-- <field name="cone_angle_pitch" string="锥角/节距" required="True"/>-->
<!-- <field name="shank_diameter" string="柄径" required="True"/>-->
<!-- <field name="taper_shank_length" string="锥柄" required="True"/>-->
<!-- <field name="tool_length" string="刀具总长" required="True"/>-->
<!-- <field name="blade_number" string="刃数" required="True"/>-->
<!-- <field name="remark" string="备注"/>-->
<!-- <field name="active" string="有效"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </group>-->
<group string="其它">
<field name="remark"/>
</group>
</form>
</field>
</record>
<record id="action_sf_cutting_tool_category" model="ir.actions.act_window">
<field name="name">刀具类别</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">sf.cutting_tool.category</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
[刀具类别] 还没有哦!点左上角的[创建]按钮,沙发归你了!
</p>
<p>
</p>
</field>
</record>
#------------------机床注册------------------

View File

@@ -127,26 +127,6 @@
sequence="1"
action="action_sf_machine_tool_category"/>
<menuitem
id="menu_sf_cutting_tool"
parent="mrp.menu_mrp_configuration"
name="刀具"
sequence="5"/>
<menuitem
id="menu_sf_cutting_tool_category"
parent="menu_sf_cutting_tool"
name="刀具类别"
sequence="1"
action="action_sf_cutting_tool_category"/>
<menuitem
id="menu_sf_cutting_tool_type"
parent="menu_sf_cutting_tool"
name="刀具型号"
sequence="1"
action="action_sf_cutting_tool_type"/>
<menuitem
id="menu_sf_machine_control_system"
parent="menu_sf_base"

View File

@@ -10,13 +10,14 @@
""",
'category': 'sf',
'website': 'https://www.sf.jikimo.com',
'depends': ['mrp', 'base', 'sf_manufacturing', 'web_widget_model_viewer', 'mrp_subcontracting', 'purchase_stock',
'depends': ['mrp', 'base', 'sale', 'sf_manufacturing', 'web_widget_model_viewer', 'mrp_subcontracting', 'purchase_stock',
'uom'],
'data': [
'data/product_data.xml',
'data/uom_data.xml',
# 'views/product_template_view.xml',
# 'views/product_workorder.xml'
'data/cutting_tool_data.xml',
'views/product_template_view.xml',
'views/product_workorder.xml'
],
'demo': [
],

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="product_category_cutting_tool_sf" model="product.category">
<field name="name">刀具</field>
<field name="type">刀具</field>
</record>
<record id="product_category_clamp_sf" model="product.category">
<field name="name">夹具</field>
<field name="type">夹具</field>
</record>
<record id="product_template_cutting_tool_sf" model="product.product">
<field name="name">刀具标准模板</field>
<field name="active" eval="False"/>
<field name="categ_id" ref="product_category_cutting_tool_sf"/>
<field name="route_ids"
eval="[ ref('purchase_stock.route_warehouse0_buy')]"/>
<!-- <field name="invoice_policy">delivery</field>-->
<field name="detailed_type">product</field>
<field name="purchase_ok">true</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="tracking">serial</field>
<!-- <field name="is_bfm">false</field>-->
</record>
</data>
</odoo>

View File

@@ -20,21 +20,32 @@
<field name="type">表面工艺</field>
</record>
<!-- <record id="product_category_cutting_tool_sf" model="product.category">-->
<!-- <field name="name">刀具</field>-->
<!-- <field name="type">刀具</field>-->
<!-- </record>-->
<!-- <record id="product_category_clamp_sf" model="product.category">-->
<!-- <field name="name">夹具</field>-->
<!-- <field name="type">夹具</field>-->
<!-- </record>-->
<record id="product_template_sf" model="product.product">
<field name="name">CNC加工产品模板</field>
<field name="active" eval="False"/>
<field name="categ_id" ref="product_category_finished_sf"/>
<field name="route_ids"
eval="[ref('stock.route_warehouse0_mto'), ref('mrp.route_warehouse0_manufacture')]"/>
<field name="invoice_policy">delivery</field>
<!-- <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="single_manufacturing">true</field>
<!-- <field name="single_manufacturing">true</field>-->
<field name="tracking">serial</field>
<field name="is_bfm">false</field>
<!-- <field name="is_bfm">false</field>-->
</record>
<record id="product_embryo_sf_self_machining" model="product.product">
<field name="name">坯料自加工模板</field>
@@ -42,15 +53,15 @@
<field name="categ_id" ref="product_category_embryo_sf"/>
<field name="route_ids"
eval="[ref('stock.route_warehouse0_mto'), ref('mrp.route_warehouse0_manufacture')]"/>
<field name="invoice_policy">delivery</field>
<!-- <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="single_manufacturing">true</field>
<!-- <field name="single_manufacturing">true</field>-->
<field name="tracking">serial</field>
<field name="is_bfm">false</field>
<!-- <field name="is_bfm">false</field>-->
</record>
<record id="product_embryo_sf_outsource" model="product.product">
@@ -59,14 +70,14 @@
<field name="categ_id" ref="product_category_embryo_sf"/>
<field name="route_ids"
eval="[ref('stock.route_warehouse0_mto'), ref('purchase_stock.route_warehouse0_buy'),ref('mrp_subcontracting.route_resupply_subcontractor_mto')]"/>
<field name="invoice_policy">delivery</field>
<!-- <field name="invoice_policy">delivery</field>-->
<field name="detailed_type">product</field>
<field name="purchase_ok">true</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="tracking">serial</field>
<field name="is_bfm">false</field>
<!-- <field name="is_bfm">false</field>-->
</record>
<record id="product_embryo_sf_purchase" model="product.product">
<field name="name">坯料采购模板</field>
@@ -74,14 +85,14 @@
<field name="categ_id" ref="product_category_embryo_sf"/>
<field name="route_ids"
eval="[ref('stock.route_warehouse0_mto'), ref('purchase_stock.route_warehouse0_buy')]"/>
<field name="invoice_policy">delivery</field>
<!-- <field name="invoice_policy">delivery</field>-->
<field name="detailed_type">product</field>
<field name="purchase_ok">true</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="tracking">serial</field>
<field name="is_bfm">false</field>
<!-- <field name="is_bfm">false</field>-->
</record>
</data>
</odoo>

View File

@@ -1,6 +1,5 @@
from. import product_template
from. import product_supplierinfo
from. import product_workorder

View File

@@ -1,356 +0,0 @@
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 ResProductTemplate(models.Model):
_inherit = 'product.template'
# 模型的长,宽,高,体积,精度,材料
model_name = fields.Char('模型名称')
categ_type = fields.Selection(
[("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺")],
string='产品的类别', related='categ_id.type',
store=True)
model_long = 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('模型体积[m³]')
model_machining_precision = fields.Selection([
('0.10', '±0.10mm'),
('0.05', '±0.05mm'),
('0.03', '±0.03mm'),
('0.02', '±0.02mm'),
('0.01', '±0.01mm')], string='加工精度')
product_model_type_id = fields.Many2one('sf.model.type', string='产品模型类型')
embryo_model_type_id = fields.Many2one('sf.model.type', string='坯料模型类型')
model_processing_panel = fields.Char('模型加工面板')
# model_surface_process_category_id = fields.Many2one('sf.production.process.category', string='表面工艺类别')
# model_surface_process_ids = fields.Many2many('sf.production.process', 'rel_product_process', string='表面工艺')
server_product_process_parameters_id = fields.Many2one('sf.production.process.parameter',
string='表面工艺参数(服务产品)')
model_process_parameters_ids = fields.Many2many('sf.production.process.parameter', 'process_parameter_rel',
string='表面工艺参数')
# model_price = fields.Float('模型单价', digits=(16, 3))
model_remark = fields.Char('模型备注说明')
length = fields.Float('长[mm]', digits=(16, 3))
width = fields.Float('宽[mm]', digits=(16, 3))
height = fields.Float('高[mm]', digits=(16, 3))
materials_id = fields.Many2one('sf.production.materials', string='材料')
materials_type_id = fields.Many2one('sf.materials.model', string='材料型号')
single_manufacturing = fields.Boolean(string="单个制造")
upload_model_file = fields.Many2many('ir.attachment', 'upload_model_file_attachment_ref', string='上传模型文件')
model_code = fields.Char('模型编码')
is_bfm = fields.Boolean('业务平台是否自动创建', default=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')
# model_file = fields.Binary('模型文件')
# 坯料的库存路线设置
# def _get_routes(self, route_type):
# route_manufacture = self.env.ref('mrp.route_warehouse0_manufacture', raise_if_not_found=False).sudo()
# route_mto = self.env.ref('stock.route_warehouse0_mto', raise_if_not_found=False).sudo()
# route_purchase = self.env.ref('purchase_stock.route_warehouse0_buy', raise_if_not_found=False).sudo()
# if route_manufacture and route_mto:
# # 外协
# if route_type == 'subcontract':
# route_subcontract = self.env.ref('mrp_subcontracting.route_resupply_subcontractor_mto',
# raise_if_not_found=False).sudo()
# return [route_mto.id, route_purchase.id, route_subcontract.id]
# elif route_type == 'purchase':
# # 采购
# return [route_mto.id, route_purchase.id]
# else:
# return [route_mto.id, route_manufacture.id]
# return []
# route_ids = fields.Many2many(default=lambda self: self._get_route())
# 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品
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_production_process_id(self, surface_process_code):
# production_process_ids = []
# for item in surface_process_code:
# production_process = self.env['sf.production.process'].search([('process_encode', '=', item)])
# production_process_ids.append(production_process.id)
# return [(6, 0, production_process_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(ResProductTemplate, 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)
logging.info('create-model_file:%s' % templates.model_file)
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 ResMrpBom(models.Model):
_inherit = 'mrp.bom'
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
class ResProductCategory(models.Model):
_inherit = "product.category"
type = fields.Selection(
[("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺")],
default="", string="类型")
# @api.constrains('type')
# def _check_type(self):
# category = self.env['product.category'].search(
# [('type', '=', self.type)])
# if category:
# raise ValidationError("该类别已存在,请选择其他类别")

View File

@@ -4,13 +4,8 @@
<record model="ir.ui.view" id="view_product_template_form_inherit_sf">
<field name="name">product.template.form.inherit.sf</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_only_form_view"/>
<field name="inherit_id" ref="sale.product_template_form_view"/>
<field name="arch" type="xml">
<!-- <field name="image_1920" position="replace">-->
<!-- <field name='categ_type' invisible="1"/>-->
<!-- <field name="upload_model_file" required="True"-->
<!-- widget='many2many_binary'/>-->
<!-- </field>-->
<field name="detailed_type" position="before">
<field name='categ_type' invisible="1"/>
<field name="upload_model_file"
@@ -20,15 +15,30 @@
attrs="{'invisible': ['|', ('categ_type', '!=', '成品'),('categ_type', '=', False)]}"/>
</field>
<field name="invoice_policy" position="after">
<field name='categ_type' invisible="1"/>
<field name="embryo_model_type_id" string="模型类型"
attrs="{'invisible': ['|',('categ_type', '!=', '坯料'),('categ_type', '=', False)]}"/>
<field name="materials_id" string="材料" attrs="{'invisible': [('categ_type', '=', '表面工艺')]}"/>
<field name="materials_id" string="材料"
attrs="{'invisible': ['|',('categ_type', '=', '表面工艺'),('categ_type', '=', '刀具')]}"/>
<field name="materials_type_id" string="型号"
domain="[('materials_id', '=', materials_id)]"
attrs="{'invisible': [('categ_type', '=', '表面工艺')]}"/>
attrs="{'invisible': ['|',('categ_type', '=', '表面工艺'),('categ_type', '=', '刀具')]}"/>
<field name="server_product_process_parameters_id" string="表面工艺参数"
options="{'no_create': True}"
attrs="{'invisible': ['|',('categ_type', '!=', '表面工艺'),('categ_type', '=', False)]}"/>
<field name="cutting_tool" attrs="{'invisible': [('categ_type', '!=', '刀具')]}"/>
<field name="integral_cutting_tool_type_id"
attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '整体式刀具')]}"/>
<field name="blade_type_id"
attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀片')]}"/>
<field name="cutter_bar_type_id"
attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀杆')]}"/>
<field name="cutter_pad_type_id"
attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀盘')]}"/>
<field name="handle_type_id"
attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀柄')]}"/>
<field name="chuck_type_id"
attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '夹头')]}"/>
</field>
<xpath expr="//label[@for='volume']" position="before">
@@ -55,21 +65,15 @@
<div class="o_address_format">
<label for="model_long" string="长"/>
<field name="model_long" class="o_address_zip"/>
<!-- <span>&amp;nbsp;</span>-->
<label for="model_width" string="宽"/>
<field name="model_width" class="o_address_zip"/>
<!-- <span>&amp;nbsp;</span>-->
<label for="model_height" string="高"/>
<field name="model_height" class="o_address_zip"/>
</div>
<!-- <field name="model_long" string="长[mm]"/>-->
<!-- <field name="model_width" string="宽[mm]"/>-->
<!-- <field name="model_height" string="高[mm]"/>-->
<field name="model_volume" string="体积[mm³]"/>
<field name="product_model_type_id" string="模型类型"/>
<field name="model_processing_panel" placeholder="例如R,U" string="加工面板"/>
<field name="model_machining_precision"/>
<!-- <field name="model_surface_process_ids" string="表面工艺"/>-->
<field name="model_process_parameters_ids" string="表面工艺参数" widget="many2many_tags"
options="{'no_create': True}"/>
<field name="model_remark" string="备注说明"/>
@@ -77,6 +81,144 @@
</group>
</page>
</xpath>
<xpath expr="//page[last()-1]" position="after">
<page string="刀具物料参数" attrs="{'invisible': [('categ_type', '!=', '刀具')]}">
<group>
<!--整体式刀具-->
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '整体式刀具')]}">
<field name="cutting_tool_parameter_brand_id"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')],'required': [('cutting_tool', '=', '整体式刀具')]}"/>
<field name="cutting_tool_parameter_total_length"/>
<field name="cutting_tool_parameter_shank_length"/>
<field name="cutting_tool_parameter_blade_length"/>
<field name="cutting_tool_parameter_diameter"/>
<field name="cutting_tool_parameter_nut"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')]}"/>
<field name="cutting_tool_parameter_blade_number"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')]}"/>
</group>
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '整体式刀具')]}">
<field name="cutting_tool_parameter_material_model_id"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')],'required': [('cutting_tool', '=', '整体式刀具')]}"/>
/>
<field name="cutting_tool_parameter_front_angle"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')]}"/>
<field name="cutting_tool_parameter_rear_angle"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')]}"/>
<field name="cutting_tool_parameter_main_included_angle"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')]}"/>
</group>
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '整体式刀具')]}">
<field name="cutting_tool_parameter_chuck_model_ids" widget="many2many_tags"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')],'required': [('cutting_tool', '=', '整体式刀具')]}"/>
<field name="cutting_tool_parameter_scope"
attrs="{'invisible': [('cutting_tool', '!=', '整体式刀具')]}"/>
</group>
<!--刀片-->
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀片')]}">
<field name="cutting_tool_parameter_brand_id"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')],'required': [('cutting_tool', '=', '刀片')]}"/>
<field name="cutting_tool_parameter_top_angle"/>
<field name="cutting_tool_parameter_front_angle"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')]}"/>
<field name="cutting_tool_parameter_rear_angle"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')]}"/>
<field name="cutting_tool_parameter_main_included_angle"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')]}"/>
<field name="cutting_tool_parameter_r_angle"/>
<field name="cutting_tool_parameter_working_hardness" attrs="{'required': [('cutting_tool', '=', '刀片')]}"/>
</group>
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀片')]}">
<field name="cutting_tool_parameter_material_model_id"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')],'required': [('cutting_tool', '=', '刀片')]}"/>
<label for="cutting_tool_parameter_length" string="尺寸[mm]"/>
<div class="o_address_format">
<label for="cutting_tool_parameter_length" string="长度L"/>
<field name="cutting_tool_parameter_length" class="o_address_zip"/>
<label for="cutting_tool_parameter_width" string="宽度D"/>
<field name="cutting_tool_parameter_width" class="o_address_zip"/>
<label for="cutting_tool_parameter_height" string="高度T"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')]}"/>
<field name="cutting_tool_parameter_height" class="o_address_zip"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')]}"/>
</div>
<field name="cutting_tool_parameter_radius"/>
<field name="cutting_tool_parameter_nut"
attrs="{'invisible': [('cutting_tool', '!=', '刀片')]}"/>
<field name="cutting_tool_parameter_cutter_bar_ids" widget="many2many_tags" attrs="{'required': [('cutting_tool', '=', '刀片')]}"/>
<field name="cutting_tool_parameter_cutter_pad_ids" widget="many2many_tags" attrs="{'required': [('cutting_tool', '=', '刀片')]}"/>
</group>
<!--刀杆/刀盘-->
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', 'not in', ['刀杆','刀盘'])]}">
<field name="cutting_tool_parameter_brand_id"
attrs="{'invisible': [('cutting_tool', 'not in', ['刀杆','刀盘'])],'required': [('cutting_tool', 'not in', ['刀杆','刀盘'])]}"/>
<field name="cutting_tool_parameter_c_diameter"/>
<field name="cutting_tool_parameter_d_diameter"/>
<field name="cutting_tool_parameter_l_total_length"/>
<field name="cutting_tool_parameter_wrench"/>
<field name="cutting_tool_parameter_screw"/>
<field name="cutting_tool_parameter_blade_ids" widget="many2many_tags"/>
<field name="cutting_tool_parameter_scope"
attrs="{'invisible': [('cutting_tool', 'not in', ['刀杆','刀盘'])]}"/>
</group>
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', 'not in', ['刀杆','刀盘'])]}">
<field name="cutting_tool_parameter_material_model_id"
attrs="{'invisible': [('cutting_tool', 'not in', ['刀杆','刀盘'])],'required': [('cutting_tool', 'not in', ['刀杆','刀盘'])]}"/>
<field name="cutting_tool_parameter_rounded_corner"/>
<field name="cutting_tool_parameter_accuracy_level"/>
<field name="cutting_tool_parameter_blade_number"
attrs="{'invisible': [('cutting_tool', 'not in', ['刀杆','刀盘'])]}"/>
<field name="cutting_tool_parameter_hardness"/>
</group>
<!--刀柄-->
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀柄')]}">
<field name="cutting_tool_parameter_brand_id"
attrs="{'invisible': [('cutting_tool', '!=', '刀柄')],'required': [('cutting_tool', '=', '刀柄')]}"/>
<field name="cutting_tool_parameter_handle_length"/>
<field name="cutting_tool_parameter_length1"/>
<field name="cutting_tool_parameter_diameter1"/>
<field name="cutting_tool_parameter_body_accuracy"/>
<field name="cutting_tool_parameter_nut"
attrs="{'invisible': [('cutting_tool', '!=', '刀柄')]}"/>
<field name="cutting_tool_parameter_clamping_range"
attrs="{'invisible': [('cutting_tool', '!=', '刀柄')]}"/>
<field name="cutting_tool_parameter_weight"/>
<field name="cutting_tool_parameter_chuck_model_ids" widget="many2many_tags"
attrs="{'invisible': [('cutting_tool', '!=', '刀柄')],'required': [('cutting_tool', '=', '刀柄')]}"/>
</group>
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '刀柄')]}">
<field name="cutting_tool_parameter_material_model_id"
attrs="{'invisible': [('cutting_tool', '!=', '刀柄')],'required': [('cutting_tool', '=', '刀柄')]}"/>
<field name="cutting_tool_parameter_detection_accuracy"/>
<field name="cutting_tool_parameter_detection_hardness"/>
<field name="cutting_tool_parameter_standard_speed"/>
</group>
<!--夹头-->
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '夹头')]}">
<field name="cutting_tool_parameter_brand_id"
attrs="{'invisible': [('cutting_tool', '!=', '夹头')],'required': [('cutting_tool', '=', '夹头')]}"/>
<field name="cutting_tool_parameter_outer_diameter"/>
<field name="cutting_tool_parameter_inner_diameter"/>
<field name="cutting_tool_parameter_accuracy"/>
<field name="cutting_tool_parameter_nut"
attrs="{'invisible': [('cutting_tool', '!=', '夹头')]}"/>
<field name="cutting_tool_parameter_clamping_range"
attrs="{'invisible': [('cutting_tool', '!=', '夹头')]}"/>
<field name="cutting_tool_parameter_handle_model_ids" widget="many2many_tags"
attrs="{'invisible': [('cutting_tool', '!=', '夹头')]}"/>
</group>
<group attrs="{'invisible': ['|',('categ_type', '!=', '刀具'),('cutting_tool', '!=', '夹头')]}">
<field name="cutting_tool_parameter_material_model_id"
attrs="{'invisible': [('cutting_tool', '!=', '夹头')],'required': [('cutting_tool', '=', '夹头')]}"/>
<field name="cutting_tool_parameter_height" string="高度[mm]"
attrs="{'invisible': [('cutting_tool', '!=', '夹头')]}"/>
<field name="cutting_tool_parameter_feature"/>
</group>
</group>
</page>
</xpath>
</field>
</record>

View File

@@ -5,6 +5,8 @@ from . import mrp_maintenance
from . import mrp_routing_workcenter
from . import mrp_workorder
from . import model_type
from . import product_template
from . import product_workorder
from . import stock
from . import res_user

View File

@@ -1,6 +1,25 @@
from odoo import fields, models
class ResProductCategory(models.Model):
_inherit = "product.category"
type = fields.Selection(
[("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺"), ("刀具", "刀具"),
("夹具", "夹具")],
default="", string="类型")
#
# class ResProductTemplateCateg(models.Model):
# _inherit = 'product.template'
#
# categ_type = fields.Selection(
# [("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺"), ("刀具", "刀具"),
# ("夹具", "夹具")],
# string='产品的类别', related='categ_id.type',
# store=True)
class ModelType(models.Model):
_name = 'sf.model.type'
_description = '模型类型'
@@ -82,5 +101,6 @@ class SurfaceTechnicsModelTypeRoutingSort(models.Model):
_sql_constraints = [
(
'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)', '表面工艺工序不能重复!')
'route_model_type_uniq', 'unique (route_workcenter_id,surface_technics_model_type_id)',
'表面工艺工序不能重复!')
]

View File

@@ -0,0 +1,684 @@
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 ResProductTemplate(models.Model):
_inherit = 'product.template'
# 模型的长,宽,高,体积,精度,材料
model_name = fields.Char('模型名称')
categ_type = fields.Selection(
[("成品", "成品"), ("坯料", "坯料"), ("原材料", "原材料"), ("表面工艺", "表面工艺"), ("刀具", "刀具"),
("夹具", "夹具")],
string='产品的类别', related='categ_id.type',
store=True)
model_long = 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('模型体积[m³]')
model_machining_precision = fields.Selection([
('0.10', '±0.10mm'),
('0.05', '±0.05mm'),
('0.03', '±0.03mm'),
('0.02', '±0.02mm'),
('0.01', '±0.01mm')], string='加工精度')
product_model_type_id = fields.Many2one('sf.model.type', string='产品模型类型')
embryo_model_type_id = fields.Many2one('sf.model.type', string='坯料模型类型')
model_processing_panel = fields.Char('模型加工面板')
# model_surface_process_category_id = fields.Many2one('sf.production.process.category', string='表面工艺类别')
# model_surface_process_ids = fields.Many2many('sf.production.process', 'rel_product_process', string='表面工艺')
server_product_process_parameters_id = fields.Many2one('sf.production.process.parameter',
string='表面工艺参数(服务产品)')
model_process_parameters_ids = fields.Many2many('sf.production.process.parameter', 'process_parameter_rel',
string='表面工艺参数')
# model_price = fields.Float('模型单价', digits=(16, 3))
model_remark = fields.Char('模型备注说明')
length = fields.Float('长[mm]', digits=(16, 3))
width = fields.Float('宽[mm]', digits=(16, 3))
height = fields.Float('高[mm]', digits=(16, 3))
materials_id = fields.Many2one('sf.production.materials', string='材料')
materials_type_id = fields.Many2one('sf.materials.model', string='材料型号')
single_manufacturing = fields.Boolean(string="单个制造")
upload_model_file = fields.Many2many('ir.attachment', 'upload_model_file_attachment_ref', string='上传模型文件')
model_code = fields.Char('模型编码')
is_bfm = fields.Boolean('业务平台是否自动创建', default=False)
cutting_tool = fields.Selection([
('整体式刀具', '整体式刀具'),
('刀片', '刀片'),
('刀杆', '刀杆'),
('刀盘', '刀盘'),
('刀柄', '刀柄'),
('夹头', '夹头')], string='刀具')
# 关联整体式刀具型号
integral_cutting_tool_type_id = fields.Many2one('sf.integral.cutting.tool', '整体式刀具型号')
# 关联刀片型号
blade_type_id = fields.Many2one('sf.blade', '刀片型号')
# 关联刀杆型号
cutter_bar_type_id = fields.Many2one('sf.cutter.bar', '刀杆型号')
# 关联刀盘型号
cutter_pad_type_id = fields.Many2one('sf.cutter.pad', '刀盘型号')
# 关联刀柄型号
handle_type_id = fields.Many2one('sf.handle', '刀柄型号')
# 关联夹头型号
chuck_type_id = fields.Many2one('sf.chuck', '夹头型号')
cutting_tool_parameter_brand_id = fields.Many2one('sf.machine.brand', '品牌')
# 整体式刀具参数
cutting_tool_parameter_total_length = fields.Float('总长度[mm]')
cutting_tool_parameter_shank_length = fields.Float('柄部长度[mm]')
cutting_tool_parameter_blade_length = fields.Float('刃部长度[mm]')
cutting_tool_parameter_diameter = fields.Float('直径[mm]')
cutting_tool_parameter_blade_number = fields.Integer('刃数')
cutting_tool_parameter_front_angle = fields.Float('前角(°)')
cutting_tool_parameter_rear_angle = fields.Float('后角(°)')
cutting_tool_parameter_main_included_angle = fields.Float('主偏角(°)')
cutting_tool_parameter_material_model_id = fields.Many2one('sf.materials.model', '材料型号')
cutting_tool_parameter_nut = fields.Float('配对螺母[mm]')
# 适用夹头型号可以多选
cutting_tool_parameter_chuck_model_ids = fields.Many2many('sf.chuck', string='适用夹头型号')
cutting_tool_parameter_scope = fields.Char('适用范围')
# 刀片参数
cutting_tool_parameter_length = fields.Float('长度L[mm]')
cutting_tool_parameter_width = fields.Float('宽度D[mm])')
cutting_tool_parameter_height = fields.Float('高度T[mm]')
cutting_tool_parameter_top_angle = fields.Float('顶角(°)')
cutting_tool_parameter_r_angle = fields.Float('R角(°)')
cutting_tool_parameter_working_hardness = fields.Char('加工硬度')
cutting_tool_parameter_cutter_bar_ids = fields.Many2many('sf.cutter.bar', string='适用刀杆型号')
cutting_tool_parameter_cutter_pad_ids = fields.Many2many('sf.cutter.pad', string='适用刀盘型号')
cutting_tool_parameter_radius = fields.Float('刀尖半径[mm]')
# 刀杆/刀盘参数
cutting_tool_parameter_c_diameter = fields.Float('C柄径[mm]')
cutting_tool_parameter_l_total_length = fields.Float('L总长[mm]')
cutting_tool_parameter_d_diameter = fields.Float('D刃径[mm]')
cutting_tool_parameter_blade_ids = fields.Many2many('sf.blade', string='适用刀片型号')
cutting_tool_parameter_wrench = fields.Float('配对扳手[mm]')
cutting_tool_parameter_screw = fields.Float('配备螺丝[mm]')
cutting_tool_parameter_accuracy_level = fields.Char('精度等级')
cutting_tool_parameter_rounded_corner = fields.Float('刀尖圆角半径[mm]')
cutting_tool_parameter_hardness = fields.Char('硬度(°)')
# 刀柄参数
cutting_tool_parameter_handle_length = fields.Float('L[mm]')
cutting_tool_parameter_length1 = fields.Float('L1[mm]')
cutting_tool_parameter_diameter1 = fields.Float('D1[mm]')
cutting_tool_parameter_weight = fields.Float('重量(kg)')
cutting_tool_parameter_body_accuracy = fields.Float('本体精度[mm]')
cutting_tool_parameter_clamping_range = fields.Float('夹持范围[mm]')
cutting_tool_parameter_detection_accuracy = fields.Float('检测精度')
cutting_tool_parameter_detection_hardness = fields.Float('检测硬度')
cutting_tool_parameter_standard_speed = fields.Float('标准转速')
# 夹头参数
cutting_tool_parameter_accuracy = fields.Float('精度[mm]')
cutting_tool_parameter_outer_diameter = fields.Float('外径[mm]')
cutting_tool_parameter_inner_diameter = fields.Float('内径[mm]')
cutting_tool_parameter_handle_model_ids = fields.Many2many('sf.handle.model', string='适用刀柄型号')
cutting_tool_parameter_feature = fields.Char('特性')
# image_1920 = fields.Image(related='cutting_tool_parameter_image', store=True,
# domain=[('cutting_tool_parameter_image', '!=', False)])
# @api.constrains('cutting_tool_parameter_length',)
# def _check_length_or_width(self):
# for record in self:
# if record.cutting_tool == '刀片':
# if record.cutting_tool_parameter_length <= 0 \
# and record.cutting_tool_parameter_width <= 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
#
#
# @api.constrains('cutting_tool_parameter_length',
# 'cutting_tool_parameter_width')
# def _check_length_or_width(self):
# for record in self:
# if record.cutting_tool == '刀片':
# if record.cutting_tool_parameter_length <= 0 \
# and record.cutting_tool_parameter_width <= 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# # if self.cutting_tool == '刀片':
# # if self.cutting_tool_parameter_length == 0 \
# # or self.cutting_tool_parameter_width == 0:
# # raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_height')
# def _check_height(self):
# if self.cutting_tool == '刀片':
# if self.cutting_tool_parameter_height <= 0:
# raise ValueError('该产品中高度不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_top_angle')
# def _check_top_angle(self):
# if self.cutting_tool == '刀片':
# if self.cutting_tool_parameter_top_angle <= 0:
# raise ValueError('该产品中顶角不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_r_angle')
# def _check_r_angle(self):
# if self.cutting_tool == '刀片':
# if self.cutting_tool_parameter_r_angle <= 0:
# raise ValueError('该产品中R角不能为零请确认并重新输入')
#
# @api.constrains('cutting_tool_parameter_radius')
# def _check_radius(self):
# if self.cutting_tool == '刀片':
# if self.cutting_tool_parameter_radius <= 0:
# raise ValueError('该产品中刀尖半径不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_handle_length',
# 'cutting_tool_parameter_length1',
# 'cutting_tool_parameter_diameter1')
# # 'cutting_tool_parameter_body_accuracy',
# # 'cutting_tool_parameter_detection_accuracy',
# # 'cutting_tool_parameter_detection_hardness')
# def _check_handle(self):
# for record in self:
# if record.cutting_tool == '刀柄':
# if record.cutting_tool_parameter_handle_length == 0 \
# or record.cutting_tool_parameter_diameter1 == 0 \
# or record.cutting_tool_parameter_length1 == 0:
# # or record.cutting_tool_parameter_detection_accuracy == 0 \
# # or record.cutting_tool_parameter_detection_hardness == 0 \
# # or record.cutting_tool_parameter_body_accuracy == 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# # if self.cutting_tool == '刀柄':
# # if self.cutting_tool_parameter_handle_length == 0 \
# # or self.cutting_tool_parameter_diameter1 == 0 \
# # or self.cutting_tool_parameter_length1 == 0 \
# # or self.cutting_tool_parameter_detection_accuracy == 0 \
# # or self.cutting_tool_parameter_detection_hardness == 0 \
# # or self.cutting_tool_parameter_body_accuracy == 0:
# # raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_weight')
# def _check_weight(self):
# if self.cutting_tool == '刀柄':
# if self.cutting_tool_parameter_weight == 0:
# raise ValueError('该产品中重量不能为零,请确认并重新输入!')
# @api.constrains('cutting_tool_parameter_c_diameter',
# 'cutting_tool_parameter_l_total_length',
# 'cutting_tool_parameter_d_diameter',
# 'cutting_tool_parameter_wrench',
# 'cutting_tool_parameter_screw',
# 'cutting_tool_parameter_rounded_corner',
# 'cutting_tool_parameter_hardness')
# def _check_angle(self):
# if self.cutting_tool in ['刀杆', '刀盘']:
# if self.cutting_tool_parameter_c_diameter == 0 \
# or self.cutting_tool_parameter_l_total_length == 0 \
# or self.cutting_tool_parameter_d_diameter == 0 \
# or self.cutting_tool_parameter_wrench == 0 \
# or self.cutting_tool_parameter_screw == 0 \
# or self.cutting_tool_parameter_rounded_corner == 0 \
# or self.cutting_tool_parameter_hardness:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# @api.constrains('cutting_tool_parameter_c_diameter',
# 'cutting_tool_parameter_l_total_length',
# 'cutting_tool_parameter_diameter1')
# def _check_angle(self):
# for record in self:
# if record.cutting_tool == '整体式刀具' or record.cutting_tool == '刀片':
# if record.cutting_tool_parameter_c_diameter == 0 \
# or record.cutting_tool_parameter_l_total_length == 0 \
# or record.cutting_tool_parameter_diameter1 == 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# @api.constrains('cutting_tool_parameter_outer_diameter',
# 'cutting_tool_parameter_inner_diameter',
# 'cutting_tool_parameter_body_accuracy',
# 'cutting_tool_parameter_handle_length',
# 'cutting_tool_parameter_length1',
# 'cutting_tool_parameter_diameter1')
# def _check_angle(self):
# for record in self:
# if record.cutting_tool == '整体式刀具' or record.cutting_tool == '刀片':
# if record.cutting_tool_parameter_front_angle == 0 \
# or record.cutting_tool_parameter_rear_angle == 0 \
# or record.cutting_tool_parameter_main_included_angle == 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# @api.constrains('cutting_tool_parameter_front_angle',
# 'cutting_tool_parameter_rear_angle',
# 'cutting_tool_parameter_main_included_angle')
# def _check_angle(self):
# for record in self:
# if record.cutting_tool == '整体式刀具' or record.cutting_tool == '刀片':
# if record.cutting_tool_parameter_front_angle <= 0 \
# or record.cutting_tool_parameter_rear_angle <= 0 \
# or record.cutting_tool_parameter_main_included_angle <= 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_total_length',
# 'cutting_tool_parameter_shank_length',
# 'cutting_tool_parameter_blade_length',
# 'cutting_tool_parameter_diameter')
# def _check_length(self):
# for record in self:
# if record.cutting_tool == '整体式刀具':
# if record.cutting_tool_parameter_total_length <= 0 \
# or record.cutting_tool_parameter_shank_length <= 0 \
# or record.cutting_tool_parameter_blade_length <= 0 \
# or record.cutting_tool_parameter_diameter <= 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# @api.constrains('cutting_tool_parameter_total_length',
# 'cutting_tool_parameter_shank_length',
# 'cutting_tool_parameter_blade_length',
# 'cutting_tool_parameter_diameter')
# def _check_length(self):
# for record in self:
# if record.cutting_tool == '整体式刀具':
# if record.cutting_tool_parameter_total_length == 0 \
# or record.cutting_tool_parameter_shank_length == 0 \
# or record.cutting_tool_parameter_blade_length == 0 \
# or record.cutting_tool_parameter_diameter == 0:
# raise ValueError('该产品中有字段不能为零,请确认并重新输入!')
# @api.constrains('cutting_tool_parameter_blade_number')
# def _check_blade_number(self):
# if self.cutting_tool in ['整体式刀具', '刀杆', '刀盘']:
# if self.cutting_tool_parameter_blade_number <= 0:
# raise ValueError('该产品中刃数不能为零,请确认并重新输入!')
#
# @api.constrains('cutting_tool_parameter_nut')
# def _check_nut(self):
# if self.cutting_tool in ['整体式刀具', '刀片', '刀柄', '夹头']:
# if self.cutting_tool_parameter_nut <= 0:
# 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(ResProductTemplate, 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)
logging.info('create-model_file:%s' % templates.model_file)
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('integral_cutting_tool_type_id')
def _get_integral_cutting_tool_type_info(self):
if self.integral_cutting_tool_type_id:
for item in self:
item.cutting_tool_parameter_brand_id = item.integral_cutting_tool_type_id.brand.id
item.cutting_tool_parameter_total_length = item.integral_cutting_tool_type_id.total_length
item.cutting_tool_parameter_shank_length = item.integral_cutting_tool_type_id.shank_length
item.cutting_tool_parameter_blade_length = item.integral_cutting_tool_type_id.blade_length
item.cutting_tool_parameter_diameter = item.integral_cutting_tool_type_id.diameter
item.cutting_tool_parameter_nut = item.integral_cutting_tool_type_id.nut
item.cutting_tool_parameter_blade_number = item.integral_cutting_tool_type_id.blade_number
item.cutting_tool_parameter_material_model_id = item.integral_cutting_tool_type_id.material_model.id
item.cutting_tool_parameter_front_angle = item.integral_cutting_tool_type_id.front_angle
item.cutting_tool_parameter_rear_angle = item.integral_cutting_tool_type_id.rear_angle
item.cutting_tool_parameter_main_included_angle = item.integral_cutting_tool_type_id.main_included_angle
item.cutting_tool_parameter_chuck_model_ids = self._get_ids(
item.integral_cutting_tool_type_id.chuck_model)
item.cutting_tool_parameter_scope = item.integral_cutting_tool_type_id.scope
item.image_1920 = '' if not item.integral_cutting_tool_type_id.image else item.integral_cutting_tool_type_id.image
@api.onchange('blade_type_id')
def _get_blade_type_info(self):
if self.blade_type_id:
for item in self:
item.cutting_tool_parameter_brand_id = item.blade_type_id.brand.id
item.cutting_tool_parameter_top_angle = item.blade_type_id.top_angle
item.cutting_tool_parameter_front_angle = item.blade_type_id.front_angle
item.cutting_tool_parameter_rear_angle = item.blade_type_id.rear_angle
item.cutting_tool_parameter_main_included_angle = item.blade_type_id.main_included_angle
item.cutting_tool_parameter_r_angle = item.blade_type_id.r_angle
item.cutting_tool_parameter_working_hardness = item.blade_type_id.hardness
item.cutting_tool_parameter_material_model_id = item.blade_type_id.material_model.id
item.cutting_tool_parameter_length = item.blade_type_id.length
item.cutting_tool_parameter_width = item.blade_type_id.width
item.cutting_tool_parameter_height = item.blade_type_id.height
item.cutting_tool_parameter_radius = item.blade_type_id.radius
item.cutting_tool_parameter_nut = item.blade_type_id.nut
item.cutting_tool_parameter_cutter_bar_ids = self._get_ids(item.blade_type_id.cutter_bar)
item.cutting_tool_parameter_cutter_pad_ids = self._get_ids(item.blade_type_id.cutter_pad)
item.image_1920 = '' if not item.blade_type_id.image else item.blade_type_id.image
@api.onchange('cutter_bar_type_id')
def _get_cutter_bar_type_info(self):
if self.cutter_bar_type_id:
for item in self:
item.cutting_tool_parameter_brand_id = item.cutter_bar_type_id.brand.id
item.cutting_tool_parameter_c_diameter = item.cutter_bar_type_id.c_diameter
item.cutting_tool_parameter_d_diameter = item.cutter_bar_type_id.d_diameter
item.cutting_tool_parameter_l_total_length = item.cutter_bar_type_id.total_length
item.cutting_tool_parameter_wrench = item.cutter_bar_type_id.wrench
item.cutting_tool_parameter_screw = item.cutter_bar_type_id.screw
item.cutting_tool_parameter_blade_ids = self._get_ids(item.cutter_bar_type_id.blade)
item.cutting_tool_parameter_scope = item.cutter_bar_type_id.scope
item.cutting_tool_parameter_material_model_id = item.cutter_bar_type_id.material_model.id
item.cutting_tool_parameter_rounded_corner = item.cutter_bar_type_id.radius
item.cutting_tool_parameter_accuracy_level = item.cutter_bar_type_id.accuracy
item.cutting_tool_parameter_blade_number = item.cutter_bar_type_id.blade_number
item.cutting_tool_parameter_hardness = item.cutter_bar_type_id.hardness
item.image_1920 = '' if not item.cutter_bar_type_id.image else item.cutter_bar_type_id.image
@api.onchange('cutter_pad_type_id')
def _get_cutter_pad_type_info(self):
if self.cutter_pad_type_id:
for item in self:
item.cutting_tool_parameter_brand_id = item.cutter_pad_type_id.brand.id
item.cutting_tool_parameter_c_diameter = item.cutter_pad_type_id.c_diameter
item.cutting_tool_parameter_d_diameter = item.cutter_pad_type_id.d_diameter
item.cutting_tool_parameter_l_total_length = item.cutter_pad_type_id.total_length
item.cutting_tool_parameter_wrench = item.cutter_pad_type_id.wrench
item.cutting_tool_parameter_screw = item.cutter_pad_type_id.screw
item.cutting_tool_parameter_blade_ids = item.cutter_pad_type_id.blade.id
item.cutting_tool_parameter_scope = item.cutter_pad_type_id.scope
item.cutting_tool_parameter_material_model_id = item.cutter_pad_type_id.material_model.id
item.cutting_tool_parameter_rounded_corner = item.cutter_pad_type_id.radius
item.cutting_tool_parameter_accuracy_level = item.cutter_pad_type_id.accuracy
item.cutting_tool_parameter_blade_number = item.cutter_pad_type_id.blade_number
item.cutting_tool_parameter_hardness = item.cutter_pad_type_id.hardness
item.image_1920 = '' if not item.cutter_pad_type_id.image else item.cutter_pad_type_id.image
@api.onchange('handle_type_id')
def _get_handle_type_info(self):
if self.handle_type_id:
for item in self:
item.cutting_tool_parameter_brand_id = item.handle_type_id.brand.id
item.cutting_tool_parameter_handle_length = item.handle_type_id.length
item.cutting_tool_parameter_length1 = item.handle_type_id.length1
item.cutting_tool_parameter_diameter1 = item.handle_type_id.diameter1
item.cutting_tool_parameter_body_accuracy = item.handle_type_id.body_accuracy
item.cutting_tool_parameter_nut = item.handle_type_id.nut
item.cutting_tool_parameter_clamping_range = item.handle_type_id.clamping_range
item.cutting_tool_parameter_weight = item.handle_type_id.weight
item.cutting_tool_parameter_material_model_id = item.handle_type_id.material_model.id
item.cutting_tool_parameter_chuck_model_ids = self._get_ids(item.handle_type_id.chuck_model)
item.cutting_tool_parameter_detection_accuracy = item.handle_type_id.detection_accuracy
item.cutting_tool_parameter_detection_hardness = item.handle_type_id.detection_hardness
item.cutting_tool_parameter_standard_speed = item.handle_type_id.standard_speed
item.image_1920 = '' if not item.handle_type_id.image else item.handle_type_id.image
@api.onchange('chuck_type_id')
def _get_chuck_type_info(self):
if self.chuck_type_id:
for item in self:
item.cutting_tool_parameter_brand_id = item.chuck_type_id.brand.id
item.cutting_tool_parameter_outer_diameter = item.chuck_type_id.diameter
item.cutting_tool_parameter_inner_diameter = item.chuck_type_id.inner_diameter
item.cutting_tool_parameter_accuracy = item.chuck_type_id.accuracy
item.cutting_tool_parameter_nut = item.chuck_type_id.nut
item.cutting_tool_parameter_clamping_range = item.chuck_type_id.clamping_range
item.cutting_tool_parameter_handle_model_ids = self._get_ids(item.chuck_type_id.handle_model)
item.cutting_tool_parameter_material_model_id = item.chuck_type_id.material_model.id
item.cutting_tool_parameter_height = item.chuck_type_id.height
item.cutting_tool_parameter_feature = item.chuck_type_id.feature
item.image_1920 = '' if not item.chuck_type_id.image else item.chuck_type_id.image
class ResMrpBom(models.Model):
_inherit = 'mrp.bom'
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
# @api.constrains('type')
# def _check_type(self):
# category = self.env['product.category'].search(
# [('type', '=', self.type)])
# if category:
# raise ValidationError("该类别已存在,请选择其他类别")

View File

@@ -0,0 +1,12 @@
from odoo import fields, models
class ResMrpWorkOrder(models.Model):
_inherit = 'mrp.workorder'
_order = 'sequence'
product_tmpl_id_length = fields.Float(related='production_id.product_tmpl_id.length', readonly=True, store=True, check_company=True, string="坯料长度(mm)")
product_tmpl_id_width = fields.Float(related='production_id.product_tmpl_id.width', readonly=True, store=True, check_company=True, string="坯料宽度(mm)")
product_tmpl_id_height = fields.Float(related='production_id.product_tmpl_id.height', readonly=True, store=True, check_company=True, string="坯料高度(mm)")
product_tmpl_id_materials_id = fields.Many2one(related='production_id.product_tmpl_id.materials_id', readonly=True, store=True, check_company=True, string="材料")
product_tmpl_id_materials_type_id = fields.Many2one(related='production_id.product_tmpl_id.materials_type_id', readonly=True, store=True, check_company=True, string="型号")

View File

@@ -99,28 +99,6 @@
<field name="doall" eval="False"/>
</record>
<record model="ir.cron" id="sf_cron10">
<field name="name">同步资源库刀具类别</field>
<field name="model_id" ref="model_sf_cutting_tool_category"/>
<field name="state">code</field>
<field name="code">model.sync_cutting_tool_category()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>
<record model="ir.cron" id="sf_cron11">
<field name="name">同步资源库刀具型号</field>
<field name="model_id" ref="model_sf_cutting_tool_type"/>
<field name="state">code</field>
<field name="code">model.sync_cutting_tool_type()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
</record>
<record model="ir.cron" id="sf_cron12">
<field name="name">同步资源库工序</field>
<field name="model_id" ref="model_sf_processing_order"/>

View File

@@ -40,10 +40,6 @@ class ResConfigSettings(models.TransientModel):
_logger.info("同步资源库机床型号")
self.env['sf.machine_tool.category'].sync_all_machine_tool_category()
_logger.info("同步资源库机床类型")
self.env['sf.cutting_tool.category'].sync_all_cutting_tool_category()
_logger.info("同步资源库刀具类别")
self.env['sf.cutting_tool.type'].sync_all_cutting_tool_type()
_logger.info("同步资源库刀具")
# self.env['sf.production.process.parameter'].sync_all_production_process_parameter()
# _logger.info("同步表面工艺参数")
# _logger.info("定时同步每日功能刀具类型列表...")

View File

@@ -883,168 +883,6 @@ class MachineToolType(models.Model):
raise ValidationError("认证未通过")
class CuttingTool(models.Model):
_inherit = 'sf.cutting_tool.category'
_description = '刀具类别'
url = '/api/cutting_tool_category/list'
# 定时同步刀具类别
def sync_cutting_tool_category(self):
sf_sync_config = self.env['res.config.settings'].get_values()
token = sf_sync_config['token']
sf_secret_key = sf_sync_config['sf_secret_key']
headers = Common.get_headers(self, token, sf_secret_key)
strUrl = sf_sync_config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
if result['status'] == 1:
for item in result['cutting_tool_category_yesterday_list']:
brand = self.env['sf.cutting_tool.category'].search(
[("code", '=', item['code'])])
if brand:
brand.id = item['id'],
brand.name = item['name'],
brand.code = item['code'],
brand.active = item['active'],
brand.remark = item['remark']
else:
self.env['sf.cutting_tool.category'].create({
"id": item['id'],
"name": item['name'],
"code": item['code'],
"remark": item['remark'],
"active": item['active'],
# "tag_ids": item['tag_ids']
})
else:
raise ValidationError("认证未通过")
# 同步所有刀具类别
def sync_all_cutting_tool_category(self):
sf_sync_config = self.env['res.config.settings'].get_values()
token = sf_sync_config['token']
sf_secret_key = sf_sync_config['sf_secret_key']
headers = Common.get_headers(self, token, sf_secret_key)
strUrl = sf_sync_config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
if result['status'] == 1:
for item in result['cutting_tool_category_all_list']:
brand = self.env['sf.cutting_tool.category'].search(
[("code", '=', item['code'])])
if not brand:
self.env['sf.cutting_tool.category'].create({
"id": item['id'],
"name": item['name'],
"code": item['code'],
"remark": item['remark'],
"active": item['active'],
# "tag_ids": item['tag_ids']
})
else:
raise ValidationError("认证未通过")
class CuttingToolType(models.Model):
_inherit = 'sf.cutting_tool.type'
_description = '刀具型号'
url = '/api/cutting_tool_type/list'
# 定时同步刀具型号
def sync_cutting_tool_type(self):
sf_sync_config = self.env['res.config.settings'].get_values()
token = sf_sync_config['token']
sf_secret_key = sf_sync_config['sf_secret_key']
headers = Common.get_headers(self, token, sf_secret_key)
strUrl = sf_sync_config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
if result['status'] == 1:
for item in result['cutting_tool_type_yesterday_list']:
brand = self.env['sf.cutting_tool.type'].search(
[("code", '=', item['code'])])
if brand:
brand.id = item['id'],
brand.name = item['name'],
brand.code = item['code'],
brand.active = item['active'],
brand.remark = item['remark'],
brand.diameter = item['diameter'],
brand.cone_angle_pitch = item['cone_angle_pitch'],
brand.shank_diameter = item['shank_diameter'],
brand.long_blade = item['long_blade'],
brand.taper_shank_length = item['taper_shank_length'],
brand.tool_length = item['tool_length'],
brand.blade_number = item['blade_number']
brand.brand_id = self.env['sf.machine.brand'].search([('code', '=', item['brand_id'])]).id,
brand.category_id = self.env['sf.cutting_tool.category'].search(
[('code', '=', item['category_id'])]).id
else:
self.env['sf.cutting_tool.type'].create({
"id": item['id'],
"name": item['name'],
"remark": item['remark'],
"code": item['code'],
"active": item['active'],
"diameter": item['diameter'],
"cone_angle_pitch": item['cone_angle_pitch'],
"shank_diameter": item['shank_diameter'],
"long_blade": item['long_blade'],
"taper_shank_length": item['taper_shank_length'],
"tool_length": item['tool_length'],
"blade_number": item['blade_number'],
'brand_id': self.env['sf.machine.brand'].search([('code', '=', item['brand_id'])]).id,
"category_id": self.env['sf.cutting_tool.category'].search(
[('code', '=', item['category_id'])]).id,
})
else:
raise ValidationError("认证未通过")
# 同步所有刀具型号
def sync_all_cutting_tool_type(self):
sf_sync_config = self.env['res.config.settings'].get_values()
token = sf_sync_config['token']
sf_secret_key = sf_sync_config['sf_secret_key']
headers = Common.get_headers(self, token, sf_secret_key)
strUrl = sf_sync_config['sf_url'] + self.url
r = requests.post(strUrl, json={}, data=None, headers=headers)
r = r.json()
result = json.loads(r['result'])
if result['status'] == 1:
for item in result['cutting_tool_type_all_list']:
brand = self.env['sf.cutting_tool.type'].search(
[("code", '=', item['code'])])
if not brand:
self.env['sf.cutting_tool.type'].create({
"id": item['id'],
"name": item['name'],
"remark": item['remark'],
"code": item['code'],
"active": item['active'],
"diameter": item['diameter'],
"cone_angle_pitch": item['cone_angle_pitch'],
"shank_diameter": item['shank_diameter'],
"long_blade": item['long_blade'],
"taper_shank_length": item['taper_shank_length'],
"tool_length": item['tool_length'],
"blade_number": item['blade_number'],
'brand_id': self.env['sf.machine.brand'].search([('code', '=', item['brand_id'])]).id,
"category_id": self.env['sf.cutting_tool.category'].search(
[('code', '=', item['category_id'])]).id,
})
else:
raise ValidationError("认证未通过")
class sfProcessingOrder(models.Model):
_inherit = 'sf.processing.order'
_description = '工序'