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; }
}