feat(swap): 完善自动互换资金记录管理功能
- 在SwapEodPositionService中添加clientCashIds列表追踪多笔资金记录 - 为UnwindData类新增ClientCashIds属性存储自动互换生成的资金记录ID集合 - 在SwapTradeBaseService中实现GetAutoSwapClientCashIds方法解析历史数据 - 添加GetLegacyAutoSwapClientCashRecords方法处理遗留资金记录删除逻辑 - 实现IsLegacyAutoSwapClientCashRecord方法精确匹配待删除资金记录 - 优化资金记录删除策略区分自动互换与手动操作产生的记录
This commit is contained in:
@@ -102,6 +102,7 @@ namespace YLErp.DBModels
|
||||
public UnwindData()
|
||||
{
|
||||
FlowEvents = new List<swap_flow_event>();
|
||||
ClientCashIds = new List<int>();
|
||||
}
|
||||
public int SwapTradeId { get; set; }
|
||||
/// <summary>
|
||||
@@ -178,6 +179,10 @@ namespace YLErp.DBModels
|
||||
/// </summary>
|
||||
public decimal SwapDividendPnl { get; set; }
|
||||
/// <summary>
|
||||
/// 自动互换生成的客户资金记录ID集合
|
||||
/// </summary>
|
||||
public List<int> ClientCashIds { get; set; }
|
||||
/// <summary>
|
||||
/// 利息腿/浮动腿 集合,不序列化存储,只做查询
|
||||
/// </summary>
|
||||
public List<swap_flow_event> FlowEvents { get; set; }
|
||||
|
||||
@@ -510,16 +510,19 @@ namespace YLErp.Modules.SwapModule
|
||||
var cashHappenDate = interval?.SettlementDate ?? unwindData.ValueDate;
|
||||
|
||||
int clientCashId = 0;
|
||||
var clientCashIds = new List<int>();
|
||||
// 利息腿:插入资金记录(使用系统操作_互换)
|
||||
if (unwindData.SwapCloseAmount != 0)
|
||||
{
|
||||
clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapCloseAmount), ClientCashInCashOut.系统操作_互换, cashHappenDate);
|
||||
clientCashIds.Add(clientCashId);
|
||||
}
|
||||
|
||||
// 预付金腿:单独插入一条资金记录(系统操作_预付金返息)
|
||||
if (unwindData.SwapMarginRebatePnl != 0)
|
||||
{
|
||||
clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut.系统操作_预付金返息, unwindData.ValueDate);
|
||||
clientCashIds.Add(clientCashId);
|
||||
}
|
||||
unwindData.SwapCloseAmount = unwindData.SwapRealizedPnL;//需要算上预付金利息 和 分红; 只是不算预付金返还
|
||||
// 分红:使用派息支付日偏移记录资金记录
|
||||
@@ -529,8 +532,10 @@ namespace YLErp.Modules.SwapModule
|
||||
? dividendEvents.First().PayDate.Value
|
||||
: unwindData.ValueDate;
|
||||
clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapDividendPnl), ClientCashInCashOut.系统操作_互换, dividendPayDate);
|
||||
clientCashIds.Add(clientCashId);
|
||||
}
|
||||
|
||||
unwindData.ClientCashIds = clientCashIds;
|
||||
string data = JsonConvert.SerializeObject(unwindData);
|
||||
var swapEvent = new SwapEventService(this).AddSwapEventDate(unwindData.ValueDate, unwindData.SwapTradeId, (int)SwapEventTypeEnum.自动互换, data, clientCashId, true, "系统操作-自动互换");//将互换总额存入事件
|
||||
if (flowEvents!=null)
|
||||
|
||||
@@ -384,28 +384,40 @@ namespace YLErp.Modules.SwapModule
|
||||
DbContext.swap_flow_event.RemoveRange(swapFlowEvents);
|
||||
|
||||
// 删除自动互换产生的资金记录(client_cash_in_out)
|
||||
var swapEventIds = swapEvents.Select(s => s.id).ToList();
|
||||
if (swapEventIds.Any())
|
||||
var autoSwapEvents = swapEvents.ToList();
|
||||
if (autoSwapEvents.Any())
|
||||
{
|
||||
// 通过 swap_event 的 ClientCashId 删除对应的资金记录(利息腿)
|
||||
var clientCashIds = swapEvents.Where(s => s.ClientCashId > 0).Select(s => s.ClientCashId).ToList();
|
||||
var clientCashIds = autoSwapEvents
|
||||
.Where(s => s.ClientCashId > 0)
|
||||
.Select(s => s.ClientCashId)
|
||||
.ToList();
|
||||
|
||||
var legacyAutoEvents = new List<swap_event>();
|
||||
foreach (var swapEvent in autoSwapEvents)
|
||||
{
|
||||
var eventCashIds = GetAutoSwapClientCashIds(swapEvent);
|
||||
if (eventCashIds.Any())
|
||||
{
|
||||
clientCashIds.AddRange(eventCashIds);
|
||||
}
|
||||
else
|
||||
{
|
||||
legacyAutoEvents.Add(swapEvent);
|
||||
}
|
||||
}
|
||||
|
||||
clientCashIds = clientCashIds.Distinct().ToList();
|
||||
if (clientCashIds.Any())
|
||||
{
|
||||
var clientCashRecords = DbContext.ClientCashInCashOut.Where(x => clientCashIds.Contains(x.id)).ToList();
|
||||
DbContext.ClientCashInCashOut.RemoveRange(clientCashRecords);
|
||||
}
|
||||
|
||||
// 删除预付金腿的资金记录(通过交易ID、日期和Action类型查找,一次性查询避免MySQL连接重用问题)
|
||||
var swapTradeIds = swapEvents.Select(s => s.SwapTradeId).Distinct().ToList();
|
||||
var actions = new List<string>() { ClientCashInCashOut.系统操作_预付金返息, ClientCashInCashOut.系统操作_互换 };
|
||||
var premiumCashRecords = DbContext.ClientCashInCashOut
|
||||
.Where(x => swapTradeIds.Contains(x.TradeId ?? 0)
|
||||
&& x.HappenDate>=valueDate
|
||||
&& actions.Contains(x.Action))
|
||||
.ToList();
|
||||
if (premiumCashRecords.Any())
|
||||
|
||||
var legacyCashRecords = GetLegacyAutoSwapClientCashRecords(legacyAutoEvents, clientCashIds);
|
||||
if (legacyCashRecords.Any())
|
||||
{
|
||||
DbContext.ClientCashInCashOut.RemoveRange(premiumCashRecords);
|
||||
DbContext.ClientCashInCashOut.RemoveRange(legacyCashRecords);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,6 +425,105 @@ namespace YLErp.Modules.SwapModule
|
||||
DbContext.eod_swap.RemoveRange(eodSwaps);
|
||||
DbContext.SaveChanges();
|
||||
}
|
||||
|
||||
private List<int> GetAutoSwapClientCashIds(swap_event swapEvent)
|
||||
{
|
||||
if (swapEvent == null || string.IsNullOrWhiteSpace(swapEvent.EventData))
|
||||
{
|
||||
return new List<int>();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
|
||||
return unwindData?.ClientCashIds?.Where(x => x > 0).Distinct().ToList() ?? new List<int>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return new List<int>();
|
||||
}
|
||||
}
|
||||
|
||||
private List<ClientCashInCashOut> GetLegacyAutoSwapClientCashRecords(List<swap_event> swapEvents, List<int> excludedClientCashIds)
|
||||
{
|
||||
if (swapEvents == null || !swapEvents.Any())
|
||||
{
|
||||
return new List<ClientCashInCashOut>();
|
||||
}
|
||||
|
||||
var eventIds = swapEvents.Select(x => x.id).ToList();
|
||||
var flowEvents = DbContext.swap_flow_event
|
||||
.Where(x => x.EventId.HasValue && eventIds.Contains(x.EventId.Value))
|
||||
.ToList();
|
||||
var manualClientCashIds = DbContext.swap_event
|
||||
.Where(x => x.SwapTradeId == swapEvents.First().SwapTradeId
|
||||
&& x.ClientCashId > 0
|
||||
&& x.EventType != (int)SwapEventTypeEnum.自动互换)
|
||||
.Select(x => x.ClientCashId)
|
||||
.ToList();
|
||||
var records = new List<ClientCashInCashOut>();
|
||||
|
||||
foreach (var swapEvent in swapEvents)
|
||||
{
|
||||
UnwindData unwindData = null;
|
||||
if (!string.IsNullOrWhiteSpace(swapEvent.EventData))
|
||||
{
|
||||
try
|
||||
{
|
||||
unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
var eventFlowEvents = flowEvents.Where(x => x.EventId == swapEvent.id).ToList();
|
||||
var candidateDates = new HashSet<DateTime> { swapEvent.ValueDate.Date };
|
||||
if (unwindData?.PayDate != null)
|
||||
{
|
||||
candidateDates.Add(unwindData.PayDate.Value.Date);
|
||||
}
|
||||
eventFlowEvents.Where(x => x.PayDate.HasValue).ToList().ForEach(x => candidateDates.Add(x.PayDate.Value.Date));
|
||||
|
||||
var eventRecords = DbContext.ClientCashInCashOut
|
||||
.Where(x => x.TradeId == swapEvent.SwapTradeId
|
||||
&& !excludedClientCashIds.Contains(x.id)
|
||||
&& !manualClientCashIds.Contains(x.id)
|
||||
&& (x.Action == ClientCashInCashOut.系统操作_预付金返息 || x.Action == ClientCashInCashOut.系统操作_互换))
|
||||
.ToList()
|
||||
.Where(x => x.HappenDate.HasValue && candidateDates.Contains(x.HappenDate.Value.Date))
|
||||
.Where(x => IsLegacyAutoSwapClientCashRecord(x, unwindData))
|
||||
.ToList();
|
||||
|
||||
records.AddRange(eventRecords);
|
||||
}
|
||||
|
||||
return records.GroupBy(x => x.id).Select(x => x.First()).ToList();
|
||||
}
|
||||
|
||||
private bool IsLegacyAutoSwapClientCashRecord(ClientCashInCashOut cashRecord, UnwindData unwindData)
|
||||
{
|
||||
if (unwindData == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var amount = Convert.ToDecimal(cashRecord.Money ?? 0);
|
||||
if (cashRecord.Action == ClientCashInCashOut.系统操作_预付金返息)
|
||||
{
|
||||
return unwindData.SwapMarginRebatePnl != 0
|
||||
&& amount == -unwindData.SwapMarginRebatePnl;
|
||||
}
|
||||
|
||||
if (cashRecord.Action == ClientCashInCashOut.系统操作_互换)
|
||||
{
|
||||
return (unwindData.SwapCloseAmount != 0 && amount == -unwindData.SwapCloseAmount)
|
||||
|| (unwindData.SwapDividendPnl != 0 && amount == -unwindData.SwapDividendPnl)
|
||||
|| (unwindData.SwapRealizedPnL != 0 && amount == -unwindData.SwapRealizedPnL);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/// <summary>
|
||||
/// 获取上一交易日
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user