diff --git a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs
index 897cee20..706a5423 100644
--- a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs
+++ b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs
@@ -1,4 +1,4 @@
-using BaseOUDAL;
+using BaseOUDAL;
using ClosedXML.Report.Utils;
using Confluent.Kafka;
using CsvHelper;
@@ -4721,8 +4721,26 @@ namespace YLErp.Modules.RiskModule
///
public QuotaTrial QuotaCheck(int tradeId, int trialSource)
{
+ _logger.Info($"[限额试算] 开始执行 - tradeId: {tradeId}, trialSource: {trialSource}");
var result = new QuotaTrial();
var tradeObj = DbContext.trade.AsNoTracking().Where(O => O.id == tradeId).FirstOrDefault();
+
+ // 检查交易对象是否存在
+ if (tradeObj == null)
+ {
+ _logger.Error($"[限额试算] 错误: 找不到交易记录 - tradeId: {tradeId}");
+ throw new ArgumentNullException(nameof(tradeObj), $"找不到ID为 {tradeId} 的交易记录");
+ }
+
+ _logger.Info($"[限额试算] 交易信息 - tradeId: {tradeObj.id}, TradeNumber: {tradeObj.TradeNumber}, TradeType: {tradeObj.TradeType}, ClientId: {tradeObj.ClientId}");
+
+ // 检查关键字段是否为null
+ if (string.IsNullOrEmpty(tradeObj.TradeType))
+ {
+ _logger.Error($"[限额试算] 错误: TradeType 为 null 或空 - tradeId: {tradeId}");
+ throw new ArgumentNullException(nameof(tradeObj.TradeType), "交易类型不能为空");
+ }
+
var tradeList = new List();
if (tradeObj.TradeType == "结构化交易")
{
@@ -4732,6 +4750,15 @@ namespace YLErp.Modules.RiskModule
{
tradeList.Add(tradeObj);
}
+ // 检查关键字段
+ if (!tradeObj.TradeDate.HasValue)
+ {
+ _logger.Error($"[限额试算] 错误: TradeDate 为 null - tradeId: {tradeId}");
+ throw new ArgumentNullException(nameof(tradeObj.TradeDate), "交易日期不能为空");
+ }
+
+ _logger.Info($"[限额试算] 检查持仓 - positions.Count: {positions?.Count ?? 0}");
+
var fundStatus = CheckFund(tradeList, tradeObj.StockEqvNotional, tradeObj.ClientId, out var fundMsg, out var availableMsg);
//var riskWarningStatus = CheckRiskWarning(tradeList, out var riskWarningMsg);
string riskWarningMsg = string.Empty;
@@ -4763,6 +4790,8 @@ namespace YLErp.Modules.RiskModule
}
List clientRiskCheckResps = new List();
var floatPosi = DbContext.swap_position.Where(x => x.SwapTradeId == tradeId && x.PosiQuantity > 0 && x.IsInitial && !x.Invalid).FirstOrDefault();
+ _logger.Info($"[限额试算] floatPosi: {(floatPosi == null ? "null" : $"id={floatPosi.id}, UnderlyingCode={floatPosi.UnderlyingCode}")}");
+
if (floatPosi != null)
{
using var bondDb = new BondOmsDBContext();
@@ -4781,15 +4810,28 @@ namespace YLErp.Modules.RiskModule
var umCodes = clientPositions.Select(s => s.security_id).Distinct().ToList();
umCodes.Add(floatPosi.UnderlyingCode);
umCodes = umCodes.Distinct().ToList();
+ _logger.Info($"[限额试算] umCodes.Count: {umCodes?.Count ?? 0}");
+
var ums = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().Where(x => umCodes.Contains(x.UnderlyingCode));
+ _logger.Info($"[限额试算] ums.Count: {ums?.Count() ?? 0}");
+
List checkPoisiList = new List();
var posiList = GetPosiQuotaMoitors();
+ _logger.Info($"[限额试算] posiList.Count: {posiList?.Count ?? 0}");
foreach (var item in clientPositions)
{
var dealDate = tradeObj.TradeDate.Value;
decimal vobp = 0;
double lastPrice = 0;
var um = ums.FirstOrDefault(x => x.UnderlyingCode == item.security_id);
+
+ _logger.Info($"[限额试算] 处理持仓 - security_id: {item.security_id}, um: {(um == null ? "null" : $"id={um.id}, UnderlyingCode={um.UnderlyingCode}")}");
+
+ if (um == null)
+ {
+ _logger.Error($"[限额试算] 错误: 找不到标的 - security_id: {item.security_id}");
+ continue;
+ }
CheckQuotaMoitorModel checkQuotaMoitorModel = new CheckQuotaMoitorModel();
checkQuotaMoitorModel.Qty = (item.position_qty ?? 0) * 10000;
checkQuotaMoitorModel.id = item.id;
@@ -4818,8 +4860,34 @@ namespace YLErp.Modules.RiskModule
var bondPrice = EodPriceQueryService.GetBondPrice(dealDate, item.security_id);
lastPrice = bondPrice != null ? bondPrice.ClosePrice : (um.Price ?? 0) * Convert.ToDouble(ConsGlobal.bondPriceMultiple);
vobp = bondPrice != null ? bondPrice.Vobp ?? 0 : 0;
- var bond = JsonHelper.Deserialize(um.ExJson);
- checkQuotaMoitorModel.Circulation = (bond.IssueSize * 100000000m) ?? 0;
+
+ // 检查 ExJson 是否为 null 或空
+ if (string.IsNullOrEmpty(um.ExJson))
+ {
+ _logger.Error($"[限额试算] 错误: um.ExJson 为 null 或空 - um.id: {um.id}, UnderlyingCode: {um.UnderlyingCode}");
+ checkQuotaMoitorModel.Circulation = 0;
+ }
+ else
+ {
+ try
+ {
+ var bond = JsonHelper.Deserialize(um.ExJson);
+ if (bond == null)
+ {
+ _logger.Error($"[限额试算] 错误: 反序列化 bond 失败 - um.id: {um.id}, ExJson: {um.ExJson.Substring(0, Math.Min(100, um.ExJson.Length))}");
+ checkQuotaMoitorModel.Circulation = 0;
+ }
+ else
+ {
+ checkQuotaMoitorModel.Circulation = (bond.IssueSize * 100000000m) ?? 0;
+ }
+ }
+ catch (Exception ex)
+ {
+ _logger.Error($"[限额试算] 错误: 反序列化 bond 异常 - um.id: {um.id}", ex);
+ checkQuotaMoitorModel.Circulation = 0;
+ }
+ }
}
}
var ratio = checkQuotaMoitorModel.Side == 0 ? 1 : -1;
@@ -4859,6 +4927,7 @@ namespace YLErp.Modules.RiskModule
result.QuotaWarningDetails = quotaWarningMsg;
result.AvailableForClient = availableMsg;
result.TrialSource = trialSource;
+ _logger.Info($"[限额试算] 试算完成 - tradeId: {tradeId}, TrialStatus: {result.TrialStatus}, FundCheck: {fundStatus}, QuotaCheck: {quotaStatus}");
SaveQuotaTrial(result);
return result;
}
@@ -4960,11 +5029,20 @@ namespace YLErp.Modules.RiskModule
private bool CheckFund(List trades, double stockEqvNotional, int clientId, out string msg, out string avmsg)
{
-
+ _logger.Info($"[CheckFund] 开始资金检查 - clientId: {clientId}, stockEqvNotional: {stockEqvNotional}, trades.Count: {trades?.Count ?? 0}");
+
msg = "";
avmsg = "";
var totalCredit = 0.0;
var availableStockEqvNotional = 0.0;
+
+ if (trades == null || trades.Count == 0)
+ {
+ _logger.Error("[CheckFund] 错误: trades 为 null 或空列表");
+ msg = "交易列表为空";
+ return false;
+ }
+
var client = DataCacheProvider.GetClientDataSource().GetData(clientId);
if (client == null)
{
@@ -5020,6 +5098,14 @@ namespace YLErp.Modules.RiskModule
var clientBalance = clientBalances[0];
if (tradePrice <= 0)
{
+ // 检查 ExerciseDate 是否为 null
+ if (!trades[0].ExerciseDate.HasValue)
+ {
+ _logger.Error($"[CheckFund] 错误: trades[0].ExerciseDate 为 null - tradeId: {trades[0].id}");
+ msg = "交易行权日期不能为空";
+ return false;
+ }
+
if (trades[0].ExerciseDate.Value.Date >= valuedateBLL.ValueDate.Date)
{
var margins = margin + tradePrice;