
【场景】小数尾差处理
针对表体,每一行的数据都是总数*比例值,得出的结果小数位数可能会比字段的精度高,导致被系统按照精度舍入掉;

【案例】二开插件,实现调整表体数值,通过调整最后一行的数值实现表头金额 = 表体金额汇总

```csharp
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Orm.DataEntity;
using System;
namespace DynamicFormPlugIn.Test
{
[Kingdee.BOS.Util.HotUpdate]
[System.ComponentModel.Description("处理单据体尾差")]
public class BillPlugIn_TailDiff : AbstractBillPlugIn
{
/// <summary>
/// 尾差处理实体
/// </summary>
private string EntityKey = "FEntity";
/// <summary>
/// 总价
/// </summary>
private string FieldKey_Total = "F_BHR_AmountTotal";
/// <summary>
/// 行比例
/// </summary>
private string FieldKey_Precent = "F_BHR_precent";
/// <summary>
/// 行金额尾差值
/// </summary>
private string FieldKey_Amount = "F_BHR_Amount";
public override void DataChanged(DataChangedEventArgs e)
{
//单据头更新时,整个表格尾差重算
if (string.Equals(e.Field.Key, FieldKey_Total, StringComparison.OrdinalIgnoreCase))
{
TailDiffHandle();
}
//比例更新时,更新当前行 和整个表格尾差重算
if (string.Equals(e.Field.Key, FieldKey_Precent, StringComparison.OrdinalIgnoreCase))
{
RefreshRowData(e.Row);
TailDiffHandle();
}
}
private bool isTailDiff = false;
private void RefreshRowData(int rowIdx)
{
decimal totalVal = ToDecimal(this.View.Model.GetValue(FieldKey_Total));
if (totalVal == 0)
return;
var entity = this.View.BillBusinessInfo.GetEntryEntity(EntityKey);
DynamicObject rowObj = this.View.Model.GetEntityDataObject(entity, rowIdx);
var precentField = this.View.BillBusinessInfo.GetField(FieldKey_Precent);
var amountField = this.View.BusinessInfo.GetField(FieldKey_Amount);
decimal rowAmount = totalVal * ToDecimal(precentField.GetFieldValue(rowObj)) / 100;
Model.SetValue(amountField, rowObj, rowAmount);
}
/// <summary>
/// 计算尾差处理,将剩余值计算到最后一行
/// (最好是放在保存时实现做校验时尾差处理,值更新时容易导致计算量过大)
/// </summary>
private void TailDiffHandle()
{
if (isTailDiff)
return;
decimal totalVal = ToDecimal(this.View.Model.GetValue(FieldKey_Total));
if (totalVal == 0)
return;
var entity = this.View.BillBusinessInfo.GetEntryEntity(EntityKey);
DynamicObjectCollection rowObjs = this.View.Model.GetEntityDataObject(entity);
if (rowObjs.Count <= 0)
return;
var precentField =