授信拆单;保证金模板选择;客户层级资金来源

This commit is contained in:
锦麟 王
2026-08-26 10:23:07 +08:00
parent 9c42852a6b
commit ca3b57bb98
14 changed files with 381 additions and 50 deletions
@@ -206,5 +206,106 @@ namespace YLErp.Modules.SwapModule
Assert.AreEqual(ConsFundTag.Cash, settlements[1].Tag);
Assert.AreEqual(-300m, settlements[1].MarginAmount);
}
// ================================================================
// §2.3 情形1 交易级资金来源回退(ConsFundTag.PreferCredit):
// 腿上显式选择优先 > 交易级 margin_fund_source 回退 > 默认现金。
// 标签定稿(ApplyMarginFundTags)与资金校验(TradeCanBeConfirm)共用本口径。
// ================================================================
[TestMethod]
public void FT_031_腿选授信或现金_交易级字段不覆盖腿上显式选择()
{
Assert.IsTrue(ConsFundTag.PreferCredit(ConsFundTag.Credit, null));
Assert.IsTrue(ConsFundTag.PreferCredit(ConsFundTag.Credit, ConsFundTag.Cash));
Assert.IsFalse(ConsFundTag.PreferCredit(ConsFundTag.Cash, ConsFundTag.Credit));
Assert.IsFalse(ConsFundTag.PreferCredit(ConsFundTag.Cash, null));
}
[TestMethod]
public void FT_032_腿未选_按交易级资金来源回退()
{
Assert.IsTrue(ConsFundTag.PreferCredit(null, ConsFundTag.Credit));
Assert.IsTrue(ConsFundTag.PreferCredit("", ConsFundTag.Credit));
Assert.IsFalse(ConsFundTag.PreferCredit(null, ConsFundTag.Cash));
//交易级也未设置 → 默认现金
Assert.IsFalse(ConsFundTag.PreferCredit(null, null));
Assert.IsFalse(ConsFundTag.PreferCredit("", ""));
}
// ================================================================
// §2.3 保存前授信拆单(FundTagCalc.ApplySaveTimeSplit2026-08-26 业务确认:
// 保存检查授信→不足拦截确认→拆完再保存;原腿=可用额度标授信、新腿=现金差额)
// ================================================================
private static LegAmount MarginLeg(long id, decimal fix, bool preferCredit = true)
=> new()
{
Leg = new swap_position
{
id = id,
InterestDirection = 1,
InterestPrincipalFix = fix,
FundTag = preferCredit ? ConsFundTag.Credit : ConsFundTag.Cash
},
Amount = (double)fix,
PreferCredit = preferCredit
};
[TestMethod]
public void FT_033_保存前拆单_额度不足_原腿授信新腿现金差额守恒()
{
var legs = new List<LegAmount> { MarginLeg(101, 1000m) };
var plans = FundTagCalc.AllocateByLegPreference(legs, 300, ignoreMoneyCheck: false);
var newLegs = FundTagCalc.ApplySaveTimeSplit(legs, plans);
Assert.AreEqual(1, newLegs.Count);
//原腿保留可用额度部分并标授信
Assert.AreEqual(300m, legs[0].Leg.InterestPrincipalFix);
Assert.AreEqual(ConsFundTag.Credit, legs[0].Leg.FundTag);
//新现金腿=差额,倒挤守恒
Assert.AreEqual(700m, newLegs[0].InterestPrincipalFix);
Assert.AreEqual(ConsFundTag.Cash, newLegs[0].FundTag);
Assert.AreEqual(0, newLegs[0].id);
Assert.IsNull(newLegs[0].Obervation);
}
[TestMethod]
public void FT_034_保存前拆单_可用授信为零_整腿定稿现金不拆()
{
var legs = new List<LegAmount> { MarginLeg(101, 1000m) };
var plans = FundTagCalc.AllocateByLegPreference(legs, 0, ignoreMoneyCheck: false);
var newLegs = FundTagCalc.ApplySaveTimeSplit(legs, plans);
Assert.AreEqual(0, newLegs.Count);
Assert.AreEqual(1000m, legs[0].Leg.InterestPrincipalFix);
Assert.AreEqual(ConsFundTag.Cash, legs[0].Leg.FundTag);
}
[TestMethod]
public void FT_035_保存前拆单_额度充足_全额授信定稿不拆_现金腿不动()
{
var legs = new List<LegAmount> { MarginLeg(101, 1000m), MarginLeg(102, 500m, preferCredit: false) };
var plans = FundTagCalc.AllocateByLegPreference(legs, 5000, ignoreMoneyCheck: false);
var newLegs = FundTagCalc.ApplySaveTimeSplit(legs, plans);
Assert.AreEqual(0, newLegs.Count);
Assert.AreEqual(ConsFundTag.Credit, legs[0].Leg.FundTag);
Assert.AreEqual(1000m, legs[0].Leg.InterestPrincipalFix);
Assert.AreEqual(ConsFundTag.Cash, legs[1].Leg.FundTag);
}
[TestMethod]
public void FT_036_保存前拆单_支付方向腿按方向比折算()
{
var leg = new swap_position { id = 101, InterestDirection = 2, InterestPrincipalFix = -1000m, FundTag = ConsFundTag.Credit };
var legs = new List<LegAmount> { new() { Leg = leg, Amount = 1000, PreferCredit = true } };
var plans = FundTagCalc.AllocateByLegPreference(legs, 300, ignoreMoneyCheck: false);
var newLegs = FundTagCalc.ApplySaveTimeSplit(legs, plans);
//应付额 = fix × -1dir=2),授信部分 300 → fix = -300;现金差额倒挤 = -700
Assert.AreEqual(-300m, leg.InterestPrincipalFix);
Assert.AreEqual(-700m, newLegs[0].InterestPrincipalFix);
}
}
}