diff --git a/sf_base/models/base.py b/sf_base/models/base.py index 7565adeb..5762822e 100644 --- a/sf_base/models/base.py +++ b/sf_base/models/base.py @@ -196,8 +196,7 @@ class MachineTool(models.Model): kw = json.dumps(machine_tool_list, ensure_ascii=False) r = requests.post(strurl, json={}, data={'kw': kw, 'token': token}, headers=headers) ret = r.json() - self.code = ret['code'] - print(r) + self.code = ret['message'] if r == 200: return "机床注册成功" else: diff --git a/sf_base/models/common.py b/sf_base/models/common.py index 809b8be0..d576129d 100644 --- a/sf_base/models/common.py +++ b/sf_base/models/common.py @@ -31,6 +31,10 @@ class MrsMaterialModel(models.Model): density = fields.Float("密度(kg/m³)") materials_id = fields.Many2one('sf.production.materials', "材料名") remark = fields.Text("备注") + gain_way = fields.Selection( + [("自加工", "自加工"), ("外协", "外协"), ("采购", "采购")], + default="", string="获取方式") + supplier_ids = fields.One2many('sf.supplier.sort', 'materials_model_id', string='供应商') active = fields.Boolean('有效', default=True) @@ -63,7 +67,6 @@ class MrsProcessingOrder(models.Model): _name = 'sf.processing.order' _description = '工序' sequence = fields.Integer('Sequence') - processing_technology_ids = fields.Many2many('sf.processing.technology', 'sf_associated_processes', index=True, string='加工工艺') production_process_id = fields.Many2one('sf.production.process', string="表面工艺") @@ -79,3 +82,17 @@ class Tray(models.Model): [("空闲", "空闲"), ("占用", "占用"), ("报损", "报损")], default="空闲", string="状态") active = fields.Boolean('有效', default=True) + + +class SupplierSort(models.Model): + _name = 'sf.supplier.sort' + _description = '供应商排序' + + sequence = fields.Integer('Sequence') + partner_id = fields.Many2one('res.partner', domain="[('is_company', '=', True),('supplier_rank', '!=', 0)]") + materials_model_id = fields.Many2one('sf.materials.model') + + _sql_constraints = [ + ('supplier_sort_uniq', 'unique (partner_id,materials_model_id)', '排序不能重复!') + ] + diff --git a/sf_base/security/ir.model.access.csv b/sf_base/security/ir.model.access.csv index a548d41c..d4441085 100644 --- a/sf_base/security/ir.model.access.csv +++ b/sf_base/security/ir.model.access.csv @@ -12,6 +12,7 @@ access_sf_production_materials,sf_production_materials,model_sf_production_mater access_sf_materials_model,sf_materials_model,model_sf_materials_model,base.group_user,1,1,1,1 access_sf_processing_technology,sf_processing_technology,model_sf_processing_technology,base.group_user,1,1,1,1 access_sf_tray,sf_tray,model_sf_tray,base.group_user,1,1,1,1 +access_sf_supplier_sort,sf_supplier_sort,model_sf_supplier_sort,base.group_user,1,1,1,1 diff --git a/sf_base/views/common_view.xml b/sf_base/views/common_view.xml index b0e2a7bc..3b4e7935 100644 --- a/sf_base/views/common_view.xml +++ b/sf_base/views/common_view.xml @@ -6,23 +6,17 @@ sf.processing.technology
- - - - - -
@@ -30,10 +24,8 @@ sf.processing.technology - - @@ -52,13 +44,13 @@ sf.production.process - + sf.production.process @@ -77,9 +69,7 @@
- -
@@ -110,24 +100,28 @@ + + - - - - + + + + + + + + - -
diff --git a/sf_bf_connect/__manifest__.py b/sf_bf_connect/__manifest__.py index 4229609b..fe5a9559 100644 --- a/sf_bf_connect/__manifest__.py +++ b/sf_bf_connect/__manifest__.py @@ -10,9 +10,9 @@ """, 'category': 'sf', 'website': 'https://www.sf.cs.jikimo.com', - 'depends': ['sf_base'], + 'depends': ['sf_base', 'sf_sale', 'sf_dlm'], 'data': [ - + 'views/res_partner_view.xml' ], 'demo': [ ], diff --git a/sf_bf_connect/controllers/controllers.py b/sf_bf_connect/controllers/controllers.py index aecdff23..9e422ca7 100644 --- a/sf_bf_connect/controllers/controllers.py +++ b/sf_bf_connect/controllers/controllers.py @@ -8,7 +8,7 @@ from odoo.http import request class Sf_Bf_Connect(http.Controller): - @http.route('/api/bfm_process_order/list', type='json', auth='sf_token', methods=['GET', 'POST'], csrf=False, + @http.route('/api/bfm_process_order/list', type='json', auth='none', methods=['GET', 'POST'], csrf=False, cors="*") def get_bfm_process_order_list(self, **kw): """ @@ -23,17 +23,43 @@ class Sf_Bf_Connect(http.Controller): ret = json.loads(datas) ret = json.loads(ret['result']) product_id = request.env.ref('sf_dlm.product_template_sf').sudo() + self_machining_id = request.env.ref('sf_dlm.product_embryo_sf_self_machining').sudo() + outsource_id = request.env.ref('sf_dlm.product_embryo_sf_outsource').sudo() + purchase_id = request.env.ref('sf_dlm.product_embryo_sf_purchase').sudo() company_id = request.env.ref('base.main_company').sudo() - order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create(ret['delivery_end_date'], company_id) + order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create( + company_id, ret['delivery_name'], ret['delivery_telephone'], ret['delivery_address'], + ret['delivery_end_date']) i = 1 for item in ret['bfm_process_order_list']: product = request.env['product.template'].sudo().product_create(product_id, item, order_id, ret['order_number'], i) order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item) - bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(product) - bom.with_user(request.env.ref("base.user_admin")).bom_create_Line(product) - i += 1 - res['factory_order_no'] = order_id.name + bom_data = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).get_bom(product) + if bom_data: + bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(product, + 'normal') + bom.with_user(request.env.ref("base.user_admin")).bom_create_Line(product) + else: + if product.materials_id.gain_way == '自加工': + self_machining = request.env['product.template'].sudo().no_bom_product_create(self_machining_id, + item, + order_i) + bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create( + self_machining, 'normal') + bom.with_user(request.env.ref("base.user_admin")).bom_create_Line(self_machining) + + elif product.materials_id.gain_way == '外协': + outsource = request.env['product.template'].sudo().no_bom_product_create(outsource_id, item, + order_id) + bom = request.env['mrp.bom'].with_user(request.env.ref("base.user_admin")).bom_create(outsource) + bom.with_user(request.env.ref("base.user_admin")).bom_create_Line(outsource, 'subcontract') + elif product.materials_id.gain_way == '采购': + purchase = request.env['product.template'].sudo().no_bom_product_create(purchase_id, item, + order_id) + + i += 1 + res['factory_order_no'] = order_id.name return json.JSONEncoder().encode(res) except Exception as e: logging.info('get_bfm_process_order_list error:%s' % e) diff --git a/sf_bf_connect/models/http.py b/sf_bf_connect/models/http.py index 2396571f..7fee2b9a 100644 --- a/sf_bf_connect/models/http.py +++ b/sf_bf_connect/models/http.py @@ -4,12 +4,14 @@ import datetime import time import hashlib from odoo import fields, models, api -from odoo.http import request, AuthenticationError +from odoo.http import request __author__ = 'jinling.yang' _logger = logging.getLogger(__name__) +class AuthenticationError(Exception): + pass class Http(models.AbstractModel): _inherit = 'ir.http' @@ -23,6 +25,7 @@ class Http(models.AbstractModel): # 查询密钥 factory_secret = request.env['res.partner'].sudo().search( [('sf_token', '=', datas['HTTP_TOKEN'])], limit=1) + logging.info('factory_secret:%s' % factory_secret) if not factory_secret: raise AuthenticationError('无效的token') timestamp_str = int(time.time()) diff --git a/sf_bf_connect/models/models.py b/sf_bf_connect/models/models.py index 3eeac229..9c9d59a1 100644 --- a/sf_bf_connect/models/models.py +++ b/sf_bf_connect/models/models.py @@ -25,4 +25,5 @@ class ResPartner(models.Model): return ran_str sf_token = fields.Char(u'Token', default=get_token) - sf_secret_key = fields.Char(u'密钥', default=get_secret) \ No newline at end of file + sf_secret_key = fields.Char(u'密钥', default=get_secret) + diff --git a/sf_bf_connect/views/res_partner_view.xml b/sf_bf_connect/views/res_partner_view.xml new file mode 100644 index 00000000..70609554 --- /dev/null +++ b/sf_bf_connect/views/res_partner_view.xml @@ -0,0 +1,20 @@ + + + + + view_partner_form + res.partner + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sf_dlm/__manifest__.py b/sf_dlm/__manifest__.py index 9fc39be7..da6dba4b 100644 --- a/sf_dlm/__manifest__.py +++ b/sf_dlm/__manifest__.py @@ -12,7 +12,7 @@ 'website': 'https://www.sf.jikimo.com', 'depends': ['mrp', 'base', 'sf_manufacturing'], 'data': [ - # 'data/product_data.xml', + 'data/product_data.xml', 'views/product_template_view.xml' ], 'demo': [ diff --git a/sf_dlm/data/product_data.xml b/sf_dlm/data/product_data.xml index 2b7bedd5..6aa4cf83 100644 --- a/sf_dlm/data/product_data.xml +++ b/sf_dlm/data/product_data.xml @@ -1,9 +1,9 @@ - - + + CNC加工产品模板 - + delivery product false @@ -12,5 +12,48 @@ false + + + 胚料 + 胚料 + + + + 自加工 + + delivery + product + false + + + + false + + + + 外协 + + delivery + product + false + + + + false + + + + 采购 + + delivery + product + false + + + + false + + + \ No newline at end of file diff --git a/sf_dlm/models/product_template.py b/sf_dlm/models/product_template.py index b626eb69..8b174d25 100644 --- a/sf_dlm/models/product_template.py +++ b/sf_dlm/models/product_template.py @@ -1,5 +1,6 @@ from odoo import models, fields, api from odoo.exceptions import ValidationError +import logging class ResProductTemplate(models.Model): @@ -9,7 +10,7 @@ class ResProductTemplate(models.Model): 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('模型体积[mm]', compute='_compute_model_volume', store=True) + model_volume = fields.Float('模型体积[m³]') model_machining_precision = fields.Selection([ ('±0.10mm', '±0.10mm'), ('±0.05mm', '±0.05mm'), @@ -22,35 +23,50 @@ class ResProductTemplate(models.Model): model_process_parameters_id = fields.Many2one('sf.processing.technology', string='工艺参数') model_price = fields.Float('模型单价', digits=(16, 3)) model_remark = fields.Char('模型备注说明') - long = fields.Float('长[mm]', digits=(16, 3)) + 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='材料型号') - volume = fields.Float(compute='_compute_volume', store=True) + # volume = fields.Float(compute='_compute_volume', store=True) + single_manufacturing = fields.Boolean(string="单个制造") - @api.depends('long', 'width', 'height') - def _compute_volume(self): - self.volume = self.long * self.width * self.height + @api.model + def _get_route(self): + route_manufacture = self.env.ref('stock.warehouse0', raise_if_not_found=False).manufacture_pull_id.route_id.id + route_mto = self.env.ref('stock.warehouse0', raise_if_not_found=False).mto_pull_id.route_id.id + if route_manufacture and route_mto: + return [route_manufacture, route_mto] + return [] - @api.depends('model_long', 'model_width', 'model_height') - def _compute_model_volume(self): - self.model_volume = self.model_long * self.model_width * self.model_height + route_ids = fields.Many2many(default=lambda self: self._get_route()) + + # @api.depends('long', 'width', 'height') + # def _compute_volume(self): + # self.volume = self.long * self.width * self.height + + # @api.depends('model_long', 'model_width', 'model_height') + # def _compute_model_volume(self): + # self.model_volume = self.model_long * self.model_width * self.model_height # 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品 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 + logging.info('product_create:%s' % item) vals = { 'name': '%s-%s' % (order_id.name, i), 'model_long': item['model_long'], 'model_width': item['model_width'], 'model_height': item['model_height'], - 'model_volume': item['model_volume'], + 'length': item['model_long'], + 'width': item['model_width'], + 'height': item['model_height'], + 'volume': item['model_long'] * item['model_width'] * item['model_height'], 'model_price': item['price'], - 'model_total_amount': item['total_amount'], - 'model_number': item['number'], + 'tracking': 'serial', + 'single_manufacturing': True, 'list_price': item['price'], 'materials_id': self.env['sf.production.materials'].search( [('materials_no', '=', item['texture_code'])]).id, @@ -61,10 +77,47 @@ class ResProductTemplate(models.Model): # 'model_process_parameters_id': self.env['sf.processing.technology'].search( # [('process_encode', '=', item['process_parameters_code'])]).id, 'model_remark': item['remark'], - 'default_code': '%s-%s' % (order_number, i), - 'barcode': item['barcode'], + # 'default_code': '%s-%s' % (order_number, i), + # 'barcode': item['barcode'], 'active': True } + logging.info('product_create1:%s' % item) + copy_product_id.sudo().write(vals) + return copy_product_id + + def no_bom_product_create(self, product_id, item, order_id): + copy_product_id = product_id.with_user(self.env.ref("base.user_admin")).copy() + copy_product_id.product_tmpl_id.active = True + logging.info('no_bom_product_create:%s' % item) + 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 + vals = { + 'name': '%s %s %s %s * %s * %s' % ( + order_id.name, materials_id.name, materials_type_id.name, item['model_long'], item['model_width'], + item['model_height']), + 'model_long': item['model_long'], + 'model_width': item['model_width'], + 'model_height': item['model_height'], + 'model_volume': item['model_long'] * item['model_width'] * item['model_height'], + 'length': item['model_long'], + 'width': item['model_width'], + 'height': item['model_height'], + 'volume': item['model_long'] * item['model_width'] * item['model_height'], + 'model_price': item['price'], + 'tracking': 'serial', + 'single_manufacturing': True, + 'list_price': item['price'], + 'materials_id': materials_id.id, + 'materials_type_id': materials_type_id.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 + } + logging.info('product_create1:%s' % item) copy_product_id.sudo().write(vals) return copy_product_id @@ -94,10 +147,10 @@ class ResMrpBom(models.Model): _inherit = 'mrp.bom' # 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom - def bom_create(self, product): + def bom_create(self, product, bom_type): bom_id = self.env['mrp.bom'].create({ 'product_tmpl_id': product.product_tmpl_id.id, - 'type': 'normal', + 'type': bom_type, 'product_qty': 1, 'product_uom_id': 1 }) @@ -108,26 +161,56 @@ class ResMrpBom(models.Model): # 二、胚料的材料型号与生成产品的材料型号一致; # 三、胚料的长宽高均要大于模型的长宽高; # 四、如果匹配成功多个胚料,则选取体积最小的胚料; - def bom_create_Line(self, product): + # 创建新的胚料,根据胚料材料型号的获取方式( + # 自加工,外协,采购) 的配置, 选择不同的库存路线,一种材料型号配置一个路线相关的配置: + # 材料型号配置不同的获取方式: (自加工, 外协, 采购); + # 原材料重量KG(公斤)= 胚料的体积(立方米m³) * 材料密度 * 1000 + def bom_create_Line(self, embryo, materials): + bom_line = self.get_raw_bom(embryo, materials) + vals = { + 'bom_id': self.id, + 'product_id': bom_line.id, + 'product_tmpl_id': bom_line.product_tmpl_id.id, + 'product_qty': bom_line.volume * bom_line.materials_type_id.density * 1000, + 'product_uom_id': bom_line.uom_id.id + } + return self.env['mrp.bom.line'].create(vals) + + def get_bom(self, product): embryo = self.env['product.product'].search( - [('categ_id.is_embryo', '=', True), ('materials_type_id', '=', product.materials_type_id.id), - ('long', '>', product.long), ('width', '>', product.width), + [('categ_id.type', '=', '胚料'), ('materials_type_id', '=', product.materials_type_id.id), + ('length', '>', product.length), ('width', '>', product.width), ('height', '>', product.height) ], limit=1, order='volume desc' ) - 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) + if embryo: + rate_of_waste = ((embryo.volume - product.model_volume) % embryo.volume) * 100 + if rate_of_waste <= 20: + return embryo + 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" - is_embryo = fields.Boolean('胚料') + 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("该类别已存在,请选择其他类别") + + diff --git a/sf_dlm/views/product_template_view.xml b/sf_dlm/views/product_template_view.xml index d8975017..e8c28167 100644 --- a/sf_dlm/views/product_template_view.xml +++ b/sf_dlm/views/product_template_view.xml @@ -13,12 +13,12 @@ -