本文介绍了在单据处理系统中实现文本字段的累加和累减功能的方法,包括累加和累减的实现方式以及通过插件进行具体操作的示例。累加功能可以通过在下游单据中设置隐藏字段,并在转换规则中使用该隐藏字段来实现累加效果,累减则由于不走反写逻辑,需要通过插件在数据保存前事件中去除反写数据。示例中详细说明了如何在单据B中设置隐藏字段,并通过反写规则和插件实现单据B备注字段对单据A备注字段的累加和累减操作。
说明:
累加: 单据多次下推,每次反写的文本数据都需要记录,既实现一个文本累加的效果,比如第一次反写“文本1”,第二次反写“文本2,。。。,得到的结果应该为“文本1,文本2,。。。”。
累减: 相应的单据被删除或反审核了,反写数据也应该要去除。
覆盖模式:
文本字段的反写只能使用覆盖模式。
目前覆盖模式只有正向操作(保存或审核)会走反写逻辑,负向操作(删除或反审核)不会走。
反写逻辑是指反写赋值逻辑,行关闭逻辑,超额判断等相关的业务逻辑和事件。
目前负向操作只是按反写规则的回退方式(不处理或清空或缺省值)来处理相关的数据。
实现:
累加实现方式:
方式1:在下游单据中加个隐藏字段,在转换规则中把上游需要被反写的字段值携带到隐藏字段中,在反写规则中使用隐藏字段+需要反写的值作为反写公式。
方式2:在下游单据中加个隐藏字段,在转换规则中把上游需要被反写的字段值携带到隐藏字段中,在反写规则中使用隐藏字段作为反写公式(这样实际上等于没有反写,只是走了反写逻辑),在反写插件反写后事件中使用隐藏字段+反写值给上游被反写的字段赋值。
累减实现方式:
累减是反向操作,不会走反写逻辑,覆盖模式也不会记录反写历史,所以累减只能用插件实现。具体为在反写插件反写数据保存之前事件中去除下游单据反写数据。
示例:
单据B的单据头备注字段累加反写单据A的单据头备注字段,累加和累减都是通过插件实现,实现步骤如下:
1. 单据B中加入隐藏备注字段,设置可见性为在页面不可见, 在转换规则字段映射中设置隐藏备注字段来源单据A的备注字段,如下图:
2.1 新建反写规则,使用累加方式1,反写值计算公式设置为:单据B隐藏备注字段+备注字段反写单据A备注字段
2.2 新建反写规则,使用累加方式2,单据B隐藏备注字段反写单据A备注字段,反写条件为单据B的备注字段=备注字段(这是因为在反向操作传入的是部分元数据和数据包,如果整个反写规则没有配置单据B的备注字段,那么将在反向操作中取不到它的元数据和值)
3. 反写插件, 具体参考插件代码
4. 正向累加效果:
5. 删除一张单据后的累减效果:
插件代码:
using System; using System.Collections.Generic; using System.Linq; using System.ComponentModel; using Kingdee.BOS; using Kingdee.BOS.Core; using Kingdee.BOS.Util; using Kingdee.BOS.Core.Metadata; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.BusinessEntity; using Kingdee.BOS.Core.BusinessFlow; using Kingdee.BOS.Core.BusinessFlow.PlugIn; using Kingdee.BOS.Core.Metadata.FieldElement; using Kingdee.BOS.Core.BusinessFlow.PlugIn.Args; using Kingdee.BOS.BusinessEntity.BusinessFlow; namespace Kingdee.BOS.TestPlugIn.BillABillB { [Description("单据B反写插件")] [Kingdee.BOS.Util.HotUpdate] public class BillBWriteBackPlugIn : AbstractBusinessFlowServicePlugIn { //需要干预的反写规则 private bool _isNeedHandleRule = false; /// <summary> /// 反写前事件,每个反写规则走一次,得到需要干预反写规则 /// </summary> /// <param name="e"></param> public override void BeforeWriteBack(BeforeWriteBackEventArgs e) { this._isNeedHandleRule = false; var ruleName = e.Rule.Name.ToString(); if(ruleName.EqualsIgnoreCase("单据B反写单据A覆盖模式累加效果_备注")) { this._isNeedHandleRule = true; } } /// <summary> /// 反写条目反写后事件,每一行都会走,使用累加方式2才需要 /// </summary> /// <param name="e"></param> public override void AfterCommitAmount(AfterCommitAmountEventArgs e) { base.AfterCommitAmount(e); if (this._isNeedHandleRule) { //保存操作 if (this.OperationNumber.EqualsIgnoreCase("Save")) { var wbRule = e.WriteBackRuleRow as WRule<Id>;//反写条目 var tBillObj = wbRule.Row.DataEntity.Parent as DynamicObject;//当前单据数据包 var pkId = Convert.ToInt64(tBillObj["Id"].ToString()); var tNoteField = this.BusinessInfo.GetField("FNote");//当前单据备注字段 var tNoteValue = Convert.ToString(tNoteField.DynamicProperty.GetValue(tBillObj));//当前单据备注字段值 var sNoteOldValue = Convert.ToString(e.SourceCommitField.DynamicProperty.GetValue(e.SourceDataObject)); //上游单据被反写字段的值 if (string.IsNullOrWhiteSpace(sNoteOldValue)) { sNoteOldValue = tNoteValue; //加上当前单据备注字段值 } else { sNoteOldValue = sNoteOldValue + "," + tNoteValue; //加上当前单据备注字段值 } e.SourceCommitField.DynamicProperty.SetValue(e.SourceDataObject, sNoteOldValue); //给上游单据被反写的自动赋值 } } } /// <summary> /// 保存之前对需要干预的反写规则进行数据处理 /// </summary> /// <param name="e"></param> public override void BeforeSaveWriteBackData(BeforeSaveWriteBackDataEventArgs e) { //假设反写规则是保存操作,则需要对保存,删除进行处理, //如果是审核操作,则需要对审核,反审核进行处理, base.BeforeSaveWriteBackData(e); if (this._isNeedHandleRule) { if (this.OperationNumber.EqualsIgnoreCase("Delete")) //删除操作 { //上游单据部分数据包 var ssubBillObjs = e.SourceDataEntitySet.FindByEntityKey("FBillHead"); var sNoteField = e.SourceBusinessInfo.GetField("FNote"); //上游单据备份字段 //这里要注意,删除操作传递的是部分元数据和数据包,如果要想此字段一定有,则必须在反写规则中配置 //可以把反写条件配置为备注=备注 var tNoteField = this.BusinessInfo.GetField("FNote"); //当前单据备份字段 foreach (var sBillObj in ssubBillObjs) { var snoteValue = Convert.ToString(sNoteField.DynamicProperty.GetValue(sBillObj.DataEntity)); //得到上游备份字段值 var snoteNewValue = HandleDeleteValue(sBillObj.DataEntity, tNoteField, snoteValue); sNoteField.DynamicProperty.SetValue(sBillObj.DataEntity, snoteNewValue);//给上游备份重新赋值 } } } } /// <summary> /// 删除时,值累减处理 /// </summary> /// <param name="sBillObj"></param> /// <param name="tNoteField"></param> /// <param name="sNoteValue"></param> /// <returns></returns> private string HandleDeleteValue(DynamicObject sBillObj, Field tNoteField, string sNoteValue) { //得到关联的当前单据 //当前单据数据包只有一个,则就是它了 if (this.DynamicObjects.Length == 1) { var tNoteValue = Convert.ToString(tNoteField.DynamicProperty.GetValue(this.DynamicObjects[0])); if (!string.IsNullOrWhiteSpace(tNoteValue)) { sNoteValue = sNoteValue.Replace("," + tNoteValue, ""); } } else { //当前单据数据包有多个,则需要根据关联关系找实际来源 var sPkId = Convert.ToInt64(sBillObj["Id"]);//上游单据内码 foreach (var tBillObj in this.DynamicObjects) { var isLink = false; var tEntryObjs = tBillObj["FEntity"] as DynamicObjectCollection; //关联的下游单据体数据包 foreach (var tEntryObj in tEntryObjs) { var linkObjs = tEntryObj["FEntity_Link"] as DynamicObjectCollection; var isContinue = true; foreach (var lkObj in linkObjs) { var sBillPkId = Convert.ToInt64(lkObj["FBillId"]); if (sPkId == sBillPkId) //上游单据内码等于当前单据来源内码说明关联 { isLink = true; isContinue = false; break; } } if (!isContinue) { break; } } if (isLink) //如果关联 { var tNoteValue = Convert.ToString(tNoteField.DynamicProperty.GetValue(tBillObj)); sNoteValue = sNoteValue.Replace("," + tNoteValue, ""); } } } return sNoteValue; } } }
推荐阅读