操作服务插件
添加操作服务校验器
OnAddValidators参照“校验器服务插件 – 在服务中增加校验器”
操作服务 BeforeExecuteOperationTransaction执行操作事务前插件。通常用于执行操作前数据处理,该插件在webservice服务调用时也会执行。该事件是操作事务前允许处理数据的最后一个插件,为保证操作事务时间最短,在性能优化时会将不需要事务保护的部分服务逻辑放到这个插件里处理。该插件中不适合用于数据校验,数据校验方法请参考数据校验章节。
例如:在直接调拨单中,增加保存服务插件,在保存事务前,计算未结算的关联数量。这个数据在结算业务逻辑中使用,必须保证数据准确有效,不需要调拨界面显示。如果在web插件中计算会有2个问题:1. 数据操作修改后必须重新计算,多次修改要多次计算,效率低;2. 外部接口调用保存服务时,需要自己计算好填到数据包,如果涉及到本地化设置(如数据精度)等问题,还要调用方特殊处理;
在保存操作增加服务处理步骤:1. 定义服务插件类StockTransferDirect.SaveService,插件继承AbstractOprerationService;2. 重载BeforeExecuteOperationTransaction方法,示例代码:
[tr][td=379]C#
[td=191]
[tr][td=2,1,569]// 保存操作事务前,计算单据上的“未结算关联数量”public override void BeforeExecuteOperationTransaction(BeforeExecuteOperationTransaction e){if (e.SelectedRows == null || e.SelectedRows.Count() == 0){ // 没有数据,取消操作(通常此类判断应在web端进行,避免不必要的资源消耗,此处仅示例如何取消操作) e.Cancel = true;return; } DynamicObject[] objs = (from p in e.SelectedRows select p.DataEntity).ToArray(); foreach (DynamicObject data in objs) { DynamicObjectCollection dataentrys = data["TransferDirectEntry"] as DynamicObjectCollection; foreach (DynamicObject entry in dataentrys) { //“未结算关联数量”=“调拨数量”-“关联退货数量”-“结算关联数量”。 decimal qty = Convert.ToDecimal(entry["Qty"]); decimal baseQty = Convert.ToDecimal(entry["BaseQty"]); decimal receiveQty = Convert.ToDecimal(entry["ReceiveQty"]); decimal baseJoinQty = Convert.ToDecimal(entry["BaseJoinQty"]); decimal baseSettQty = Convert.ToDecimal(entry["JoinBaseSettQty"]); decimal SettQty = Convert.ToDecimal(entry["JoinSettleQty"]); entry["JoinUnSettleQty"] = qty - receiveQty - SettQty; entry["JoinBaseUnSettQty"] = baseQty - baseJoinQty - baseSettQty; } }}
3. 编译后,运行系统,在IDE中配置保存服务插件;(图2.2 )4. 调试测试; AfterExecuteOperationTransaction执行操作事务后插件。通常用来处理操作后的相关的数据处理,如生成其他单据、更新状态、运行业务运算等。该插件在操作事务外,执行结果不影响操作,因此该插件要考虑执行失败的逻辑处理。AfterExecuteOperationTransaction参数:
[tr][td]
[td]Name
[td]Description
[tr][td=18][td=30%]DataEntitys
[td=70%]本次操作事务处理成功的数据实体集合
[tr][td=18][td=30%]SelectedRows
[td=70%]当前操作校验通过的所有行对象
(参数命名空间:BOS.Core.DynamicForm.PlugIn.Args)审核结束自动生成付款单的代码示例:
[tr][td]C#
[td]
[tr][td=2,1]public override void AfterExecuteOperationTransaction(AfterExecuteOperationTransaction e){ //审核时,如果弹出信用相关提示警示信息时,e.DataEntitys将没有记录。此时直接退出 if (e.DataEntitys.IsNullOrEmpty() || e.DataEntitys.Count() == 0) { return; } foreach (var dataEntity in e.DataEntitys) { if (this.IsCanSoureBillPush(dataEntity)) //申请借款,下推付款申请单 { DynamicObject[] objs = new DynamicObject[1] { dataEntity }; //初始化备用信息 this.OnInit(objs); //生成下游单据 this.ProduceBill(this.OperationResult as ConvertOperationResult); } }}
BeginOperationTransaction操作事务开始插件。用于在执行操作前处理数据,该方法与BeforeExecuteOperationTransaction区别主要在于该插件在操作事务内,出错后系统会回滚事务。该插件开发时要特别关注对性能的影响,建议对分录的所有处理考虑批量进行。参数:CancelFormService是否取消执行本操作所关联的表单服务;即终止服务插件,不执行其他表单服务插件。CancelOperation是否取消本操作;即终止操作。简单生产领料单保存前,根据当前单据删除的领料单分录获取关联的源单分录,在保存后,检测简单领料分录是否仍存在该分录ID上拉的行,然后再判断应该更新简单领料分录还是源单分录,重置该分录行的领料标识。
[tr][td]C#
[td]
[tr][td=2,1]//更新操作前,获取删除的分录数据,在更新后做处理public override void BeginOperationTransaction(BeginOperationTransactionArgs e){//获取删除的行 IDbDriver driver = new Kingdee.BOS.App.Data.OLEDbDriver(this.Context); IDataManager manager = DataManagerUtils.GetDataManager(this.BusinessInfo.GetDynamicObjectType(), driver); ISaveDataSet updateData = manager.GetSaveDataSet(e.DataEntitys.ToArray()); DeleteRows = updateData.Tables["T_SP_PICKMTRLDATA"].DeleteRows; if (DeleteRows != null && DeleteRows.Length > 0) { List lstDeleteIds = DeleteRows.Select(w => w.Oid).ToList();//根据领料单ENTRYID获取关联的源单SRCENTRYID listInStockEntryId = ServiceFactory.GetSpInStockService(this.Context).GetInStcokEntryByPickMtrlEntryId(this.Context, lstDeleteIds); base.BeginOperationTransaction(e); }}
[tr][td]C#
[td]
[tr][td=2,1]//更新操作后,根据更新前获取的删除分录的数据,重新计算领料标识public override void EndOperationTransaction(EndOperationTransactionArgs e){ base.EndOperationTransaction(e); ISpInStockService service= ServiceFactory.GetSpInStockService(this.Context); // 检测简单领料分录是否仍存在该分录ID上拉过来的行,否则更新简单入库的分录行领料标识 if (listInStockEntryId != null && listInStockEntryId.Count > 0){ // 批量检测 service.ResetIsPickInInStcokEntry(this.Context, listInStockEntryId);} foreach (var dataEntity in e.DataEntitys) { IEnumerable lstEntryId = dataEntity.GetDynamicObjectItemValue(ENTITY_ORM_Entity).Where(w => w.GetDynamicObjectItemValue( ORM_SrcBillType_Id) == SCMFormIdConst.SpInStockBill).Distinct().Select(w => w.GetDynamicObjectItemValue( ORM_SrcEnteryId)); // 根据分录ID重置该分录行的领料标识(批量更新) service.UpdateIsPickInInStcokEntry(this.Context, lstEntryId.ToList()); }}
EndOperationTransaction操作事务结束插件,此插件在事务内运行,出错后系统会回滚事务。示例参照BeginOperationTransaction