bool RollbackWhenValidationError 设置为true时,操作校验,发现其中有一条单据不符合条件,即会直接退出操作,整批单据均不处理; 默认为false,操作校验,发现有不符合条件的单据时,不直接退出,但会过滤掉不符合条件的单据,继续其余符合条件的单据。 通过设置此选项为true,可以实现整批单据同进同出 备注
通过设置本方法参数对象的一些属性值,控制操作执行策略;
案例–初始化库存保存
代码来源
Kingdee.K3.SCM.App.Stock.ServicePlugIn.InvInitBillService.Save
需求背景
初始化库存单据,部分检查无法在保存前进行,需要在保存结束后,数据已经入库,执行检查。
如果某条数据保存检查失败,需要撤销本条数据的保存,但是之前已经保存成功的数据,则不受影响。
实现方案
在操作执行前,设置操作执行参数,要求单据逐条保存,逐条开启事务。
在事务结束时,检索数据库中是否产生了重复库存条目,如果存在,说明本单据与历史保存的初始化库存单据有数据冲突,本单据不允许保存,需提示用户;
关键字
逐条执行操作操作结束后检查给出交互提示
示例代码
C#
using Kingdee.BOS;
using Kingdee.BOS.App.Data; using Kingdee.BOS.Core;
using Kingdee.BOS.Core.DynamicForm; using Kingdee.BOS.Core.DynamicForm.PlugIn; using Kingdee.BOS.Core.Interaction;
using Kingdee.BOS.Core.Metadata.FieldElement; using Kingdee.BOS.Core.Validation;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Orm.Metadata.DataEntity; using Kingdee.BOS.Resource; using Kingdee.BOS.Util; using Kingdee.K3.Core.SCM; using Kingdee.K3.Core.SCM.STK; using Kingdee.K3.SCM.App.Validator; using Kingdee.K3.SCM.Contracts; using System;
using System.Collections.Generic; using System.Data; using System.Linq; using System.Text;
usingKingdee.BOS.Core.DynamicForm.PlugIn.Args;
namespace Kingdee.K3.SCM.App.Stock.ServicePlugIn.InvInitBillService {
///
///初始库存单据保存操作服务端插件 ///
publicclassSave : AbstractOperationServicePlugIn {
publicoverridevoid OnPreparePropertys(PreparePropertysEventArgs e) {
// 无关代码,略过 }
///
///
publicoverridevoid OnPrepareOperationServiceOption(
OnPrepareOperationServiceEventArgs e)
{
base.OnPrepareOperationServiceOption(e);
//为了在EndOperationTransaction里检查数据抛出交互异常的时候 //只回滚当前单据的事务,这里设置为不支持批量事务,这样BOS会 //循环为每一张单据创建事务调用操作
e.SupportTransaction = true; e.SurportBatchTransaction = false; }
publicoverridevoid OnAddValidators(AddValidatorsEventArgs e)
{
// 无关代码,略过 }
///
///初始库存单据保存后校验数据重复性 ///
///
publicoverridevoid EndOperationTransaction(EndOperationTransactionArgs e) {
if (e.DataEntitys.Count
CheckDuplicateData(e); } }
///
///
privatevoid CheckDuplicateData(EndOperationTransactionArgs e) {
//先获得单据头关键字段完全相同的单据列表 StringBuilder builder = newStringBuilder(); string billIds = \;
foreach (DynamicObject obj in e.DataEntitys) {
builder.AppendFormat(\, (obj[\] == null ? \ : obj[\])); }
//限定获得的单据内码的范围,只取这次保存的,历史数据的忽略
billIds = builder.ToString(1, builder.Length - 1);
string sql = string.Format(@\ FROM T_STK_INVINIT t1 INNER JOIN
(SELECT COUNT(1) AS FCOUNT, t2.FSTOCKID, t2.FKEEPERID, t2.FOWNERID, t2.FSTOCKORGID, t2.FOWNERTYPEID,
t2.FKEEPERTYPEID,t3.FSTOCKSTATUSID,t3.FPROJECTNO,t3.FMTONO,t3.FBOMID, t3.FProduceDate,t3.FSECUNITID,t3.FExpiryDate,t3.FUNITID, t3.FMATERIALID,t3.FStockLocId,t3.FLOT,t3.FAUXPROPID
FROM T_STK_INVINIT t2 INNER JOIN T_STK_INVINITDETAIL T3 ON t2.FID = t3.FID GROUP BY t2.FSTOCKID, t2.FKEEPERID, t2.FOWNERID, t2.FSTOCKORGID,
t2.FOWNERTYPEID,
t2.FKEEPERTYPEID,t3.FSTOCKSTATUSID,t3.FPROJECTNO,t3.FMTONO,t3.FBOMID, t3.FProduceDate,t3.FSECUNITID,t3.FExpiryDate,t3.FUNITID, t3.FMATERIALID,t3.FStockLocId,t3.FLOT,t3.FAUXPROPID
HAVING COUNT(1) > 1 ) ta ON t1.FSTOCKID = ta.FSTOCKID AND t1.FKEEPERID = ta.FKEEPERID AND t1.FOWNERID = ta.FOWNERID AND t1.FSTOCKORGID = ta.FSTOCKORGID
AND t1.FOWNERTYPEID = ta.FOWNERTYPEID AND t1.FKEEPERTYPEID = ta.FKEEPERTYPEID INNER JOIN T_STK_INVINITDETAIL t4 ON t1.FID = t4.FID AND ta.FSTOCKSTATUSID = t4.FSTOCKSTATUSID AND ta.FPROJECTNO = t4.FPROJECTNO AND ta.FMTONO = t4.FMTONO AND ta.FBOMID = t4.FBOMID AND (ta.FProduceDate = t4.FProduceDate OR (ta.FProduceDate IS NULL AND t4.FProduceDate IS NULL))
AND (ta.FExpiryDate = t4.FExpiryDate OR (ta.FExpiryDate IS NULL AND t4.FExpiryDate IS NULL))
AND ta.FUNITID = t4.FUNITID AND ta.FSECUNITID = t4.FSECUNITID
AND ta.FMATERIALID = t4. FMATERIALID AND ta.FStockLocId = t4.FStockLocId AND ta.FLOT = t4.FLOT
AND ta.FAUXPROPID = t4.FAUXPROPID WHERE t1.FID IN ({0}) \, billIds);
Dictionary
idInfos[Convert.ToInt64(dr[\])] = Convert.ToInt64(dr[\]); }
dr.Close(); }
if (idInfos.Count < 1) { return; }
_ownerTypeField = this.BusinessInfo.GetField(\)
asItemClassTypeField;
_keeperTypeField = this.BusinessInfo.GetField(\)
asItemClassTypeField;
_auxPropertyField = this.BusinessInfo.GetField(\)
asRelatedFlexGroupField;
_locPlaceField = this.BusinessInfo.GetField(\)
asRelatedFlexGroupField;
/*用k3显示器显示错误信息*/
string formTitle = \系统中已存在相同的初始库存数据或者单据中存在重复的明细数据分录,校验不通过\; string title = \库存组织~|~仓库~|~仓位~|~物料~|~辅助属性~|~批号~|~生产日期~|~有效期至~|~库存状态
~|~BOM版~|~货主类型~|~货主~|~保管者类型~|~保管者\;
K3DisplayerModel model = K3DisplayerModel.Create(this.Context, title);
model.Option.SetVariableValue(K3DisplayerModel.CST_FormTitle, formTitle); model.OKButton.Visible = false; model.CancelButton.Caption = new
BOS.LocaleValue(Kingdee.BOS.Resource.ResManager.LoadKDString(\确定\, \, Kingdee.BOS.Resource.SubSystemType.SCM), this.Context.UserLocale.LCID);
foreach (DynamicObject dyObj in e.DataEntitys) {
DynamicObjectCollection dyEntrys = dyObj[\] asDynamicObjectCollection; foreach (DynamicObject dyEntry in dyEntrys) { long id = 0;
idInfos.TryGetValue(Convert.ToInt64(dyEntry[\]), out id); if (id == Convert.ToInt64(dyObj[\])) { //获取错误消息
List
model.AddMessage(string.Join(\, errMsgList)); } } }
KDInteractionException ie = newKDInteractionException(this.Option,
\);
ie.InteractionContext.InteractionFormId = FormIdConst.BOS_K3Displayer; ie.InteractionContext.K3DisplayerModel = model; ie.InteractionContext.IsInteractive = false; ie.InteractionContext.SimpleMessage = formTitle;
throw ie;
}
///
///获取当前单据单据行的错误信息 ///
///