MRP干预下层需求数据解决方案
【应用场景】
在一些特殊场景下,MRP运算生成计划订单及其计划BOM表体的标准业务逻辑并不能满足业务需求,因此需要在MRP运算过程中进行干预,之前有一个文章讲述了如何在MRP中干预计划订单(详见文章:MRP运算过程添加数据策略干预计划订单信息),但该方案有一定局限性,就是只是针对计划订单自身进行干预,当遇到干预之后需要往下层需求传递时,则该方案不适用。本知识贴主要介绍这类场景的解决方案,即添加MRP数据模型策略实现类,实现干预计划订单或计划BOM的信息,并且将更改后的信息往下层需求传递。
【注意事项】
该实现方案涉及到MRP数据模型添加数据策略并替换标准的数据策略,有较高的开发要求非最佳实践,不推荐使用,仅限于特殊场景下的特殊应用。实际场景中尽可能使用业务上的变通方案或沿用标准MRP相关逻辑,非必要不采用本方案干预MRP中间过程的数据传递逻辑。
【案例演示】
本方案演示的是MRP运算生成的计划订单的计划BOM相关需求数量字段向上取整。
【实现步骤】
<1>,本方案默认阅读者已经掌握二开添加MRP数据模型实现策略的方法(若尚未掌握,详见知识贴:MRP如何二开数据模型策略实现类)。但要是注意,本案要编辑策略实现类的MRP数据数据模型编码是MRP_DP_NC_TransferDemand,在系统前端修改编码为MRP_DP_NC_TransferDemand的MRP数据模型的策略实现类(路径:生产制造》计划管理》MRP建模》MRP数据模型),注意策略实现类文本框填对插件的命名空间和类名,结构是(命名空间.类名,组件名),如图。
<2>经过上一步掌握了添加MRP数据策略实现类之后,再二开实现本案示例业务场景的数据策略功能,示例代码如下。
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Util;
using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.K3.Core.MFG.EntityHelper;
using Kingdee.K3.MFG.PLN.App.MrpModel;
using Kingdee.K3.MFG.PLN.App.MrpModel.PolicyImpl.NetCalc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
namespace CustMrpModel_23231206
{
[Kingdee.BOS.Util.HotUpdate]
[Description("MRP插件:(传递净需求数据策略)")]
public class MyTransferDSDataPolicy : Kingdee.K3.MFG.PLN.App.MrpModel.PolicyImpl.NetCalc.TransferDSDataPolicy
{
protected override void OnExecuteDataPolicy()
{
base.OnExecuteDataPolicy(); //首先处理标准逻辑
//Kingdee.K3.MFG.PLN.App.MrpModel.PolicyImpl.NetCalc.TransferDSDataPolicy,Kingdee.K3.MFG.PLN.App.MrpModel
if (this.MrpGlobalDataContext.TransferDemandRows.IsEmpty() || this.MrpDemandDimContext.MrpNetDemandContextGroup.PlanOrderItem == null) return;
Dictionary<long, DynamicObject> plbomEntryDct = new Dictionary<long, DynamicObject>();
DynamicObject planOrderData = this.MrpDemandDimContext.MrpNetDemandContextGroup.PlanOrderItem;
DynamicObjectCollection plEntrys = planOrderData["PLBOMENTRY"] as DynamicObjectCollection;
foreach (DynamicObject plEntry in plEntrys)
{
decimal stdQty = plEntry.GetDynamicValue<decimal>("StdQty");
stdQty = Math.Ceiling(stdQty); //数量向上取整
plEntry.SetDynamicObjectItemValue("StdQty", stdQty);
plEntry.SetDynamicObjectItemValue("BaseStdQty", stdQty); //注意若基本单位与业务单位不一致,此处须换算
decimal needQty = plEntry.GetDynamicValue<decimal>("NeedQty");
needQty = Math.Ceiling(needQty); //数量向上取整
plEntry.SetDynamicObjectItemValue("NeedQty", needQty);
plEntry.SetDynamicObjectItemValue("BaseNeedQty", needQty); //注意若基本单位与业务单位不一致,此处须换算
decimal mustQty = plEntry.GetDynamicValue<decimal>("MustQty");
mustQty = Math.Ceiling(mustQty); //数量向上取整
plEntry.SetDynamicObjectItemValue("MustQty", mustQty);
plEntry.SetDynamicObjectItemValue("BaseMustQty", mustQty); //注意若基本单位与业务单位不一致,此处须换算
//注意因为更改了需求数量,要重算并更新分子,才能正确计算需求数量等
decimal baseNumerator = plEntry.GetDynamicValue<decimal>("BaseNumerator"); //分子
decimal Individual = mustQty / baseNumerator;
baseNumerator = this.CalcNumerator(Individual, mustQty);
plEntry.SetDynamicObjectItemValue("BaseNumerator", baseNumerator);
plEntry.SetDynamicObjectItemValue("Numerator", baseNumerator); //注意若基本单位与业务单位不一致,此处须换算
//收集已处理的计划BOM数据,用于后面更新需求数据
long plbomEntryId = plEntry.GetDynamicValue<long>("Id");
plbomEntryDct[plbomEntryId] = plEntry;
}
//给计划BOM数量取整之后,还要对其对应的需求数据也要进行更新
foreach (DynamicObject demandRow in this.MrpGlobalDataContext.TransferDemandRows)
{
string demandFormId = demandRow.GetDynamicValue<string>("RelationFormId_Id");
if (!demandFormId.EqualsIgnoreCase("PLN_PLANORDER")) continue;
string demandEntryIdStr = demandRow.GetDynamicValue<string>("RelationEntryId");
long demandEntryId = 0;
if (demandEntryIdStr.IsNullOrEmptyOrWhiteSpace() || !long.TryParse(demandEntryIdStr, out demandEntryId)) continue;
DynamicObject plbomEntry;
if (plbomEntryDct.TryGetValue(demandEntryId, out plbomEntry))
{
demandRow["BASEDEMANDQTY"] = plbomEntry["BaseMustQty"];
demandRow["BASEGROSSQTY"] = plbomEntry["BaseMustQty"];
demandRow["BASEORDERQTY"] = plbomEntry["BaseMustQty"];
demandRow["BASEQTY"] = plbomEntry["BaseMustQty"];
demandRow["BaseNumerator"] = plbomEntry["BaseNumerator"];
}
}
}
private decimal CalcNumerator(decimal individual, decimal mustQty)
{
string numString = (mustQty / individual).ToString();
int decimalIndex = numString.IndexOf('.') + 4;
if (decimalIndex < numString.Length)
{
int fourthDecimal = int.Parse(numString[decimalIndex - 1].ToString());
int newValue = fourthDecimal + 1;
numString = numString.Remove(decimalIndex - 1, 1).Insert(decimalIndex - 1, newValue.ToString());
}
return decimal.Parse(numString.Substring(0, decimalIndex));
}
}
}
【功能验证】
<1>通过本案开发干预后,MRP运算生成的订单订单的计划BOM需求相关数量都是向上取整的整数,且预留也是整数,在一些单位精度因为关联业务偶合或历史原因无法更改为0,且又需要整领整发的场景中适用。
MRP干预下层需求数据解决方案
本文2024-09-23 03:13:14发表“云星空知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-k3cloud-157464.html