表单插件给核算维度字段赋值
金蝶云社区-Jaden
Jaden
7人赞赏了该文章 1,185次浏览 未经作者许可,禁止转载编辑于2020年12月01日 17:37:00

1、新建一个获取/生成核算维度的方法
public static class CustFlexSaveService
{
///

/// 保存弹性域字段的数据包,确保在数据库产生一个组合值,返回的数据包中为保存成功的弹性域组合
///
/// 数据库上下文
/// 单据上的弹性域字段,如仓位字段
/// 单据上弹性域字段的数据包
///
///
/// 弹性域字段说明:
/// 1. 弹性域字段,由多个不确定的维度组合而成;
/// 2. 每个维度都会有一定的可选值;
/// 3. 使用时,弹性域各个维度值确定后,就会形成了一个唯一的弹性域维度值组合,并对应产生一个唯一内码;
/// 4. 单据上存储的弹性域字段值,仅存放其弹性域维度值组合对应的唯一内码;
/// 5. 如仓位,可能包括栋、层、排这三个维度,第1栋、第1层、第1排就是一个弹性域值组合,对应有个内码(如100005)
/// 6. 如出库单使用了仓位,用到了第1栋、第1层、第1排这个值组合,则单据上仓位字段,仅保存组合内码(如100005)
///
/// 为什么要提供特别的函数,保存弹性域字段值数据包?
/// 1. 对于用户来说,最直观看到的是弹性域的维度,如仓位的栋、层、排;
/// 2. 因此用户对弹性域赋值,首先会对各维度赋值,如确定为第1栋、第1层、第1排;
/// 3. 用户给维度填了值,但是系统并没有自动根据维度值组合,产生组合内码,并提交到数据;
/// 4. 单据上引用的弹性域字段值,依然是空值,保存后,重新加载单据,加载弹性域组合会失败,所有的维度值丢失;
///
/// 本函数,首先判断数据库是否已经给定的组组合,如果存在,则读取,否则,创建组合,存储后返回;
///
public static Kingdee.BOS.Orm.DataEntity.DynamicObject SaveFlexData(
Kingdee.BOS.Context ctx,
Kingdee.BOS.Core.Metadata.FieldElement.RelatedFlexGroupField flexField,
Kingdee.BOS.Orm.DataEntity.DynamicObject flexFldDataObj)
{
// 首先判断参数是否合理,如果参数不合理,无法进行后续处理
if (flexField == null)
{
// 后面逻辑必须用到弹性域字段
return flexFldDataObj;
}
if (flexFldDataObj == null)
{
return flexFldDataObj;
}
// 拼接维度值,如果拼接失败,说明无维度值,直接返回
string flexValString = string.Empty;
if (FlexValToString(flexFldDataObj, out flexValString) == false)
{
return flexFldDataObj;
}
// 判断值组合是否已经存在?
// 通过BOS平台提供的服务,读取弹性域组合对应的组合编码,如果数据库不存在此组合,则返回为0
Kingdee.BOS.App.Core.FlexService flexService = new Kingdee.BOS.App.Core.FlexService();
long id = flexService.GetFlexDataId(ctx, flexFldDataObj, flexField.BDFlexType.FormId);
if (id == 0)
{
// 不存在此组合,需要主动创建
// 调用BOS平台提供的标准保存服务,直接保存此组合,并接受保存成功后返回的数据包
//Kingdee.BOS.Contracts.ISaveService saveService = Kingdee.BOS.App.ServiceHelper.GetService();
//var objs = saveService.Save(ctx, new Kingdee.BOS.Orm.DataEntity.DynamicObject[] { flexFldDataObj });
var objs = BusinessDataServiceHelper.Save(ctx, new Kingdee.BOS.Orm.DataEntity.DynamicObject[] { flexFldDataObj });

if (objs != null && objs.Length > 0)
{
// 回填保存成功返回的数据包内码
flexFldDataObj[0] = objs[0][0];
}
}
else if (id != -1)
{
// 存在此组合,直接把内码填写到数据包上
flexFldDataObj[0] = id;
}
// 返回已经填写了内码的原始数据包
return flexFldDataObj;
}
///

/// 拼接各维度值为一个长字符串,并输出。如果各维度均没有填写值,则返回false,表示值拼接失败
///
/// 弹性域字段数据包
/// 输出拼接的值组合字符串
///
/// 此函数可以按照统一的格式,为每种弹性域字段值,产生一个维度值组合字符串;
/// 因此,批量处理时,可以据此把保存后返回的弹性域数据包(有内码),与原始数据包(无内码)对应起来
///
public static bool FlexValToString(Kingdee.BOS.Orm.DataEntity.DynamicObject flexFldDataObj,
out string flexValString)
{
// 维度组合是否为空串?默认为空,只有遇到了第一个不为空的维度后,才会被设为false
bool isNull = true;
StringBuilder sb = new StringBuilder();
foreach (var item in flexFldDataObj.DynamicObjectType.Properties)
{
// 内码("Id")会在保存前后,产生变化,由0变为100005,不需要拼接输出
// 维度值内码("_Id")与维度值数据包有重复,而且绝对不为空(最多为0),不好判断是否填写,所以取值时,使用维度值数据包
if (item.Name != "Id" && !item.Name.EndsWith("_Id"))
{
string val;
// 取本列值
object colValue = item.GetValue(flexFldDataObj);
// 把本列值转化为字符串
if (colValue == null)
{
val = "";
}
else if (colValue is Kingdee.BOS.Orm.DataEntity.DynamicObject)
{// 如果本列是复杂数据包,仅输出其内码
object pkvalue = ((Kingdee.BOS.Orm.DataEntity.DynamicObject)colValue)[0];
val = pkvalue == null ? "" : Convert.ToString(pkvalue);
}
else
{
val = Convert.ToString(colValue);
}

// 如果本列不为空,则整个组合不为空
if (!string.IsNullOrWhiteSpace(val))
{
isNull = false;
}
sb.Append("||").Append(val);
}
}
flexValString = sb.ToString();

// 输出是否有值
if (isNull)
{
// 无值,返回失败
return false;
}
else
{
return true;
}
}
}

2、新建科目对应的核算维度信息映射类
///


/// 核算维度信息
///

public class FlexItem
{
///
/// 数据来源 --基础资料类型
///

public string Source { get; set; }

///


/// 维度表扩展字段
///

public string ColumnName { get; set; }

///


/// 是否必录
///

public bool Needed { get; set; }

}

3、构建一个获取科目对应的核算维度映射信息的方法
///


/// 根据科目ID获取对应的核算维度扩展字段
///

///
///
public List GetFlexColumn(long ID)
{
List flexItems = new List();
string querySql = string.Format("select t1.FINPUTTYPE,t2.FVALUESOURCE,t2.FFLEXNUMBER from T_BD_ACCOUNTFLEXENTRY t1 inner join T_BD_FLEXITEMPROPERTY t2 on t1.FFLEXITEMPROPERTYID=t2.FID where t1.FACCTID={0}", ID);
DynamicObjectCollection results= DBUtils.ExecuteDynamicObject(this.Context, querySql);
if(results!=null)
{
foreach(DynamicObject item in results)
{
FlexItem flexItem = new FlexItem();
flexItem.Source = Convert.ToString(item["FVALUESOURCE"]);
int inputtype = Convert.ToInt32(item["FINPUTTYPE"]);
flexItem.Needed = inputtype == 1;
flexItem.ColumnName = Convert.ToString(item["FFLEXNUMBER"]);
flexItems.Add(flexItem);
}
}
return flexItems;
}

4、构建生成核算维度数据包的方法
///


/// 构建核算维度数据包
///

///
///
///
public DynamicObject CreateFlexValue(RelatedFlexGroupField field,List flexItems)
{
DynamicObject flexValue = new DynamicObject(field.RefFormDynamicObjectType); //核算维度数据包
foreach(FlexItem flexItem in flexItems)
{
DynamicObject baseValue = ; //TODO这个baseValue是核算维度对应的基础资料的数据包,有两种方式可以获取:1直接在界面上获取(通过this.Model.GetValue()方法获取) 2、通过BusinessDataServiceHelper.load()方法获取
if(baseValue==null)
{
continue;
}
foreach(var pro in flexValue.DynamicObjectType.Properties)
{
if (flexItem.ColumnName.Equals("F" + pro.Name, StringComparison.OrdinalIgnoreCase))
{
flexValue[pro.Name] = baseValue;
flexValue[pro.Name + "_Id"] = baseValue["Id"];
}
}
}
return flexValue;
}

5、调用上面的方法给界面上的核算维度字段赋值
long id=0; //科目内码
RelatedFlexGroupField flex = this.Model.BusinessInfo.GetField("") as RelatedFlexGroupField;; //获取界面上的核算维度字段
DynamicObject flexValue = CreateFlexValue(flex, GetFlexColumn(id));
DynamicObject result = CustFlexSaveService.SaveFlexData(this.Context, flex, flexValue);
this.Model.SetValue("", result["Id"], index); //给核算维度字段赋值