Files
zszq-trs/YLErpDAL/Modules/SwapModule/InterestEodScenarioDispatch.cs
T
hjhan 9ae2e66b75 refactor(swap-eod): L0 纯函数出仓——InterestEodScenario/ResolveInterestScenario/FindObservationInterval 移至独立 InterestEodScenarioDispatch(零行为变更)
- 上帝类减重 42 行;枚举与两个纯函数零实例状态、零 DB 依赖,符合 Accrual/ 既有纯函数迁移模式
- 测试不再继承 TestableSwapEodPositionService(原仅为够到 protected),plain 测试类
- SwapEodPositionService 两处调用点改为 InterestEodScenarioDispatch.FindObservationInterval 限定名
- 编译 0 错误;表驱动 8/8 通过
2026-08-17 17:36:41 +08:00

48 lines
2.4 KiB
C#

using YLErp.Models;
namespace YLErp.Modules.SwapModule;
/// <summary>
/// 利息腿 EOD 归档场景分派规格(纯函数集;表驱动单测见 InterestEodScenarioDispatchTest)。
/// 优先级链(承重业务语义,不能乱序):
/// ① hasSwap(手工互换) → 按事件流水重新生成,压制观察日自动结息
/// ② observationInterval(观察日) 存在 → 自动结息;同日有平仓 → autoSwap=true
/// ③ hasClose(纯平仓, 非观察日) → autoSwap=false
/// ④ 普通日 → 复制上一日终并计提当日新增
/// 注意:hasSwap/hasClose 是交易级标志(整笔合约当天有无事件),
/// observationInterval 是腿级(本条利息腿当天是否观察日)——粒度不同,分派依赖此区分。
/// 生产分派点:SwapEodPositionService.DealInterests(分派结构接线前为影子规格,见其分派处注释)。
/// </summary>
public enum InterestEodScenario
{
ManualSwap, // ① 手工互换:压制观察日自动结息
AutoSettleWithClose, // ② 观察日 + 当日平仓 (autoSwap=true)
AutoSettle, // ② 观察日 + 当日无平仓
CloseOnly, // ③ 非观察日 + 当日平仓 (autoSwap=false)
RollForward, // ④ 普通日滚动
}
public static class InterestEodScenarioDispatch
{
/// <summary>三分量布尔 → 场景(8 组合表驱动见 InterestEodScenarioDispatchTest)。</summary>
public static InterestEodScenario ResolveInterestScenario(bool hasInterval, bool hasSwap, bool hasClose)
{
if (hasSwap)
return InterestEodScenario.ManualSwap;
if (hasInterval)
return hasClose ? InterestEodScenario.AutoSettleWithClose : InterestEodScenario.AutoSettle;
if (hasClose)
return InterestEodScenario.CloseOnly;
return InterestEodScenario.RollForward;
}
/// <summary>
/// 查找利息腿在指定结算日的观察日信息(SwapIntervalList 中 Date==settleDate 且 Settlement==1 的记录)。
/// 观察日即自动结息触发日;返回 null 表示当日非观察日。分派见 ResolveInterestScenario。
/// </summary>
public static IntervalModel FindObservationInterval(swap_position interest, DateTime settleDate)
{
return interest.SwapIntervalList.FirstOrDefault(x => x.Date == settleDate && x.Settlement == 1);
}
}