From c14e2c19bfa185da372aa37fc0031498c760b9e6 Mon Sep 17 00:00:00 2001 From: guanhuan Date: Thu, 26 Jun 2025 11:13:56 +0800 Subject: [PATCH] =?UTF-8?q?=E7=89=A9=E6=96=99=E9=9C=80=E6=B1=82=E8=AE=A1?= =?UTF-8?q?=E5=88=92=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sf_demand_plan/__manifest__.py | 1 + sf_demand_plan/models/__init__.py | 1 + sf_demand_plan/models/mrp_bom.py | 20 +++ .../models/sf_production_demand_plan.py | 159 +++++++++++++++++- sf_demand_plan/security/ir.model.access.csv | 3 + sf_demand_plan/views/demand_plan_info.xml | 6 +- sf_demand_plan/wizard/__init__.py | 1 + .../wizard/sf_release_plan_wizard.py | 22 +++ .../wizard/sf_release_plan_wizard_views.xml | 22 +++ 9 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 sf_demand_plan/models/mrp_bom.py create mode 100644 sf_demand_plan/wizard/sf_release_plan_wizard.py create mode 100644 sf_demand_plan/wizard/sf_release_plan_wizard_views.xml diff --git a/sf_demand_plan/__manifest__.py b/sf_demand_plan/__manifest__.py index 8a913e0b..4327514a 100644 --- a/sf_demand_plan/__manifest__.py +++ b/sf_demand_plan/__manifest__.py @@ -19,6 +19,7 @@ 'views/stock_route.xml', 'views/sale_order_views.xml', 'wizard/sf_demand_plan_print_wizard_view.xml', + 'wizard/sf_release_plan_wizard_views.xml', ], 'demo': [ ], diff --git a/sf_demand_plan/models/__init__.py b/sf_demand_plan/models/__init__.py index 2952477c..b6bb7609 100644 --- a/sf_demand_plan/models/__init__.py +++ b/sf_demand_plan/models/__init__.py @@ -4,3 +4,4 @@ from . import sf_demand_plan from . import sf_production_demand_plan from . import sale_order from . import stock_route +from . import mrp_bom diff --git a/sf_demand_plan/models/mrp_bom.py b/sf_demand_plan/models/mrp_bom.py new file mode 100644 index 00000000..8973cb87 --- /dev/null +++ b/sf_demand_plan/models/mrp_bom.py @@ -0,0 +1,20 @@ +from odoo import models, fields + + +class MrpBom(models.Model): + _inherit = 'mrp.bom' + + # 业务平台分配工厂后在智能工厂先创建销售订单再创建该产品后再次进行创建bom + def bom_create(self, product, bom_type, product_type, code=None): + 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, + 'code': code + }) + 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 diff --git a/sf_demand_plan/models/sf_production_demand_plan.py b/sf_demand_plan/models/sf_production_demand_plan.py index 97d0fcfb..97e8b99a 100644 --- a/sf_demand_plan/models/sf_production_demand_plan.py +++ b/sf_demand_plan/models/sf_production_demand_plan.py @@ -6,6 +6,7 @@ from odoo.exceptions import ValidationError from odoo.tools import float_compare from datetime import datetime, timedelta from odoo.exceptions import UserError +import re class SfProductionDemandPlan(models.Model): @@ -30,7 +31,7 @@ class SfProductionDemandPlan(models.Model): ('50', '待下达生产'), ('60', '已下达'), ('100', '取消'), - ], string='状态', default='30', readonly=True) + ], string='状态', default='30') demand_plan_id = fields.Many2one(comodel_name="sf.demand.plan", string="物料需求", readonly=True) sale_order_id = fields.Many2one(comodel_name="sale.order", @@ -144,6 +145,7 @@ class SfProductionDemandPlan(models.Model): blank_arrival_date = fields.Date('采购计划到货(坯料)') finished_product_arrival_date = fields.Date('采购计划到货(成品)') + bom_id = fields.Many2one('mrp.bom', readonly=True, string="BOM") @api.depends('supply_method') def _compute_route_ids(self): @@ -532,3 +534,158 @@ class SfProductionDemandPlan(models.Model): if len(self.demand_plan_id.line_ids) == 1: raise ValidationError(f"最后一条计划,不能删除!") self.unlink() + + def button_release_plan(self): + if not self.supply_method: + raise ValidationError(f"供货方式不能为空!") + if self.plan_uom_qty > self.product_uom_qty: + return { + 'name': _('需求计划'), + 'type': 'ir.actions.act_window', + 'views': [(self.env.ref( + 'sf_demand_plan.sf_release_plan_wizard_form').id, + 'form')], + 'res_model': 'sf.release.plan.wizard', + 'target': 'new', + 'context': { + 'default_demand_plan_line_id': self.id, + 'default_release_message': f"您正在下达计划量 {self.plan_uom_qty},需求数量为 {self.product_uom_qty},已超过需求数量,是否继续?", + }} + self.mrp_bom_create() + + def mrp_bom_create(self): + self.ensure_one() + bom_type = '' + # 根据供货方式修改成品模板 + if self.supply_method == 'automation': + bom_type = 'normal' + product_template_id = self.env.ref('sf_dlm.product_template_sf').sudo().product_tmpl_id + elif self.supply_method == 'outsourcing': + bom_type = 'subcontract' + product_template_id = self.env.ref( + 'jikimo_sale_multiple_supply_methods.product_template_outsourcing').sudo() + elif self.supply_method == 'purchase': + product_template_id = self.env.ref( + 'jikimo_sale_multiple_supply_methods.product_template_purchase').sudo() + elif self.supply_method == 'manual': + bom_type = 'normal' + product_template_id = self.env.ref( + 'jikimo_sale_multiple_supply_methods.product_template_manual_processing').sudo() + + # 复制成品模板上的属性 + self.product_id.product_tmpl_id.copy_template(product_template_id) + + # 生成BOM单据编码 + code = f"{self.product_id.default_code}-{bom_type}-{datetime.now().strftime('%Y%m%d%H%M%S')}" + + order_id = self.sale_order_id + product = self.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, + 'blank_volume': product.model_volume, + 'blank_area': product.model_area, + 'price': product.list_price, + 'embryo_redundancy_id': self.sale_order_line_id.embryo_redundancy_id, + 'model_id': self.model_id + } + product_name = '' + match = re.search(r'(S\d{5}-\d+)', product.name) + product_seria = 0 + # 如果匹配成功,提取结果 + if match: + product_name = match.group(0) + # 获取成品名结尾-n的n + product_seria = int(product_name.split('-')[-1]) + + # 成品供货方式为采购则不生成bom + if self.supply_method != 'purchase': + # 当成品上带有客供料选项时,生成坯料时选择“客供料”路线 + if self.sale_order_line_id.embryo_redundancy_id: + # 将成品模板的内容复制到成品上 + customer_provided_embryo = self.env.ref( + 'jikimo_sale_multiple_supply_methods.product_template_embryo_customer_provided').sudo() + # 创建坯料,客供料的批量不需要创建bom + material_customer_provided_embryo = self.env['product.template'].sudo().no_bom_product_create( + customer_provided_embryo.with_context(active_test=False).product_variant_id, + item, + order_id, 'material_customer_provided', product_seria, product) + # 成品配置bom + product_bom_material_customer_provided = self.env['mrp.bom'].with_user( + self.env.ref("base.user_admin")).bom_create( + product, bom_type, 'product', code) + product_bom_material_customer_provided.with_user( + self.env.ref("base.user_admin")).bom_create_line_has( + material_customer_provided_embryo) + self.bom_id = product_bom_material_customer_provided.id + elif self.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', product_seria, 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, 'product', code) + product_bom_self_machining.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + self_machining_embryo) + self.bom_id = product_bom_self_machining.id + elif self.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', + product_seria, + 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, 'product', code) + product_bom_outsource.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + outsource_embryo) + self.bom_id = product_bom_outsource.id + elif self.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', + product_seria, + product) + if purchase_embryo and 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, 'product', code) + product_bom_purchase.with_user(self.env.ref("base.user_admin")).bom_create_line_has( + purchase_embryo) + self.bom_id = product_bom_purchase.id diff --git a/sf_demand_plan/security/ir.model.access.csv b/sf_demand_plan/security/ir.model.access.csv index 5a35ba20..9bd2e29b 100644 --- a/sf_demand_plan/security/ir.model.access.csv +++ b/sf_demand_plan/security/ir.model.access.csv @@ -11,3 +11,6 @@ access_sf_demand_plan_for_dispatch,sf.demand.plan for dispatch,model_sf_demand_p access_stock_route_group,stock.route.group,model_stock_route_group,base.group_user,1,0,0,0 access_stock_route_group_dispatch,stock.route.group.dispatch,model_stock_route_group,sf_base.group_plan_dispatch,1,1,0,0 + +access_sf_release_plan_wizard,sf.release.plan.wizard,model_sf_release_plan_wizard,base.group_user,1,0,0,0 +access_sf_release_plan_wizard_for_dispatch,sf.release.plan.wizard for dispatch,model_sf_release_plan_wizard,sf_base.group_plan_dispatch,1,1,1,1 \ No newline at end of file diff --git a/sf_demand_plan/views/demand_plan_info.xml b/sf_demand_plan/views/demand_plan_info.xml index 16f75b35..7057efc1 100644 --- a/sf_demand_plan/views/demand_plan_info.xml +++ b/sf_demand_plan/views/demand_plan_info.xml @@ -44,7 +44,7 @@ - + @@ -54,6 +54,10 @@ +