From 7227e1e59cf22e4bbeb14037f02fdd23457d7d25 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Fri, 25 Oct 2024 14:58:29 +0800 Subject: [PATCH 01/61] =?UTF-8?q?=E6=B3=A8=E9=87=8Aocc=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/product_template.py | 4 ++-- sf_sale/models/quick_easy_order.py | 4 ++-- sf_sale/models/quick_easy_order_old.py | 4 ++-- sf_sale/views/quick_easy_order_view.xml | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/sf_manufacturing/models/product_template.py b/sf_manufacturing/models/product_template.py index 0b512c36..e61f9b32 100644 --- a/sf_manufacturing/models/product_template.py +++ b/sf_manufacturing/models/product_template.py @@ -9,8 +9,8 @@ from odoo.exceptions import ValidationError, UserError from odoo.modules import get_resource_path -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file class ResProductMo(models.Model): diff --git a/sf_sale/models/quick_easy_order.py b/sf_sale/models/quick_easy_order.py index 081807a4..cb1886a1 100644 --- a/sf_sale/models/quick_easy_order.py +++ b/sf_sale/models/quick_easy_order.py @@ -8,8 +8,8 @@ from datetime import datetime import requests from odoo import http from odoo.http import request -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo import models, fields, api from odoo.modules import get_resource_path from odoo.exceptions import ValidationError, UserError diff --git a/sf_sale/models/quick_easy_order_old.py b/sf_sale/models/quick_easy_order_old.py index 5207ec15..46724fc6 100644 --- a/sf_sale/models/quick_easy_order_old.py +++ b/sf_sale/models/quick_easy_order_old.py @@ -6,8 +6,8 @@ import os from datetime import datetime from stl import mesh # from OCC.Core.GProp import GProp_GProps -from OCC.Extend.DataExchange import read_step_file -from OCC.Extend.DataExchange import write_stl_file +# from OCC.Extend.DataExchange import read_step_file +# from OCC.Extend.DataExchange import write_stl_file from odoo.addons.sf_base.commons.common import Common from odoo import models, fields, api from odoo.modules import get_resource_path diff --git a/sf_sale/views/quick_easy_order_view.xml b/sf_sale/views/quick_easy_order_view.xml index 9111403d..22c342f2 100644 --- a/sf_sale/views/quick_easy_order_view.xml +++ b/sf_sale/views/quick_easy_order_view.xml @@ -74,7 +74,7 @@ - + From 537fbf7e14b50389ce882bb126ca090cf5e8f777 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Fri, 25 Oct 2024 17:19:10 +0800 Subject: [PATCH 02/61] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 573bb73f..1b9ddf39 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -836,6 +836,7 @@ class MrpProduction(models.Model): backorders = backorders - productions_to_backorder productions_not_to_backorder._post_inventory(cancel_backorder=True) + #查出最后一张工单完成入库操作 # if self.workorder_ids.filtered(lambda w: w.routing_type in ['表面工艺']): # move_finish = self.env['stock.move'].search([('created_production_id', '=', self.id)]) # if move_finish: From aa9bdfe37206341232db1c7ea46974044a837473 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 6 Nov 2024 10:40:11 +0800 Subject: [PATCH 03/61] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/__init__.py | 1 + sf_manufacturing/models/mrp_production.py | 8 ++--- sf_manufacturing/models/mrp_workorder.py | 31 ------------------ .../models/sf_technology_design.py | 22 +++++++++++++ sf_manufacturing/models/stock.py | 32 +++++++++++++++---- .../views/mrp_production_addional_change.xml | 2 +- 6 files changed, 52 insertions(+), 44 deletions(-) create mode 100644 sf_manufacturing/models/sf_technology_design.py diff --git a/sf_manufacturing/models/__init__.py b/sf_manufacturing/models/__init__.py index 7d6aa8ae..234d208e 100644 --- a/sf_manufacturing/models/__init__.py +++ b/sf_manufacturing/models/__init__.py @@ -11,3 +11,4 @@ from . import production_line_base from . import agv_setting from . import agv_scheduling from . import res_config_setting +from . import sf_technology_design diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index 43cfc434..ebe08942 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -98,6 +98,7 @@ class MrpProduction(models.Model): # ]) state = fields.Selection([ ('draft', '草稿'), + ('technology_to_confirmed', '待工艺确认'), ('confirmed', '待排程'), ('pending_cam', '待加工'), ('progress', '加工中'), @@ -158,6 +159,7 @@ class MrpProduction(models.Model): is_remanufacture = fields.Boolean('是否重新制造', default=False) remanufacture_count = fields.Integer("重新制造订单数量", compute='_compute_remanufacture_production_ids') remanufacture_production_id = fields.Many2one('mrp.production', string='') + technology_design_ids = fields.One2many('sf.technology.design', 'production_id', string='工艺设计') @api.depends('remanufacture_production_id') def _compute_remanufacture_production_ids(self): @@ -838,7 +840,7 @@ class MrpProduction(models.Model): backorders = backorders - productions_to_backorder productions_not_to_backorder._post_inventory(cancel_backorder=True) - #查出最后一张工单完成入库操作 + # 查出最后一张工单完成入库操作 # if self.workorder_ids.filtered(lambda w: w.routing_type in ['表面工艺']): # move_finish = self.env['stock.move'].search([('created_production_id', '=', self.id)]) # if move_finish: @@ -1217,10 +1219,6 @@ class sf_detection_result(models.Model): 'type': 'ir.actions.act_window', 'res_id': self.id, 'views': [(self.env.ref('sf_manufacturing.sf_test_report_form').id, 'form')], - # 'view_mode': 'form', - # 'context': { - # 'default_id': self.id - # }, 'target': 'new' } diff --git a/sf_manufacturing/models/mrp_workorder.py b/sf_manufacturing/models/mrp_workorder.py index 37d42b42..649d51bc 100644 --- a/sf_manufacturing/models/mrp_workorder.py +++ b/sf_manufacturing/models/mrp_workorder.py @@ -1068,37 +1068,6 @@ class ResMrpWorkOrder(models.Model): workorder.state = 'waiting' continue - # elif workorder.routing_type == 'CNC加工' and workorder.state not in ['done', 'cancel', 'progress', - # 'rework']: - # per_work = self.env['mrp.workorder'].search( - # [('routing_type', '=', '装夹预调'), ('production_id', '=', workorder.production_id.id), - # ('processing_panel', '=', workorder.processing_panel), ('is_rework', '=', True)]) - # if per_work: - # workorder.state = 'waiting' - # if workorder.routing_type == 'CNC加工' and workorder.state == 'progress': - # workorder.state = 'to be detected' - - # for workorder in self: - # if workorder.is_rework is True and workorder.state == 'done': - # cnc_work = self.env['mrp.workorder'].search([('routing_type','=','CNC加工'),('production_id','=',workorder.production_id.id)]) - # if cnc_work: - # cnc_work.state = 'waiting' - # if workorder.state == 'pending': - # if all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): - # workorder.state = 'ready' if workorder.production_id.reservation_state == 'assigned' else 'waiting' - # continue - # if workorder.state not in ('waiting', 'ready'): - # continue - # if not all([wo.state in ('done', 'cancel') for wo in workorder.blocked_by_workorder_ids]): - # workorder.state = 'pending' - # continue - # if workorder.production_id.reservation_state not in ('waiting', 'confirmed', 'assigned'): - # continue - # if workorder.production_id.reservation_state == 'assigned' and workorder.state == 'waiting': - # workorder.state = 'ready' - # elif workorder.production_id.reservation_state != 'assigned' and workorder.state == 'ready': - # workorder.state = 'waiting' - # 重写工单开始按钮方法 def button_start(self): if self.routing_type == 'CNC加工': diff --git a/sf_manufacturing/models/sf_technology_design.py b/sf_manufacturing/models/sf_technology_design.py new file mode 100644 index 00000000..f4e4d176 --- /dev/null +++ b/sf_manufacturing/models/sf_technology_design.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from odoo import fields, models + + +class sf_technology_design(models.Model): + _name = 'sf.technology.design' + _description = "工艺设计" + + name = fields.Char('工序') + panel = fields.Char('加工面') + sequence = fields.Integer('序号') + time_cycle_manual = fields.Float('预计时长') + production_id = fields.Many2one('mrp.production') + active = fields.Boolean('有效', default=True) + + def json_technology_design_str(self, k, route): + workorders_values_str = [0, '', { + 'name': route.route_workcenter_id.name, + 'panel': k, + 'sequence': False, + 'time_cycle_manual':route.route_workcenter_id.time_cycle_manual }] + return workorders_values_str diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 40d159d5..a48d9461 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -284,6 +284,7 @@ class StockRule(models.Model): 'product_id': production.product_id.id, 'state': 'draft', }) + technology_design_values = [] all_production = productions grouped_product_ids = {k: list(g) for k, g in groupby(all_production, key=lambda x: x.product_id.id)} # 初始化一个字典来存储每个product_id对应的生产订单名称列表 @@ -355,15 +356,32 @@ class StockRule(models.Model): self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i], production_item, product_id_to_production_names) + + if production.product_id.categ_id.type == '成品': + # 根据加工面板的面数及成品工序模板生成工序设计 + i = 0 + for k in (production.product_id.model_processing_panel.split(',')): + product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search( + [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], + order='sequence asc' + ) + i += 1 + for route in product_routing_workcenter: + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(k, route)) + for process in sorted_process_parameters: + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(k, process)) + # # 同一个产品多个制造订单对应一个编程单和模型库 # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递 - if not production_item.programming_no: - if not production_programming.programming_no: - production_item.fetchCNC( - ', '.join(product_id_to_production_names[production_item.product_id.id])) - else: - production_item.write({'programming_no': production_programming.programming_no, - 'programming_state': '编程中'}) + # if not production_item.programming_no: + # if not production_programming.programming_no: + # production_item.fetchCNC( + # ', '.join(product_id_to_production_names[production_item.product_id.id])) + # else: + # production_item.write({'programming_no': production_programming.programming_no, + # 'programming_state': '编程中'}) return True diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 4c06c544..3d5aa625 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -70,7 +70,7 @@ - confirmed,pending_cam,progress,rework,scrap,done + technology_to_confirmed,confirmed,pending_cam,progress,rework,scrap,done From 84db3a92beb761347104bb09301c35367aefde1a Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 6 Nov 2024 10:46:21 +0800 Subject: [PATCH 04/61] =?UTF-8?q?=E8=A1=A8=E9=9D=A2=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E5=A4=96=E5=8D=8F=E9=87=87=E8=B4=AD=E5=8D=95=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E2=80=9C=E9=87=87=E8=B4=AD=E7=B1=BB=E5=9E=8B",=E9=BB=98?= =?UTF-8?q?=E8=AE=A4consignment=EF=BC=88=E5=A7=94=E5=A4=96=E5=8A=A0?= =?UTF-8?q?=E5=B7=A5=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_sale/models/sale_order.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 3f2aa5f9..10418d05 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -208,7 +208,8 @@ class RePurchaseOrder(models.Model): compute='_compute_user_id', store=True) - purchase_type = fields.Selection([('standard', '标准采购'), ('consignment', '委外加工')], string='采购类型', default='standard') + purchase_type = fields.Selection([('standard', '标准采购'), ('consignment', '委外加工')], string='采购类型', + default='standard') @api.depends('partner_id') def _compute_user_id(self): @@ -273,6 +274,7 @@ class RePurchaseOrder(models.Model): 'partner_id': server_template.seller_ids.partner_id.id, 'origin': ','.join(production_process), 'state': 'draft', + 'purchase_type': 'consignment', 'order_line': server_product_process}) # self.env.cr.commit() From fa30e0c1dab00cae518a77f3997b7bab3f46130d Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Wed, 6 Nov 2024 17:44:13 +0800 Subject: [PATCH 05/61] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_base/security/group_security.xml | 5 + .../models/mrp_routing_workcenter.py | 7 +- .../models/sf_technology_design.py | 13 +- sf_manufacturing/models/stock.py | 131 +++++++++++------- sf_manufacturing/security/ir.model.access.csv | 5 +- .../views/mrp_production_addional_change.xml | 14 ++ .../views/mrp_routing_workcenter_view.xml | 1 + 7 files changed, 119 insertions(+), 57 deletions(-) diff --git a/sf_base/security/group_security.xml b/sf_base/security/group_security.xml index b45a2dbd..c08a0ad4 100644 --- a/sf_base/security/group_security.xml +++ b/sf_base/security/group_security.xml @@ -46,6 +46,11 @@ + + 工艺工程师 + + + 计划 diff --git a/sf_manufacturing/models/mrp_routing_workcenter.py b/sf_manufacturing/models/mrp_routing_workcenter.py index a584379f..ef451df7 100644 --- a/sf_manufacturing/models/mrp_routing_workcenter.py +++ b/sf_manufacturing/models/mrp_routing_workcenter.py @@ -7,15 +7,16 @@ class ResMrpRoutingWorkcenter(models.Model): _inherit = 'mrp.routing.workcenter' routing_type = fields.Selection([ - # ('获取CNC加工程序', '获取CNC加工程序'), ('装夹预调', '装夹预调'), - # ('前置三元定位检测', '前置三元定位检测'), ('CNC加工', 'CNC加工'), - # ('后置三元质量检测', '后置三元质量检测'), ('解除装夹', '解除装夹'), ('切割', '切割'), ('表面工艺', '表面工艺') ], string="工序类型") + routing_tag = fields.Selection([ + ('Standard', '标准'), + ('special', '特殊') + ], string="标签") is_repeat = fields.Boolean('重复', default=False) workcenter_id = fields.Many2one('mrp.workcenter', required=False) workcenter_ids = fields.Many2many('mrp.workcenter', 'rel_workcenter_route', required=True) diff --git a/sf_manufacturing/models/sf_technology_design.py b/sf_manufacturing/models/sf_technology_design.py index f4e4d176..afb5f05b 100644 --- a/sf_manufacturing/models/sf_technology_design.py +++ b/sf_manufacturing/models/sf_technology_design.py @@ -11,12 +11,17 @@ class sf_technology_design(models.Model): sequence = fields.Integer('序号') time_cycle_manual = fields.Float('预计时长') production_id = fields.Many2one('mrp.production') + is_auto = fields.Boolean('是否自动生成', default=False) active = fields.Boolean('有效', default=True) - def json_technology_design_str(self, k, route): + def json_technology_design_str(self, k, route_name, time_cycle_manual, i): workorders_values_str = [0, '', { - 'name': route.route_workcenter_id.name, + 'name': route_name, 'panel': k, - 'sequence': False, - 'time_cycle_manual':route.route_workcenter_id.time_cycle_manual }] + 'sequence': i, + 'is_auto': True, + 'time_cycle_manual': time_cycle_manual}] return workorders_values_str + + def unlink_technology_design(self): + self.active = False diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index a48d9461..6fd56eb3 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -294,33 +294,31 @@ class StockRule(models.Model): # 为同一个product_id创建一个生产订单名称列表 product_id_to_production_names[product_id] = [production.name for production in all_production] for production_item in productions: - production_programming = self.env['mrp.production'].search( [('product_id.id', '=', production_item.product_id.id), ('origin', '=', production_item.origin)], limit=1, order='id asc') if production_item.product_id.id in product_id_to_production_names: - if not production_programming.programming_no: - if production_item.product_id.model_process_parameters_ids: - is_purchase = False - sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids, - key=lambda w: w.id) + if production_item.product_id.model_process_parameters_ids: + is_purchase = False + sorted_process_parameters = sorted(production_item.product_id.model_process_parameters_ids, + key=lambda w: w.id) - consecutive_process_parameters = [] - m = 0 - for i in range(len(sorted_process_parameters) - 1): - if m == 0: - is_purchase = False - if self.env['product.template']._get_process_parameters_product( - sorted_process_parameters[i]).partner_id == self.env[ - 'product.template']._get_process_parameters_product(sorted_process_parameters[ - i + 1]).partner_id and \ - sorted_process_parameters[i].gain_way == '外协': - if sorted_process_parameters[i] not in consecutive_process_parameters: - consecutive_process_parameters.append(sorted_process_parameters[i]) - consecutive_process_parameters.append(sorted_process_parameters[i + 1]) - m += 1 - continue + consecutive_process_parameters = [] + m = 0 + for i in range(len(sorted_process_parameters) - 1): + if m == 0: + is_purchase = False + if self.env['product.template']._get_process_parameters_product( + sorted_process_parameters[i]).partner_id == self.env[ + 'product.template']._get_process_parameters_product(sorted_process_parameters[ + i + 1]).partner_id and \ + sorted_process_parameters[i].gain_way == '外协': + if sorted_process_parameters[i] not in consecutive_process_parameters: + consecutive_process_parameters.append(sorted_process_parameters[i]) + consecutive_process_parameters.append(sorted_process_parameters[i + 1]) + m += 1 + continue else: if m == len(consecutive_process_parameters) - 1 and m != 0: self.env['purchase.order'].get_purchase_order(consecutive_process_parameters, @@ -330,7 +328,7 @@ class StockRule(models.Model): is_purchase = True consecutive_process_parameters = [] m = 0 - # 当前面的连续外协采购单生成再生成当前外协采购单 + # 当前面的连续外协采购单生成再生成当前外协采购单 if is_purchase is False: self.env['purchase.order'].get_purchase_order(consecutive_process_parameters, production_item, @@ -356,33 +354,70 @@ class StockRule(models.Model): self.env['purchase.order'].get_purchase_order(sorted_process_parameters[i], production_item, product_id_to_production_names) + if not technology_design_values: + if production.product_id.categ_id.type == '成品': + production.product_id.model_processing_panel = 'ZM,FM' + # 根据加工面板的面数及成品工序模板生成工序设计 + i = 0 + for k in (production.product_id.model_processing_panel.split(',')): + product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search( + [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], + order='sequence asc' + ) + for route in product_routing_workcenter: + i += 1 + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(k, + route.route_workcenter_id.name, + route.route_workcenter_id.time_cycle_manual, + i)) + surface_technics_arr = [] + route_workcenter_arr = [] + for process_param in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids.filtered( + lambda st: st.id in production.product_id.model_process_parameters_ids.ids): + # if item.route_workcenter_id.surface_technics_id.id: + # for process_param in production.product_id.model_process_parameters_ids: + logging.info('process_param:%s%s' % (process_param.id, process_param.name)) + if item.route_workcenter_id.surface_technics_id == process_param.process_id: + logging.info( + 'surface_technics_id:%s%s' % ( + item.route_workcenter_id.surface_technics_id.id, + item.route_workcenter_id.surface_technics_id.name)) + surface_technics_arr.append( + item.route_workcenter_id.surface_technics_id.id) + route_workcenter_arr.append(item.route_workcenter_id.id) + if surface_technics_arr: + production_process = self.env['sf.production.process'].search( + [('id', 'in', surface_technics_arr)], + order='sequence asc' + ) + for p in production_process: + logging.info('production_process:%s' % p.name) + process_parameter = production.product_id.model_process_parameters_ids.filtered( + lambda pm: pm.process_id.id == p.id) + if process_parameter: + i += 1 + route_production_process = self.env[ + 'mrp.routing.workcenter'].search( + [('surface_technics_id', '=', p.id), + ('id', 'in', route_workcenter_arr)]) + technology_design_values.append( + self.env['sf.technology.design'].json_technology_design_str(k, + process_parameter.display_name, + route_production_process.time_cycle_manual, + i)) + productions.technology_design_ids = technology_design_values - if production.product_id.categ_id.type == '成品': - # 根据加工面板的面数及成品工序模板生成工序设计 - i = 0 - for k in (production.product_id.model_processing_panel.split(',')): - product_routing_workcenter = self.env['sf.product.model.type.routing.sort'].search( - [('product_model_type_id', '=', production.product_id.product_model_type_id.id)], - order='sequence asc' - ) - i += 1 - for route in product_routing_workcenter: - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(k, route)) - for process in sorted_process_parameters: - technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(k, process)) - - # # 同一个产品多个制造订单对应一个编程单和模型库 - # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递 - # if not production_item.programming_no: - # if not production_programming.programming_no: - # production_item.fetchCNC( - # ', '.join(product_id_to_production_names[production_item.product_id.id])) - # else: - # production_item.write({'programming_no': production_programming.programming_no, - # 'programming_state': '编程中'}) - return True + # # 同一个产品多个制造订单对应一个编程单和模型库 + # # 只调用一次fetchCNC,并将所有生产订单的名称作为字符串传递 + # if not production_item.programming_no: + # if not production_programming.programming_no: + # production_item.fetchCNC( + # ', '.join(product_id_to_production_names[production_item.product_id.id])) + # else: + # production_item.write({'programming_no': production_programming.programming_no, + # 'programming_state': '编程中'}) + return True class ProductionLot(models.Model): diff --git a/sf_manufacturing/security/ir.model.access.csv b/sf_manufacturing/security/ir.model.access.csv index be71cb0d..270c0f18 100644 --- a/sf_manufacturing/security/ir.model.access.csv +++ b/sf_manufacturing/security/ir.model.access.csv @@ -165,7 +165,8 @@ access_sf_agv_scheduling_group_sf_order_user,sf_agv_scheduling_group_sf_order_us access_sf_agv_scheduling_group_sf_mrp_manager,sf_agv_scheduling_group_sf_mrp_manager,model_sf_agv_scheduling,sf_base.group_sf_mrp_manager,1,1,1,0 access_sf_agv_scheduling_group_sf_equipment_user,sf_agv_scheduling_group_sf_equipment_user,model_sf_agv_scheduling,sf_base.group_sf_equipment_user,1,1,1,0 - - +access_sf_technology_design_group_plan_dispatch,sf_technology_design_group_plan_dispatch,model_sf_technology_design,sf_base.group_plan_dispatch,1,1,1,0 +access_sf_technology_design_group_sf_mrp_manager,sf_technology_design_group_sf_mrp_manager,model_sf_technology_design,sf_base.group_sf_mrp_manager,1,1,1,0 +access_sf_technology_design_group_production_engineer,sf_technology_design_group_production_engineer,model_sf_technology_design,sf_base.group_production_engineer,1,1,1,0 diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 3d5aa625..42b68eae 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -337,6 +337,20 @@ + + + + + + + + + + + + diff --git a/sf_manufacturing/views/mrp_routing_workcenter_view.xml b/sf_manufacturing/views/mrp_routing_workcenter_view.xml index eada92d9..ddb9558c 100644 --- a/sf_manufacturing/views/mrp_routing_workcenter_view.xml +++ b/sf_manufacturing/views/mrp_routing_workcenter_view.xml @@ -16,6 +16,7 @@ + From 111c0f6dae80c8cd7ff491011d1207ab2dacd57c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Wed, 6 Nov 2024 17:53:33 +0800 Subject: [PATCH 06/61] =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_sale_route_picking/__init__.py | 4 + jikimo_sale_route_picking/__manifest__.py | 26 ++++++ .../controllers/__init__.py | 2 + jikimo_sale_route_picking/controllers/main.py | 46 ++++++++++ .../data/product_templates.xml | 85 +++++++++++++++++++ .../data/stock_routes.xml | 31 +++++++ jikimo_sale_route_picking/models/__init__.py | 3 + .../models/product_product.py | 7 ++ .../models/product_template.py | 10 +++ .../security/group_security.xml | 10 +++ .../security/ir.model.access.csv | 8 ++ .../views/product_product_views.xml | 15 ++++ .../views/sale_order_views.xml | 83 ++++++++++++++++++ .../product_template_management_view.xml | 10 +-- sf_plan_management/i18n/zh_CN.po | 2 +- sf_sale/models/sale_order.py | 10 +-- sf_sale/views/sale_order_view.xml | 8 +- 17 files changed, 342 insertions(+), 18 deletions(-) create mode 100644 jikimo_sale_route_picking/__init__.py create mode 100644 jikimo_sale_route_picking/__manifest__.py create mode 100644 jikimo_sale_route_picking/controllers/__init__.py create mode 100644 jikimo_sale_route_picking/controllers/main.py create mode 100644 jikimo_sale_route_picking/data/product_templates.xml create mode 100644 jikimo_sale_route_picking/data/stock_routes.xml create mode 100644 jikimo_sale_route_picking/models/__init__.py create mode 100644 jikimo_sale_route_picking/models/product_product.py create mode 100644 jikimo_sale_route_picking/models/product_template.py create mode 100644 jikimo_sale_route_picking/security/group_security.xml create mode 100644 jikimo_sale_route_picking/security/ir.model.access.csv create mode 100644 jikimo_sale_route_picking/views/product_product_views.xml create mode 100644 jikimo_sale_route_picking/views/sale_order_views.xml diff --git a/jikimo_sale_route_picking/__init__.py b/jikimo_sale_route_picking/__init__.py new file mode 100644 index 00000000..7909ef3a --- /dev/null +++ b/jikimo_sale_route_picking/__init__.py @@ -0,0 +1,4 @@ +# -*- coding: utf-8 -*- +from . import models + +from . import controllers diff --git a/jikimo_sale_route_picking/__manifest__.py b/jikimo_sale_route_picking/__manifest__.py new file mode 100644 index 00000000..b72e9a37 --- /dev/null +++ b/jikimo_sale_route_picking/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +{ + 'name': '机企猫 供货路线选择', + 'version': '16.0.1.0.0', + 'summary': """ 报价单提供(自动化产线加工/人工线下加工/外购/委外加工)多种供货路线选择 """, + 'author': 'fox', + 'website': '', + 'category': '', + 'depends': ['product', 'sf_dlm_management', 'sale_stock'], + "data": [ + 'security/group_security.xml', + 'security/ir.model.access.csv', + 'data/stock_routes.xml', + 'data/product_templates.xml', + 'views/sale_order_views.xml', + 'views/product_product_views.xml', + ],'assets': { + # 'web.assets_backend': [ + # 'jikimo_sale_route_picking/static/src/**/*' + # ], + }, + 'application': True, + 'installable': True, + 'auto_install': False, + 'license': 'LGPL-3', +} diff --git a/jikimo_sale_route_picking/controllers/__init__.py b/jikimo_sale_route_picking/controllers/__init__.py new file mode 100644 index 00000000..cd4d6a8b --- /dev/null +++ b/jikimo_sale_route_picking/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import main \ No newline at end of file diff --git a/jikimo_sale_route_picking/controllers/main.py b/jikimo_sale_route_picking/controllers/main.py new file mode 100644 index 00000000..0c0390e7 --- /dev/null +++ b/jikimo_sale_route_picking/controllers/main.py @@ -0,0 +1,46 @@ +import logging +import json +from odoo import http +from odoo.http import request +from odoo.addons.sf_bf_connect.controllers.controllers import Sf_Bf_Connect + +_logger = logging.getLogger(__name__) + +class JikimoSaleRoutePicking(Sf_Bf_Connect): + + @http.route('/api/bfm_process_order/list', type='http', auth='sf_token', methods=['GET', 'POST'], csrf=False, + cors="*") + def get_bfm_process_order_list(self, **kw): + """ + 接收业务平台加工订单分配工厂时传送来的订单数据并生成销售订单和产品及坯料 + :param kw: + :return: + """ + res = {'status': 1, 'factory_order_no': ''} + _logger.info('get_bfm_process_order_list:%s' % kw['order_number']) + try: + product_id = request.env.ref('jikimo_sale_route_picking.product_template_default').sudo() + company_id = request.env.ref('base.main_company').sudo() + bfm_process_order_list = json.loads(kw['bfm_process_order_list']) + order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create( + company_id, kw['delivery_name'], kw['delivery_telephone'], kw['delivery_address'], + kw['delivery_end_date'], kw['payments_way'], kw['pay_way'], state='draft') + i = 1 + # 给sale_order的default_code字段赋值 + aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)]) + _logger.info('get_bfm_process_or===================================:%s' % order_id.name) + aa.default_code = kw['order_number'] + if kw.get('logistics_way'): + aa.logistics_way = kw['logistics_way'] + _logger.info('get_bfm_process_order_listaaaaaaaaaaaaaaaaaaaaaaaaaaaa================:%s' % aa.default_code) + for item in bfm_process_order_list: + product = request.env['product.template'].sudo().product_create(product_id, item, order_id, + kw['order_number'], i) + order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item) + i += 1 + res['factory_order_no'] = order_id.name + except Exception as e: + _logger.info('get_bfm_process_order_list error:%s' % e) + res['status'] = -1 + res['message'] = '工厂创建销售订单和产品失败,请联系管理员' + return json.JSONEncoder().encode(res) diff --git a/jikimo_sale_route_picking/data/product_templates.xml b/jikimo_sale_route_picking/data/product_templates.xml new file mode 100644 index 00000000..df965fd0 --- /dev/null +++ b/jikimo_sale_route_picking/data/product_templates.xml @@ -0,0 +1,85 @@ + + + + + 人工线下加工模板 + + + + delivery + product + false + + + + true + serial + true + true + + + + 成品外购模板 + + + + serial + product + + + + true + + + + 成品委外加工模板 + + + + serial + product + + + + true + + + + 成品初始化模板 + + + + serial + product + + + + true + + + + + + + + + 坯料客供料模板 + + + + false + serial + product + + + + + + + \ No newline at end of file diff --git a/jikimo_sale_route_picking/data/stock_routes.xml b/jikimo_sale_route_picking/data/stock_routes.xml new file mode 100644 index 00000000..eb6a340c --- /dev/null +++ b/jikimo_sale_route_picking/data/stock_routes.xml @@ -0,0 +1,31 @@ + + + + + 带料加工 + true + true + + 16 + + + + 客供料入库 + incoming + true + + DL + + + + + + 带料收货 + + + + + pull + + + \ No newline at end of file diff --git a/jikimo_sale_route_picking/models/__init__.py b/jikimo_sale_route_picking/models/__init__.py new file mode 100644 index 00000000..f59a4700 --- /dev/null +++ b/jikimo_sale_route_picking/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import product_template +from . import product_product diff --git a/jikimo_sale_route_picking/models/product_product.py b/jikimo_sale_route_picking/models/product_product.py new file mode 100644 index 00000000..996a9d5c --- /dev/null +++ b/jikimo_sale_route_picking/models/product_product.py @@ -0,0 +1,7 @@ +from odoo import models, fields + +class ProductProduct(models.Model): + _inherit = 'product.product' + + # 是否客供料 + is_customer_provided = fields.Boolean(string='是否客供料', related='product_tmpl_id.is_customer_provided') diff --git a/jikimo_sale_route_picking/models/product_template.py b/jikimo_sale_route_picking/models/product_template.py new file mode 100644 index 00000000..6b2bc29d --- /dev/null +++ b/jikimo_sale_route_picking/models/product_template.py @@ -0,0 +1,10 @@ +from odoo import models, fields + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + is_manual_processing = fields.Boolean(string='人工线下加工') + is_customer_provided = fields.Boolean(string='客供料') + + def product_create(self, product_id, item, order_id, order_number, i): + product_id = super(ProductTemplate, self).product_create(product_id, item, order_id, order_number, i) diff --git a/jikimo_sale_route_picking/security/group_security.xml b/jikimo_sale_route_picking/security/group_security.xml new file mode 100644 index 00000000..84bf5b89 --- /dev/null +++ b/jikimo_sale_route_picking/security/group_security.xml @@ -0,0 +1,10 @@ + + + + + + 工艺工程师 + + + + \ No newline at end of file diff --git a/jikimo_sale_route_picking/security/ir.model.access.csv b/jikimo_sale_route_picking/security/ir.model.access.csv new file mode 100644 index 00000000..aac13f29 --- /dev/null +++ b/jikimo_sale_route_picking/security/ir.model.access.csv @@ -0,0 +1,8 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sale_order_group_production_engineer,sale.order_group_production_engineer,sale.model_sale_order,jikimo_sale_route_picking.group_production_engineer,1,1,0,0 +access_sale_order_line_group_production_engineer,sale_order_line_group_production_engineer,sale.model_sale_order_line,jikimo_sale_route_picking.group_production_engineer,1,1,0,0 +access_product_product_group_production_engineer,product_product_group_production_engineer,product.model_product_product,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 +access_product_template_group_production_engineer,product_template_group_production_engineer,product.model_product_template,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 +access_stock_picking_group_production_engineer,stock_picking_group_production_engineer,stock.model_stock_picking,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 +access_stock_move_group_production_engineer,stock_move_group_production_engineer,stock.model_stock_move,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 +access_mrp_bom_group_production_engineer,mrp_bom_group_production_engineer,mrp.model_mrp_bom,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 \ No newline at end of file diff --git a/jikimo_sale_route_picking/views/product_product_views.xml b/jikimo_sale_route_picking/views/product_product_views.xml new file mode 100644 index 00000000..e3f896b5 --- /dev/null +++ b/jikimo_sale_route_picking/views/product_product_views.xml @@ -0,0 +1,15 @@ + + + + view.product.template.form.inherit.sf + product.template + + + + + + + + + + \ No newline at end of file diff --git a/jikimo_sale_route_picking/views/sale_order_views.xml b/jikimo_sale_route_picking/views/sale_order_views.xml new file mode 100644 index 00000000..027a3054 --- /dev/null +++ b/jikimo_sale_route_picking/views/sale_order_views.xml @@ -0,0 +1,83 @@ + + + + view.sale.order.form.inherit.sf + + sale.order + + + + + + + + + + jikimo.sale.order.search.inherit.quotation + sale.order + primary + + + + + + + + + + jikimo.sale.order.search.inherit.quotation + sale.order + primary + + + + + + + + + + + + + + + + + 报价单 + ir.actions.act_window + sale.order + tree,kanban,form,calendar,pivot,graph,activity + + {'search_default_route': 1} + +

+ Create a new quotation, the first step of a new sale! +

+ Once the quotation is confirmed by the customer, it becomes a sales order.
You will be able to create an invoice and collect the payment. +

+
+
+ + + + + + + +
diff --git a/sf_dlm_management/views/product_template_management_view.xml b/sf_dlm_management/views/product_template_management_view.xml index 1862e33c..0fe6413b 100644 --- a/sf_dlm_management/views/product_template_management_view.xml +++ b/sf_dlm_management/views/product_template_management_view.xml @@ -110,15 +110,13 @@ - - + + - - + + diff --git a/sf_plan_management/i18n/zh_CN.po b/sf_plan_management/i18n/zh_CN.po index 0b957921..d9511db1 100644 --- a/sf_plan_management/i18n/zh_CN.po +++ b/sf_plan_management/i18n/zh_CN.po @@ -7059,7 +7059,7 @@ msgstr "" #. module: sf_dlm #: model:product.template,name:sf_dlm.product_template_sf_product_template msgid "CNC加工产品模板" -msgstr "冲压模具滑块" +msgstr "自动化产线加工模板" #. module: sf_tool_management #: model:ir.model,name:sf_tool_management.model_sf_cnc_processing diff --git a/sf_sale/models/sale_order.py b/sf_sale/models/sale_order.py index 53f73aef..251554b5 100644 --- a/sf_sale/models/sale_order.py +++ b/sf_sale/models/sale_order.py @@ -60,7 +60,7 @@ class ReSaleOrder(models.Model): # 业务平台分配工厂后在智能工厂先创建销售订单 def sale_order_create(self, company_id, delivery_name, delivery_telephone, delivery_address, - deadline_of_delivery, payments_way, pay_way): + deadline_of_delivery, payments_way, pay_way, state='sale'): now_time = datetime.datetime.now() partner = self.get_customer() data = { @@ -69,7 +69,7 @@ class ReSaleOrder(models.Model): 'name': self.env['ir.sequence'].next_by_code('sale.order', sequence_date=now_time), 'partner_id': partner.id, 'check_status': 'approved', - 'state': 'sale', + 'state': state, 'user_id': partner.user_id.id, 'person_of_delivery': delivery_name, 'telephone_of_delivery': delivery_telephone, @@ -133,8 +133,7 @@ class ReSaleOrder(models.Model): 'product_uom_qty': item['number'], 'model_glb_file': base64.b64decode(item['model_file']), 'remark': item.get('remark'), - 'is_incoming_material': item.get('is_incoming_material'), - 'incoming_size': item.get('incoming_size'), + 'is_incoming_material': item.get('is_incoming_material') } return self.env['sale.order.line'].with_context(skip_procurement=True).create(vals) @@ -175,8 +174,7 @@ class ResaleOrderLine(models.Model): check_status = fields.Selection(related='order_id.check_status') remark = fields.Char('备注') - is_incoming_material = fields.Boolean('是否带料', default=False) - incoming_size = fields.Char('带料尺寸') + is_incoming_material = fields.Boolean('客供料', default=False) @api.depends('product_template_id') def _compute_model_glb_file(self): diff --git a/sf_sale/views/sale_order_view.xml b/sf_sale/views/sale_order_view.xml index a84a2b44..f5dba649 100644 --- a/sf_sale/views/sale_order_view.xml +++ b/sf_sale/views/sale_order_view.xml @@ -118,8 +118,7 @@ - - + {'readonly': [('state', 'in', ['cancel','sale'])]} @@ -167,7 +166,6 @@ - @@ -207,12 +205,12 @@ 下单时间 - + From 6679c200e1e936ae9de812cf72566a90587108ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Thu, 7 Nov 2024 08:41:25 +0800 Subject: [PATCH 07/61] =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jikimo_sale_route_picking/__manifest__.py | 1 - .../security/group_security.xml | 10 ---------- .../security/ir.model.access.csv | 14 +++++++------- .../views/sale_order_views.xml | 6 +++--- 4 files changed, 10 insertions(+), 21 deletions(-) delete mode 100644 jikimo_sale_route_picking/security/group_security.xml diff --git a/jikimo_sale_route_picking/__manifest__.py b/jikimo_sale_route_picking/__manifest__.py index b72e9a37..e3da3a60 100644 --- a/jikimo_sale_route_picking/__manifest__.py +++ b/jikimo_sale_route_picking/__manifest__.py @@ -8,7 +8,6 @@ 'category': '', 'depends': ['product', 'sf_dlm_management', 'sale_stock'], "data": [ - 'security/group_security.xml', 'security/ir.model.access.csv', 'data/stock_routes.xml', 'data/product_templates.xml', diff --git a/jikimo_sale_route_picking/security/group_security.xml b/jikimo_sale_route_picking/security/group_security.xml deleted file mode 100644 index 84bf5b89..00000000 --- a/jikimo_sale_route_picking/security/group_security.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - 工艺工程师 - - - - \ No newline at end of file diff --git a/jikimo_sale_route_picking/security/ir.model.access.csv b/jikimo_sale_route_picking/security/ir.model.access.csv index aac13f29..3b276af9 100644 --- a/jikimo_sale_route_picking/security/ir.model.access.csv +++ b/jikimo_sale_route_picking/security/ir.model.access.csv @@ -1,8 +1,8 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_sale_order_group_production_engineer,sale.order_group_production_engineer,sale.model_sale_order,jikimo_sale_route_picking.group_production_engineer,1,1,0,0 -access_sale_order_line_group_production_engineer,sale_order_line_group_production_engineer,sale.model_sale_order_line,jikimo_sale_route_picking.group_production_engineer,1,1,0,0 -access_product_product_group_production_engineer,product_product_group_production_engineer,product.model_product_product,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 -access_product_template_group_production_engineer,product_template_group_production_engineer,product.model_product_template,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 -access_stock_picking_group_production_engineer,stock_picking_group_production_engineer,stock.model_stock_picking,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 -access_stock_move_group_production_engineer,stock_move_group_production_engineer,stock.model_stock_move,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 -access_mrp_bom_group_production_engineer,mrp_bom_group_production_engineer,mrp.model_mrp_bom,jikimo_sale_route_picking.group_production_engineer,1,0,0,0 \ No newline at end of file +access_sale_order_group_production_engineer,sale.order_group_production_engineer,sale.model_sale_order,sf_base.group_production_engineer,1,1,0,0 +access_sale_order_line_group_production_engineer,sale_order_line_group_production_engineer,sale.model_sale_order_line,sf_base.group_production_engineer,1,1,0,0 +access_product_product_group_production_engineer,product_product_group_production_engineer,product.model_product_product,sf_base.group_production_engineer,1,0,0,0 +access_product_template_group_production_engineer,product_template_group_production_engineer,product.model_product_template,sf_base.group_production_engineer,1,0,0,0 +access_stock_picking_group_production_engineer,stock_picking_group_production_engineer,stock.model_stock_picking,sf_base.group_production_engineer,1,0,0,0 +access_stock_move_group_production_engineer,stock_move_group_production_engineer,stock.model_stock_move,sf_base.group_production_engineer,1,0,0,0 +access_mrp_bom_group_production_engineer,mrp_bom_group_production_engineer,mrp.model_mrp_bom,sf_base.group_production_engineer,1,0,0,0 \ No newline at end of file diff --git a/jikimo_sale_route_picking/views/sale_order_views.xml b/jikimo_sale_route_picking/views/sale_order_views.xml index 027a3054..a178df0a 100644 --- a/jikimo_sale_route_picking/views/sale_order_views.xml +++ b/jikimo_sale_route_picking/views/sale_order_views.xml @@ -60,14 +60,14 @@ From 330726007d54f7fb4cb632b8c0886fc3568696a5 Mon Sep 17 00:00:00 2001 From: yuxianghui <3437689193@qq.com> Date: Thu, 7 Nov 2024 16:26:48 +0800 Subject: [PATCH 08/61] =?UTF-8?q?1=E3=80=81=E6=B7=BB=E5=8A=A0=E5=8F=AA?= =?UTF-8?q?=E6=9C=89=E5=AE=A2=E4=BE=9B=E6=96=99=E5=85=A5=E5=BA=93=E5=8D=95?= =?UTF-8?q?=E6=89=8D=E8=83=BD=E7=9C=8B=E8=A7=81=E6=94=B6=E8=B4=A7=E4=BA=BA?= =?UTF-8?q?/=E8=81=94=E7=B3=BB=E5=9C=B0=E5=9D=80/=E7=94=B5=E8=AF=9D?= =?UTF-8?q?=E5=8F=B7=E7=A0=81=E7=AD=89=E5=AD=97=E6=AE=B5;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_maintenance/models/sf_maintenance.py | 4 ++++ sf_manufacturing/models/stock.py | 19 +++++++++++-------- sf_manufacturing/views/stock_picking_view.xml | 11 +++++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/sf_maintenance/models/sf_maintenance.py b/sf_maintenance/models/sf_maintenance.py index 3d68bb9a..de6be8da 100644 --- a/sf_maintenance/models/sf_maintenance.py +++ b/sf_maintenance/models/sf_maintenance.py @@ -689,6 +689,8 @@ class SfMaintenanceEquipment(models.Model): if next_date < date_now: next_date = date_now else: + if not equipment.initial_action_date: + raise ValidationError('重置保养日期不能为空!!!') next_date = equipment.initial_action_date + timedelta(days=equipment.period) equipment.next_action_date = next_date else: @@ -735,6 +737,8 @@ class SfMaintenanceEquipment(models.Model): if next_date < date_now: next_date = date_now else: + if not equipment.initial_overhaul_date: + raise ValidationError('重置维修日期不能为空') next_date = equipment.initial_overhaul_date + timedelta(days=equipment.overhaul_period) equipment.overhaul_date = next_date else: diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 55667d41..2060ea48 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -554,7 +554,9 @@ class StockPicking(models.Model): retrospect_ref = fields.Char('追溯参考', compute='_compute_move_ids', store=True) - @api.depends('move_ids') + picking_type_sequence_code = fields.Char(related='picking_type_id.sequence_code') + + @api.depends('move_ids', 'move_ids.product_id') def _compute_move_ids(self): for item in self: if item.move_ids: @@ -574,13 +576,14 @@ class StockPicking(models.Model): default_codes = '' if boms: for bom in boms: - code = bom.product_tmpl_id.default_code.split('-')[-1] - default_code = bom.product_tmpl_id.default_code.split(f'-{code}')[0] - if default_code not in default_codes: - if default_codes == '': - default_codes = default_code - else: - default_codes = default_codes + ',' + default_code + if bom.product_tmpl_id.default_code: + code = bom.product_tmpl_id.default_code.split('-')[-1] + default_code = bom.product_tmpl_id.default_code.split(f'-{code}')[0] + if default_code not in default_codes: + if default_codes == '': + default_codes = default_code + else: + default_codes = default_codes + ',' + default_code item.retrospect_ref = default_codes elif item.picking_type_id.sequence_code in ['INT', 'PC']: pass diff --git a/sf_manufacturing/views/stock_picking_view.xml b/sf_manufacturing/views/stock_picking_view.xml index 356059c2..2fae1fac 100644 --- a/sf_manufacturing/views/stock_picking_view.xml +++ b/sf_manufacturing/views/stock_picking_view.xml @@ -18,10 +18,13 @@ - - - - + + + + + From d419efa3c327ab71ba702876afb0779ca0a26142 Mon Sep 17 00:00:00 2001 From: "jinling.yang" Date: Thu, 7 Nov 2024 17:59:28 +0800 Subject: [PATCH 09/61] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=B7=A5=E8=89=BA?= =?UTF-8?q?=E7=A1=AE=E8=AE=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_manufacturing/models/mrp_production.py | 38 +++++++++++++++++++ .../models/mrp_routing_workcenter.py | 13 ++++++- .../models/sf_technology_design.py | 13 ++++--- sf_manufacturing/models/stock.py | 20 ++++------ .../views/mrp_production_addional_change.xml | 17 +++++++-- 5 files changed, 79 insertions(+), 22 deletions(-) diff --git a/sf_manufacturing/models/mrp_production.py b/sf_manufacturing/models/mrp_production.py index ebe08942..54b1a61c 100644 --- a/sf_manufacturing/models/mrp_production.py +++ b/sf_manufacturing/models/mrp_production.py @@ -254,6 +254,44 @@ class MrpProduction(models.Model): if production.tool_state == '2': production.state = 'rework' + def technology_confirm(self): + # 判断同一个加工面的标准工序的顺序是否依次排序 + technology_design = self.technology_design_ids.sorted(key=lambda m: m.sequence) + current_design_index = None + for index, design in enumerate(technology_design.filtered(lambda a: a.routing_tag == 'standard')): + if design == current_design: + current_design_index = index + break # 找到了 current_design,跳出循环 + + # 现在我们有了 current_design 的索引,我们可以找到下一条设计 + if current_design_index is not None and current_design_index + 1 < len(technology_design): + next_design = technology_design[current_design_index + 1] + # 下一条设计是 next_design + else: + # 如果 current_design_index 为 None 或者没有下一条设计,则 next_design 为 None + next_design = None + for design in technology_design.filtered(lambda a: a.routing_tag == 'standard'): + routing_type = design.route_id.routing_type + if routing_type in ['装夹预调', 'CNC加工', '解除装夹']: + # standard_designs = [d for d in technology_design_ids if d.routing_tag == 'standard'] + # last_design = technology_design[technology_design.index(design) - 1] + next_design = technology_design[2] + for next_design in technology_design: + next_design_routing_type = next_design.route_id.routing_type + logging.info('next_design:%s' % next_design.route_id.name) + logging.info('next_design面:%s' % next_design.panel) + logging.info('design:%s' % design.route_id.name) + logging.info('design面:%s' % design.panel) + if next_design == design: + break + if design.panel != next_design.panel and routing_type not in ['解除装夹']: + raise UserError('【加工面】为%s的标准工序里含有其他加工面的工序,请调整后重试' % design.panel) + if design.panel == next_design.panel: + if (routing_type == '装夹预调' and next_design_routing_type == '解除装夹') or ( + routing_type == 'CNC加工' and next_design_routing_type == '装夹预调'): + raise UserError('【加工面】为%s的标准工序顺序有误,请调整后重试' % design.panel) + return True + def action_check(self): """ 审核启用 diff --git a/sf_manufacturing/models/mrp_routing_workcenter.py b/sf_manufacturing/models/mrp_routing_workcenter.py index ef451df7..2916bdce 100644 --- a/sf_manufacturing/models/mrp_routing_workcenter.py +++ b/sf_manufacturing/models/mrp_routing_workcenter.py @@ -14,7 +14,7 @@ class ResMrpRoutingWorkcenter(models.Model): ('表面工艺', '表面工艺') ], string="工序类型") routing_tag = fields.Selection([ - ('Standard', '标准'), + ('standard', '标准'), ('special', '特殊') ], string="标签") is_repeat = fields.Boolean('重复', default=False) @@ -23,6 +23,7 @@ class ResMrpRoutingWorkcenter(models.Model): bom_id = fields.Many2one('mrp.bom', required=False) surface_technics_id = fields.Many2one('sf.production.process', string="表面工艺") reserved_duration = fields.Float('预留时长', default=30, tracking=True) + def get_no(self): international_standards = self.search( [('code', '!=', ''), ('active', 'in', [True, False])], @@ -79,3 +80,13 @@ class ResMrpRoutingWorkcenter(models.Model): else: workcenter_id = workcenter_ids[0] return workcenter_id + + @api.model + def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): + if self._context.get('production_id'): + technology_design = self.env['sf.technology.design'].search( + [('production_id', '=', self._context.get('production_id'))]) + route_ids = [t.route_id.id for t in technology_design] + domain = [('id', 'not in', route_ids)] + return self._search(domain, limit=limit, access_rights_uid=name_get_uid) + return super()._name_search(name, args, operator, limit, name_get_uid) diff --git a/sf_manufacturing/models/sf_technology_design.py b/sf_manufacturing/models/sf_technology_design.py index afb5f05b..e5ce0c69 100644 --- a/sf_manufacturing/models/sf_technology_design.py +++ b/sf_manufacturing/models/sf_technology_design.py @@ -6,22 +6,23 @@ class sf_technology_design(models.Model): _name = 'sf.technology.design' _description = "工艺设计" - name = fields.Char('工序') + route_id = fields.Many2one('mrp.routing.workcenter', '工序') panel = fields.Char('加工面') sequence = fields.Integer('序号') - time_cycle_manual = fields.Float('预计时长') + routing_tag = fields.Selection(related='route_id.routing_tag', string='标签', store=True) + time_cycle_manual = fields.Float(related='route_id.time_cycle_manual', string='预计时长') production_id = fields.Many2one('mrp.production') is_auto = fields.Boolean('是否自动生成', default=False) active = fields.Boolean('有效', default=True) - def json_technology_design_str(self, k, route_name, time_cycle_manual, i): + def json_technology_design_str(self, k, route, i): workorders_values_str = [0, '', { - 'name': route_name, + 'route_id': route.id, 'panel': k, 'sequence': i, - 'is_auto': True, - 'time_cycle_manual': time_cycle_manual}] + 'is_auto': True}] return workorders_values_str def unlink_technology_design(self): self.active = False + diff --git a/sf_manufacturing/models/stock.py b/sf_manufacturing/models/stock.py index 64c89d46..70dbdf68 100644 --- a/sf_manufacturing/models/stock.py +++ b/sf_manufacturing/models/stock.py @@ -367,10 +367,7 @@ class StockRule(models.Model): for route in product_routing_workcenter: i += 1 technology_design_values.append( - self.env['sf.technology.design'].json_technology_design_str(k, - route.route_workcenter_id.name, - route.route_workcenter_id.time_cycle_manual, - i)) + self.env['sf.technology.design'].json_technology_design_str(k, route, i)) surface_technics_arr = [] route_workcenter_arr = [] for process_param in production.product_id.product_model_type_id.surface_technics_routing_tmpl_ids.filtered( @@ -403,8 +400,7 @@ class StockRule(models.Model): ('id', 'in', route_workcenter_arr)]) technology_design_values.append( self.env['sf.technology.design'].json_technology_design_str(k, - process_parameter.display_name, - route_production_process.time_cycle_manual, + route_production_process, i)) productions.technology_design_ids = technology_design_values @@ -624,12 +620,12 @@ class StockPicking(models.Model): item.telephone_of_delivery = sale_id.telephone_of_delivery item.address_of_delivery = sale_id.address_of_delivery - bom = self.env['mrp.bom'].sudo().search([('bom_line_ids.product_id', '=', self.move_ids.product_id.id)]) - if bom: - if item.picking_type_id.sequence_code == 'DL': - item.retrospect_ref = bom.product_tmpl_id.default_code - elif item.picking_type_id.sequence_code in ['INT', 'PC']: - item.retrospect_ref = bom.product_tmpl_id.name + # bom = self.env['mrp.bom'].sudo().search([('bom_line_ids.product_id', '=', self.move_ids.product_id.id)]) + # if bom: + # if item.picking_type_id.sequence_code == 'DL': + # item.retrospect_ref = bom.product_tmpl_id.default_code + # elif item.picking_type_id.sequence_code in ['INT', 'PC']: + # item.retrospect_ref = bom.product_tmpl_id.name # 设置外协出入单的名称 def _get_name_Res(self, rescode): diff --git a/sf_manufacturing/views/mrp_production_addional_change.xml b/sf_manufacturing/views/mrp_production_addional_change.xml index 42b68eae..1899aad2 100644 --- a/sf_manufacturing/views/mrp_production_addional_change.xml +++ b/sf_manufacturing/views/mrp_production_addional_change.xml @@ -114,12 +114,18 @@ string="验证" type="object" class="oe_highlight" confirm="There are no components to consume. Are you still sure you want to continue?" data-hotkey="g" groups="sf_base.group_sf_mrp_user"/> + + From 2798ce6183bc6a571f8fcc3aa69e03adde44b926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=83=A1=E5=B0=A7?= Date: Fri, 8 Nov 2024 16:23:34 +0800 Subject: [PATCH 10/61] =?UTF-8?q?=E5=BC=80=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../__init__.py | 14 ++ .../__manifest__.py | 26 +++ .../controllers/__init__.py | 2 + .../controllers/main.py | 52 ++++++ .../data/product_data.xml | 85 ++++++++++ .../data/stock_routes.xml | 32 ++++ .../models/__init__.py | 3 + .../models/product_template.py | 31 ++++ .../models/sale_order.py | 156 ++++++++++++++++++ .../security/ir.model.access.csv | 8 + .../views/product_product_views.xml | 15 ++ .../views/sale_order_views.xml | 104 ++++++++++++ 12 files changed, 528 insertions(+) create mode 100644 jikimo_sale_multiple_supply_methods/__init__.py create mode 100644 jikimo_sale_multiple_supply_methods/__manifest__.py create mode 100644 jikimo_sale_multiple_supply_methods/controllers/__init__.py create mode 100644 jikimo_sale_multiple_supply_methods/controllers/main.py create mode 100644 jikimo_sale_multiple_supply_methods/data/product_data.xml create mode 100644 jikimo_sale_multiple_supply_methods/data/stock_routes.xml create mode 100644 jikimo_sale_multiple_supply_methods/models/__init__.py create mode 100644 jikimo_sale_multiple_supply_methods/models/product_template.py create mode 100644 jikimo_sale_multiple_supply_methods/models/sale_order.py create mode 100644 jikimo_sale_multiple_supply_methods/security/ir.model.access.csv create mode 100644 jikimo_sale_multiple_supply_methods/views/product_product_views.xml create mode 100644 jikimo_sale_multiple_supply_methods/views/sale_order_views.xml diff --git a/jikimo_sale_multiple_supply_methods/__init__.py b/jikimo_sale_multiple_supply_methods/__init__.py new file mode 100644 index 00000000..d5b81964 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/__init__.py @@ -0,0 +1,14 @@ +# -*- coding: utf-8 -*- +from . import models +from . import controllers + +from odoo import api, SUPERUSER_ID + +def _set_init_product_active_false(cr, registry): + env = api.Environment(cr, SUPERUSER_ID, {}) + # 获取所有需要设置的产品模板 + env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').product_variant_id.write({'active': False}) + env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').product_variant_id.write({'active': False}) + env.ref('jikimo_sale_multiple_supply_methods.product_template_default').product_variant_id.write({'active': False}) + env.ref('jikimo_sale_multiple_supply_methods.product_template_raw_material_customer_provided').product_variant_id.write({'active': False}) + env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').product_variant_id.write({'active': False}) diff --git a/jikimo_sale_multiple_supply_methods/__manifest__.py b/jikimo_sale_multiple_supply_methods/__manifest__.py new file mode 100644 index 00000000..dec1cf62 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/__manifest__.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +{ + 'name': '机企猫 多供货方式', + 'version': '16.0.1.0.0', + 'summary': """ 报价单提供(自动化产线加工/人工线下加工/外购/委外加工)多种供货方式选择 """, + 'author': 'fox', + 'website': '', + 'category': '', + 'depends': ['product', 'sf_dlm_management', 'sale_stock'], + "data": [ + 'security/ir.model.access.csv', + 'data/stock_routes.xml', + 'data/product_data.xml', + 'views/sale_order_views.xml', + 'views/product_product_views.xml', + ],'assets': { + # 'web.assets_backend': [ + # 'jikimo_sale_multiple_supply_methods/static/src/**/*' + # ], + }, + 'post_init_hook': '_set_init_product_active_false', + 'application': True, + 'installable': True, + 'auto_install': False, + 'license': 'LGPL-3', +} diff --git a/jikimo_sale_multiple_supply_methods/controllers/__init__.py b/jikimo_sale_multiple_supply_methods/controllers/__init__.py new file mode 100644 index 00000000..cd4d6a8b --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/controllers/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import main \ No newline at end of file diff --git a/jikimo_sale_multiple_supply_methods/controllers/main.py b/jikimo_sale_multiple_supply_methods/controllers/main.py new file mode 100644 index 00000000..9c20e687 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/controllers/main.py @@ -0,0 +1,52 @@ +import logging +import json +from odoo import http +from odoo.http import request +from odoo.addons.sf_bf_connect.controllers.controllers import Sf_Bf_Connect + +_logger = logging.getLogger(__name__) + +class JikimoSaleRoutePicking(Sf_Bf_Connect): + + @http.route('/api/bfm_process_order/list', type='http', auth='sf_token', methods=['GET', 'POST'], csrf=False, + cors="*") + def get_bfm_process_order_list(self, **kw): + """ + 接收业务平台加工订单分配工厂时传送来的订单数据并生成销售订单和产品及坯料 + :param kw: + :return: + """ + res = {'status': 1, 'factory_order_no': ''} + # _logger.info('get_bfm_process_order_list:%s' % kw['order_number']) + try: + product_tmpl_id = request.env.ref('jikimo_sale_multiple_supply_methods.product_template_default').sudo() + product_id = request.env['product.product'].sudo().search( + [('product_tmpl_id', '=', product_tmpl_id.id), ('active', '=', False)], + limit=1, + order='id asc' + ) + company_id = request.env.ref('base.main_company').sudo() + bfm_process_order_list = json.loads(kw['bfm_process_order_list']) + order_id = request.env['sale.order'].with_user(request.env.ref("base.user_admin")).sale_order_create( + company_id, kw['delivery_name'], kw['delivery_telephone'], kw['delivery_address'], + kw['delivery_end_date'], kw['payments_way'], kw['pay_way'], state='draft') + i = 1 + # 给sale_order的default_code字段赋值 + aa = request.env['sale.order'].sudo().search([('name', '=', order_id.name)]) + _logger.info('get_bfm_process_or===================================:%s' % order_id.name) + aa.default_code = kw['order_number'] + if kw.get('logistics_way'): + aa.logistics_way = kw['logistics_way'] + _logger.info('get_bfm_process_order_listaaaaaaaaaaaaaaaaaaaaaaaaaaaa================:%s' % aa.default_code) + for item in bfm_process_order_list: + product = request.env['product.template'].sudo().product_create(product_id, item, order_id, + kw['order_number'], i) + order_id.with_user(request.env.ref("base.user_admin")).sale_order_create_line(product, item) + i += 1 + res['factory_order_no'] = order_id.name + except Exception as e: + _logger.info('get_bfm_process_order_list error:%s' % e) + res['status'] = -1 + res['message'] = '工厂创建销售订单和产品失败,请联系管理员' + request.cr.rollback() + return json.JSONEncoder().encode(res) diff --git a/jikimo_sale_multiple_supply_methods/data/product_data.xml b/jikimo_sale_multiple_supply_methods/data/product_data.xml new file mode 100644 index 00000000..6f804ad5 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/data/product_data.xml @@ -0,0 +1,85 @@ + + + + + 人工线下加工模板 + + + + delivery + product + false + + + + true + serial + true + true + + + + 成品外购模板 + + + + serial + product + + + + true + + + + 成品委外加工模板 + + + + serial + product + + + + true + + + + 成品初始化模板 + + + + serial + product + + + + true + + + + + + + + + 坯料客供料模板 + + + + false + serial + product + + + + + + + \ No newline at end of file diff --git a/jikimo_sale_multiple_supply_methods/data/stock_routes.xml b/jikimo_sale_multiple_supply_methods/data/stock_routes.xml new file mode 100644 index 00000000..de4c2106 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/data/stock_routes.xml @@ -0,0 +1,32 @@ + + + + + 带料加工 + true + true + + 16 + + + + 客供料入库 + incoming + true + + DL + + + + + + + 带料收货 + + + + + pull + + + \ No newline at end of file diff --git a/jikimo_sale_multiple_supply_methods/models/__init__.py b/jikimo_sale_multiple_supply_methods/models/__init__.py new file mode 100644 index 00000000..28c7877f --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/models/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- +from . import product_template +from . import sale_order diff --git a/jikimo_sale_multiple_supply_methods/models/product_template.py b/jikimo_sale_multiple_supply_methods/models/product_template.py new file mode 100644 index 00000000..e5b3ba0e --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/models/product_template.py @@ -0,0 +1,31 @@ +from odoo import models, fields, api + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + is_manual_processing = fields.Boolean(string='人工线下加工') + is_customer_provided = fields.Boolean(string='客供料') + + def product_create(self, product_id, item, order_id, order_number, i): + product_id = super(ProductTemplate, self).product_create(product_id, item, order_id, order_number, i) + product_id.product_tmpl_id.is_customer_provided = item['is_incoming_material'] + return product_id + + + def copy_template(self, product_template_id): + if not isinstance(product_template_id, ProductTemplate): + raise ValueError('%s必须是ProductTemplate类型' % product_template_id) + + self.route_ids = product_template_id.route_ids + self.categ_id = product_template_id.categ_id + self.invoice_policy = product_template_id.invoice_policy + self.detailed_type = product_template_id.detailed_type + self.purchase_ok = product_template_id.purchase_ok + self.uom_id = product_template_id.uom_id + self.uom_po_id = product_template_id.uom_po_id + self.company_id = product_template_id.company_id + self.single_manufacturing = product_template_id.single_manufacturing + self.tracking = product_template_id.tracking + self.is_bfm = product_template_id.is_bfm + self.is_manual_processing = product_template_id.is_manual_processing + self.seller_ids = product_template_id.seller_ids diff --git a/jikimo_sale_multiple_supply_methods/models/sale_order.py b/jikimo_sale_multiple_supply_methods/models/sale_order.py new file mode 100644 index 00000000..1db9541c --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/models/sale_order.py @@ -0,0 +1,156 @@ +import logging +import json +from odoo import models, fields, api +from odoo.exceptions import UserError + +_logger = logging.getLogger(__name__) + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + state = fields.Selection([ + ('draft', "报价"), + ('sent', "报价已发送"), + ('supply method', "供货方式待确认"), + ('sale', "销售订单"), + ('done', "已锁定"), + ('cancel', "已取消"), + ]) + + def confirm_to_supply_method(self): + self.state = 'supply method' + + def action_confirm(self): + for line in self.order_line: + if not line.supply_method: + raise UserError('请先选择供货方式') + bom_type = '' + # 根据供货方式修改成品模板 + if line.supply_method == 'automation': + bom_type = 'normal' + product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id + elif line.supply_method == 'outsourcing': + bom_type = 'subcontract' + product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo() + elif line.supply_method == 'purchase': + product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_purchase').sudo() + elif line.supply_method == 'manual': + bom_type = 'normal' + product_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo() + + # 复制成品模板上的属性 + line.product_id.product_tmpl_id.copy_template(product_template_id) + + order_id = self + product = line.product_id + # 拼接方法需要的item结构 + item = { + 'texture_code': product.materials_id.materials_no, + 'texture_type_code': product.materials_type_id.materials_no, + 'model_long': product.length, + 'model_width': product.width, + 'model_height': product.height, + 'price': product.list_price, + } + # 成品供货方式为采购则不生成bom + if line.supply_method != 'purchase': + bom_data = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).get_bom(product) + _logger.info('bom_data:%s' % bom_data) + if bom_data: + bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create(product, 'normal', False) + bom.with_user(self.env.ref("base.user_admin")).bom_create_line_has(bom_data) + else: + # 当成品上带有客供料选项时,生成坯料时选择“客供料”路线 + if line.is_incoming_material: + # 将成品模板的内容复制到成品上 + embryo_template_id = self.env.ref('jikimo_sale_multiple_supply_methods.product_template_raw_material_customer_provided').sudo() + embryo_id = self.env['product.product'].search( + [('product_tmpl_id', '=', embryo_template_id.id), ('active', '=', False)], + limit=1, + order='id asc' + ) + # 创建坯料,客供料的批量不需要创建bom + material_customer_provided_embryo = self.env['product.template'].sudo().no_bom_product_create( + embryo_id, + item, + order_id, 'material_customer_provided', 0, product) + # 成品配置bom + product_bom_material_customer_provided = self.env['mrp.bom'].with_user( + self.env.ref("base.user_admin")).bom_create( + product, bom_type, True) + product_bom_material_customer_provided.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + material_customer_provided_embryo) + elif line.product_id.materials_type_id.gain_way == '自加工': + self_machining_id = self.env.ref('sf_dlm.product_embryo_sf_self_machining').sudo() + # 创建坯料 + self_machining_embryo = self.env['product.template'].sudo().no_bom_product_create( + self_machining_id, + item, + order_id, 'self_machining', 0, product) + # 创建坯料的bom + self_machining_bom = self.env['mrp.bom'].with_user( + self.env.ref("base.user_admin")).bom_create( + self_machining_embryo, 'normal', False) + # 创建坯料里bom的组件 + self_machining_bom_line = self_machining_bom.with_user( + self.env.ref("base.user_admin")).bom_create_line( + self_machining_embryo) + if not self_machining_bom_line: + raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配') + # 产品配置bom + product_bom_self_machining = self.env['mrp.bom'].with_user( + self.env.ref("base.user_admin")).bom_create( + product, bom_type, True) + product_bom_self_machining.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + self_machining_embryo) + elif line.product_id.materials_type_id.gain_way == '外协': + outsource_id = self.env.ref('sf_dlm.product_embryo_sf_outsource').sudo() + # 创建坯料 + outsource_embryo = self.env['product.template'].sudo().no_bom_product_create(outsource_id, + item, + order_id, + 'subcontract', + 0, product) + if outsource_embryo == -3: + raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配') + # 创建坯料的bom + outsource_bom = self.env['mrp.bom'].with_user(self.env.ref("base.user_admin")).bom_create( + outsource_embryo, + 'subcontract', True) + # 创建坯料的bom的组件 + outsource_bom_line = outsource_bom.with_user( + self.env.ref("base.user_admin")).bom_create_line(outsource_embryo) + if not outsource_bom_line: + raise UserError('该订单模型的材料型号暂未有原材料,请先配置再进行分配') + # 产品配置bom + product_bom_outsource = self.env['mrp.bom'].with_user( + self.env.ref("base.user_admin")).bom_create(product, bom_type, True) + product_bom_outsource.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + outsource_embryo) + elif line.product_id.materials_type_id.gain_way == '采购': + purchase_id = self.env.ref('sf_dlm.product_embryo_sf_purchase').sudo() + purchase_embryo = self.env['product.template'].sudo().no_bom_product_create(purchase_id, + item, + order_id, + 'purchase', i, + product) + if purchase_embryo == -3: + raise UserError('该订单模型的材料型号暂未设置获取方式和供应商,请先配置再进行分配') + else: + # 产品配置bom + product_bom_purchase = self.env['mrp.bom'].with_user( + self.env.ref("base.user_admin")).bom_create(product, bom_type, True) + product_bom_purchase.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + purchase_embryo) + return super(SaleOrder, self).action_confirm() + +class SaleOrderLine(models.Model): + _inherit = 'sale.order.line' + + # 供货方式 + supply_method = fields.Selection([ + ('automation', "自动化产线加工"), + ('manual', "人工线下加工"), + ('purchase', "外购"), + ('outsourcing', "委外加工"), + ], string='供货方式') diff --git a/jikimo_sale_multiple_supply_methods/security/ir.model.access.csv b/jikimo_sale_multiple_supply_methods/security/ir.model.access.csv new file mode 100644 index 00000000..3b276af9 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/security/ir.model.access.csv @@ -0,0 +1,8 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_sale_order_group_production_engineer,sale.order_group_production_engineer,sale.model_sale_order,sf_base.group_production_engineer,1,1,0,0 +access_sale_order_line_group_production_engineer,sale_order_line_group_production_engineer,sale.model_sale_order_line,sf_base.group_production_engineer,1,1,0,0 +access_product_product_group_production_engineer,product_product_group_production_engineer,product.model_product_product,sf_base.group_production_engineer,1,0,0,0 +access_product_template_group_production_engineer,product_template_group_production_engineer,product.model_product_template,sf_base.group_production_engineer,1,0,0,0 +access_stock_picking_group_production_engineer,stock_picking_group_production_engineer,stock.model_stock_picking,sf_base.group_production_engineer,1,0,0,0 +access_stock_move_group_production_engineer,stock_move_group_production_engineer,stock.model_stock_move,sf_base.group_production_engineer,1,0,0,0 +access_mrp_bom_group_production_engineer,mrp_bom_group_production_engineer,mrp.model_mrp_bom,sf_base.group_production_engineer,1,0,0,0 \ No newline at end of file diff --git a/jikimo_sale_multiple_supply_methods/views/product_product_views.xml b/jikimo_sale_multiple_supply_methods/views/product_product_views.xml new file mode 100644 index 00000000..e3f896b5 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/views/product_product_views.xml @@ -0,0 +1,15 @@ + + + + view.product.template.form.inherit.sf + product.template + + + + + + + + + + \ No newline at end of file diff --git a/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml b/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml new file mode 100644 index 00000000..3021f301 --- /dev/null +++ b/jikimo_sale_multiple_supply_methods/views/sale_order_views.xml @@ -0,0 +1,104 @@ + + + + view.sale.order.form.inherit.sf + + sale.order + + + + + + + + + + view.sale.order.form.inherit.supply.method + + sale.order + + + {'invisible': [('state', '!=', 'draft')]} + confirm_to_supply_method + + + + + - - +