diff --git a/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs b/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs index 325b7dca..db8ceeac 100644 --- a/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs +++ b/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs @@ -1,80 +1,62 @@ namespace YLErp.DBModels { /// - /// 保证金配置期限常量定义 + /// 保证金配置期限常量定义(利率债TRS) /// public static class ConsMarginTerm { /// - /// 默认期限(空字符串) + /// 5年以下(同时也是兜底默认期限) /// - public const string Default = ""; - + public const string UnderFiveYear = "<5y"; + /// - /// 2年期 + /// 5年-10年 /// - public const string TwoYear = "2Y"; - + public const string FiveToTenYear = "5y-10y"; + /// - /// 5年期 + /// 10年-30年 /// - public const string FiveYear = "5Y"; - + public const string TenToThirtyYear = "10y-30y"; + /// - /// 10年期 + /// 30年以上 /// - public const string TenYear = "10Y"; - - /// - /// 30年期 - /// - public const string ThirtyYear = "30Y"; - - /// - /// 30年以上期 - /// - public const string OverThirtyYear = "Over30Y"; - + public const string OverThirtyYear = ">30y"; + /// /// 所有允许的期限值 /// public static readonly List AllowedTerms = new List { - Default, - TwoYear, - FiveYear, - TenYear, - ThirtyYear, + UnderFiveYear, + FiveToTenYear, + TenToThirtyYear, OverThirtyYear }; - + /// /// 验证期限是否有效 /// - /// 期限值 - /// 是否有效 public static bool IsValidTerm(string term) { return AllowedTerms.Contains(term ?? string.Empty); } - + /// /// 获取期限的显示名称 /// - /// 期限值 - /// 显示名称 public static string GetDisplayName(string term) { return term switch { - Default => "默认", - TwoYear => "2年", - FiveYear => "5年", - TenYear => "10年", - ThirtyYear => "30年", - OverThirtyYear => "30年以上", - _ => term?.Replace("Y", "年") ?? "默认" + UnderFiveYear => "<5y", + FiveToTenYear => "5y-10y", + TenToThirtyYear => "10y-30y", + OverThirtyYear => ">30y", + _ => term ?? "<5y" }; } } -} \ No newline at end of file +} diff --git a/Framework/YLErp.Core/DBModels/UnderlyingBond.cs b/Framework/YLErp.Core/DBModels/UnderlyingBond.cs index 8d461b4d..5797f652 100644 --- a/Framework/YLErp.Core/DBModels/UnderlyingBond.cs +++ b/Framework/YLErp.Core/DBModels/UnderlyingBond.cs @@ -75,5 +75,10 @@ /// 利率类型代码 /// public string CouponCode { get; set; } + + /// + /// 债券期限(利率债) + /// + public string BondTerm { get; set; } } } diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx index 68db4302..e8bc1811 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【债券ETF】-清洁版.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【现券】-清洁版.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【现券】-清洁版.docx index f161e0b7..91453642 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【现券】-清洁版.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看多】-【现券】-清洁版.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx index 6ebf3b88..21592e05 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【债券ETF】-清洁版.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【现券】-清洁版.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【现券】-清洁版.docx index 188c493d..ca409473 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【现券】-清洁版.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/contract_template/国联民生-收益互换交易确认书-境内模板-【客户看空】-【现券】-清洁版.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/settlement_template/settle_01.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/settlement_template/settle_01.docx index e69de29b..56ec3f15 100644 Binary files a/Plugins/YLErp.Plugins.GuoLian/App_Docs/settlement_template/settle_01.docx and b/Plugins/YLErp.Plugins.GuoLian/App_Docs/settlement_template/settle_01.docx differ diff --git a/Plugins/YLErp.Plugins.GuoLian/App_Docs/settlement_template/unwind_01.docx b/Plugins/YLErp.Plugins.GuoLian/App_Docs/settlement_template/unwind_01.docx deleted file mode 100644 index e69de29b..00000000 diff --git a/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs b/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs index 2ff46907..d0ad079e 100644 --- a/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs +++ b/Plugins/YLErp.Plugins.GuoLian/DocumentGenerator/TradeConfirmationGenerator.cs @@ -244,6 +244,41 @@ namespace YLErp.Plugins.GuoLian.DocumentGenerator dic["期初预付比例"] = "0.0000"; dic["期初预付金额"] = "0.00"; } + bool posiLong = swapPosition?.PositionType == (int)PositionTypeFlag.Short ? false : true; + // 计算平仓线、预警线、档位值(利率债TRS,固定4档) + var maintainRatePercent = (double)(clientMarginRate?.maintain_rate ?? 0) * 100; // 维持保证金率 A(%) + if (maintainRatePercent > 0) + { + if (posiLong) + { + // 客户看多:档位n = 100 - n * A + dic["平仓线"] = (100 - 4 * maintainRatePercent).ToString("0.##"); + dic["预警线"] = (100 - 3 * maintainRatePercent).ToString("0.##"); + dic["档位1"] = (100 - 1 * maintainRatePercent).ToString("0.##"); + dic["档位2"] = (100 - 2 * maintainRatePercent).ToString("0.##"); + dic["档位3"] = (100 - 3 * maintainRatePercent).ToString("0.##"); + dic["档位4"] = (100 - 4 * maintainRatePercent).ToString("0.##"); + } + else + { + // 客户看空:档位n = 100 + n * A + dic["平仓线"] = (100 + 4 * maintainRatePercent).ToString("0.##"); + dic["预警线"] = (100 + 3 * maintainRatePercent).ToString("0.##"); + dic["档位1"] = (100 + 1 * maintainRatePercent).ToString("0.##"); + dic["档位2"] = (100 + 2 * maintainRatePercent).ToString("0.##"); + dic["档位3"] = (100 + 3 * maintainRatePercent).ToString("0.##"); + dic["档位4"] = (100 + 4 * maintainRatePercent).ToString("0.##"); + } + } + else + { + dic["平仓线"] = ""; + dic["预警线"] = ""; + dic["档位1"] = ""; + dic["档位2"] = ""; + dic["档位3"] = ""; + dic["档位4"] = ""; + } // 期初预付金利率(InterestMode == 初始预付金) var initialMarginPosition = swapPositions diff --git a/Plugins/YLErp.Plugins.GuoLian/YLErp.Plugins.GuoLian.csproj b/Plugins/YLErp.Plugins.GuoLian/YLErp.Plugins.GuoLian.csproj index eb416ec0..58b7c9f7 100644 --- a/Plugins/YLErp.Plugins.GuoLian/YLErp.Plugins.GuoLian.csproj +++ b/Plugins/YLErp.Plugins.GuoLian/YLErp.Plugins.GuoLian.csproj @@ -31,9 +31,6 @@ PreserveNewest - - PreserveNewest - diff --git a/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs b/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs index cd78397a..ac751ae6 100644 --- a/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs +++ b/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs @@ -9,54 +9,45 @@ namespace YLErp.UnitTestProject.Modules.UnderlyingModule [TestMethod] public void GetApplicableMarginTerm_RuleTable_AllCases() { - // <=2年,应返回2年 - var code1 = "UNLIMITED_2Y"; + // <=5年,应返回<5y + var code1 = "UNLIMITED_UNDER5Y"; var maturity1 = new DateTime(2030, 1, 1); var underlying1 = CreateTestUnderlying(code1, null, maturity1); var valueDate1 = maturity1.AddYears(-1); // 剩余1年 var result1 = UnderlyingHelper.GetApplicableMarginTerm(code1, valueDate1); - Assert.AreEqual(ConsMarginTerm.TwoYear, result1, "<=2年 应为2年"); + Assert.AreEqual(ConsMarginTerm.UnderFiveYear, result1, "<=5年 应为<5y"); - // (2,5]年,应返回5年 - var code2 = "UNLIMITED_5Y"; + // (5,10]年,应返回5y-10y + var code2 = "UNLIMITED_5Y_10Y"; var maturity2 = new DateTime(2030, 1, 1); var underlying2 = CreateTestUnderlying(code2, null, maturity2); - var valueDate2 = maturity2.AddYears(-3); // 剩余3年 + var valueDate2 = maturity2.AddYears(-7); // 剩余7年 var result2 = UnderlyingHelper.GetApplicableMarginTerm(code2, valueDate2); - Assert.AreEqual(ConsMarginTerm.FiveYear, result2, "(2,5]年 应为5年"); + Assert.AreEqual(ConsMarginTerm.FiveToTenYear, result2, "(5,10]年 应为5y-10y"); - // (5,10]年,应返回10年 - var code3 = "UNLIMITED_10Y"; - var maturity3 = new DateTime(2030, 8, 2); + // (10,30]年,应返回10y-30y + var code3 = "UNLIMITED_10Y_30Y"; + var maturity3 = new DateTime(2050, 1, 1); var underlying3 = CreateTestUnderlying(code3, null, maturity3); - var valueDate3 = maturity3.AddYears(-7); // 剩余13年 - var valueDate3_2 = DateTime.Now.Date; // 剩余10年 - var result3 = UnderlyingHelper.GetApplicableMarginTerm(code3, valueDate3_2); - Assert.AreEqual(ConsMarginTerm.TenYear, result3, "(5,10]年 应为10年"); + var valueDate3 = maturity3.AddYears(-20); // 剩余20年 + var result3 = UnderlyingHelper.GetApplicableMarginTerm(code3, valueDate3); + Assert.AreEqual(ConsMarginTerm.TenToThirtyYear, result3, "(10,30]年 应为10y-30y"); - // (10,30]年,应返回30年 - var code4 = "UNLIMITED_30Y"; - var maturity4 = new DateTime(2050, 1, 1); + // >30年,应返回>30y + var code4 = "OVER_30Y"; + var maturity4 = new DateTime(2060, 1, 1); var underlying4 = CreateTestUnderlying(code4, null, maturity4); - var valueDate4 = maturity4.AddYears(-28); // 剩余28年 + var valueDate4 = maturity4.AddYears(-31); // 剩余31年 var result4 = UnderlyingHelper.GetApplicableMarginTerm(code4, valueDate4); - Assert.AreEqual(ConsMarginTerm.ThirtyYear, result4, "(10,30]年 应为30年"); + Assert.AreEqual(ConsMarginTerm.OverThirtyYear, result4, ">30年 应为>30y"); - // >30年,应返回30年以上 - var code5 = "OVER_30Y"; - var maturity5 = new DateTime(2060, 1, 1); + // 无效的到期日,应为<5y(兜底默认) + var code5 = "INVALID_TERM"; + DateTime? maturity5 = null; var underlying5 = CreateTestUnderlying(code5, null, maturity5); - var valueDate5 = maturity5.AddYears(-31); // 剩余31年 + var valueDate5 = DateTime.Now.Date; var result5 = UnderlyingHelper.GetApplicableMarginTerm(code5, valueDate5); - Assert.AreEqual(ConsMarginTerm.OverThirtyYear, result5, ">30年 应为30年以上"); - - // 无效的到期日,应为默认 - var code6 = "INVALID_TERM"; - DateTime? maturity6 = null; - var underlying6 = CreateTestUnderlying(code6, null, maturity6); - var valueDate6 = DateTime.Now.Date; - var result6 = UnderlyingHelper.GetApplicableMarginTerm(code6, valueDate6); - Assert.AreEqual(ConsMarginTerm.Default, result6, "无效的到期日 应为默认"); + Assert.AreEqual(ConsMarginTerm.UnderFiveYear, result5, "无效的到期日 应为<5y"); } #region 辅助方法 diff --git a/YLErpDAL/Model/ClientMarginDetailDto.cs b/YLErpDAL/Model/ClientMarginDetailDto.cs index c3a07861..53d0b199 100644 --- a/YLErpDAL/Model/ClientMarginDetailDto.cs +++ b/YLErpDAL/Model/ClientMarginDetailDto.cs @@ -20,12 +20,12 @@ namespace YLErp.Model /// 初始保证金率(%) - 可空 /// public decimal? init_rate { get; set; } - + /// /// 维持保证金率(%) - 可空 /// public decimal? maintain_rate { get; set; } - + /// /// 互换默认天数 - 可空 /// @@ -42,40 +42,40 @@ namespace YLErp.Model /// 配置ID /// public int id { get; set; } - + /// /// 客户ID /// public int client_id { get; set; } - + /// /// 客户名称 /// public string client_name { get; set; } - + /// /// 生效日期 /// public DateTime value_date { get; set; } - + /// /// 操作人ID /// public int? OptId { get; set; } - + /// /// 操作人姓名 /// public string OptName { get; set; } - + /// /// 操作时间 /// public DateTime? OptDate { get; set; } - + /// /// 配置详情列表 /// public List details { get; set; } = new List(); } -} \ No newline at end of file +} diff --git a/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs b/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs index 93d7c6c6..be030982 100644 --- a/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs +++ b/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs @@ -100,6 +100,19 @@ namespace YLErp.Modules.UnderlyingModule var marginConfig = GetClientMarginConfig(clientId, valueDate); if (marginConfig == null) return null; + + // 2.1 尝试使用标的资产上手动设置的债券期限 + var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); + if (underlying != null && !string.IsNullOrEmpty(underlying.ExJson)) + { + var bondInfo = JsonHelper.Deserialize(underlying.ExJson); + if (bondInfo != null && !string.IsNullOrEmpty(bondInfo.BondTerm)) + { + // 优先使用标的资产上设置的债券期限 + applicableTerm = bondInfo.BondTerm; + } + } + var marginDetail = GetMarginDetailByTerm(marginConfig.id, applicableTerm); // 3. 放入Redis @@ -167,9 +180,9 @@ namespace YLErp.Modules.UnderlyingModule var details = context.clientMarginDetail .Where(d => d.config_id == configId).ToList(); var detail = details.FirstOrDefault(d => d.bond_term == bondTerm); - if (detail==null&& !string.IsNullOrEmpty(bondTerm)) + if (detail == null) { - detail=details.FirstOrDefault(d => string.IsNullOrEmpty(d.bond_term)); + detail = details.FirstOrDefault(d => d.bond_term == ConsMarginTerm.UnderFiveYear); } return detail; } @@ -292,14 +305,14 @@ namespace YLErp.Modules.UnderlyingModule public static string GetApplicableMarginTerm(string underlyingCode, DateTime valueDate) { if (string.IsNullOrEmpty(underlyingCode)) - return ConsMarginTerm.Default; + return ConsMarginTerm.UnderFiveYear; try { // 获取标的信息 var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); if (underlying == null || !underlying.MaturityDate.HasValue) - return ConsMarginTerm.Default; + return ConsMarginTerm.UnderFiveYear; // 计算剩余期限(从估值日期到到期日期) var remainingTermYears = getYearTerm(valueDate, underlying.MaturityDate); @@ -310,38 +323,33 @@ namespace YLErp.Modules.UnderlyingModule { // 记录异常日志 Console.WriteLine($"计算保证金率期限时发生异常: {ex.Message}"); - return ConsMarginTerm.Default; + return ConsMarginTerm.UnderFiveYear; } } /// - /// 根据剩余年限确定适用的保证金率期限(新版规则,仅看剩余期限) - /// | 剩余期限(年) | 则适用于 | - /// |------------------|----------| - /// | <=2 | 2年档位 | - /// | (2,5] | 5年 | - /// | (5,10] | 10年 | - /// | (10,30] | 30年 | - /// | >30 | 30年以上 | - /// 未设置或无法计算剩余期限,使用“默认” + /// 根据剩余年限确定适用的保证金率期限(利率债TRS) + /// | 剩余期限(年) | 则适用于 | + /// |------------------|-------------| + /// | <=5 | <5y | + /// | (5,10] | 5y-10y | + /// | (10,30] | 10y-30y | + /// | >30 | >30y | + /// 未设置或无法计算剩余期限,使用”默认” /// - private static string DetermineMarginTerm( double? remainingYears) + private static string DetermineMarginTerm(double? remainingYears) { - // 新版规则:只看剩余期限 + // 利率债TRS规则:只看剩余期限 if (!remainingYears.HasValue) - return ConsMarginTerm.Default; + return ConsMarginTerm.UnderFiveYear; - if (remainingYears <= 2.0) - return ConsMarginTerm.TwoYear; - if (remainingYears > 2.0 && remainingYears <= 5.0) - return ConsMarginTerm.FiveYear; + if (remainingYears <= 5.0) + return ConsMarginTerm.UnderFiveYear; if (remainingYears > 5.0 && remainingYears <= 10.0) - return ConsMarginTerm.TenYear; + return ConsMarginTerm.FiveToTenYear; if (remainingYears > 10.0 && remainingYears <= 30.0) - return ConsMarginTerm.ThirtyYear; - if (remainingYears > 30.0) - return ConsMarginTerm.OverThirtyYear; - return ConsMarginTerm.Default; + return ConsMarginTerm.TenToThirtyYear; + return ConsMarginTerm.OverThirtyYear; } } } diff --git a/YLErpWeb/App_Data/Config/otcformat.js b/YLErpWeb/App_Data/Config/otcformat.js index f43ba8d2..b1f37cff 100644 --- a/YLErpWeb/App_Data/Config/otcformat.js +++ b/YLErpWeb/App_Data/Config/otcformat.js @@ -1,125 +1,2 @@ var main = main || {}; -main.formatOptions={ - "trading": { - "umprice": { - "precision": 9, - "grouping": true, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "umpriceP": { - "percent": true, - "precision": 9, - "grouping": false, - "rounded": true, - "minDecimals": 9, - "maxDecimals": 9 - }, - "umpricePR": { - "precision": 9, - "grouping": false, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "tradeSinglePrice": { - "precision": 9, - "grouping": true, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "premiumRateP": { - "percent": true, - "precision": 9, - "grouping": false, - "rounded": true, - "minDecimals": 9, - "maxDecimals": 9 - }, - "premiumRate": { - "precision": 9, - "grouping": false, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "tradePrice": { - "precision": 9, - "grouping": false, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "StockEqvNotional": { - "precision": 9, - "grouping": true, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "notional": { - "precision": 9, - "grouping": true, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "notionalP": { - "percent": true, - "precision": 9, - "grouping": false, - "rounded": true, - "minDecimals": 9, - "maxDecimals": 9 - }, - "volatility": { - "precision": 9, - "grouping": false, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "volatilityP": { - "percent": true, - "precision": 9, - "grouping": false, - "rounded": true, - "minDecimals": 9, - "maxDecimals": 9 - }, - "greek": { - "precision": 9, - "grouping": false, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - }, - "marginRateP": { - "percent": true, - "precision": 9, - "grouping": false, - "rounded": true, - "minDecimals": 9, - "maxDecimals": 9 - }, - "marginRate": { - "precision": 9, - "grouping": false, - "rounded": true, - "percent": false, - "minDecimals": 9, - "maxDecimals": 9 - } - } -}; \ No newline at end of file +main.formatOptions={ "trading": { "umprice": { "precision": 9, "grouping": true, "rounded": true, "percent": false, "minDecimals": 9, "maxDecimals": 0 }, "umpriceP": { "percent": true, "precision": 6, "grouping": false, "rounded": true, "minDecimals": 6, "maxDecimals": 0 }, "umpricePR": { "precision": 8, "grouping": false, "rounded": true, "percent": false, "minDecimals": 8, "maxDecimals": 2 }, "tradeSinglePrice": { "precision": 6, "grouping": true, "rounded": true, "percent": false, "minDecimals": 6, "maxDecimals": 0 }, "premiumRateP": { "percent": true, "precision": 4, "grouping": false, "rounded": true, "minDecimals": 4, "maxDecimals": 0 }, "premiumRate": { "precision": 6, "grouping": false, "rounded": true, "percent": false, "minDecimals": 6, "maxDecimals": 2 }, "tradePrice": { "precision": 2, "grouping": false, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 0 }, "StockEqvNotional": { "precision": 2, "grouping": true, "rounded": true, "percent": false, "minDecimals": 2, "maxDecimals": 0 }, "notional": { "precision": 4, "grouping": true, "rounded": true, "percent": false, "minDecimals": 4, "maxDecimals": 0 }, "notionalP": { "percent": true, "precision": 4, "grouping": false, "rounded": true, "minDecimals": 4, "maxDecimals": 0 }, "volatility": { "precision": 4, "grouping": false, "rounded": true, "percent": false, "minDecimals": 4, "maxDecimals": 2 }, "volatilityP": { "percent": true, "precision": 2, "grouping": false, "rounded": true, "minDecimals": 2, "maxDecimals": 0 }, "greek": { "precision": 3, "grouping": false, "rounded": true, "percent": false, "minDecimals": 3, "maxDecimals": 0 }, "marginRateP": { "percent": true, "precision": 4, "grouping": false, "rounded": true, "minDecimals": 4, "maxDecimals": 0 }, "marginRate": { "precision": 6, "grouping": false, "rounded": true, "percent": false, "minDecimals": 6, "maxDecimals": 2 } }}; \ No newline at end of file diff --git a/YLErpWeb/Controllers/ClientMarginConfigController.cs b/YLErpWeb/Controllers/ClientMarginConfigController.cs index 26e22a9a..919be706 100644 --- a/YLErpWeb/Controllers/ClientMarginConfigController.cs +++ b/YLErpWeb/Controllers/ClientMarginConfigController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Authorization; using YLErp.Cache; +using YLErp.DBModels; using YLErp.Modules.MarginModule; namespace YLErp.Web.Controllers @@ -101,7 +102,7 @@ namespace YLErp.Web.Controllers if (_cache!=null) { // 删除缓存ClientMarginRate开头的key - _cache.BatchDelete("ClientMarginRate:*"); + _cache.BatchDelete("Otc:ClientMarginRate:*"); } return JsonSuccess("已删除"); } @@ -111,26 +112,26 @@ namespace YLErp.Web.Controllers { // 将DTO转换为数据库实体,处理必填和可选逻辑 var detailEntities = new List(); - var hasDefaultTerm = false; - + var hasUnderFiveYear = false; + if (details != null) { foreach (var dto in details) { - // 默认期限(空字符串)必填 - if (string.IsNullOrEmpty(dto.bond_term)) + // <5y期限必填 + if (dto.bond_term == ConsMarginTerm.UnderFiveYear) { if (!dto.init_rate.HasValue || !dto.maintain_rate.HasValue) { - return JsonError("默认期限的初始保证金率和维持保证金率必须填写"); + return JsonError("<5y期限的初始保证金率和维持保证金率必须填写"); } - hasDefaultTerm = true; - + hasUnderFiveYear = true; + detailEntities.Add(new client_margin_detail { - bond_term = "", - init_rate = dto.init_rate.Value / 100, // 转换百分比 - maintain_rate = dto.maintain_rate.Value / 100, // 转换百分比 + bond_term = ConsMarginTerm.UnderFiveYear, + init_rate = dto.init_rate.Value / 100, + maintain_rate = dto.maintain_rate.Value / 100, swap_days = dto.swap_days ?? 0 }); } @@ -139,35 +140,33 @@ namespace YLErp.Web.Controllers // 其他期限非必填,但如果填写了任何字段就需要验证 if (dto.init_rate.HasValue || dto.maintain_rate.HasValue || dto.swap_days.HasValue) { - // 如果swap_days有值,则init_rate和maintain_rate必须有值 if (dto.swap_days.HasValue && (!dto.init_rate.HasValue || !dto.maintain_rate.HasValue)) { return JsonError($"期限\"{dto.bond_term}\":当互换默认天数有值时,初始保证金率和维持保证金率必须填写"); } - + detailEntities.Add(new client_margin_detail { bond_term = dto.bond_term, - init_rate = (dto.init_rate ?? 0) / 100, // 转换百分比 - maintain_rate = (dto.maintain_rate ?? 0) / 100, // 转换百分比 + init_rate = (dto.init_rate ?? 0) / 100, + maintain_rate = (dto.maintain_rate ?? 0) / 100, swap_days = dto.swap_days ?? 0 }); } } } } - - // 验证默认期限必须填写 - if (!hasDefaultTerm) + + if (!hasUnderFiveYear) { - return JsonError("默认期限的保证金配置信息必须填写"); + return JsonError("<5y期限的保证金配置信息必须填写"); } new ClientMarginConfigService(CurUser).SaveMarginConfigWithDetails(marginConfig, detailEntities); if (_cache != null) { // 删除缓存ClientMarginRate开头的key - _cache.BatchDelete("ClientMarginRate:*"); + _cache.BatchDelete("Otc:ClientMarginRate:*"); } return JsonSuccess("已修改"); } diff --git a/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml b/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml index 6940667d..7754a8cf 100644 --- a/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml +++ b/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml @@ -43,15 +43,15 @@ var initRateInput = row.querySelector('input[name*="init_rate"]'); var maintainRateInput = row.querySelector('input[name*="maintain_rate"]'); var swapDaysInput = row.querySelector('input[name*="swap_days"]'); - + var initRateValue = initRateInput.value.trim(); var maintainRateValue = maintainRateInput.value.trim(); var swapDaysValue = swapDaysInput.value.trim(); - + var initRate = initRateValue === '' ? null : parseFloat(initRateValue); var maintainRate = maintainRateValue === '' ? null : parseFloat(maintainRateValue); var swapDays = swapDaysValue === '' ? null : parseInt(swapDaysValue); - + // 验证数值不能为负数 if (initRate !== null && initRate < 0) { hasError = true; @@ -68,12 +68,12 @@ errorMessage = "互换天数不能为负数"; return; } - - // 默认数据(第一条,bond_term为空)的所有字段都必填 - if (bondTerm === "") { + + // <5y期限的所有字段都必填 + if (bondTerm === "<5y") { if (initRate === null || maintainRate === null || swapDays === null) { hasError = true; - errorMessage = "默认配置的所有字段都必须填写"; + errorMessage = "<5y期限配置的所有字段都必须填写"; return; } details.push({ @@ -89,7 +89,7 @@ errorMessage = "当保证金率有值时,互换天数必须填写"; return; } - + // 当保证金率与互换天数都为空时,不加到details里 if (initRate !== null || maintainRate !== null || swapDays !== null) { details.push({ diff --git a/YLErpWeb/Views/underlying_manager/underlying_managerEdit.cshtml b/YLErpWeb/Views/underlying_manager/underlying_managerEdit.cshtml index db4e13a7..6ea28715 100644 --- a/YLErpWeb/Views/underlying_manager/underlying_managerEdit.cshtml +++ b/YLErpWeb/Views/underlying_manager/underlying_managerEdit.cshtml @@ -302,6 +302,17 @@ + +
+ + +
diff --git a/YLErpWeb/Views/underlying_manager/underlying_managerView.cshtml b/YLErpWeb/Views/underlying_manager/underlying_managerView.cshtml index f22e7837..731c26d4 100644 --- a/YLErpWeb/Views/underlying_manager/underlying_managerView.cshtml +++ b/YLErpWeb/Views/underlying_manager/underlying_managerView.cshtml @@ -169,6 +169,12 @@ @(bond.IssueSize.OtcFormatMoney()) @Html.MyDisplayFor(m => m.Price) + + 债券期限 + @(bond.BondTerm) + + + }