Files
zszq-trs/UnitTestProject/Modules/SwapModule/GLMS20260819Fr007TradeDiscoveryTest.cs
T
hjhan 952295a78a fix(fr007): 界面手工录入定盘精度 4→6 位——1.4150% 不再被截成 1.4200%
UAT 实测发现(EQD-6968 测试期间):录入 1.4150 落库变 0.0142。两层拆解:
- ÷100 为设计(界面按百分数录入,SwapflowList.js toNumber(value/100,6) 已传 6 位)
- Math.Round(price,4) 为精度截断:FR007 官方发布百分数下 4 位=小数 6 位,
  4 位舍入只保百分数下 2 位,丢 0.5bp(1 亿本金 7 天约 96 元)
修复:抽 RoundFr007Price(6位) 替换三处 Round(,4),与前端 6 位对齐;
DB 列 double(18,10) 已验证容纳;bond-sync 自动同步链(BigDecimal 全精度透传)
不经此路径零影响。已截断的历史行(如 2026-08-19 的 0.0142)不自愈,需重录。
附带修复 GLMS20260819Fr007TradeDiscoveryTest 编译错误:@"" 逐字字符串内
应用 "" 转义、UnderlyingCode→FutureContractId(实际列名)、EF6 Database.Connection
→ EF Core GetDbConnection()。

验证:SwapFlowFr007EntryPrecisionTest 2/2;全量 985 例 145 败与基线 diff=0
2026-08-19 14:29:16 +08:00

121 lines
5.3 KiB
C#

using System;
using System.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using YLErp.DBModels;
namespace YLErp.Modules.SwapModule
{
/// <summary>
/// EQD-6968 UAT 辅助:从 96 真实库抽取"在途 FR007 互换"具体历史交易,
/// 打印完整交易要素,供 UAT 直接选用(替代手动猜要素)。
/// 标 [Ignore],手动跑一次即可;依赖 app.config 中 xray 连接(你的环境已指向 96)。
/// 复用 GLMS20260105GoldenTest 的连库写法:DbContextFactory.GetYLDbContext()。
/// 用原生 ADO.NET 读结果,规避 EF 实体映射类型踩坑。
/// </summary>
[TestClass]
public class GLMS20260819Fr007TradeDiscoveryTest
{
private const string TradeSql = @"
SELECT
t.id AS TradeId,
p.id AS PositionId,
t.TradeNumber AS TradeNumber,
t.StartDate AS StartDate,
t.ExerciseDate AS ExerciseDate,
t.ValidState AS ValidState,
p.interest_rest_days AS interest_rest_days,
p.interest_rule AS interest_rule,
p.FloatRateUnderlyingCode AS FloatRateUnderlyingCode,
p.IsInitial AS IsInitial,
p.InterestType AS InterestType,
p.InterestMode AS InterestMode,
CASE WHEN te.ExtendJson LIKE '%""InterestCalcMode""%'
THEN SUBSTRING_INDEX(SUBSTRING_INDEX(te.ExtendJson, '""InterestCalcMode"":""', -1), '""', 1)
ELSE '11' END AS InterestCalcMode
FROM trade t
JOIN swap_position p ON p.SwapTradeId = t.id
LEFT JOIN trade_extend te ON te.TradeId = t.id
WHERE t.ValidState = 'Valid'
AND p.Invalid = 0
AND p.IsInitial = 1
AND p.FloatRateUnderlyingCode = 'FR007'
AND t.ExerciseDate >= CURDATE()
ORDER BY t.StartDate;";
private const string FixingSql = @"
SELECT ValueDate, ReferencePrice
FROM eod_commodity_future_price
WHERE FutureContractId = 'FR007'
AND ValueDate >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
ORDER BY ValueDate DESC;";
private TestContext _testContext;
public TestContext TestContext
{
get => _testContext;
set => _testContext = value;
}
private static string Fmt(object v) =>
v == null || v == DBNull.Value ? "NULL"
: (v is DateTime dt ? dt.ToString("yyyy-MM-dd") : v.ToString());
[TestMethod]
[Ignore]
[TestCategory("Discovery")]
public void Discover_InTransitFr007Trades()
{
using (var db = DbContextFactory.GetYLDbContext())
{
var conn = db.Database.GetDbConnection();
if (conn.State != ConnectionState.Open) conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = TradeSql;
using (var reader = cmd.ExecuteReader())
{
int n = 0;
while (reader.Read())
{
n++;
TestContext.WriteLine(
$"TradeId={reader["TradeId"]} PosId={reader["PositionId"]} No={reader["TradeNumber"]} " +
$"Start={Fmt(reader["StartDate"])} Expr={Fmt(reader["ExerciseDate"])} " +
$"CalcMode={Fmt(reader["InterestCalcMode"])} rule={Fmt(reader["interest_rule"])} rest={Fmt(reader["interest_rest_days"])} " +
$"IntType={Fmt(reader["InterestType"])} Mode={Fmt(reader["InterestMode"])}");
}
TestContext.WriteLine($"=== 在途 FR007 互换共 {n} 笔 ===");
}
}
}
}
[TestMethod]
[Ignore]
[TestCategory("Discovery")]
public void Discover_Fr007FixingStatus()
{
using (var db = DbContextFactory.GetYLDbContext())
{
var conn = db.Database.GetDbConnection();
if (conn.State != ConnectionState.Open) conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = FixingSql;
using (var reader = cmd.ExecuteReader())
{
int n = 0;
while (reader.Read())
{
n++;
TestContext.WriteLine($"FR007 ValueDate={Fmt(reader["ValueDate"])} ReferencePrice={Fmt(reader["ReferencePrice"])}");
}
TestContext.WriteLine($"=== FR007 定盘近 30 天共 {n} 条 ===");
}
}
}
}
}
}