diff --git a/Framework/YLErp.Core/DBModels/EodPriceBase.cs b/Framework/YLErp.Core/DBModels/EodPriceBase.cs index 6c5c1399..b92d1672 100644 --- a/Framework/YLErp.Core/DBModels/EodPriceBase.cs +++ b/Framework/YLErp.Core/DBModels/EodPriceBase.cs @@ -10,8 +10,6 @@ namespace YLErp.DBModels { public static string 人工 = "人工"; public static string 系统 = "系统"; - /// 中债估值(china_bond_valuation 的来源恒为此值;聚源仅转发,无人手工维护) - public static string 中债估值 = "中债估值"; /// /// 合约代码 diff --git a/UnitTestProject/Modules/EodModule/EodPriceDtoTest.cs b/UnitTestProject/Modules/EodModule/EodPriceDtoTest.cs index 6f64b3f5..459ba7af 100644 --- a/UnitTestProject/Modules/EodModule/EodPriceDtoTest.cs +++ b/UnitTestProject/Modules/EodModule/EodPriceDtoTest.cs @@ -6,7 +6,7 @@ namespace YLErp.Modules.EodModule /// 日终价格管理 —— 纯单元测试(不连库、秒级)。 /// 锁定两处改动的意图: /// 问题4:列表"标的种类"按真实类型显示,且路由键 UnderlyingInstrumentType 不变; - /// 问题3:债券(china_bond_valuation)数据来源固定为"中债估值"(聚源仅转发,无人手工维护)。 + /// 问题3:债券(china_bond_valuation)数据来源按是否手工改过区分"人工"/"系统"。 /// [TestClass] public class EodPriceDtoTest @@ -85,28 +85,22 @@ namespace YLErp.Modules.EodModule #endregion - #region 问题3:债券数据来源固定为"中债估值" + #region 问题3:债券数据来源按是否手工改过区分"人工"/"系统" [TestMethod] - [Description("债券来源恒为'中债估值',不随 JSID 是否为空变化(聚源仅转发中债,无人手工维护)")] - public void 债券来源固定为中债估值() + [Description("债券来源:被手工改过(update_user 有值)→人工,中债自动同步(update_user 为 NULL)→系统")] + public void 债券来源_手工改过为人工_否则为系统() { - // 无论是否有 JSID,债券来源都应是中债估值(对应 SearchUnderlyingList 后处理固定赋值) - var dtoWithJsid = new EodUnderlyingPriceDto { IsBond = true }; - var dtoNoJsid = new EodUnderlyingPriceDto { IsBond = true }; - // 生产逻辑在后处理统一置为 EodPriceBase.中债估值,这里直接断言常量值与约定一致 - Assert.AreEqual("中债估值", EodPriceBase.中债估值); - Assert.AreEqual(EodPriceBase.中债估值, dtoWithJsid.IsBond ? EodPriceBase.中债估值 : ""); - Assert.AreEqual(EodPriceBase.中债估值, dtoNoJsid.IsBond ? EodPriceBase.中债估值 : ""); + Assert.AreEqual(EodPriceBase.人工, EodPriceService.ResolveBondDisplaySource(1024L)); + Assert.AreEqual(EodPriceBase.系统, EodPriceService.ResolveBondDisplaySource(null)); } [TestMethod] - [Description("来源常量应为约定的中文'人工'/'系统'/'中债估值'")] + [Description("来源常量应为约定的中文'人工'/'系统'")] public void 来源常量取值正确() { Assert.AreEqual("系统", EodPriceBase.系统); Assert.AreEqual("人工", EodPriceBase.人工); - Assert.AreEqual("中债估值", EodPriceBase.中债估值); } #endregion @@ -172,34 +166,7 @@ namespace YLErp.Modules.EodModule #endregion - #region 问题3补充:债券被手工改过 → 来源列显示操作人姓名而非"中债估值" - - [TestMethod] - [Description("债券被手工改过(update_user 有值)且能解析到姓名 → 来源列显示改这个人名")] - public void 手工改过_显示操作人姓名() - { - var nameMap = new Dictionary { [1024] = "张三" }; - Assert.AreEqual("张三", EodPriceService.ResolveBondDisplaySource(1024L, nameMap)); - } - - [TestMethod] - [Description("聚源自动同步(update_user 为 NULL) → 来源列固定显示'中债估值'")] - public void 自动同步_显示中债估值() - { - var nameMap = new Dictionary { [1024] = "张三" }; - Assert.AreEqual(EodPriceBase.中债估值, EodPriceService.ResolveBondDisplaySource(null, nameMap)); - } - - [TestMethod] - [Description("手工改过但解析不到姓名(用户已删除/字典为空) → 回退显示'中债估值',不崩")] - public void 改过但无姓名_回退中债估值() - { - var nameMap = new Dictionary { [1024] = "张三" }; - Assert.AreEqual(EodPriceBase.中债估值, EodPriceService.ResolveBondDisplaySource(999L, nameMap), - "update_user 命中不到姓名时应回退"); - Assert.AreEqual(EodPriceBase.中债估值, EodPriceService.ResolveBondDisplaySource(7L, null), - "姓名字典为空时应回退"); - } + #region 问题3补充:债券来源人工/系统(判定逻辑已并入上方"问题3"区域) #endregion diff --git a/UnitTestProject/Modules/EodModule/EodPriceGoldenReplayTest.cs b/UnitTestProject/Modules/EodModule/EodPriceGoldenReplayTest.cs index bf5a0633..f6f36a6f 100644 --- a/UnitTestProject/Modules/EodModule/EodPriceGoldenReplayTest.cs +++ b/UnitTestProject/Modules/EodModule/EodPriceGoldenReplayTest.cs @@ -90,10 +90,10 @@ namespace YLErp.Modules.EodModule RealInstrumentType = row.RealInstrumentType, // 真实类型 IsBond = row.IsBond }; - // 债券来源固定为中债估值(等价 SearchUnderlyingList 后处理赋值) + // 债券来源:自动同步(中债)→系统(等价 SearchUnderlyingList 后处理赋值;synthetic 无 UpdateUser 故为系统) if (dto.IsBond) { - dto.DataSource = EodPriceBase.中债估值; + dto.DataSource = EodPriceBase.系统; } // 守护点1:显示按真实类型 @@ -153,7 +153,7 @@ namespace YLErp.Modules.EodModule .Select(x => new { x.UnderlyingCode, x.UnderlyingInstrumentType }) .Take(30).ToList(); - // 债券估值采样(来源恒为中债估值,无需按 JSID 判定) + // 债券估值采样(来源:自动同步→系统,手工改过→人工) var bonds = db.china_bond_valuation .Select(b => new { b.bond_id }) .Take(200).ToList(); @@ -176,7 +176,7 @@ namespace YLErp.Modules.EodModule RealInstrumentType = un.UnderlyingInstrumentType, IsBond = isBond, ExpectedTypeCn = ConsGlobal.InstrumentType.GetDesc(un.UnderlyingInstrumentType), - ExpectedDataSource = isBond ? EodPriceBase.中债估值 : null + ExpectedDataSource = isBond ? EodPriceBase.系统 : null }); } } diff --git a/UnitTestProject/Resources/GoldenFiles/EodPriceGolden/golden_标的种类与来源_synthetic.json b/UnitTestProject/Resources/GoldenFiles/EodPriceGolden/golden_标的种类与来源_synthetic.json index 92f8a808..ae9f1fa1 100644 --- a/UnitTestProject/Resources/GoldenFiles/EodPriceGolden/golden_标的种类与来源_synthetic.json +++ b/UnitTestProject/Resources/GoldenFiles/EodPriceGolden/golden_标的种类与来源_synthetic.json @@ -1,6 +1,6 @@ { "Scenario": "标的种类与数据来源", - "Description": "合成 Mock:覆盖现券/贵金属/真期货/股票 的种类显示,以及债券来源固定为中债估值。回放守护'不再一律显示商品期货'+'路由键不变'+'债券来源=中债估值'。", + "Description": "合成 Mock:覆盖现券/贵金属/真期货/股票 的种类显示,以及债券来源(自动同步→系统/手工改过→人工)。回放守护'不再一律显示商品期货'+'路由键不变'+'债券来源=系统'。", "Source": "synthetic", "RecordedAt": null, "Rows": [ @@ -10,7 +10,7 @@ "RealInstrumentType": "CreditBonds", "IsBond": true, "ExpectedTypeCn": "信用债", - "ExpectedDataSource": "中债估值" + "ExpectedDataSource": "系统" }, { "UnderlyingCode": "220210.IB", @@ -18,7 +18,7 @@ "RealInstrumentType": "TBonds", "IsBond": true, "ExpectedTypeCn": "利率债", - "ExpectedDataSource": "中债估值" + "ExpectedDataSource": "系统" }, { "UnderlyingCode": "AU9999.SGE", diff --git a/YLErpDAL/Modules/EodModule/EodPriceService.cs b/YLErpDAL/Modules/EodModule/EodPriceService.cs index 7e2146dc..4df04d2d 100644 --- a/YLErpDAL/Modules/EodModule/EodPriceService.cs +++ b/YLErpDAL/Modules/EodModule/EodPriceService.cs @@ -45,9 +45,13 @@ namespace YLErp.Modules.EodModule { predicatEoc = predicatEoc.And(d => d.DataSource.Contains(req.DataSource)); predicatEot = predicatEot.And(d => d.DataSource.Contains(req.DataSource)); - // 债券来源恒为"中债估值"(聚源仅转发,无人手工维护), - // 只有按"中债估值"筛选时才命中债券;人工/系统筛选不命中债券。 - if (req.DataSource != EodPriceBase.中债估值) + // 债券来源:自动同步(中债)归为"系统"、被手工改过的(update_user 非空)归为"人工"。 + // 故按"系统"筛选命中全部债券;按"人工"筛选只命中被手工改过的债券。 + if (req.DataSource == EodPriceBase.人工) + { + predicatEob = predicatEob.And(d => d.update_user != null); + } + else if (req.DataSource != EodPriceBase.系统) { predicatEob = predicatEob.And(d => false); } @@ -129,7 +133,7 @@ namespace YLErp.Modules.EodModule IsBond = true, id = bondClose.id, UpdateUser = bondClose.update_user, - // 债券 DataSource 在后处理统一置为人名/"中债估值"(见下方 foreach); + // 债券 DataSource 在后处理统一置为"人工"/"系统"(见下方 foreach); // 此处仍须显式设 null 以对齐 Concat 各分支投影成员集合(见 query1 注释)。 DataSource = null, LaunchState = un.LaunchState, @@ -160,27 +164,12 @@ namespace YLErp.Modules.EodModule } var result = finalQuery.ToSearchList(req); - // 解析手工改过估值的债券操作人姓名:update_user 非空 = 被人手工改过(聚源同步为 NULL)。 - // 此时来源列显示改这个人名,而非"中债估值",以便溯源到具体操作人。 - var manualBondRows = result.rows.Where(r => r.IsBond && r.UpdateUser.HasValue).ToList(); - Dictionary operatorNameMap = null; - if (manualBondRows.Any()) - { - var operatorIds = manualBondRows.Select(r => r.UpdateUser.Value).Distinct().ToList(); - using (var erpCtx = DbContextFactory.GetErpBaseContext()) - { - operatorNameMap = erpCtx.SystemUsers.AsNoTracking() - .Where(u => operatorIds.Contains((long)u.Id)) - .ToDictionary(u => (long)u.Id, u => u.Name); - } - } - foreach (var item in result.rows) { if (item.IsBond) { - // 人工改动过则显示改这个人名,否则显示"中债估值"。 - item.DataSource = ResolveBondDisplaySource(item.UpdateUser, operatorNameMap); + // 债券来源:被手工改过的(update_user 非空)→"人工";其余(中债自动同步)→"系统"。 + item.DataSource = ResolveBondDisplaySource(item.UpdateUser); item.SourceTime = item.UpdateTime.HasValue? item.UpdateTime.Value.ToString("yyyy-MM-dd HH:mm:ss"):""; item.SettlePrice=Convert.ToDouble(item.DeciSettlePrice); item.ClosePrice = Convert.ToDouble(item.DeciClosePrice); @@ -279,22 +268,14 @@ namespace YLErp.Modules.EodModule } /// - /// 债券来源列该显示什么: - /// - update_user 有值(被人手工改过)且能解析到操作人姓名 → 显示改这个人名,便于溯源; - /// - 否则(聚源/中债自动同步,update_user 为 NULL)→ 固定显示"中债估值"。 - /// 抽为纯静态函数,与解析姓名所需的 sys_user 查询解耦,便于无库单元测试。 + /// 债券来源列该显示什么:被手工改过的(update_user 有值)→"人工";其余(中债自动同步)→"系统"。 + /// 抽为纯静态函数,便于无库单元测试。 /// - /// china_bond_valuation.update_user(NULL = 自动同步) - /// update_user(ID) → 操作人姓名 的字典(由调用方按需从 sys_user 解析) - public static string ResolveBondDisplaySource(long? updateUser, IDictionary operatorNameMap) + public static string ResolveBondDisplaySource(long? updateUser) { - if (updateUser.HasValue && operatorNameMap != null - && operatorNameMap.TryGetValue(updateUser.Value, out var opName) && !string.IsNullOrEmpty(opName)) - { - return opName; - } - return EodPriceBase.中债估值; + return updateUser.HasValue ? EodPriceBase.人工 : EodPriceBase.系统; } + /// /// 保存日终股票价格 /// @@ -420,8 +401,8 @@ namespace YLErp.Modules.EodModule /// /// 手工改过估值时的操作人ID(china_bond_valuation.update_user)。 - /// NULL = 聚源/中债自动同步(无人手工维护);有值 = 被人手工改过、可溯源。 - /// 仅债券行可能非空,用于列表来源列显示改这个人名而非"中债估值"。 + /// NULL = 中债自动同步;有值 = 被人手工改过(来源列显示"人工")。 + /// 仅债券行可能非空,用于列表来源列区分"人工"/"系统"。 /// public long? UpdateUser { get; set; } }