From 99ffa9c2bb7ff119b67d72cd69ee3d60391a201c Mon Sep 17 00:00:00 2001 From: hjhan Date: Wed, 25 Mar 2026 10:40:12 +0800 Subject: [PATCH 1/2] =?UTF-8?q?style(logging):=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E7=BA=A7=E5=88=AB=E4=BB=8E=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E5=88=B0=E4=BF=A1=E6=81=AF=20-=20=E5=B0=86=20QuotaMonitorServi?= =?UTF-8?q?ce=20=E4=B8=AD=E7=9A=84=E7=A9=BA=E5=80=BC=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E4=BB=8E=20Error=20=E7=BA=A7=E5=88=AB?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20Info=20=E7=BA=A7=E5=88=AB=20-=20=E5=B0=86?= =?UTF-8?q?=20SwapEodPositionService=20=E4=B8=AD=E7=9A=84=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E9=AA=8C=E8=AF=81=E6=97=A5=E5=BF=97=E4=BB=8E=20Error?= =?UTF-8?q?=20=E7=BA=A7=E5=88=AB=E6=94=B9=E4=B8=BA=20Info=20=E7=BA=A7?= =?UTF-8?q?=E5=88=AB=20-=20=E4=BF=9D=E6=8C=81=E5=8E=9F=E6=9C=89=E7=9A=84?= =?UTF-8?q?=E5=BC=82=E5=B8=B8=E6=8A=9B=E5=87=BA=E9=80=BB=E8=BE=91=E4=B8=8D?= =?UTF-8?q?=E5=8F=98=EF=BC=8C=E4=BB=85=E4=BF=AE=E6=94=B9=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=BE=93=E5=87=BA=E7=BA=A7=E5=88=AB=20-=20=E7=BB=9F=E4=B8=80?= =?UTF-8?q?=E5=8F=82=E6=95=B0=E9=AA=8C=E8=AF=81=E7=9B=B8=E5=85=B3=E7=9A=84?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Modules/RiskModule/QuotaMonitorService.cs | 8 ++++---- .../SwapModule/SwapEodPositionService.cs | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs index bf5b1926..7c43ed2c 100644 --- a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs +++ b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs @@ -4952,13 +4952,13 @@ namespace YLErp.Modules.RiskModule var item = positions[i]; if (item == null) { - _logger.Error($"[CheckUnderlyingWhiteList] 错误: positions[{i}] 为 null"); + _logger.Info($"[CheckUnderlyingWhiteList] positions[{i}] 为 null"); quotaMsg = "持仓数据异常:存在空记录"; return false; } if (string.IsNullOrEmpty(item.UnderlyingCode)) { - _logger.Error($"[CheckUnderlyingWhiteList] 错误: positions[{i}].UnderlyingCode 为 null 或空 - id: {item.id}, SwapTradeId: {item.SwapTradeId}"); + _logger.Info($"[CheckUnderlyingWhiteList] positions[{i}].UnderlyingCode 为 null 或空 - id: {item.id}, SwapTradeId: {item.SwapTradeId}"); quotaMsg = "持仓数据异常:标的代码为空"; return false; } @@ -5073,7 +5073,7 @@ namespace YLErp.Modules.RiskModule if (trades == null || trades.Count == 0) { - _logger.Error("[CheckFund] 错误: trades 为 null 或空列表"); + _logger.Info("[CheckFund] trades 为 null 或空列表"); msg = "交易列表为空"; return false; } @@ -5139,7 +5139,7 @@ namespace YLErp.Modules.RiskModule // 检查 ExerciseDate 是否为 null if (!trades[0].ExerciseDate.HasValue) { - _logger.Error($"[CheckFund] 错误: trades[0].ExerciseDate 为 null - tradeId: {trades[0].id}"); + _logger.Info($"[CheckFund] trades[0].ExerciseDate 为 null - tradeId: {trades[0].id}"); msg = "交易行权日期不能为空"; return false; } diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index c05a5b0a..95fef6b3 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -223,25 +223,25 @@ namespace YLErp.Modules.SwapModule // 验证关键参数 if (td == null) { - Log.Error("[DealInterests] 参数错误: td (trade) 为 null"); + Log.Info("[DealInterests] 参数验证: td (trade) 为 null"); throw new ArgumentNullException(nameof(td), "交易对象不能为null"); } if (interestList == null) { - Log.Error($"[DealInterests] 参数错误: interestList 为 null, td.id: {td.id}"); + Log.Info($"[DealInterests] 参数验证: interestList 为 null, td.id: {td.id}"); throw new ArgumentNullException(nameof(interestList), "利息腿列表不能为null"); } if (flowEvents == null) { - Log.Error($"[DealInterests] 参数错误: flowEvents 为 null, td.id: {td.id}"); + Log.Info($"[DealInterests] 参数验证: flowEvents 为 null, td.id: {td.id}"); throw new ArgumentNullException(nameof(flowEvents), "流水事件列表不能为null"); } if (autoInterests == null) { - Log.Error($"[DealInterests] 参数错误: autoInterests 为 null, td.id: {td.id}"); + Log.Info($"[DealInterests] 参数验证: autoInterests 为 null, td.id: {td.id}"); throw new ArgumentNullException(nameof(autoInterests), "自动互换列表不能为null"); } var hasClose = flowEvents.Any(x => x.EventType == (int)SwapEventTypeEnum.平仓); @@ -715,25 +715,25 @@ namespace YLErp.Modules.SwapModule // 详细的参数验证 if (td == null) { - Log.Error("[SaveAutoEodInterestPosition] 参数错误: td (trade) 为 null"); + Log.Info("[SaveAutoEodInterestPosition] 参数验证: td (trade) 为 null"); throw new ArgumentNullException(nameof(td), "交易对象不能为null"); } if (position == null) { - Log.Error($"[SaveAutoEodInterestPosition] 参数错误: position 为 null, td.id: {td.id}"); + Log.Info($"[SaveAutoEodInterestPosition] 参数验证: position 为 null, td.id: {td.id}"); throw new ArgumentNullException(nameof(position), "持仓对象不能为null"); } if (interval == null) { - Log.Error($"[SaveAutoEodInterestPosition] 参数错误: interval 为 null, td.id: {td.id}, position.id: {position.id}"); + Log.Info($"[SaveAutoEodInterestPosition] 参数验证: interval 为 null, td.id: {td.id}, position.id: {position.id}"); throw new ArgumentNullException(nameof(interval), "观察日信息不能为null"); } if (td.trade_extend == null) { - Log.Error($"[SaveAutoEodInterestPosition] 参数错误: td.trade_extend 为 null, td.id: {td.id}, td.TradeNumber: {td.TradeNumber}"); + Log.Info($"[SaveAutoEodInterestPosition] 参数验证: td.trade_extend 为 null, td.id: {td.id}, td.TradeNumber: {td.TradeNumber}"); throw new ArgumentNullException("td.trade_extend", "交易扩展信息不能为null"); } @@ -742,7 +742,7 @@ namespace YLErp.Modules.SwapModule // 验证 ExtendObj if (td.trade_extend.ExtendObj == null) { - Log.Error($"[SaveAutoEodInterestPosition] 参数错误: td.trade_extend.ExtendObj 为 null, td.id: {td.id}"); + Log.Info($"[SaveAutoEodInterestPosition] 参数验证: td.trade_extend.ExtendObj 为 null, td.id: {td.id}"); throw new ArgumentNullException("td.trade_extend.ExtendObj", "交易扩展对象不能为null"); } From f201dde293bf77245c27c1d109bfa2e206c2deb3 Mon Sep 17 00:00:00 2001 From: hjhan Date: Wed, 25 Mar 2026 11:05:23 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feat(trade):=20=E6=B7=BB=E5=8A=A0=E7=A1=AE?= =?UTF-8?q?=E8=AE=A4=E4=B9=A6=E7=94=9F=E6=88=90=E6=9C=8D=E5=8A=A1=E7=9A=84?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=E5=8A=9F=E8=83=BD=20-=20?= =?UTF-8?q?=E5=9C=A8=20GJGenerateConfirmBook=20=E6=96=B9=E6=B3=95=E4=B8=AD?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E8=AF=A6=E7=BB=86=E7=9A=84=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=20-=20=E8=AE=B0=E5=BD=95=E4=BA=A4=E6=98=93ID?= =?UTF-8?q?=E6=95=B0=E9=87=8F=E3=80=81=E6=96=87=E6=A1=A3=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E3=80=81=E5=BC=80=E5=A7=8B=E7=BB=93=E6=9D=9F=E6=97=A5=E6=9C=9F?= =?UTF-8?q?=E7=AD=89=E5=85=B3=E9=94=AE=E5=8F=82=E6=95=B0=20-=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=B5=99=E5=95=86=E7=94=9F=E6=88=90=E7=A1=AE=E8=AE=A4?= =?UTF-8?q?=E4=B9=A6=E6=B5=81=E7=A8=8B=E7=9A=84=E6=97=A5=E5=BF=97=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=20-=20=E8=AE=B0=E5=BD=95=20tradeIds=20=E4=B8=BA?= =?UTF-8?q?=E7=A9=BA=E6=88=96=E6=9C=AA=E6=89=BE=E5=88=B0=E4=BA=A4=E6=98=93?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E7=9A=84=E6=83=85=E5=86=B5=20-=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=9F=A5=E8=AF=A2=E4=BA=A4=E6=98=93=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E3=80=81=E5=AE=A2=E6=88=B7ID=E3=80=81=E6=8C=81=E4=BB=93?= =?UTF-8?q?=E8=AE=B0=E5=BD=95=E7=9A=84=E7=BB=9F=E8=AE=A1=E6=97=A5=E5=BF=97?= =?UTF-8?q?=20-=20=E8=AE=B0=E5=BD=95=E5=88=86=E7=BB=84=E5=A4=84=E7=90=86?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=E4=B8=AD=E7=9A=84=E8=AF=A6=E7=BB=86=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=20-=20=E4=B8=BA=20groupGenerateHandle=5FDate=20?= =?UTF-8?q?=E5=92=8C=20groupGenerateHandle=20=E6=96=B9=E6=B3=95=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E6=97=A5=E5=BF=97=E8=AE=B0=E5=BD=95=20-=20=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E4=BA=A4=E6=98=93=E5=A4=84=E7=90=86=E3=80=81=E8=A1=A5?= =?UTF-8?q?=E5=85=85=E5=8D=8F=E8=AE=AE=E6=97=A5=E6=9C=9F=E3=80=81=E5=8D=95?= =?UTF-8?q?=E5=8F=8C=E7=AB=A0=E7=A1=AE=E8=AE=A4=E4=B9=A6=E7=94=9F=E6=88=90?= =?UTF-8?q?=E8=BF=87=E7=A8=8B=20-=20=E6=B7=BB=E5=8A=A0=E6=9C=80=E7=BB=88?= =?UTF-8?q?=E7=94=9F=E6=88=90=E7=BB=93=E6=9E=9C=E7=9A=84=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TradeContractGenerateService.cs | 100 +++++++++++++++++- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs b/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs index 019471f3..23797147 100644 --- a/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs +++ b/YLErpDAL/Modules/TradeModule/DealModule/TradeContractGenerateService.cs @@ -195,6 +195,9 @@ namespace YLErp.Modules.TradeModule.DealModule public bool GJGenerateConfirmBook(List tradeIds, string docType, out IEnumerable errors, out IEnumerable files, DateTime? startDate = null, DateTime? endDate = null) { + var logger = LogFactory.GetLogger("生成确认书"); + logger.Info($"[GJGenerateConfirmBook] 开始生成确认书 - tradeIds.Count: {tradeIds?.Count ?? 0}, docType: {docType}, startDate: {startDate}, endDate: {endDate}"); + Func getUnderlyingInstrumentType = new Func((underlyingId) => { return DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingId)?.UnderlyingInstrumentType; @@ -204,9 +207,30 @@ namespace YLErp.Modules.TradeModule.DealModule List file = new List(); if (PS.Config.Company == CompanyEnum.浙商) { - LogFactory.GetLogger("生成确认书").Error("浙商生成确认书"); + logger.Info("[GJGenerateConfirmBook] 生成确认书流程"); + + if (tradeIds == null || !tradeIds.Any()) + { + logger.Info("[GJGenerateConfirmBook] tradeIds 为空,直接返回"); + errors = new List(); + files = new List(); + return true; + } + var trades = DbContext.trade.Where(x => tradeIds.Contains(x.id)).AsNoTracking().ToList(); + logger.Info($"[GJGenerateConfirmBook] 查询到交易记录数: {trades.Count}"); + + if (!trades.Any()) + { + logger.Info("[GJGenerateConfirmBook] 未找到交易记录,直接返回"); + errors = new List(); + files = new List(); + return true; + } + var clientIds = trades.Select(x => x.ClientId).Distinct().ToList(); + logger.Info($"[GJGenerateConfirmBook] 客户ID数: {clientIds.Count}"); + var allTrades = DbContext.trade.Where(x => clientIds.Contains(x.ClientId) && x.ValidState != ConsGlobal.InValid); if (startDate.HasValue) { @@ -219,59 +243,127 @@ namespace YLErp.Modules.TradeModule.DealModule var Ids = allTrades.Select(o => o.id).Distinct().ToArray(); var swapPositions = DbContext.swap_position.Where(s => Ids.Contains(s.SwapTradeId) && s.IsInitial && s.PositionType > 0 && !s.Invalid) .Distinct().ToList(); + logger.Info($"[GJGenerateConfirmBook] 查询到持仓记录数: {swapPositions.Count}"); + var allTradeList = allTrades.AsNoTracking().ToList(); foreach (var item in allTradeList) { item.swap_positions.Add(swapPositions.FirstOrDefault(o => o.SwapTradeId == item.id)); } allTradeList = allTradeList.Where(x => x.swap_positions.Any()).ToList(); + logger.Info($"[GJGenerateConfirmBook] 过滤后有持仓的交易数: {allTradeList.Count}"); + // 按照客户ID、交易日期、多空头进行分组 - var group = allTradeList.GroupBy(O => new { O.ClientId, O.StartDate, O.swap_positions.FirstOrDefault().PositionType }) + var group = allTradeList.GroupBy(O => new { O.ClientId, O.StartDate, O.swap_positions.FirstOrDefault()?.PositionType }) .ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); + + logger.Info($"[GJGenerateConfirmBook] 分组数: {group.Count}"); foreach (var item in group) { - LogFactory.GetLogger("生成确认书").Error("浙商生成确认书" + item.Value.Distinct().ToList().Count()); + var tradeCount = item.Value.Distinct().Count(); + logger.Info($"[GJGenerateConfirmBook] 处理分组 - ClientId: {item.Key.ClientId}, StartDate: {item.Key.StartDate}, PositionType: {item.Key.PositionType}, 交易数: {tradeCount}"); groupGenerateHandle(item.Value.Distinct().ToList(), docType, startDate, endDate, results, error, file); } } errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToList(); files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList(); + logger.Info($"[GJGenerateConfirmBook] 完成生成确认书 - 错误数: {errors.Count()}, 文件数: {files.Count()}"); return !errors.Any(); } private void groupGenerateHandle_Date(List ids, string docType, DateTime? startDate, DateTime? endDate, List results, List error, List file) { + var logger = LogFactory.GetLogger("生成确认书"); + logger.Info($"[groupGenerateHandle_Date] 开始处理 - ids.Count: {ids?.Count ?? 0}"); + + if (ids == null || !ids.Any()) + { + logger.Info("[groupGenerateHandle_Date] ids 为空,直接返回"); + return; + } + var trades = DbContext.trade.Where(c => ids.Contains(c.id)).ToList(); - var supProtocolDate = DataCacheProvider.GetClientDataSource().GetData(trades.FirstOrDefault().ClientId).SupProtocolDate; + logger.Info($"[groupGenerateHandle_Date] 查询到交易数: {trades.Count}"); + + if (!trades.Any()) + { + logger.Info("[groupGenerateHandle_Date] 未找到交易记录,直接返回"); + return; + } + + var firstTrade = trades.FirstOrDefault(); + if (firstTrade == null) + { + logger.Info("[groupGenerateHandle_Date] 第一条交易记录为 null,直接返回"); + return; + } + + var client = DataCacheProvider.GetClientDataSource().GetData(firstTrade.ClientId); + if (client == null) + { + logger.Info($"[groupGenerateHandle_Date] 未找到客户信息 - ClientId: {firstTrade.ClientId}"); + return; + } + + var supProtocolDate = client.SupProtocolDate; + logger.Info($"[groupGenerateHandle_Date] 客户补充协议日期: {supProtocolDate}"); + var groupDateDouble = trades.Where(x => supProtocolDate == null || x.TradeDate < supProtocolDate).Select(x => x.id).ToList(); var groupDateSingle = trades.Where(x => supProtocolDate != null && x.TradeDate >= supProtocolDate).Select(x => x.id).ToList(); + + logger.Info($"[groupGenerateHandle_Date] 双章确认书交易数: {groupDateDouble.Count}, 单章确认书交易数: {groupDateSingle.Count}"); + // 单章确认书和双章确认书同时生成要生成两个文件 if (groupDateDouble.Any() && groupDateSingle.Any()) { + logger.Info("[groupGenerateHandle_Date] 同时生成单章和双章确认书"); groupGenerateHandle(groupDateDouble, docType, startDate, supProtocolDate.Value.AddDays(-1), results, error, file); groupGenerateHandle(groupDateSingle, docType, supProtocolDate, endDate, results, error, file); } else if (groupDateDouble.Any()) { + logger.Info("[groupGenerateHandle_Date] 仅生成双章确认书"); groupGenerateHandle(groupDateDouble, docType, startDate, endDate, results, error, file); } else if (groupDateSingle.Any()) { + logger.Info("[groupGenerateHandle_Date] 仅生成单章确认书"); groupGenerateHandle(groupDateSingle, docType, startDate, endDate, results, error, file); } + else + { + logger.Info("[groupGenerateHandle_Date] 没有需要生成的确认书"); + } } private void groupGenerateHandle(List ids, string docType, DateTime? startDate, DateTime? endDate, List results, List error, List file) { + var logger = LogFactory.GetLogger("生成确认书"); + logger.Info($"[groupGenerateHandle] 开始处理 - ids.Count: {ids?.Count ?? 0}, docType: {docType}"); + + if (ids == null || !ids.Any()) + { + logger.Info("[groupGenerateHandle] ids 为空,直接返回"); + return; + } + var trade_contract_r = DbContext.trade_contract_r.Where(c => ids.Contains(c.TradeId) && c.Type == "交易确认书" && c.IsValid).ToList(); + logger.Info($"[groupGenerateHandle] 找到已存在的确认书记录数: {trade_contract_r.Count}"); + //DbContext.trade_contract_r.RemoveRange(trade_contract_r); trade_contract_r.ForEach(O => O.IsValid = false); DbContext.SaveChanges(); + + logger.Info("[groupGenerateHandle] 调用 BatchConfirmationGenerateService.Generate"); var result = new BatchConfirmationGenerateService(this).Generate(ids, docType, startDate, endDate); + logger.Info($"[groupGenerateHandle] 生成结果 - 成功数: {result.Count(r => string.IsNullOrWhiteSpace(r.ErrorMessage))}, 失败数: {result.Count(r => !string.IsNullOrWhiteSpace(r.ErrorMessage))}"); + results.AddRange(result); error.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray()); file.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList()); + + logger.Info($"[groupGenerateHandle] 完成处理 - 当前总错误数: {error.Count}, 当前总文件数: {file.Count}"); } public bool GXJY_CorrespondingConfirmationTemplate(List tradeIds, out string ErrMsg)