授信/现金资金标签分配链路 double→decimal 精度收敛

- FundTagCalc 全链路(LegAmount/LegFundPlan/UnwindTagSplit/TagRelease/MarginLegSettlement)金额类型改 decimal,消除 double 二进制误差在拆单倒挤、守恒校验中的分位尾差
- 边界处显式转换:writeCash 委托与 ClientCreditInoutService.Occupy/Release(仍 double)、GetAvailableCredit 返回值 (decimal) 强转
- SwapDealService.RecordMarginCashFlow/ReleaseMarginByFundTag 签名同步 decimal,测试桩 TestableSwapDealService 对齐
- 单测断言去掉 1e-6 容差(decimal 精确比较)
This commit is contained in:
hjhan
2026-08-27 18:22:56 +08:00
parent 74bf82ab1d
commit 15d25228af
6 changed files with 37 additions and 37 deletions
@@ -11,7 +11,7 @@ namespace YLErp.Modules.SwapModule
[TestClass]
public class FundTagCalcTest
{
private static LegAmount Leg(long id, double amount, bool preferCredit)
private static LegAmount Leg(long id, decimal amount, bool preferCredit)
=> new() { Leg = new swap_position { id = id }, Amount = amount, PreferCredit = preferCredit };
// ================================================================
@@ -273,7 +273,7 @@ namespace YLErp.Modules.SwapModule
InterestPrincipalFix = fix,
FundTag = preferCredit ? ConsFundTag.Credit : ConsFundTag.Cash
},
Amount = (double)fix,
Amount = fix,
PreferCredit = preferCredit
};
@@ -71,8 +71,8 @@ namespace YLErp.Modules.SwapModule
new List<LegAmount> { new() { Leg = leg, Amount = 1000, PreferCredit = true } },
creditAvailable: 5_000, ignoreMoneyCheck: false);
Assert.AreEqual(1000, plans[0].CreditAmount, 1e-6);
Assert.AreEqual(0, plans[0].CashAmount, 1e-6);
Assert.AreEqual(1000, plans[0].CreditAmount);
Assert.AreEqual(0, plans[0].CashAmount);
Assert.IsFalse(plans[0].NeedSplit);
//CashAmount==0 → ApplyMarginFundTags 不写现金流水;占用 remark 前缀断言
Assert.IsTrue((ClientCreditInoutService.AdditionalMarginRemark + "占用")
@@ -94,8 +94,8 @@ namespace YLErp.Modules.SwapModule
var legs = new List<LegAmount> { new() { Leg = leg, Amount = 1000, PreferCredit = true } };
var plans = FundTagCalc.AllocateByLegPreference(legs, creditAvailable: 300, ignoreMoneyCheck: false);
Assert.IsTrue(plans[0].NeedSplit);
Assert.AreEqual(300, plans[0].CreditAmount, 1e-6);
Assert.AreEqual(700, plans[0].CashAmount, 1e-6);
Assert.AreEqual(300, plans[0].CreditAmount);
Assert.AreEqual(700, plans[0].CashAmount);
//ApplySaveTimeSplit 与 SplitLeg 同口径(原腿=授信部分、克隆现金腿倒挤守恒)
var newLegs = FundTagCalc.ApplySaveTimeSplit(legs, plans);
@@ -126,8 +126,8 @@ namespace YLErp.Modules.SwapModule
new List<LegAmount> { new() { Leg = leg, Amount = 1000, PreferCredit = false } },
creditAvailable: 5_000, ignoreMoneyCheck: false);
Assert.AreEqual(0, plans[0].CreditAmount, 1e-6);
Assert.AreEqual(1000, plans[0].CashAmount, 1e-6);
Assert.AreEqual(0, plans[0].CreditAmount);
Assert.AreEqual(1000, plans[0].CashAmount);
Assert.IsFalse(plans[0].NeedSplit);
}
@@ -141,10 +141,10 @@ namespace YLErp.Modules.SwapModule
return ReleaseMarginByFundTagResult
?? new UnwindTagSplit
{
CashMargin = Convert.ToDouble(marginAmount),
CashRebate = Convert.ToDouble(marginLegs.Any()
CashMargin = marginAmount,
CashRebate = marginLegs.Any()
? marginLegs.Sum(x => x.InterestClosePnL)
: marginRebate)
: marginRebate
};
}