();
- existTradeTypes.ForEach(x => tradeTypes.AddRange(x.Split(',')));
+ var marginTemplateDefault = yldb.margin_template_v2
+ .Where(x => x.id != marginTemplate.id && x.IsDefault && x.IsValid && !x.IsForClient && (x.BuySellType & marginTemplate.BuySellType) > 0 && (x.MarginScenarios & marginTemplate.MarginScenarios) > 0 && x.ValueDate == marginTemplate.ValueDate)
+ .ToList()
+ .Where(x => margin_template_v2.AreBookScopesOverlapping(x.BookIds, marginTemplate.BookIds));
+ var tradeTypes = margin_template_v2.GetOverlappingTradeTypes(marginTemplateDefault, marginTemplate.BookIds).ToList();
tradeTypes.ForEach(x =>
{
if (marginTemplate.TradeTypes.Contains(x))
@@ -481,6 +486,7 @@ namespace YLErp.Web.Controllers
r.Name = marginTemplate.Name;
r.IsDefault = marginTemplate.IsDefault;
r.IsForClient = marginTemplate.IsForClient;
+ r.BookIds = marginTemplate.BookIds;
r.Comments = marginTemplate.Comments;
r.RuleType = marginTemplate.RuleType;
r.TradeTypes = marginTemplate.TradeTypes;
@@ -605,6 +611,27 @@ namespace YLErp.Web.Controllers
}
}
+ private void ValidateBookIds(string bookIds)
+ {
+ if (string.IsNullOrWhiteSpace(bookIds))
+ {
+ return;
+ }
+
+ var ids = margin_template_v2.ParseBookIds(bookIds)
+ .Select(x => int.Parse(x))
+ .ToList();
+ var existingIds = yldb.assetunit
+ .Where(x => ids.Contains(x.id))
+ .Select(x => x.id)
+ .ToList();
+ var missingIds = ids.Except(existingIds).ToList();
+ if (missingIds.Any())
+ {
+ throw new Exception("适用簿记账户组包含不存在的簿记账户ID:" + string.Join(",", missingIds));
+ }
+ }
+
[HttpPost]
public JsonResult deleteEditmargin_template_v2(string enid)
{
@@ -742,4 +769,4 @@ namespace YLErp.Web.Controllers
}
-}
\ No newline at end of file
+}
diff --git a/YLErpWeb/Controllers/tradeController.cs b/YLErpWeb/Controllers/tradeController.cs
index ce50fdab..2bd5d5e5 100644
--- a/YLErpWeb/Controllers/tradeController.cs
+++ b/YLErpWeb/Controllers/tradeController.cs
@@ -7980,7 +7980,11 @@ namespace YLErp.Web.Controllers
var trade = yldb.trade.Find(tradeId);
//R1 三层级(2026-08-24 配合修改):候选只列有效模板——已作废模板一旦绑定,
//解析一级"找到即停"会让该交易直接视为无预付金(仅留日志),必须从源头挡住
- var marginTemplates = yldb.margin_template_v2.Where(x => x.IsValid && x.TradeTypes.Contains(trade.TradeType) && !x.IsDefault).ToList();
+ var marginTemplates = yldb.margin_template_v2
+ .Where(x => x.IsValid && x.TradeTypes.Contains(trade.TradeType) && !x.IsDefault)
+ .ToList()
+ .Where(x => x.IsApplicableToBook(trade.AssetId))
+ .ToList();
marginTemplates.ForEach(x => x.Details = yldb.margin_template_detail.Where(y => y.MarginTemplateId == x.id).ToList());
var latestTradeMarginTemplate = yldb.trade_margin_template.Where(x => x.TradeId == tradeId).OrderByDescending(x => x.ValueDate).FirstOrDefault();
@@ -8025,6 +8029,26 @@ namespace YLErp.Web.Controllers
throw new Exception("请选择有效的预付金模板");
}
+ var trade = yldb.trade.Find(tradeMarginTemplate.TradeId);
+ if (trade == null)
+ {
+ throw new Exception("交易不存在");
+ }
+
+ var marginTemplate = yldb.margin_template_v2
+ .FirstOrDefault(x => x.id == tradeMarginTemplate.MarginTemplateId
+ && x.IsValid
+ && !x.IsDefault
+ && x.TradeTypes.Contains(trade.TradeType));
+ if (marginTemplate == null)
+ {
+ throw new Exception("请选择有效的预付金模板");
+ }
+ if (!marginTemplate.IsApplicableToBook(trade.AssetId))
+ {
+ throw new Exception("所选预付金模板不适用当前簿记账户");
+ }
+
var deletedRecords = yldb.trade_margin_template.Where(x => x.TradeId == tradeMarginTemplate.TradeId && x.ValueDate >= tradeMarginTemplate.ValueDate).ToArray();
yldb.trade_margin_template.RemoveRange(deletedRecords);
var updatedRecords = yldb.trade_margin_template.Where(x => x.TradeId == tradeMarginTemplate.TradeId && x.ValueDate < tradeMarginTemplate.ValueDate).ToList();
@@ -8040,7 +8064,6 @@ namespace YLErp.Web.Controllers
#region 重置初始预付金
- var trade = yldb.trade.Find(tradeMarginTemplate.TradeId);
//R1 三层级(2026-08-24 配合修改):收益互换跳过系统重算——互换初始预付金为手工录入/预付金腿承载
//(方案B 引擎回落链消费 trade.InitialMargin),且试算链路(GetInitialMarginWithPreHandle 克隆 id=0)
//对互换取不到模板绑定恒得 0,无条件重置会把手工录入值清零;与 TradeSaveService 保存守卫语义对齐
diff --git a/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml b/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml
index ce7eb5d6..3c3f3251 100644
--- a/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml
+++ b/YLErpWeb/Views/SwapTrade2/TradeEdit.cshtml
@@ -15,11 +15,20 @@
var jsClient = canChangeClient && Model.ClientId > 0 ? jsClients.FirstOrDefault(n => n.id == Model.ClientId) : null;
var jsAssetUnits = JsDataModel.GetAssetUnits(CurUser);
var tradeMarginTemplates = new tradeController().GetMarginTemplates();
- var swapMarginTemplateItems = SwapMarginTemplateConfigService.GetConfig().options.ToList();
+ var allSwapMarginTemplateItems = SwapMarginTemplateConfigService.GetConfig().options.ToList();
+ var swapMarginTemplateItems = allSwapMarginTemplateItems.ToList();
//保证金模板V2迁移:存量交易的保证金模板可能是历史文本值(如字典配置的"现金保证金"),不在模板V2选项中时追加显示,避免编辑保存时被静默清空
if (!string.IsNullOrWhiteSpace(Model.MarginTemplateName) && !swapMarginTemplateItems.Any(n => n.Value == Model.MarginTemplateName))
{
- swapMarginTemplateItems.Add(new YLErp.Models.SelectItem { Text = Model.MarginTemplateName + "(历史值)", Value = Model.MarginTemplateName });
+ var legacyMarginTemplateItem = new SwapMarginTemplateOption
+ {
+ Text = Model.MarginTemplateName + "(历史值)",
+ Value = Model.MarginTemplateName,
+ BookIds = null,
+ IsLegacy = true
+ };
+ allSwapMarginTemplateItems.Add(legacyMarginTemplateItem);
+ swapMarginTemplateItems.Add(legacyMarginTemplateItem);
}
var tradeMarginTemplateItems = new tradeController().GetMarginTemplateItems();
var jsAssetUnit = Model.AssetId > 0 ? jsAssetUnits.FirstOrDefault(n => n.id == Model.AssetId) : null;
@@ -75,6 +84,7 @@
jsTrader,
jsTraders,
tradeMarginTemplates = tradeMarginTemplates,
+ allSwapMarginTemplateItems = allSwapMarginTemplateItems,
swapMarginTemplateItems = swapMarginTemplateItems,
tradeMarginTemplateItems = tradeMarginTemplateItems,
needRemark = !isAdd && valuedateBLL.SystemDate.EditTradeNeedRemark,
diff --git a/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml b/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml
index 593f2612..66f204fc 100644
--- a/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml
+++ b/YLErpWeb/Views/margin_template_v2/margin_template_v2ClientEdit.cshtml
@@ -13,6 +13,7 @@
isGFSM = PS.Config.Company == CompanyEnum.广发商贸,
etfSubtypeItems = YLErp.BLL.DictionaryBLL.GetDictionaryItems("ETF 子类").Select(x => x.Name).ToList()
};
+ var selectedBookIds = margin_template_v2.ParseBookIds(Model?.BookIds);
}
@section CSS{
@@ -63,6 +64,16 @@
+
+
+
+
+
@if (PS.Config.Company != CompanyEnum.广发商贸)
{
diff --git a/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml b/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml
index baf49537..a2c38876 100644
--- a/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml
+++ b/YLErpWeb/Views/margin_template_v2/margin_template_v2DefaultEdit.cshtml
@@ -1,4 +1,4 @@
-@using YLErp.Enums;
+@using YLErp.Enums;
@model margin_template_v2
@{
@@ -12,6 +12,7 @@
detail = new margin_template_detail() { ValueDate = new DateTime(2020, 1, 1), ComparedInitialMarginRate = 1 },
etfSubtypeItems = YLErp.BLL.DictionaryBLL.GetDictionaryItems("ETF 子类").Select(x => x.Name).ToList()
};
+ var selectedBookIds = margin_template_v2.ParseBookIds(Model?.BookIds);
}
@section CSS{
@@ -63,6 +64,16 @@
+
+
+
+
+