diff --git a/Framework/YLErp.Core/DBModels/margin_template_v2.cs b/Framework/YLErp.Core/DBModels/margin_template_v2.cs index f58cb003..c9ea9826 100644 --- a/Framework/YLErp.Core/DBModels/margin_template_v2.cs +++ b/Framework/YLErp.Core/DBModels/margin_template_v2.cs @@ -25,6 +25,19 @@ namespace YLErp.DBModels [Column("book_id")] public string BookIds { get; set; } + private string _bookScopeName; + + /// + /// 适用簿记账户名称,仅用于列表展示,不持久化。 + /// + [NotMapped] + [DisplayName("适用簿记账户")] + public string BookScopeName + { + get => string.IsNullOrWhiteSpace(BookIds) ? "全部" : _bookScopeName ?? string.Empty; + set => _bookScopeName = value; + } + /// /// 将簿记账户ID列表规范化为去空格、去重的逗号分隔字符串。 /// diff --git a/UnitTestProject/Modules/CalcModules/MarginTemplateV2BookScopeTest.cs b/UnitTestProject/Modules/CalcModules/MarginTemplateV2BookScopeTest.cs new file mode 100644 index 00000000..3da20b87 --- /dev/null +++ b/UnitTestProject/Modules/CalcModules/MarginTemplateV2BookScopeTest.cs @@ -0,0 +1,110 @@ +using YLErp.DBModels; +using YLErp.Modules.MarginModule; +using YLErp.Modules.SwapModule; + +namespace YLErp.Modules.CalcModules +{ + [TestClass] + public class MarginTemplateV2BookScopeTest + { + [TestMethod] + public void BS_001_空范围适用全部簿记账户() + { + var template = new margin_template_v2 { BookIds = null }; + + Assert.IsTrue(template.IsApplicableToBook(1)); + Assert.IsTrue(template.IsApplicableToBook(11)); + } + + [TestMethod] + public void BS_002_按完整token精确匹配避免1命中11() + { + var template = new margin_template_v2 { BookIds = "11, 12,11" }; + + Assert.IsFalse(template.IsApplicableToBook(1)); + Assert.IsTrue(template.IsApplicableToBook(11)); + Assert.IsTrue(template.IsApplicableToBook(12)); + Assert.AreEqual("11,12", margin_template_v2.NormalizeBookIds(template.BookIds)); + } + + [TestMethod] + public void BS_003_账户范围只接受正整数并规范前导零() + { + Assert.IsNull(margin_template_v2.NormalizeBookIds(null)); + Assert.IsNull(margin_template_v2.NormalizeBookIds(" ")); + Assert.AreEqual("1,2", margin_template_v2.NormalizeBookIds("001, 2,001")); + + Assert.ThrowsException(() => margin_template_v2.NormalizeBookIds("abc")); + Assert.ThrowsException(() => margin_template_v2.NormalizeBookIds("0")); + Assert.ThrowsException(() => margin_template_v2.NormalizeBookIds("-1")); + Assert.ThrowsException(() => margin_template_v2.NormalizeBookIds("1,,2")); + } + + [TestMethod] + public void BS_004_范围重叠空范围视为全部() + { + Assert.IsTrue(margin_template_v2.AreBookScopesOverlapping(null, "11")); + Assert.IsTrue(margin_template_v2.AreBookScopesOverlapping("11,12", "12,13")); + Assert.IsFalse(margin_template_v2.AreBookScopesOverlapping("1", "11")); + } + + [TestMethod] + public void BS_005_收集所有重叠范围的适用结构() + { + var candidates = new[] + { + new margin_template_v2 { BookIds = "1", TradeTypes = "收益互换" }, + new margin_template_v2 { BookIds = "2", TradeTypes = "香草期权" }, + new margin_template_v2 { BookIds = "3", TradeTypes = "远期" } + }; + + var tradeTypes = margin_template_v2.GetOverlappingTradeTypes(candidates, "1,2").ToList(); + + CollectionAssert.AreEquivalent(new[] { "收益互换", "香草期权" }, tradeTypes); + } + + [TestMethod] + public void BS_006_空交易ID不触发簿记账户查询() + { + Assert.IsNull(MarginTemplateV2RateHelper.GetTradeAssetId(null, null)); + Assert.IsNull(MarginTemplateV2RateHelper.GetTradeAssetId(0, null)); + } + + [TestMethod] + public void LEGACY_001_存量原样未知名称可保留() + { + Assert.IsTrue(SwapTradeService.CanKeepLegacyMarginTemplateName( + false, "历史模板", "历史模板", false)); + } + + [TestMethod] + public void LEGACY_002_新增交易的未知名称不可保留() + { + Assert.IsFalse(SwapTradeService.CanKeepLegacyMarginTemplateName( + true, "历史模板", "历史模板", false)); + } + + [TestMethod] + public void LEGACY_003_修改为不同未知名称不可保留() + { + Assert.IsFalse(SwapTradeService.CanKeepLegacyMarginTemplateName( + false, "历史模板", "另一历史模板", false)); + } + + [TestMethod] + public void LEGACY_004_已存在V2名称不作为历史值() + { + Assert.IsFalse(SwapTradeService.CanKeepLegacyMarginTemplateName( + false, "模板V2", "模板V2", true)); + } + + [TestMethod] + public void LEGACY_005_空名称不作为历史值() + { + Assert.IsFalse(SwapTradeService.CanKeepLegacyMarginTemplateName( + false, null, null, false)); + Assert.IsFalse(SwapTradeService.CanKeepLegacyMarginTemplateName( + false, " ", " ", false)); + } + } +} diff --git a/YLErpDAL/Modules/MarginModule/MarginTemplateService.cs b/YLErpDAL/Modules/MarginModule/MarginTemplateService.cs index 10539fbb..55ff63c5 100644 --- a/YLErpDAL/Modules/MarginModule/MarginTemplateService.cs +++ b/YLErpDAL/Modules/MarginModule/MarginTemplateService.cs @@ -1,4 +1,5 @@ using BaseOUDAL; +using System.Globalization; using YLErp.Model; namespace YLErp.Modules.MarginModule @@ -77,8 +78,67 @@ namespace YLErp.Modules.MarginModule } var retListResult = query.ToSearchList(req); + SetBookScopeNames(retListResult); return retListResult; } + + private void SetBookScopeNames(SearchListResult result) + { + var rows = result?.rows?.ToList(); + if (rows == null || rows.Count == 0) + { + return; + } + + var parsedRows = rows.Select(row => new + { + Row = row, + BookIds = row == null ? new List() : ParseBookIdsForDisplay(row.BookIds) + }).ToList(); + var bookIds = parsedRows.SelectMany(item => item.BookIds).Distinct().ToList(); + var bookNames = bookIds.Count == 0 + ? new Dictionary() + : DbContext.assetunit + .AsNoTracking() + .Where(book => bookIds.Contains(book.id)) + .Select(book => new { book.id, book.Name }) + .ToDictionary(book => book.id, book => book.Name); + + foreach (var item in parsedRows) + { + if (item.Row == null) + { + continue; + } + + item.Row.BookScopeName = string.IsNullOrWhiteSpace(item.Row.BookIds) + ? "全部" + : string.Join(",", item.BookIds + .Where(bookId => bookNames.ContainsKey(bookId)) + .Select(bookId => bookNames[bookId])); + } + + result.rows = rows; + } + + private static List ParseBookIdsForDisplay(string bookIds) + { + var ids = new List(); + if (string.IsNullOrWhiteSpace(bookIds)) + { + return ids; + } + + foreach (var rawId in bookIds.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + { + if (int.TryParse(rawId.Trim(), NumberStyles.None, CultureInfo.InvariantCulture, out var id) && id > 0) + { + ids.Add(id); + } + } + + return ids; + } } } diff --git a/YLErpDAL/Modules/TradeModule/TradeApprovalOAService.cs b/YLErpDAL/Modules/TradeModule/TradeApprovalOAService.cs index 63baf9a4..1884fa2f 100644 --- a/YLErpDAL/Modules/TradeModule/TradeApprovalOAService.cs +++ b/YLErpDAL/Modules/TradeModule/TradeApprovalOAService.cs @@ -244,9 +244,10 @@ namespace YLErp.Modules.TradeModule // 3 + 结束:审批人批准,本地按通过处理; // 3 + 强制归档:OA 流程被强制关闭。正常情况下,本地发起 // forceEndOaFlow 后记录会先变为“归档中”、成功后变为“已归档”, - // 不会进入本轮待查询集合;若仍被查询到,则按客户确认的口径视为同意。 - // 0(非退回)及 1 + 审批人:草稿/待办,继续等待。 - // 其他组合也必须继续等待,不能仅凭 flowStatusType=1 或 3 推进本地流程。 + // 不会进入本轮待查询集合;若仍被查询到,则视为同意。 + // 0(非退回):草稿,继续等待。 + // 1 + 审批人:OA 待办,继续等待。 + // 其他组合也必须继续等待,不会仅凭 flowStatusType=1 或 3 推进本地流程。 var isReturned = flowStatusType == "0" && flowNode == "退回"; var isApproved = flowStatusType == "3" && (flowNode == "结束" || flowNode == "强制归档"); diff --git a/YLErpWeb/Views/client_margin_template/client_margin_templateEdit.cshtml b/YLErpWeb/Views/client_margin_template/client_margin_templateEdit.cshtml index 6f84ee02..50a45b9b 100644 --- a/YLErpWeb/Views/client_margin_template/client_margin_templateEdit.cshtml +++ b/YLErpWeb/Views/client_margin_template/client_margin_templateEdit.cshtml @@ -10,8 +10,7 @@ isAdd = Model == null || Model.id == 0, marginTemplates = ViewBag.MarginTemplates, marginTemplate = ViewBag.MarginTemplate, - clientMarginTemplate = Model, - isGFSM = PS.Config.Company == CompanyEnum.广发商贸 + clientMarginTemplate = Model }; } @@ -43,26 +42,26 @@
-
+

新模板信息

- @if (pageObj.isGFSM) - { -
- - -
- }
- + @if (pageObj.isAdd) + { + @*新增:客户多选(类似适用簿记账户),保存时按选中客户逐条调用原有单条保存接口*@ + + } + else + { + @*编辑:单条绑定,仅改模板/日期,客户不可多选*@ + + }
@@ -98,7 +97,7 @@
-
@@ -170,26 +169,6 @@
- @if (PS.Config.Company == CompanyEnum.广发商贸) - { - - }