fix(eod): FR007收盘检查日按计息取价日回拨,抽出EodCheckFr007Price

- 检查日改用 IndexFixerBase.GetFixingDate(与计息取价同源):
  交易日=当日(行为零变更),周末/节假日=上一交易日,
  解除非交易日收盘"必报FR007未入库"死锁(2026-08-28:0523周六收盘)
- 缺价报错附回拨说明与涉及FR007浮动的交易编号(上限20笔),
  交易日缺价文案与旧版格式一致
- FR007检查从EodCheckSettlePrice抽出为独立检查服务EodCheckFr007Price,
  报错沿用原步骤名;新增8个无库单测
This commit is contained in:
hjhan
2026-08-28 15:46:06 +08:00
parent 587c0d3fc2
commit 4c6251164d
3 changed files with 187 additions and 4 deletions
@@ -0,0 +1,86 @@
using YLErp.Modules.EodModule.SettlementModule;
namespace YLErp.Modules.EodModule
{
/// <summary>
/// 收盘 FR007 定盘检查(EodCheckFr007Price)行为契约(纯内存,不连库):
/// ① 检查日回拨:交易日 = 收盘日自身(对既有交易日收盘行为零变更);
/// 周末/节假日 = 上一交易日——非交易日无 FR007 定盘,按裸收盘日检查会形成
/// "收盘必报缺价"死锁(2026-08-280523 周六收盘即此症);
/// ② 回拨规则与计息取价同源(IndexFixerBase.GetFixingDate),检查的日期
/// 就是计息路径实际会读的日期;
/// ③ 报错文案:交易日缺价保持旧格式,非交易日注明回拨,附交易编号供定位。
/// </summary>
[TestClass]
public class EodCheckFr007PriceTest
{
[TestMethod]
public void _交易日收盘_等于收盘日自身()
{
// 2026-05-22 周五、2026-08-28 周五:正常交易日收盘,行为必须与改造前一致
Assert.AreEqual(new DateTime(2026, 5, 22), EodCheckFr007Price.GetCheckDate(new DateTime(2026, 5, 22)));
Assert.AreEqual(new DateTime(2026, 8, 28), EodCheckFr007Price.GetCheckDate(new DateTime(2026, 8, 28)));
}
[TestMethod]
public void _周六收盘_回拨到上一交易日周五()
{
// 2026-08-28 缺陷场景:0523 为周六,FR007 非发布日永无定盘行,
// 旧逻辑检查裸收盘日必报"未入库"且无法通过补交易要素绕过
Assert.AreEqual(new DateTime(2026, 5, 22), EodCheckFr007Price.GetCheckDate(new DateTime(2026, 5, 23)));
}
[TestMethod]
public void _周日收盘_回拨跳过周末到周五()
{
// 与 GetInterestsUnitTest_T0 记录的取价回拨先例一致:GetNonHolidayDefore(4/26周日)→4/24周五
Assert.AreEqual(new DateTime(2026, 4, 24), EodCheckFr007Price.GetCheckDate(new DateTime(2026, 4, 26)));
}
[TestMethod]
public void _与计息取价日同源()
{
// 同一收盘日,检查日必须等于计息路径 interest_rule=0 腿实际读的取价日
var settleDate = new DateTime(2026, 5, 23);
var interestPathFixingDate = YLErp.Derivatives.Interest.IndexFixerBase.GetFixingDate(settleDate, 0);
Assert.AreEqual(interestPathFixingDate, EodCheckFr007Price.GetCheckDate(settleDate));
}
[TestMethod]
public void _交易日缺价_格式与旧版一致()
{
// 交易日缺价:不带回拨说明、无交易则不带交易段,保持"yyyy年MM月dd日FR007价格未入库"原格式
var msg = EodCheckFr007Price.BuildMissingMessage(new DateTime(2026, 5, 22), new DateTime(2026, 5, 22), Array.Empty<string>());
Assert.AreEqual("2026年05月22日FR007价格未入库", msg);
}
[TestMethod]
public void _非交易日回拨缺价_注明回拨()
{
var msg = EodCheckFr007Price.BuildMissingMessage(new DateTime(2026, 5, 23), new DateTime(2026, 5, 22), null);
StringAssert.Contains(msg, "2026年05月22日FR007价格未入库");
StringAssert.Contains(msg, "收盘日2026年05月23日为非交易日,已回拨至上一交易日检查");
}
[TestMethod]
public void _带交易编号供定位()
{
var msg = EodCheckFr007Price.BuildMissingMessage(
new DateTime(2026, 5, 22), new DateTime(2026, 5, 22),
new[] { "TRS-001", "TRS-002" });
StringAssert.EndsWith(msg, ";涉及FR007浮动的交易: TRS-001、TRS-002");
}
[TestMethod]
public void _交易超过上限_截断并以等N笔收尾()
{
var trades = Enumerable.Range(1, 25).Select(i => $"TRS-{i:D3}").ToArray();
var msg = EodCheckFr007Price.BuildMissingMessage(
new DateTime(2026, 5, 22), new DateTime(2026, 5, 22), trades);
StringAssert.Contains(msg, $"TRS-{EodCheckFr007Price.MaxTradesInMessage:D3}");
StringAssert.Contains(msg, "等25笔");
Assert.IsFalse(msg.Contains("TRS-021"), "超过上限的交易编号不应完整列出");
Assert.IsFalse(msg.Contains("TRS-025、"), "截断后不应再拼接后续编号");
}
}
}