@@ -1,24 +1,15 @@
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 ) :
class ResProductMo ( models . Model ) :
_inherit = ' product.template '
# 模型的长,宽,高,体积,精度,材料
model_name = fields . Char ( ' 模型名称 ' )
model_file = fields . Binary ( ' 模型文件 ' )
categ_type = fields . Selection (
[ ( " 成品 " , " 成品 " ) , ( " 坯料 " , " 坯料 " ) , ( " 原材料 " , " 原材料 " ) , ( " 表面工艺 " , " 表面工艺 " ) , ( " 刀具 " , " 刀具 " ) ,
( " 夹具 " , " 夹具 " ) ] ,
string = ' 产品的类别 ' , related = ' categ_id.type ' ,
store = True )
model_name = fields . Char ( ' 模型名称 ' )
model_long = fields . Float ( ' 模型长[mm] ' , digits = ( 16 , 3 ) )
model_width = fields . Float ( ' 模型宽[mm] ' , digits = ( 16 , 3 ) )
model_height = fields . Float ( ' 模型高[mm] ' , digits = ( 16 , 3 ) )
@@ -29,46 +20,31 @@ class ResProductTemplate(models.Model):
( ' 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 )
upload_model_file = fields . Many2many ( ' ir.attachment ' , ' upload_model_file_attachment_ref ' , string = ' 上传模型文件 ' )
product_model_type_id = fields . Many2one ( ' sf.model.type ' , string = ' 产品模型类型 ' )
embryo_model_type_id = fields . Many2one ( ' sf.model.type ' , string = ' 坯料模型类型 ' )
materials_id = fields . Many2one ( ' sf.production.materials ' , string = ' 材料 ' )
materials_type_id = fields . Many2one ( ' sf.materials.model ' , 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 = ' 表面工艺参数 ' )
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_model_id = fields . Many2one ( ' sf.cutting.tool.model ' , string = ' 型号 ' ,
)
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] ' )
@@ -82,7 +58,13 @@ class ResProductTemplate(models.Model):
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_chuck_model_ids = fields . Many2many (
' sf.cutting.tool.model ' ,
relation = ' product_cutting_tool_model_handle_chuck_rel ' ,
column1 = ' model_id_1 ' ,
column2 = ' model_id_2 ' ,
domain = " [( ' mrs_cutting_tool_material_id.name ' , ' = ' , ' 夹头 ' )] " ,
string = ' 适用夹头型号 ' )
cutting_tool_parameter_scope = fields . Char ( ' 适用范围 ' )
# 刀片参数
cutting_tool_parameter_length = fields . Float ( ' 长度L[mm] ' )
@@ -91,14 +73,35 @@ class ResProductTemplate(models.Model):
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_cutter_bar_ids = fields . Many2many (
' sf.cutting.tool.model ' ,
relation = ' product_cutting_tool_model_blade_cutter_bar_rel ' ,
column1 = ' model_id_1 ' ,
column2 = ' model_id_2 ' ,
domain = " [( ' mrs_cutting_tool_material_id.name ' , ' = ' , ' 刀杆 ' )] " ,
string = ' 适用刀杆型号 '
)
cutting_tool_parameter_cutter_pad_ids = fields . Many2many (
' sf.cutting.tool.model ' ,
relation = ' product_cutting_tool_model_blade_cutter_pad_rel ' ,
column1 = ' model_id_1 ' ,
column2 = ' model_id_2 ' ,
domain = " [( ' mrs_cutting_tool_material_id.name ' , ' = ' , ' 刀盘 ' )] " ,
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_blade_ids = fields . Many2many (
' sf.cutting.tool.model ' ,
relation = ' product_cutting_tool_model_pad_blade_rel ' ,
column1 = ' model_id_1 ' ,
column2 = ' model_id_2 ' ,
domain = " [( ' mrs_cutting_tool_material_id.name ' , ' = ' , ' 刀片 ' )] " ,
string = ' 适用刀片型号 ' # 使用空列表作为默认值
)
cutting_tool_parameter_wrench = fields . Float ( ' 配对扳手[mm] ' )
cutting_tool_parameter_screw = fields . Float ( ' 配备螺丝[mm] ' )
cutting_tool_parameter_accuracy_level = fields . Char ( ' 精度等级 ' )
@@ -118,567 +121,29 @@ class ResProductTemplate(models.Model):
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_handle_model_ids = fields . Many2many (
' sf.cutting.tool.model ' ,
relation = ' product_cutting_tool_model_chuck_handle_rel ' ,
column1 = ' model_id_1 ' ,
column2 = ' model_id_2 ' ,
domain = " [( ' mrs_cutting_tool_material_id.name ' , ' = ' , ' 刀柄 ' )] " ,
string = ' 适用刀柄型号 '
)
cutting_tool_parameter_feature = fields . Char ( ' 特性 ' )
# image_1920 = fields.Image(related='cutting_tool_parame ter _image', store=True,
# domain=[('cutting_tool_parame ter _image', '!=', False)])
@api.onchange ( ' ca teg _id ' )
def _onchange_ca teg _id ( self ) :
if self . categ_type == ' 刀具 ' :
self . invoice_policy = ' delivery '
self . sale_ok = False
# @api.c onstrains('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.onchange ( ' cutting_tool_material_id ' )
def _onchange_cutting_tool_material_id ( self ) :
if self . cutting_tool_material_id != self . cutting_tool_model_id . mrs_cutting_tool_material_id :
self . cutting_tool_model_id = False
# @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 ) :
class ResMrpBomMo ( 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("该类别已存在,请选择其他类别")