本文讲述了在处理销售订单价格变更后,如何同步更新下游单据(如发货通知单和销售出库单)的价格及税额等相关运算的需求。实现方式包括通过插件脚本直接更新字段,或模拟界面操作加载和修改单据信息,以触发字段联动公式逻辑和服务。详细步骤包括加载单据View、修改字段值并触发联动更新、保存单据,以及同步流程数据和触发审核相关的反写规则。此外,还提到了在处理单据变更时需注意信用重算和库存校对的情况。
需求背景:例如:
销售订单已经审核,且下推了发货通知单和销售出库单,应收时候调整了价格,按最新价格进行了结算,随后销售订单通过变更方式,变更了销售订单的价格信息,此时希望同步变更更新下游发货通知单和销售出库单的价格,且需要联动更新税额、金额等相关运算(需要实现单据自身所有的联动运算)。
实现方式:
1.插件通过脚本直接更新对应字段值。(比较直接,但是局限在于不能达到界面录单时的字段联动公式逻辑和服务触发。可能会有数据缺陷,需要脚本考虑完善整个逻辑过程,较为复杂)
2.类似这种业务需求就需要在插件代码中需要通过代码模拟单据View加载单据和修改单据信息:
通过模拟View加载单据模式,可以利用单据的View和Model,就像界面操作修改单据一样,修改字段触发字段配置的公式逻辑。
构造模拟单据View,并加载单据
FormMetadata meta = (FormMetadata)Kingdee.BOS.ServiceHelper.MetaDataServiceHelper.Load(this.Context, SCMFormIdConst.SAL_OUTSTOCK);//单据唯一标识
public IDynamicFormView OpenWebView(Context ctx, FormMetadata meta, object pkid = null)
{
BusinessInfo info = meta.BusinessInfo;
Form form = info.GetForm();
BillOpenParameter param = new BillOpenParameter(SCMFormIdConst.SAL_OUTSTOCK, null);
param.SetCustomParameter("formID", form.Id);
//根据主键是否为空 置为新增或修改状态
param.SetCustomParameter("status", !IsPrimaryValueEmpty(PkId) ? "Edit" : "AddNew");
param.SetCustomParameter("PlugIns", form.CreateFormPlugIns()); //插件实例模型
//修改主业务组织无须用户确认
param.SetCustomParameter("ShowConformDialogWhenChangeOrg", false);
param.Context = this.Context;
param.FormMetaData = meta;
param.LayoutId = param.FormMetaData.GetLayoutInfo().Id;
param.PkValue = !IsPrimaryValueEmpty(PkId) ? PkId: null;//单据主键内码FID
param.Status= !IsPrimaryValueEmpty(PkId) ? OperationStatus.EDIT : OperationStatus.ADDNEW;
IResourceServiceProvider provider = form.GetFormServiceProvider();
//普通的动态表单模式DynamicFormView
//IDynamicFormView billview = provider.GetService(typeof(IDynamicFormView)) as IDynamicFormView;
//这里模拟为引入模式的WebView,否则遇到交互的时候会有问题,移动端目前无法直接交互
Type type = Type.GetType("Kingdee.BOS.Web.Import.ImportBillView,Kingdee.BOS.Web");
IDynamicFormView billview = (IDynamicFormView)Activator.CreateInstance(type);
(billview as IBillViewService).Initialize(param, provider);//初始化
(billview as IBillViewService).LoadData();//加载单据数据
//如果是普通DynamicFormView时,LoadData的时候会加网控,要清除。//引入模式View不需要
// (billview as IBillView).CommitNetworkCtrl();
return billview ;
}
private bool IsPrimaryValueEmpty(object pk)
{
return pk == null || pk.ToString() == "0" || string.IsNullOrWhiteSpace(pk.ToString());
}
2.触发单据相关字段更新赋值,并触发联动触发配置的值更新事件(相关配置公式和服务)
billview.Model.SetValue("FTaxPrice",row);//含税单价字段赋值,row为具体行号
billview.InvokeFieldUpdateService("FTaxPrice", row);//联动触发含税单价值更新事件,row为具体行号
3.修改完单据需要调用保存操作
方式1: //直接调用保存操作
billview.InvokeFormOperation(Kingdee.BOS.Core.DynamicForm.FormOperationEnum.Save);
方式2: //通过保存数据包模式,可以得到保存操作结果
DynamicObject saveResult=BOS.ServiceHelper.BusinessDataServiceHelper.Save(this.Context, billview.Model.DataObject);
4.拓展知识:
IBusinessFlowTrackerService 有自己的保存、审核等方法,仅只是业务流程跟踪、执行反写相关逻辑
以上仅只是修改、保存了单据数据 如果单据有上游关联关系,需要通过IBusinessFlowTrackerService 同步流程数据,执行触发以下(审核)相关的反写规则
//客户端得到IBusinessFlowTrackerService 服务对象,通过接口获取
//IBusinessFlowTrackerService flowTracker = Kingdee.BOS.Contracts.ServiceFactory.GetBusinessFlowTrackerService(this.Context);
//服务端获取IBusinessFlowTrackerService 服务对象,通过BOS.App.ServiceHelper获取
IBusinessFlowTrackerService flowTracker = Kingdee.BOS.App.ServiceHelper.GetService<IBusinessFlowTrackerService>();
//调用流程跟踪对象的 审核,不是真正的审核单据,仅只是触发审核相关业务流程和反写而已
flowTracker.Audit(this.Context, new DynamicObject[] { billview.Model.DataObject }, billview.Model.BusinessInfo, OperateOption.Create());
5. 注意事项:
如果启用了信用管理,那么修改单据(单价、数量)影响了金额时,需要进行信用重算。
如果是库存单据,那么修改单据(数量联动库存数量)时,需要进行即时库存校对。
推荐阅读