diff --git a/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs b/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs index 17a2d00f..325b7dca 100644 --- a/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs +++ b/Framework/YLErp.Core/DBModels/Consts/ConsMarginTerm.cs @@ -30,6 +30,11 @@ namespace YLErp.DBModels /// public const string ThirtyYear = "30Y"; + /// + /// 30年以上期 + /// + public const string OverThirtyYear = "Over30Y"; + /// /// 所有允许的期限值 /// @@ -39,7 +44,8 @@ namespace YLErp.DBModels TwoYear, FiveYear, TenYear, - ThirtyYear + ThirtyYear, + OverThirtyYear }; /// @@ -66,6 +72,7 @@ namespace YLErp.DBModels FiveYear => "5年", TenYear => "10年", ThirtyYear => "30年", + OverThirtyYear => "30年以上", _ => term?.Replace("Y", "年") ?? "默认" }; } diff --git a/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs b/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs index 79546f38..d5df606c 100644 --- a/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs +++ b/Plugins/YLErp.Plugins.ZheShang/DocumentGenerator/TradeConfirmationGenerator.cs @@ -1,6 +1,7 @@ using Microsoft.VisualBasic; using Newtonsoft.Json.Linq; using NPOI.SS.Formula.Functions; +using Org.BouncyCastle.Ocsp; using System.Diagnostics; using System.Net.Http.Headers; using System.Text.RegularExpressions; @@ -11,6 +12,7 @@ using YLErp.DBModels.Enums; using YLErp.Enums; using YLErp.Plugins.TradeDocGenerator; using YLErp.Plugins.TradeDocGenerator.Abstracts; +using static NPOI.HSSF.Util.HSSFColor; namespace YLErp.Plugins.ShanXi.DocumentGenerator { @@ -100,7 +102,6 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator var clientduties = Context.GetClientDuties(); var table1 = new JArray(); var table2 = new JArray(); - var clientMarginRate = Context.GetClientMarginRate(client.id); dic["交易编号"] = GetContractNo(out string contractIndex); dic["交易对手方全称"] = client.ClientType != "产品" ? client.Name : $"{client.Manager}作为管理人代表{client.Name}"; dic["主协议编号"] = client.MainProtocolCode; @@ -126,7 +127,7 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator var initialMarginQuery = swapPositions.Where(x => x.InterestMode == 5); var additionMarginQuery = swapPositions.Where(x => x.InterestMode == 6); var underlyingCode = swapPosition?.UnderlyingCode; - + var clientMarginRate = YLErp.Modules.UnderlyingModule.UnderlyingHelper.GetApplicableMarginRate(client.id, underlyingCode, trade.TradeDate.Value); if (count == 0) { var interestMargin = allinterestMargins.FirstOrDefault(o => o.interest_rest_days != null); @@ -197,9 +198,9 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator //} //dic["计算基准"] = calculationBasis; - dic["初始保障金率"] = ((clientMarginRate?.InitMarginRate ?? 0) * 100).ToString("0.####") + "%"; - dic["维持保障金率"] = ((clientMarginRate?.MaintenanceRate ?? 0) * 100).ToString("0.####") + "%"; - + dic["初始保障金率"] = ((clientMarginRate?.init_rate ?? 0) * 100).ToString("0.####") + "%"; + dic["维持保障金率"] = ((clientMarginRate?.maintain_rate ?? 0) * 100).ToString("0.####") + "%"; + dic["期初预付金".Insert("期初预付金".Length, "2?")] = (StockEqvNotionalRealSum * Convert.ToDouble(clientMarginRate?.init_rate??0)).ToString("0.##"); //var initialMarginSum = initialMarginQuery.Sum(x => // x.InterestDirection == 2 ? x.InterestPrincipalFix * -1 : x.InterestPrincipalFix); //dic["期初预付金".Insert("期初预付金".Length, "2?")] = initialMarginSum.ToString("0.##"); @@ -224,7 +225,7 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator FormatToDict("交易费用", (double)((swapPosition?.PosiTradingFeePending * 2) ?? 0), row); row["期初预付金利率"] = ((initialMarginQuery.FirstOrDefault()?.InterestRateDefault) ?? 0) * 100; - row["追加预付金返息率"] = ((clientMarginRate?.AddToMarginRebateRate) ?? 0) * 100; + //row["追加预付金返息率"] = ((clientMarginRate?.AddToMarginRebateRate) ?? 0) * 100; if (!string.IsNullOrEmpty(underlyingCode)) { var um = Context.GetTradeUnderlying(underlyingCode); @@ -258,7 +259,7 @@ namespace YLErp.Plugins.ShanXi.DocumentGenerator dic["交易费率"] = dic["基本费率"]; dic["交易费用"] = PosiTradingFeePending; dic["名义本金".Insert("名义本金".Length, "2?")] = StockEqvNotionalRealSum.ToString("0.##"); - dic["期初预付金".Insert("期初预付金".Length, "2?")] = (StockEqvNotionalRealSum * clientMarginRate?.InitMarginRate)?.ToString("0.##"); + clientduties = clientduties.Where(x => x.ContactTypeId.Contains("3")).OrderBy(o => o.id).ToList();//交易确认书邮件接收人 diff --git a/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj b/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj index 5c668224..80af5486 100644 --- a/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj +++ b/Plugins/YLErp.Plugins.ZheShang/YLErp.Plugins.ZheShang.csproj @@ -9,6 +9,7 @@ + diff --git a/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs b/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs index 97e60b01..7e722e0a 100644 --- a/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs +++ b/UnitTestProject/Modules/UnderlyingModule/UnderlyingHelperTest.cs @@ -9,76 +9,54 @@ namespace YLErp.UnitTestProject.Modules.UnderlyingModule [TestMethod] public void GetApplicableMarginTerm_RuleTable_AllCases() { - // 发行期限不限(OpenDate=null),测试(0.00,2.00],应返回2年 + // <=2年,应返回2年 var code1 = "UNLIMITED_2Y"; var maturity1 = new DateTime(2030, 1, 1); - var underlying1 = CreateTestUnderlying ( code1, null,maturity1); + var underlying1 = CreateTestUnderlying(code1, null, maturity1); var valueDate1 = maturity1.AddYears(-1); // 剩余1年 - var result1=UnderlyingHelper.GetApplicableMarginTerm(code1, valueDate1); - Assert.AreEqual(ConsMarginTerm.TwoYear, result1, "(0,2]年 不限 应为2年"); + var result1 = UnderlyingHelper.GetApplicableMarginTerm(code1, valueDate1); + Assert.AreEqual(ConsMarginTerm.TwoYear, result1, "<=2年 应为2年"); - // (2.00,2.25] <5年,应返回2年 - var code2 = "LT5_2_25"; - var open2 = new DateTime(2020, 1, 1); var maturity2 = new DateTime(2024, 3, 1); // 4.17年 - var underlying2 = CreateTestUnderlying(code2, open2, maturity2); - var valueDate2 = maturity2.AddYears(-2).AddMonths(-2); // 剩余约2.17年 + // (2,5]年,应返回5年 + var code2 = "UNLIMITED_5Y"; + var maturity2 = new DateTime(2030, 1, 1); + var underlying2 = CreateTestUnderlying(code2, null, maturity2); + var valueDate2 = maturity2.AddYears(-3); // 剩余3年 var result2 = UnderlyingHelper.GetApplicableMarginTerm(code2, valueDate2); - Assert.AreEqual(ConsMarginTerm.TwoYear, result2, "(2,2.25]年 <5 应为2年"); + Assert.AreEqual(ConsMarginTerm.FiveYear, result2, "(2,5]年 应为5年"); - // (2.00,2.25] >=5年,应返回5年 - var code3 = "GE5_2_25"; - var open3 = new DateTime(2020, 1, 1); var maturity3 = new DateTime(2026, 1, 1); // 6年 - var underlying3 = CreateTestUnderlying(code3, open3, maturity3); - var valueDate3_2 = maturity3.AddYears(-2).AddMonths(-1); // 剩余约2.08年 + // (5,10]年,应返回10年 + var code3 = "UNLIMITED_10Y"; + var maturity3 = new DateTime(2040, 1, 1); + var underlying3 = CreateTestUnderlying(code3, null, maturity3); + var valueDate3 = maturity3.AddYears(-7); // 剩余13年 + var valueDate3_2 = maturity3.AddYears(-10); // 剩余10年 var result3 = UnderlyingHelper.GetApplicableMarginTerm(code3, valueDate3_2); - Assert.AreEqual(ConsMarginTerm.FiveYear, result3, "(2,2.25]年 >=5 应为5年"); + Assert.AreEqual(ConsMarginTerm.TenYear, result3, "(5,10]年 应为10年"); - // (2.25,5.00] 不限,应返回5年 - var code4 = "UNLIMITED_5Y"; - var maturity4 = new DateTime(2030, 1, 1); + // (10,30]年,应返回30年 + var code4 = "UNLIMITED_30Y"; + var maturity4 = new DateTime(2050, 1, 1); var underlying4 = CreateTestUnderlying(code4, null, maturity4); - var valueDate4 = maturity4.AddYears(-3); // 剩余3年 + var valueDate4 = maturity4.AddYears(-28); // 剩余28年 var result4 = UnderlyingHelper.GetApplicableMarginTerm(code4, valueDate4); - Assert.AreEqual(ConsMarginTerm.FiveYear, result4, "(2.25,5]年 不限 应为5年"); + Assert.AreEqual(ConsMarginTerm.ThirtyYear, result4, "(10,30]年 应为30年"); - // (5.00,5.25] <7年,应返回5年 - var code5 = "LT7_5_25"; - var open5 = new DateTime(2020, 1, 1); var maturity5 = new DateTime(2026, 1, 1); // 6年 - var underlying5 = CreateTestUnderlying(code5, open5, maturity5); - var valueDate5 = maturity5.AddYears(-5).AddMonths(-1); // 剩余约5.08年 - var result5 = UnderlyingHelper.GetApplicableMarginTerm(underlying5.UnderlyingCode, valueDate5); - Assert.AreEqual(ConsMarginTerm.FiveYear, result5, "(5,5.25]年 <7 应为5年"); + // >30年,应返回30年以上 + var code5 = "OVER_30Y"; + var maturity5 = new DateTime(2060, 1, 1); + var underlying5 = CreateTestUnderlying(code5, null, maturity5); + var valueDate5 = maturity5.AddYears(-31); // 剩余31年 + var result5 = UnderlyingHelper.GetApplicableMarginTerm(code5, valueDate5); + Assert.AreEqual(ConsMarginTerm.OverThirtyYear, result5, ">30年 应为30年以上"); - // (5.00,5.25] >=7年,应返回10年 - var code6 = "GE7_5_25"; - var open6 = new DateTime(2015, 1, 1); var maturity6 = new DateTime(2023, 2, 1); // 8.08年 - var underlying6 = CreateTestUnderlying(code6, open6, maturity6); - var valueDate6 = maturity6.AddYears(-5).AddMonths(-1); // 剩余约5.08年 + // 无效的到期日,应为默认 + 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.TenYear, result6, "(5,5.25]年 >=7 应为10年"); - - // (5.25,25.00] 不限,应返回10年 - var code7 = "UNLIMITED_10Y"; - var maturity7 = new DateTime(2040, 1, 1); - var underlying7 = CreateTestUnderlying(code7, null, maturity7); - var valueDate7 = maturity7.AddYears(-10); // 剩余10年 - var result7 = UnderlyingHelper.GetApplicableMarginTerm(code7, valueDate7); - Assert.AreEqual(ConsMarginTerm.TenYear, result7, "(5.25,25]年 不限 应为10年"); - - // (25.00,30.00] 不限,应返回30年 - var code8 = "UNLIMITED_30Y"; - var maturity8 = new DateTime(2050, 1, 1); - var underlying8 = CreateTestUnderlying(code8, null, maturity8); - var valueDate8 = maturity8.AddYears(-28); // 剩余28年 - var result8 = UnderlyingHelper.GetApplicableMarginTerm(code8, valueDate8); - Assert.AreEqual(ConsMarginTerm.ThirtyYear, result8, "(25,30]年 不限 应为30年"); - - var code9 = "INVALID_TERM"; - DateTime? maturity9 = null; - var underlying9 = CreateTestUnderlying(code9, null, maturity9); - var valueDate9 = DateTime.Now.Date; - var result9 = UnderlyingHelper.GetApplicableMarginTerm(code9, valueDate9); - Assert.AreEqual(ConsMarginTerm.Default, result9, "无效的到期日 不限 应为默认"); + Assert.AreEqual(ConsMarginTerm.Default, result6, "无效的到期日 应为默认"); } #region 辅助方法 diff --git a/YLErpDAL/Model/ClientMarginDetailDto.cs b/YLErpDAL/Model/ClientMarginDetailDto.cs index 5c079852..c3a07861 100644 --- a/YLErpDAL/Model/ClientMarginDetailDto.cs +++ b/YLErpDAL/Model/ClientMarginDetailDto.cs @@ -8,10 +8,14 @@ namespace YLErp.Model public class ClientMarginDetailDto { /// - /// 利率债期限 + /// 债券期限 /// public string bond_term { get; set; } - + /// + /// 债券期限显示 + /// + public string bond_term_desc => ConsMarginTerm.GetDisplayName(bond_term); + /// /// 初始保证金率(%) - 可空 /// diff --git a/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs b/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs index 48fb0846..5be1bc17 100644 --- a/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs +++ b/YLErpDAL/Modules/UnderlyingModule/UnderlyingHelper.cs @@ -298,15 +298,11 @@ namespace YLErp.Modules.UnderlyingModule var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); if (underlying == null || !underlying.MaturityDate.HasValue) return ConsMarginTerm.Default; - - // 计算发行年限(从上市日期到到期日期) - var issueTermYears = getYearTerm(underlying.OpenDate, underlying.MaturityDate); - // 计算剩余期限(从估值日期到到期日期) var remainingTermYears = getYearTerm(valueDate, underlying.MaturityDate); // 根据业务规则确定适用的保证金率期限 - return DetermineMarginTerm(issueTermYears, remainingTermYears); + return DetermineMarginTerm(remainingTermYears); } catch (Exception ex) { @@ -317,55 +313,32 @@ namespace YLErp.Modules.UnderlyingModule } /// - /// 根据发行年限和剩余年限确定适用的保证金率期限 - /// 规则表格: - /// | 剩余期限(年) | 发行期限(年) | 则适用于 | - /// |------------------|---------------|----------| - /// | (0.00,2.00] | 不限 | 2年 | - /// | (2.00,2.25] | <5 | 2年 | - /// | (2.00,2.25] | >=5 | 5年 | - /// | (2.25,5.00] | 不限 | 5年 | - /// | (5.00,5.25] | <7 | 5年 | - /// | (5.00,5.25] | >=7 | 10年 | - /// | (5.25,25.00] | 不限 | 10年 | - /// | (25.00,30.00] | 不限 | 30年 | - /// 说明:发行年限为null或0时视为“不限” + /// 根据剩余年限确定适用的保证金率期限(新版规则,仅看剩余期限) + /// | 剩余期限(年) | 则适用于 | + /// |------------------|----------| + /// | <=2 | 2年档位 | + /// | (2,5] | 5年 | + /// | (5,10] | 10年 | + /// | (10,30] | 30年 | + /// | >30 | 30年以上 | + /// 未设置或无法计算剩余期限,使用“默认” /// - private static string DetermineMarginTerm(double? issueYears, double? remainingYears) + private static string DetermineMarginTerm( double? remainingYears) { - // (0.00,2.00]年 不限 2年 - if (remainingYears > 0.00 && remainingYears <= 2.00) + // 新版规则:只看剩余期限 + if (!remainingYears.HasValue) + return ConsMarginTerm.Default; + + if (remainingYears <= 2.0) return ConsMarginTerm.TwoYear; - - // (2.00,2.25] <5 2年 - if (remainingYears > 2.00 && remainingYears <= 2.25 && issueYears.HasValue && issueYears < 5) - return ConsMarginTerm.TwoYear; - - // (2.00,2.25] >=5 5年 - if (remainingYears > 2.00 && remainingYears <= 2.25 && issueYears.HasValue && issueYears >= 5) + if (remainingYears > 2.0 && remainingYears <= 5.0) return ConsMarginTerm.FiveYear; - - // (2.25,5.00] 不限 5年 - if (remainingYears > 2.25 && remainingYears <= 5.00) - return ConsMarginTerm.FiveYear; - - // (5.00,5.25] <7 5年 - if (remainingYears > 5.00 && remainingYears <= 5.25 && issueYears.HasValue && issueYears < 7) - return ConsMarginTerm.FiveYear; - - // (5.00,5.25] >=7 10年 - if (remainingYears > 5.00 && remainingYears <= 5.25 && issueYears.HasValue && issueYears >= 7) + if (remainingYears > 5.0 && remainingYears <= 10.0) return ConsMarginTerm.TenYear; - - // (5.25,25.00] 不限 10年 - if (remainingYears > 5.25 && remainingYears <= 25.00) - return ConsMarginTerm.TenYear; - - // (25.00,30.00] 不限 30年 - if (remainingYears > 25.00 && remainingYears <= 30.00) + if (remainingYears > 10.0 && remainingYears <= 30.0) return ConsMarginTerm.ThirtyYear; - - // 其他情况返回默认 + if (remainingYears > 30.0) + return ConsMarginTerm.OverThirtyYear; return ConsMarginTerm.Default; } } diff --git a/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml b/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml index c837a9d3..6940667d 100644 --- a/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml +++ b/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigEdit.cshtml @@ -161,7 +161,7 @@ @for (int i = 0; i < details.Count; i++) { var detail = details[i]; - var displayName = detail.bond_term == "" ? "默认" : detail.bond_term.Replace("Y", "年"); + var displayName = YLErp.DBModels.ConsMarginTerm.GetDisplayName(detail.bond_term); diff --git a/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigList.cshtml b/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigList.cshtml index 382fc3ba..d1033898 100644 --- a/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigList.cshtml +++ b/YLErpWeb/Views/ClientMarginConfig/ClientMarginConfigList.cshtml @@ -247,19 +247,9 @@ } } - // 辅助函数:格式化期限显示 - function formatBondTerm(bondTerm) { - if (!bondTerm || bondTerm === '') return '默认'; - if (bondTerm === null || bondTerm === undefined) return '--'; - - // 将Y替换为年 - var formatted = bondTerm.toString().replace(/Y/g, '年'); - return escapeHtml(formatted); - } - // 辅助函数:生成详情单元格HTML function generateDetailCells(detail) { - return '' + formatBondTerm(detail.bond_term) + '' + + return '' + detail.bond_term_desc + '' + '' + formatPercentage(detail.init_rate) + '' + '' + formatPercentage(detail.maintain_rate) + '' + '' + (detail.swap_days || '--') + '天';