using YLErp.Modules.EodModule.SettlementModule; namespace YLErp.Modules.EodModule { /// /// 验证 EodCheckSettlePrice 的持仓分支按 ClientIds 收敛: /// 给定收盘客户时,不应再把“仅属于其他客户”的上一交易日持仓标的纳入结算价缺失检查。 /// /// 采用确定性夹具:插入两条合成持仓(客户A持标的A、客户B持标的B),直接调用抽出的 /// static 查询方法断言过滤语义,finally 中清理,避免依赖测试库现有数据形状。 /// 若 underlying_manager 无足够的对冲类型标的,则 Assert.Inconclusive 跳过。 /// [TestClass] public class EodCheckSettlePriceClientScopeTest : UnitTestBase { [TestMethod] public void PositionUnderlyingQuery_ExcludesOtherClients_WhenClientIdsGiven() { using var db = DbContextFactory.GetYLDbContext(); // 选两个存在的、非期货的标的(避开 GetFutureTypes,保证通过方法内部的期货到期过滤); // 持仓 TradeType 固定为"股票"(属于 TradeTypesForHedge),才能进入结算价检查。 var futureTypes = ConsGlobal.InstrumentType.GetFutureTypes(); var underlyings = db.underlying_manager .Where(u => u.UnderlyingCode != null && !futureTypes.Contains(u.UnderlyingInstrumentType)) .Take(5) .ToList(); if (underlyings.Count < 2) { Assert.Inconclusive("underlying_manager 无足够的非期货标的,跳过"); return; } var uA = underlyings[0]; var uB = underlyings[1]; // 复用一条现有持仓的 BookId/TradeId,确保外键合法(若存在) var sample = db.eod_trade_position.FirstOrDefault(p => p.BookId != 0); int bookId = sample?.BookId ?? 1; int tradeId = sample?.TradeId ?? 0; // 合成日期与客户,避免与测试库真实数据冲突 var preSettleDate = new DateTime(2026, 5, 1); var settleDate = new DateTime(2026, 5, 2); int clientA = 900001; int clientB = 900002; var rows = new List { new eod_trade_position { ValueDate = preSettleDate, ClientId = clientA, UnderlyingCode = uA.UnderlyingCode, UnderlyingId = uA.id, TradeType = "股票", BookId = bookId, TradeId = tradeId, Amount = 1, HedgeUniqueCode = "UT_CLIENTSCOPE_A" }, new eod_trade_position { ValueDate = preSettleDate, ClientId = clientB, UnderlyingCode = uB.UnderlyingCode, UnderlyingId = uB.id, TradeType = "股票", BookId = bookId, TradeId = tradeId, Amount = 1, HedgeUniqueCode = "UT_CLIENTSCOPE_B" } }; foreach (var r in rows) { r.OptId = 0; r.OptName = "UT_CLIENTSCOPE"; r.OptDate = DateTime.Now; } try { db.eod_trade_position.AddRange(rows); db.SaveChanges(); var fullSet = EodCheckSettlePrice.QueryPositionUnderlyingCodes(db, preSettleDate, settleDate, null) .ToHashSet(StringComparer.OrdinalIgnoreCase); var filteredA = EodCheckSettlePrice.QueryPositionUnderlyingCodes(db, preSettleDate, settleDate, new List { clientA }) .ToHashSet(StringComparer.OrdinalIgnoreCase); Assert.IsTrue(fullSet.Contains(uA.UnderlyingCode), "全客户结果应包含客户A的标的"); Assert.IsTrue(fullSet.Contains(uB.UnderlyingCode), "全客户结果应包含客户B的标的"); Assert.IsTrue(filteredA.Contains(uA.UnderlyingCode), "按客户A收敛后仍应包含客户A的标的"); // 关键断言:修复点——按客户A收敛后不应再包含“仅属客户B”的标的 Assert.IsFalse(filteredA.Contains(uB.UnderlyingCode), "修复验证失败:按客户A收敛后仍包含仅属客户B的持仓标的(ClientId 过滤未生效)"); } finally { // 清理合成数据,使测试库状态不变 foreach (var r in rows) { var exist = db.eod_trade_position.FirstOrDefault(x => x.ValueDate == preSettleDate && x.ClientId == r.ClientId && x.UnderlyingCode == r.UnderlyingCode && x.HedgeUniqueCode == r.HedgeUniqueCode); if (exist != null) { db.eod_trade_position.Remove(exist); } } db.SaveChanges(); } } } }