物料需求计划管理
This commit is contained in:
@@ -19,6 +19,7 @@
|
|||||||
'views/stock_route.xml',
|
'views/stock_route.xml',
|
||||||
'views/sale_order_views.xml',
|
'views/sale_order_views.xml',
|
||||||
'wizard/sf_demand_plan_print_wizard_view.xml',
|
'wizard/sf_demand_plan_print_wizard_view.xml',
|
||||||
|
'wizard/sf_release_plan_wizard_views.xml',
|
||||||
],
|
],
|
||||||
'demo': [
|
'demo': [
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -4,3 +4,4 @@ from . import sf_demand_plan
|
|||||||
from . import sf_production_demand_plan
|
from . import sf_production_demand_plan
|
||||||
from . import sale_order
|
from . import sale_order
|
||||||
from . import stock_route
|
from . import stock_route
|
||||||
|
from . import mrp_bom
|
||||||
|
|||||||
20
sf_demand_plan/models/mrp_bom.py
Normal file
20
sf_demand_plan/models/mrp_bom.py
Normal file
@@ -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
|
||||||
@@ -6,6 +6,7 @@ from odoo.exceptions import ValidationError
|
|||||||
from odoo.tools import float_compare
|
from odoo.tools import float_compare
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from odoo.exceptions import UserError
|
from odoo.exceptions import UserError
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
class SfProductionDemandPlan(models.Model):
|
class SfProductionDemandPlan(models.Model):
|
||||||
@@ -30,7 +31,7 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
('50', '待下达生产'),
|
('50', '待下达生产'),
|
||||||
('60', '已下达'),
|
('60', '已下达'),
|
||||||
('100', '取消'),
|
('100', '取消'),
|
||||||
], string='状态', default='30', readonly=True)
|
], string='状态', default='30')
|
||||||
demand_plan_id = fields.Many2one(comodel_name="sf.demand.plan",
|
demand_plan_id = fields.Many2one(comodel_name="sf.demand.plan",
|
||||||
string="物料需求", readonly=True)
|
string="物料需求", readonly=True)
|
||||||
sale_order_id = fields.Many2one(comodel_name="sale.order",
|
sale_order_id = fields.Many2one(comodel_name="sale.order",
|
||||||
@@ -144,6 +145,7 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
|
|
||||||
blank_arrival_date = fields.Date('采购计划到货(坯料)')
|
blank_arrival_date = fields.Date('采购计划到货(坯料)')
|
||||||
finished_product_arrival_date = fields.Date('采购计划到货(成品)')
|
finished_product_arrival_date = fields.Date('采购计划到货(成品)')
|
||||||
|
bom_id = fields.Many2one('mrp.bom', readonly=True, string="BOM")
|
||||||
|
|
||||||
@api.depends('supply_method')
|
@api.depends('supply_method')
|
||||||
def _compute_route_ids(self):
|
def _compute_route_ids(self):
|
||||||
@@ -532,3 +534,158 @@ class SfProductionDemandPlan(models.Model):
|
|||||||
if len(self.demand_plan_id.line_ids) == 1:
|
if len(self.demand_plan_id.line_ids) == 1:
|
||||||
raise ValidationError(f"最后一条计划,不能删除!")
|
raise ValidationError(f"最后一条计划,不能删除!")
|
||||||
self.unlink()
|
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
|
||||||
|
|||||||
@@ -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,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_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
|
||||||
|
@@ -44,7 +44,7 @@
|
|||||||
<field name="supply_method" attrs="{'readonly': [('status', '!=', '30')]}"/>
|
<field name="supply_method" attrs="{'readonly': [('status', '!=', '30')]}"/>
|
||||||
<field name="route_ids" widget="many2many_tags" optional="hide"/>
|
<field name="route_ids" widget="many2many_tags" optional="hide"/>
|
||||||
<!--<field name="需求位置"/>-->
|
<!--<field name="需求位置"/>-->
|
||||||
<!--<field name="bom"/>-->
|
<field name="bom_id" optional="hide"/>
|
||||||
<field name="plan_uom_qty"/>
|
<field name="plan_uom_qty"/>
|
||||||
<field name="blank_arrival_date"/>
|
<field name="blank_arrival_date"/>
|
||||||
<field name="finished_product_arrival_date"/>
|
<field name="finished_product_arrival_date"/>
|
||||||
@@ -54,6 +54,10 @@
|
|||||||
<field name="plan_remark"/>
|
<field name="plan_remark"/>
|
||||||
<field name="procurement_reason" widget="radio"/>
|
<field name="procurement_reason" widget="radio"/>
|
||||||
<field name="write_date" string="更新时间"/>
|
<field name="write_date" string="更新时间"/>
|
||||||
|
<button string="下达计划" name="button_release_plan" type="object"
|
||||||
|
class="btn-primary"
|
||||||
|
attrs="{'invisible': [('status', 'in', ('60','100'))]}"
|
||||||
|
/>
|
||||||
<button name="button_delete" type="object" string="删除"
|
<button name="button_delete" type="object" string="删除"
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
attrs="{'invisible': [('status', 'not in', ('10','20','30'))]}"
|
attrs="{'invisible': [('status', 'not in', ('10','20','30'))]}"
|
||||||
|
|||||||
@@ -1 +1,2 @@
|
|||||||
from . import sf_demand_plan_print_wizard
|
from . import sf_demand_plan_print_wizard
|
||||||
|
from . import sf_release_plan_wizard
|
||||||
|
|||||||
22
sf_demand_plan/wizard/sf_release_plan_wizard.py
Normal file
22
sf_demand_plan/wizard/sf_release_plan_wizard.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import logging
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class SfReleasePlanWizard(models.TransientModel):
|
||||||
|
_name = 'sf.release.plan.wizard'
|
||||||
|
_description = u'下达计划向导'
|
||||||
|
|
||||||
|
demand_plan_id = fields.Many2one(comodel_name="sf.demand.plan",
|
||||||
|
string="需求计划", readonly=True)
|
||||||
|
|
||||||
|
demand_plan_line_id = fields.Many2one(comodel_name="sf.production.demand.plan",
|
||||||
|
string="需求计划明细", readonly=True)
|
||||||
|
|
||||||
|
release_message = fields.Char(string='提示', readonly=True)
|
||||||
|
|
||||||
|
def confirm(self):
|
||||||
|
if self.demand_plan_line_id:
|
||||||
|
self.demand_plan_line_id.mrp_bom_create()
|
||||||
22
sf_demand_plan/wizard/sf_release_plan_wizard_views.xml
Normal file
22
sf_demand_plan/wizard/sf_release_plan_wizard_views.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<odoo>
|
||||||
|
<record model="ir.ui.view" id="sf_release_plan_wizard_form">
|
||||||
|
<field name="name">sf.release.plan.wizard.form</field>
|
||||||
|
<field name="model">sf.release.plan.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form>
|
||||||
|
<sheet>
|
||||||
|
<div>
|
||||||
|
<div style="white-space: pre-wrap;">
|
||||||
|
<field name="release_message"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
<button string="确认" name="confirm" type="object" class="oe_highlight"/>
|
||||||
|
<button string="取消" class="btn btn-secondary" special="cancel"/>
|
||||||
|
</footer>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
Reference in New Issue
Block a user