feat(bond): 支持股票和基金现金分红纳入债券支付计算 - 收紧过度开发行为

- 实现股票/基金现金分红数据从 ex_dividend_info 同步到 BondPayment
- 新增公司行为去重机制,避免镜像任务完成后重复计息
- 统一现金分红存储口径为"每 10 份派现金额",保持与同步任务一致性
- 修改 CalcPayment 方法,股票/基金分红需除以 10 转换实际现金金额
- 添加单元测试验证债券票息和股票/基金分红的不同计算方式
- 更新文档注释说明"每 10 份派现金额"存储规范
- 修复公司行为生效日处理逻辑,确保正确应用除权系数
- 扩展测试覆盖股票类证券的公司行为处理场景
This commit is contained in:
张名锐
2026-08-20 13:30:36 +08:00
parent aa3548e77f
commit b2f4e16782
13 changed files with 384 additions and 368 deletions
@@ -76,7 +76,12 @@ namespace YLErp.Modules.SwapModule
/// <param name="eodPayPosition"></param>
public void UpdateSwapPositionWithRealTime(eod_swap_position eodPayPosition)
{
var position = DbContext.swap_position.FirstOrDefault(x => x.PositionId == eodPayPosition.PositionId);
// 同一 PositionId 同时对应初始腿(id=PositionId)和实时腿(IsInitial=0)。
// 日终/公司行为同步只能更新实时腿;若直接 FirstOrDefault,会随机命中初始腿,
// 造成 EOD 已是 200000/50 而交易详情仍保持 100000/100,或反向污染交易初始腿。
var position = DbContext.swap_position.FirstOrDefault(x => x.PositionId == eodPayPosition.PositionId
&& !x.IsInitial
&& !x.Invalid);
if (position != null)
{
position.PosiQuantity = eodPayPosition.PosiQuantity;
@@ -96,7 +101,13 @@ namespace YLErp.Modules.SwapModule
}
else
{
// 兼容实时腿尚未生成的首日/自动合成场景:只从初始腿克隆创建实时腿,
// 不能把初始腿当作可更新对象。
position = DbContext.swap_position.FirstOrDefault(x => x.id == eodPayPosition.PositionId);
if (position == null)
{
return;
}
var posi = position.Clone();
posi.id = 0;
posi.PositionId = position.id;