二开案例.服务插件.辅助资料校验编码名称重复区分大小写
【应用场景】辅助资料保存操作校验编码名称唯一性时,在SqlServer账套下默认是忽略大小写的,而某些应用场景需要区分大小写。
【案例演示】自定义服务插件,重写标准产品的唯一性校验器,校验编码名称重复时,区分大小写。
【实现步骤】
<1>编写服务插件,代码如下。
using Kingdee.BOS;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Core.Validation;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Util;
using System.Collections.Generic;
using System.ComponentModel;
namespace Jac.XkDemo.BOS.App.PlugIn
{
/// <summary>
/// 【服务插件】辅助资料校验编码名称重复区分大小写
/// </summary>
[Description("【服务插件】辅助资料校验编码名称重复区分大小写"), HotUpdate]
public class AssistantSaveOperationServicePlugIn : Kingdee.BOS.App.ServicePlugIn.Assistant.Save
{
/// <summary>
/// 注册自定义校验器
/// </summary>
/// <param name="e"></param>
public override void OnAddValidators(Kingdee.BOS.Core.DynamicForm.PlugIn.Args.AddValidatorsEventArgs e)
{
// 添加名称重复校验器
var nameValidator = new IsExistNameSaveValidator();
nameValidator.EntityKey = "FBillHead";
e.Validators.Add(nameValidator);
// 添加编码重复校验器
var numberValidator = new IsExistCodeSaveValidator();
numberValidator.EntityKey = "FBillHead";
e.Validators.Add(numberValidator);
}
/// <summary>
/// 获取SqlServer数据库符号集
/// </summary>
/// <param name="ctx"></param>
/// <returns></returns>
public static string GetCollate(Context ctx)
{
return DbQueryUtils.IsSqlServerDb(ctx) ? " COLLATE Chinese_PRC_CS_AS " : "";
}
/// <summary>
/// 获取方言标记
/// </summary>
/// <param name="ctx"></param>
/// <returns></returns>
public static string GetCollateDialect(Context ctx)
{
return DbQueryUtils.IsSqlServerDb(ctx) ? "/*dialect*/" : "";
}
}
/// <summary>
/// 名称重复校验器
/// 1、有禁用项目分类重名,则提示,是否继续新增。
/// 2、非禁用项目分类重名,则阻止新增。
/// </summary>
internal class IsExistNameSaveValidator : AbstractValidator
{
public override void Validate(ExtendedDataEntity[] dataEntities, ValidateContext validateContext, Context ctx)
{
foreach (var dynObj in dataEntities)
{
//如果有重名,iExistState不为0则表示为有重名
var exists = IsExistSameName(Context, dynObj.DataEntity);
if (exists != 0)
{
//定义错误信息
ValidationErrorInfo errorInfo;
switch (exists)
{
case 2: //有禁用项目重名,则提示,是否继续新增。ErrorLevel.Warning
errorInfo = new ValidationErrorInfo(
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString(),
dynObj.DataEntity["Id"].ToString(),
dynObj.DataEntityIndex,
dynObj.RowIndex,
dynObj.DataEntity["Id"].ToString(),
string.Format(Kingdee.BOS.Resource.ResManager.LoadKDString("辅助资料类别", "002006030013537", Kingdee.BOS.Resource.SubSystemType.BOS)
+ "\"{0}\"" + Kingdee.BOS.Resource.ResManager.LoadKDString("中已存在禁用状态的名称为", "002006030013540", Kingdee.BOS.Resource.SubSystemType.BOS)
+ "\"{1}\"" + Kingdee.BOS.Resource.ResManager.LoadKDString("的辅助资料,是否继续保存?", "002006030013543", Kingdee.BOS.Resource.SubSystemType.BOS),
dynObj.DataEntity["FID"] == null ? "'0'" : ((DynamicObject)dynObj.DataEntity["FID"])["Name"].ToString(),
dynObj.DataEntity["DataValue"]),
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString(),
ErrorLevel.Warning);
break;
default: //非禁用项目重名,则阻止新增。ErrorLevel.FatalError
errorInfo = new ValidationErrorInfo(
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString(),
dynObj.DataEntity["Id"].ToString(),
dynObj.DataEntityIndex,
dynObj.RowIndex,
dynObj.DataEntity["Id"].ToString(),
string.Format(Kingdee.BOS.Resource.ResManager.LoadKDString("辅助资料类别", "002006030013537", Kingdee.BOS.Resource.SubSystemType.BOS)
+ "\"{0}\"" + Kingdee.BOS.Resource.ResManager.LoadKDString("中已存在名称为", "002006030013546", Kingdee.BOS.Resource.SubSystemType.BOS)
+ "\"{1}\"" + Kingdee.BOS.Resource.ResManager.LoadKDString("的辅助资料!", "002006030013549", Kingdee.BOS.Resource.SubSystemType.BOS),
dynObj.DataEntity["FID"] == null ? "'0'" : ((DynamicObject)dynObj.DataEntity["FID"])["Name"].ToString(),
dynObj.DataEntity["DataValue"]),
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString(),
ErrorLevel.FatalError);
break;
}
//添加错误提示信息。
validateContext.AddError(dynObj.DataEntity, errorInfo);
}
}
}
/// <summary>
/// 名称重复校验器
/// </summary>
/// <param name="ctx"></param>
/// <param name="dynamicObject"></param>
/// <returns>0:无重名;1:与未禁用数据重名;2:与禁用数据重名</returns>
private int IsExistSameName(Context ctx, DynamicObject dynamicObject)
{
// 返回值
var iResult = 0;
var fEntryId = "0";
if (dynamicObject.DataEntityState.FromDatabase)
{
fEntryId = dynamicObject["Id"].ToString();
}
// 获取父节点内码
var parentFID = dynamicObject["FID"] == null ? "0" : ((DynamicObject)dynamicObject["FID"])["Id"].ToString();
// 获取当前的多语言字段
var multiLanguageText = (LocalDynamicObjectCollection)dynamicObject["MultiLanguageText"];
var sqlParameterList = new List<SqlParam>();
var filterList = new List<string>();
foreach (var languageText in multiLanguageText)
{
if (languageText["DataValue"] == null || string.IsNullOrWhiteSpace(languageText["DataValue"].ToString()))
{
continue;
}
var dataValue = languageText["DataValue"].ToString();
filterList.Add(string.Format("(b.FDATAVALUE{0}=@FDATAVALUE{1} AND b.FLOCALEID={2}) ", AssistantSaveOperationServicePlugIn.GetCollate(ctx), sqlParameterList.Count, languageText["LocaleId"]));
sqlParameterList.Add(new SqlParam("@FDATAVALUE" + sqlParameterList.Count, KDDbType.String, dataValue));
}
//根据语言种类,拼装所有的条件
var strFilterString = string.Join("OR", filterList);
if (string.IsNullOrEmpty(strFilterString))
{
strFilterString = "1=1";
}
// 只查询多语言表,判断是否有重名
string sqlExists = string.Format(@"{0}
SELECT FIsExist=1 WHERE EXISTS(
SELECT 0 FROM T_BAS_ASSISTANTDATAENTRY a
LEFT JOIN T_BAS_ASSISTANTDATAENTRY_L b
ON a.FENTRYID=b.FENTRYID
WHERE a.FID='{1}' AND ({2}) AND a.FENTRYID<>'{3}'
)", AssistantSaveOperationServicePlugIn.GetCollateDialect(ctx), parentFID, strFilterString, fEntryId);
// 关联业务表及多语言表,判断重名的是否是非禁用的
string sqlForbidded = string.Format(@"{0}
SELECT FIsExist=1 WHERE EXISTS(
SELECT 0 FROM T_BAS_ASSISTANTDATAENTRY a
LEFT JOIN T_BAS_ASSISTANTDATAENTRY_L b
ON a.FENTRYID=b.FENTRYID
WHERE a.FID='{1}' AND a.FFORBIDSTATUS<>'B' AND ({2}) AND a.FENTRYID<>'{3}'
)", AssistantSaveOperationServicePlugIn.GetCollateDialect(ctx), parentFID, strFilterString, fEntryId);
// 判断是否有重复
if (DBUtils.ExecuteScalar(ctx, sqlExists, 0, sqlParameterList.ToArray()) > 0)
{
// 如果重复的是非禁用状态的则返回1,禁止继续新增
if (DBUtils.ExecuteScalar(ctx, sqlForbidded, 0, sqlParameterList.ToArray()) > 0)
{
iResult = 1;
}
else // 否则重复的都是已禁用的,返回2,提示是否继续,可以让用户继续新增
{
iResult = 2;
}
}
return iResult;
}
}
/// <summary>
/// 编码重复校验器
/// 检查当前辅助资料类型下的辅助资料的编码是否重复
/// </summary>
internal class IsExistCodeSaveValidator : AbstractValidator
{
public override void Validate(ExtendedDataEntity[] dataEntities, ValidateContext validateContext, Context ctx)
{
foreach (var dynObj in dataEntities)
{
var exists = false;
if (dynObj["Number"] != null)
{
exists = IsExistSameCode(Context, dynObj.DataEntity);
}
if (exists)
{
var errorInfo = new ValidationErrorInfo(
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString(),
dynObj.DataEntity["Id"].ToString(),
dynObj.DataEntityIndex,
dynObj.RowIndex,
dynObj.DataEntity["Id"].ToString(),
string.Format(Kingdee.BOS.Resource.ResManager.LoadKDString("辅助资料类别", "002006030013537", Kingdee.BOS.Resource.SubSystemType.BOS)
+ "\"{0}\"" + Kingdee.BOS.Resource.ResManager.LoadKDString("中已存在编码为", "002006030025355", Kingdee.BOS.Resource.SubSystemType.BOS)
+ "\"{1}\"" + Kingdee.BOS.Resource.ResManager.LoadKDString("的辅助资料!", "002006030013549", Kingdee.BOS.Resource.SubSystemType.BOS),
dynObj.DataEntity["FID"] == null ? "'0'" : ((DynamicObject)dynObj.DataEntity["FID"])["Name"].ToString(),
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString()),
dynObj.DataEntity["Number"].IsNullOrEmptyOrWhiteSpace() ? "" : dynObj.DataEntity["Number"].ToString(),
ErrorLevel.FatalError);
// 添加错误提示信息。
validateContext.AddError(dynObj.DataEntity, errorInfo);
}
}
}
/// <summary>
/// 检查当前辅助资料类型下的辅助资料的编码是否重复
/// </summary>
/// <param name="ctx"></param>
/// <param name="dynamicObject"></param>
/// <returns></returns>
private bool IsExistSameCode(Context ctx, DynamicObject dynamicObject)
{
var fEntryId = "0";
if (dynamicObject.DataEntityState.FromDatabase)
{
fEntryId = dynamicObject["Id"].ToString();
}
var fNumber = dynamicObject["Number"].ToString();
var fId = dynamicObject["Fid_id"].ToString();
var sqlparams = new[]
{
new SqlParam("@FID", KDDbType.AnsiString, fId),
new SqlParam("@FNUMBER", KDDbType.String, fNumber),
new SqlParam("@FENTRYID", KDDbType.AnsiString, fEntryId),
};
var sql = string.Format(@"{0}
SELECT 1 FROM T_BAS_ASSISTANTDATAENTRY WHERE FID=@FID AND FNUMBER{1}=@FNUMBER AND FENTRYID<>@FENTRYID"
, AssistantSaveOperationServicePlugIn.GetCollateDialect(ctx), AssistantSaveOperationServicePlugIn.GetCollate(ctx));
return DBUtils.ExecuteScalar(ctx, sql, 0, sqlparams) > 0;
}
}
}
<2>拷贝插件组件到应用站点的WebSite\Bin目录下,重启IIS。
<3>BOSIDE扩展辅助资料[BOS_ASSISTANTDATA_DETAIL],保存操作禁用标准产品的服务插件,注册自定义服务插件,保存元数据,开发完毕。
现在可以登录业务站点,打开辅助资料列表,新增辅助资料,检验一下插件效果啦。
此时新增的辅助资料名称已经支持区分大小写啦(加盟A,加盟a)
【知识点】
<1>Oracle默认区分大小写,SqlServer默认不区分大小写。
<2>如果SqlServer账套下要区分大小写,可通过SQL中强制指定字符集排序规则变通实现:
COLLATE Chinese_PRC_CS_AS
<3>SQL用法示例:
SELECT * FROM T_BAS_ASSISTANTDATAENTRY_L WHERE FDATAVALUE COLLATE Chinese_PRC_CS_AS ='自营'
<4>辅助资料的保存操作上注册的标准插件Kingdee.BOS.App.ServicePlugIn.Assistant.Save,其内部主要业务逻辑是进行辅助资料的编码和名称的唯一性校验,以及在保存后刷新辅助资料的缓存,取消此标准插件会导致执行保存操作时的编码和名称的唯一性校验失效,不再有其他副作用,有特殊使用场景的可酌情取消该插件或重写该插件。
【金蝶云星空BOS二次开发案例演示】https://vip.kingdee.com/article/94751030918525696
二开案例.服务插件.辅助资料校验编码名称重复区分大小写
本文2024-09-23 04:20:16发表“云星空知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-k3cloud-164659.html