diff --git a/YLErpWeb/fe-tests/bondCalc.test.js b/YLErpWeb/fe-tests/bondCalc.test.js index 8b9efc73..20982548 100644 --- a/YLErpWeb/fe-tests/bondCalc.test.js +++ b/YLErpWeb/fe-tests/bondCalc.test.js @@ -206,3 +206,35 @@ describe('错误反馈:getBondCalcErrorMessage(对齐 C# BondCalcHepler 的 expect(item.InitYtm).toBe(2.6); }); }); + +describe('单位换算边界(前端↔债券计算器 存储态小数 ↔ 展示态百分比)', () => { + test('bondPriceToCalc:存储态 0.995 → 发送计算器的展示态 99.5', () => { + expect(SwapCalc.bondPriceToCalc(0.995)).toBeCloseTo(99.5, 6); + expect(SwapCalc.bondPriceToCalc(1.0)).toBe(100); // 用户敲全价100 → percent:true 收成 1.0 → 发 100 + }); + + test('bondCalcPriceToStorage:展示态 97.82 → 落库存储态 0.9782', () => { + expect(SwapCalc.bondCalcPriceToStorage(97.82)).toBeCloseTo(0.9782, 6); + expect(SwapCalc.bondCalcPriceToStorage(6.37)).toBeCloseTo(0.0637, 6); + }); + + // 复刻用户实测的 -117.93 / 378543 离谱值根因,验证修复后不再出现: + // 旧:模型 1.0(用户敲100) 漏×100 直接发 1.0 → 计算器当 1% of par → 返回 cleanPrice=-1.1793, ytm=37.8543 + // → 漏÷100 原样写回 -1.1793 → percent:true 显示 ×100 → -117.93 / 378543 + // 新:发前×100、回写÷100 → 模型 0.9782 / 1.0 / 0.0637 → 显示 97.82 / 100 / 6.37 + test('端到端:用户敲全价100 → 修复后模型与显示均为合理值(不再 -117.93/378543)', () => { + const modelGross = 1.0; // percent:true 把界面 100 收成 1.0(存储态) + const sentToCalc = SwapCalc.bondPriceToCalc(modelGross); + expect(sentToCalc).toBe(100); // 必须 ×100,不是 1.0 + const calcResp = { errCode: 0, cleanPrice: 97.82, dirtyPrice: 100, ytm: 6.37 }; + const modelNet = SwapCalc.bondCalcPriceToStorage(calcResp.cleanPrice); + const modelGrossBack = SwapCalc.bondCalcPriceToStorage(calcResp.dirtyPrice); + const modelYtm = SwapCalc.bondCalcPriceToStorage(calcResp.ytm); + expect(modelNet).toBeCloseTo(0.9782, 6); + expect(modelGrossBack).toBe(1.0); + expect(modelYtm).toBeCloseTo(0.0637, 6); + // percent:true 显示时再 ×100:97.82 / 100 / 6.37,与计算器一致,无离谱值 + expect(modelNet * 100).toBeCloseTo(97.82, 4); + expect(modelYtm * 100).toBeCloseTo(6.37, 4); + }); +}); diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapCalc.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapCalc.js index d88945cf..97b968a8 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapCalc.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/swapCalc.js @@ -248,10 +248,10 @@ * - 空响应(计算器无响应) * - 业务错误码 errCode!=0(债券不存在 / 债券信息不全 / 参数非法) * - 防御性值域校验(errCode=0 但数值离谱):即便计算器返回 success, - * 仍可能因【部署环境债券主数据量纲错误(如票息/应计被存成百分数×100)】或 + * 仍可能因【前端↔计算器的单位换算不匹配】或 * 行权收益率哨兵(-999999) 而给出负净价 / 收益率量级爆炸(如 378543) 之类的垃圾值。 * 现有 errCode 守卫拦不住这类"成功但离谱"的响应,故在此加值域闸门, - * 宁可不回写并提示用户核对主数据,也绝不用垃圾值覆盖手工输入。 + * 宁可不回写并提示用户,也绝不用垃圾值覆盖手工输入。 * 与 C# BondCalcHepler 的 errCode 守卫一一对应,确保"坏结果"不会静默回写覆盖手工输入。 * 纯函数,jest 可直接测(见 fe-tests/bondCalc.test.js)。 */ @@ -267,7 +267,7 @@ return typeof v === 'number' && (v === SENTINEL || v === SENTINEL * 100); }; if (absurd(cp) || absurd(dp) || absurd(yd)) { - return "债券计算返回哨兵值(部分指标不可用),已保留手工输入,请核对债券主数据"; + return "债券计算返回哨兵值(部分指标不可用),已保留手工输入,请检查估值日/价格输入或联系管理员核对债券计算服务"; } // 净价/全价:占面值百分比,正常约 20~300,绝不为负、也不会破千 if ((typeof cp === 'number' && (cp <= 0 || cp > 1000)) ||