From 13b9c2a451481868f3bc5eedbacea385bf567b5d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 10:14:42 +0800
Subject: [PATCH 01/17] =?UTF-8?q?refactor(Trade=5FSelf):=20=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E4=BA=92=E6=8D=A2=E4=BA=A4=E6=98=93=E7=BC=96=E8=BE=91?=
=?UTF-8?q?=E6=9D=83=E9=99=90=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 提取互换事件检查条件为独立变量 hasSwapDealEvent
- 添加对平仓、互换、自动互换事件类型的检查
- 将复杂条件判断重构为更清晰的逻辑结构
- 保持原有业务逻辑不变的情况下提高代码可读性
---
YLErpDAL/Model/Trade_Self.cs | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/YLErpDAL/Model/Trade_Self.cs b/YLErpDAL/Model/Trade_Self.cs
index 237a7b44..8f2e69a6 100644
--- a/YLErpDAL/Model/Trade_Self.cs
+++ b/YLErpDAL/Model/Trade_Self.cs
@@ -199,8 +199,14 @@ namespace YLErp.DBModels
}
public bool SwapCanEdit()
{
+ var hasSwapDealEvent = swap_Events.Any(x =>
+ !x.Invalid
+ && (x.EventType == (int)SwapEventTypeEnum.平仓
+ || x.EventType == (int)SwapEventTypeEnum.互换
+ || x.EventType == (int)SwapEventTypeEnum.自动互换));
+
//确认成交
- return !(ConsTrade.TradeStatusAfterAndWithOutConfirmed.Contains(TradeStatus) || ConsTrade.审批中.Equals(TradeStatus) || UnWindDate.HasValue || (!PS.Config.TradeElement.IsAmendableAfterConfirm && TradeDate < valuedateBLL.ValueDate && ConsTrade.确认成交.Equals(TradeStatus)));
+ return !(ConsTrade.TradeStatusAfterAndWithOutConfirmed.Contains(TradeStatus) || ConsTrade.审批中.Equals(TradeStatus) || UnWindDate.HasValue || hasSwapDealEvent || (!PS.Config.TradeElement.IsAmendableAfterConfirm && TradeDate < valuedateBLL.ValueDate && ConsTrade.确认成交.Equals(TradeStatus)));
}
public bool CanDelete()
{
From 7d523112205b58437d820417e35c4b9055ee342a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 13:32:02 +0800
Subject: [PATCH 02/17] =?UTF-8?q?fix(swap-trade):=20=E4=BF=AE=E6=AD=A3?=
=?UTF-8?q?=E5=B1=95=E6=9C=9F=E5=B9=B3=E4=BB=93=E9=A1=B5=E9=9D=A2=E6=95=B0?=
=?UTF-8?q?=E9=87=8F=E6=98=BE=E7=A4=BA=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 将浮仓数量字段从 floatPosition.Quantity 更新为 deal.CloseQty
- 确保页面显示正确的平仓数量信息
---
YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml b/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml
index 029907c6..9eb4bd3b 100644
--- a/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml
+++ b/YLErpWeb/Views/SwapTrade2/SwapUnwind.cshtml
@@ -204,7 +204,7 @@
-
{{floatPosition.Quantity}} |
+ {{deal.CloseQty}} |
我方{{floatPosition.PayDirection==1?"支付":"收取"}}交易费用
From 3534ebb342ae670777f2666d95dc4f8803192891 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 14:07:19 +0800
Subject: [PATCH 03/17] =?UTF-8?q?fix(trade):=20=E4=BF=AE=E6=AD=A3=E5=AF=B9?=
=?UTF-8?q?=E5=AE=A2=E4=BA=A4=E6=98=93=E5=88=A4=E6=96=AD=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 修改了GuolianContractNoGenerator中对客交易的判断条件
- 将判断标准从"乙方=对客"改为"甲方=对客"
- 更新了相关注释以反映新的业务规则
---
.../DocGenerateModule/GuolianContractNoGenerator.cs | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs b/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs
index 4ca0b788..67901f31 100644
--- a/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs
+++ b/YLErpDAL/Modules/TradeModule/DocGenerateModule/GuolianContractNoGenerator.cs
@@ -8,9 +8,9 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule
///
/// 国贸交易确认书编号生成器
/// 规则:
- /// - 对客交易(OpponentRole为"乙方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-{当日第N笔对客交易(数字递增)}-{标的代码},从01开始
+ /// - 对客交易(OpponentRole为"甲方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-FICC-{当日第N笔对客交易(数字递增)}-{标的代码},从01开始
/// 例:GLMS-IS-20260424-01-250210IB
- /// - 非对客交易(OpponentRole为"甲方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-{当日第N笔非对客交易使用字母递增}-{标的代码},从A开始
+ /// - 非对客交易(OpponentRole为"乙方"):GLMS-{对手方代码}-{成交日期(yyyyMMdd)}-FICC-{当日第N笔非对客交易使用字母递增}-{标的代码},从A开始
/// 例:GLMS-IS-20260424-A-250210IB
///
public class GuolianContractNoGenerator
@@ -29,8 +29,8 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule
trade trade,
string clientCode)
{
- // 根据trade的OpponentRole判断是否为对客交易(乙方=对客)
- var isClientTrade = trade.OpponentRole == "乙方";
+ // 根据trade的OpponentRole判断是否为对客交易(甲方=对客)。glms客户规定甲方=对客
+ var isClientTrade = trade.OpponentRole == "甲方";
var underlyingCode = (trade.UnderlyingCode ?? "").Replace(".", ""); // 去掉标的代码中的点号
var tradeDate = trade.TradeDate ?? DateTime.MinValue;
var tradeDateStr = tradeDate.ToString("yyyyMMdd");
From b2dce0e4f7b04e94441d0243e8959b7b12844903 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 14:28:47 +0800
Subject: [PATCH 04/17] =?UTF-8?q?fix(swap):=20=E4=BF=AE=E5=A4=8D=E4=BA=92?=
=?UTF-8?q?=E6=8D=A2=E4=BA=A4=E6=98=93=E6=B5=81=E7=A8=8B=E4=BA=8B=E4=BB=B6?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E5=A1=AB=E5=85=85=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- 添加SwapTradeNo、EventType和EventReason字段到流程事件
- 修正EventType枚举类型从SwapEventTypeEnum改为SwapFlowEventTypeEnum
- 在SaveSwapDeal方法中添加交易信息验证逻辑
- 提取FillSwapFlowEvent方法统一处理流程事件数据填充
- 优化数据库保存操作确保数据一致性
---
.../Modules/SwapModule/SwapDealService.cs | 29 +++++++++++++++++--
1 file changed, 26 insertions(+), 3 deletions(-)
diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs
index c79a30a5..fcffad1c 100644
--- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs
+++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs
@@ -254,6 +254,9 @@ namespace YLErp.Modules.SwapModule
unwindData.PayDate = QdpCalendarHelper.GetNonHoliday(unwindData.UnwindDate.Value.AddDays(td.trade_extend.ExtendObj.SettlementRules));
floatEvent.PayDate = unwindData.PayDate;
floatEvent.SwapTradeId = tradeId;
+ floatEvent.SwapTradeNo = td.TradeNumber;
+ floatEvent.EventType = (int)SwapFlowEventTypeEnum.互换;
+ floatEvent.EventReason = "交易";
unwindData.SwapTradeId = tradeId;
unwindData.StructureType = td.StructureType;
unwindData.NotionalValue = Convert.ToDecimal(td.OriginalStockEqvNotional ?? 0);
@@ -265,8 +268,6 @@ namespace YLErp.Modules.SwapModule
unwindData.CloseNotionalValue = unwindData.PosiNotionalValue;
if (position != null)
{
- floatEvent.EventType = (int)SwapEventTypeEnum.互换;
- floatEvent.EventReason = "交易";
floatEvent.PositionId = position.PositionId;
floatEvent.DividendIn = 0;
floatEvent.UnderlyingCode = position.UnderlyingCode;
@@ -1619,6 +1620,11 @@ namespace YLErp.Modules.SwapModule
///
private long SaveSwapDeal(UnwindData unwindData, int eventType, int clientCashId, string eventResason = "", bool approve = false)
{
+ var td = DbContext.trade.Find(unwindData.SwapTradeId);
+ if (td == null)
+ {
+ throw new ServiceException("未找到交易信息");
+ }
var flowList = new List(unwindData.FlowEvents);
unwindData.FlowEvents.Clear();
string data = JsonConvert.SerializeObject(unwindData);
@@ -1633,7 +1639,7 @@ namespace YLErp.Modules.SwapModule
item.PayDate = unwindData.PayDate;
item.UnwindDate = unwindData.UnwindDate;
item.EventDate = unwindData.ValueDate;
- item.EventId = swapEvent.id;
+ FillSwapFlowEvent(item, unwindData, td, eventType, swapEvent.id);
DbContext.swap_flow_event.Add(item);
}
if (!approve)
@@ -1641,8 +1647,25 @@ namespace YLErp.Modules.SwapModule
UpdateInitalPosition(flowList, unwindData, eventType);
}
DbContext.SaveChanges();
+ var savedFlowEvents = DbContext.swap_flow_event.Where(x => x.EventId == swapEvent.id).ToList();
+ foreach (var item in savedFlowEvents)
+ {
+ FillSwapFlowEvent(item, unwindData, td, eventType, swapEvent.id);
+ }
+ DbContext.SaveChanges();
return swapEvent.id;
}
+
+ private void FillSwapFlowEvent(swap_flow_event item, UnwindData unwindData, trade td, int eventType, long eventId)
+ {
+ item.EventId = eventId;
+ item.SwapTradeId = unwindData.SwapTradeId;
+ item.SwapTradeNo = td.TradeNumber;
+ item.EventType = eventType;
+ item.EventReason = string.IsNullOrWhiteSpace(item.EventReason) ? "交易" : item.EventReason;
+ UpdateDbOption(item);
+ }
+
///
/// 计算平仓数据
///
From 1a15918f3de9e949d9d5742d90c4ebc9f9cdb3cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:01:38 +0800
Subject: [PATCH 05/17] =?UTF-8?q?Revert=20"=E4=BF=AE=E6=94=B9=E9=A3=8E?=
=?UTF-8?q?=E6=8E=A7=E8=A7=84=E5=88=99=E6=93=8D=E4=BD=9C=E6=9D=83=E9=99=90?=
=?UTF-8?q?"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 29ac61e2d51aeb5a45924cbae8bfdae0fff59142.
---
.../Ver-5.6.0/seed_menu_risk_alert.sql | 36 +----------
YLErpWeb/Common/BaseController.cs | 8 +++
YLErpWeb/Controllers/RiskRuleController.cs | 62 +++++++++----------
3 files changed, 41 insertions(+), 65 deletions(-)
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql
index 68a57b0d..3ab5fb65 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql
@@ -9,42 +9,10 @@
-- 1. sys_menu 页面+按钮(type=1,2)
-- ----------------------------
INSERT INTO `yltrs_admin`.`sys_menu` (`id`, `pid`, `pids`, `name`, `code`, `type`, `icon`, `router`, `component`, `permission`, `application`, `open_type`, `visible`, `link`, `redirect`, `weight`, `sort`, `remark`, `status`, `create_time`, `create_user`, `update_time`, `update_user`) VALUES
-(1077, 99, NULL, '异常交易监控', NULL, 1, NULL, NULL, NULL, '异常交易监控', NULL, NULL, NULL, NULL, NULL, NULL, 0, '', 0, NULL, NULL, NULL, NULL),
-(1078, 1077, NULL, '风控规则查看', NULL, 2, NULL, NULL, NULL, '风控规则查看', NULL, NULL, NULL, NULL, NULL, NULL, 1, '', 0, NULL, NULL, NULL, NULL),
-(1079, 1077, NULL, '风控规则新增', NULL, 2, NULL, NULL, NULL, '风控规则新增', NULL, NULL, NULL, NULL, NULL, NULL, 2, '', 0, NULL, NULL, NULL, NULL),
-(1080, 1077, NULL, '风控规则编辑', NULL, 2, NULL, NULL, NULL, '风控规则编辑', NULL, NULL, NULL, NULL, NULL, NULL, 3, '', 0, NULL, NULL, NULL, NULL),
-(1081, 1077, NULL, '风控规则删除', NULL, 2, NULL, NULL, NULL, '风控规则删除', NULL, NULL, NULL, NULL, NULL, NULL, 4, '', 0, NULL, NULL, NULL, NULL),
-(1082, 1077, NULL, '风控规则启停', NULL, 2, NULL, NULL, NULL, '风控规则启停', NULL, NULL, NULL, NULL, NULL, NULL, 5, '', 0, NULL, NULL, NULL, NULL),
-(1083, 1077, NULL, '风控应用查看', NULL, 2, NULL, NULL, NULL, '风控应用查看', NULL, NULL, NULL, NULL, NULL, NULL, 6, '', 0, NULL, NULL, NULL, NULL),
-(1084, 1077, NULL, '风控应用新增', NULL, 2, NULL, NULL, NULL, '风控应用新增', NULL, NULL, NULL, NULL, NULL, NULL, 7, '', 0, NULL, NULL, NULL, NULL),
-(1085, 1077, NULL, '风控应用编辑', NULL, 2, NULL, NULL, NULL, '风控应用编辑', NULL, NULL, NULL, NULL, NULL, NULL, 8, '', 0, NULL, NULL, NULL, NULL),
-(1086, 1077, NULL, '风控应用删除', NULL, 2, NULL, NULL, NULL, '风控应用删除', NULL, NULL, NULL, NULL, NULL, NULL, 9, '', 0, NULL, NULL, NULL, NULL),
-(1087, 1077, NULL, '风控应用启停', NULL, 2, NULL, NULL, NULL, '风控应用启停', NULL, NULL, NULL, NULL, NULL, NULL, 10, '', 0, NULL, NULL, NULL, NULL),
-(1088, 1077, NULL, '风控变量查看', NULL, 2, NULL, NULL, NULL, '风控变量查看', NULL, NULL, NULL, NULL, NULL, NULL, 11, '', 0, NULL, NULL, NULL, NULL),
-(1089, 1077, NULL, '风控变量新增', NULL, 2, NULL, NULL, NULL, '风控变量新增', NULL, NULL, NULL, NULL, NULL, NULL, 12, '', 0, NULL, NULL, NULL, NULL),
-(1090, 1077, NULL, '风控变量编辑', NULL, 2, NULL, NULL, NULL, '风控变量编辑', NULL, NULL, NULL, NULL, NULL, NULL, 13, '', 0, NULL, NULL, NULL, NULL),
-(1091, 1077, NULL, '风控变量删除', NULL, 2, NULL, NULL, NULL, '风控变量删除', NULL, NULL, NULL, NULL, NULL, NULL, 14, '', 0, NULL, NULL, NULL, NULL),
-(1092, 1077, NULL, '风控日志查看', NULL, 2, NULL, NULL, NULL, '风控日志查看', NULL, NULL, NULL, NULL, NULL, NULL, 15, '', 0, NULL, NULL, NULL, NULL),
-(1093, 1077, NULL, '风控日志导出', NULL, 2, NULL, NULL, NULL, '风控日志导出', NULL, NULL, NULL, NULL, NULL, NULL, 16, '', 0, NULL, NULL, NULL, NULL);
+(1077, 99, NULL, '异常交易监控', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, '', 0, NULL, NULL, NULL, NULL);
-- ----------------------------
-- 2. sys_role_menu 角色1的按钮权限
-- ----------------------------
INSERT INTO `yltrs_admin`.`sys_role_menu` (`id`, `role_id`, `menu_id`) VALUES
-(1097, 1, 1077),
-(1098, 1, 1078),
-(1099, 1, 1079),
-(1100, 1, 1080),
-(1101, 1, 1081),
-(1102, 1, 1082),
-(1103, 1, 1083),
-(1104, 1, 1084),
-(1105, 1, 1085),
-(1106, 1, 1086),
-(1107, 1, 1087),
-(1108, 1, 1088),
-(1109, 1, 1089),
-(1110, 1, 1090),
-(1111, 1, 1091),
-(1112, 1, 1092),
-(1113, 1, 1093);
+(1097, 1, 1077);
diff --git a/YLErpWeb/Common/BaseController.cs b/YLErpWeb/Common/BaseController.cs
index e8224105..be2e8e8a 100644
--- a/YLErpWeb/Common/BaseController.cs
+++ b/YLErpWeb/Common/BaseController.cs
@@ -180,6 +180,14 @@ namespace YLErp.Web
return;
}
var hasRight = false;
+ #if DEBUG
+ if (context.Controller is Controllers.RiskRuleController)
+ {
+ hasRight = true;
+ base.OnActionExecuting(context);
+ return;
+ }
+ #endif
var isAjaxRequest = Request.Headers["X-Requested-With"] == "XMLHttpRequest";
var typedHeaders = Request.GetTypedHeaders();
diff --git a/YLErpWeb/Controllers/RiskRuleController.cs b/YLErpWeb/Controllers/RiskRuleController.cs
index bbb5a6fb..55ba98e9 100644
--- a/YLErpWeb/Controllers/RiskRuleController.cs
+++ b/YLErpWeb/Controllers/RiskRuleController.cs
@@ -1,4 +1,4 @@
-using Qdp.Foundation.Utilities;
+using Qdp.Foundation.Utilities;
using YLErp.DBModels;
using YLErp.Modules.RiskEngine;
using YLErp.Modules.RiskEngine.Dto;
@@ -13,7 +13,7 @@ namespace YLErp.Web.Controllers
#region Rule Management
[HttpGet("risk-rules")]
- [MyAuthorize("风险控制-风控规则查看")]
+ [MyAuthorize("风控规则查看")]
public JsonResult QueryRiskRules(QueryRiskRuleReq req)
{
try
@@ -34,7 +34,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-rules/{id}")]
- [MyAuthorize("风险控制-风控规则查看")]
+ [MyAuthorize("风控规则查看")]
public JsonResult GetRiskRule(long id)
{
try
@@ -55,7 +55,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-rules/{id}/versions")]
- [MyAuthorize("风险控制-风控规则查看")]
+ [MyAuthorize("风控规则查看")]
public JsonResult GetRiskRuleVersions(long id)
{
try
@@ -76,7 +76,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-rules")]
- [MyAuthorize("风险控制-风控规则新增")]
+ [MyAuthorize("风控规则新增")]
public JsonResult CreateRiskRule([FromBody] CreateRiskRuleReq req)
{
try
@@ -97,7 +97,7 @@ namespace YLErp.Web.Controllers
}
[HttpPut("risk-rules/{id}")]
- [MyAuthorize("风险控制-风控规则编辑")]
+ [MyAuthorize("风控规则编辑")]
public JsonResult UpdateRiskRule(long id, [FromBody] UpdateRiskRuleReq req)
{
try
@@ -118,7 +118,7 @@ namespace YLErp.Web.Controllers
}
[HttpDelete("risk-rules/{id}")]
- [MyAuthorize("风险控制-风控规则删除")]
+ [MyAuthorize("风控规则删除")]
public JsonResult DeleteRiskRule(long id)
{
try
@@ -139,7 +139,7 @@ namespace YLErp.Web.Controllers
}
[HttpDelete("risk-rules/batch")]
- [MyAuthorize("风险控制-风控规则删除")]
+ [MyAuthorize("风控规则删除")]
public JsonResult BatchDeleteRiskRules([FromBody] List ids)
{
try
@@ -160,7 +160,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-rules/{id}/enable")]
- [MyAuthorize("风险控制-风控规则启停")]
+ [MyAuthorize("风控规则启停")]
public JsonResult EnableRiskRule(long id)
{
try
@@ -181,7 +181,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-rules/{id}/disable")]
- [MyAuthorize("风险控制-风控规则启停")]
+ [MyAuthorize("风控规则启停")]
public JsonResult DisableRiskRule(long id)
{
try
@@ -202,7 +202,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-rules/{id}/applications")]
- [MyAuthorize("风险控制-风控规则查看")]
+ [MyAuthorize("风控规则查看")]
public JsonResult GetRuleApplications(long id)
{
try
@@ -223,7 +223,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-rules/list")]
- [MyAuthorize("风险控制-风控规则查看")]
+ [MyAuthorize("风控规则查看")]
public JsonResult GetAllRiskRules()
{
try
@@ -248,7 +248,7 @@ namespace YLErp.Web.Controllers
#region Application Management
[HttpGet("risk-applications")]
- [MyAuthorize("风险控制-风控应用查看")]
+ [MyAuthorize("风控应用查看")]
public JsonResult QueryRiskApplications(QueryRiskApplicationReq req)
{
try
@@ -269,7 +269,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-applications/{id}")]
- [MyAuthorize("风险控制-风控应用查看")]
+ [MyAuthorize("风控应用查看")]
public JsonResult GetRiskApplication(long id)
{
try
@@ -290,7 +290,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-applications")]
- [MyAuthorize("风险控制-风控应用新增")]
+ [MyAuthorize("风控应用新增")]
public JsonResult CreateRiskApplication([FromBody] CreateRiskApplicationReq req)
{
try
@@ -311,7 +311,7 @@ namespace YLErp.Web.Controllers
}
[HttpPut("risk-applications/{id}")]
- [MyAuthorize("风险控制-风控应用编辑")]
+ [MyAuthorize("风控应用编辑")]
public JsonResult UpdateRiskApplication(long id, [FromBody] UpdateRiskApplicationReq req)
{
try
@@ -332,7 +332,7 @@ namespace YLErp.Web.Controllers
}
[HttpDelete("risk-applications/{id}")]
- [MyAuthorize("风险控制-风控应用删除")]
+ [MyAuthorize("风控应用删除")]
public JsonResult DeleteRiskApplication(long id)
{
try
@@ -353,7 +353,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-applications/{id}/enable")]
- [MyAuthorize("风险控制-风控应用启停")]
+ [MyAuthorize("风控应用启停")]
public JsonResult EnableRiskApplication(long id)
{
try
@@ -374,7 +374,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-applications/{id}/disable")]
- [MyAuthorize("风险控制-风控应用启停")]
+ [MyAuthorize("风控应用启停")]
public JsonResult DisableRiskApplication(long id)
{
try
@@ -395,7 +395,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-applications/batch-enable")]
- [MyAuthorize("风险控制-风控应用启停")]
+ [MyAuthorize("风控应用启停")]
public JsonResult BatchEnableRiskApplications([FromBody] List ids)
{
try
@@ -416,7 +416,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-applications/batch-disable")]
- [MyAuthorize("风险控制-风控应用启停")]
+ [MyAuthorize("风控应用启停")]
public JsonResult BatchDisableRiskApplications([FromBody] List ids)
{
try
@@ -441,7 +441,7 @@ namespace YLErp.Web.Controllers
#region Variable Management
[HttpGet("risk-variables")]
- [MyAuthorize("风险控制-风控变量查看")]
+ [MyAuthorize("风控变量查看")]
public JsonResult QueryRiskVariables(QueryRiskVariableReq req)
{
try
@@ -462,7 +462,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-variables/{id}")]
- [MyAuthorize("风险控制-风控变量查看")]
+ [MyAuthorize("风控变量查看")]
public JsonResult GetRiskVariable(long id)
{
try
@@ -483,7 +483,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-variables/list")]
- [MyAuthorize("风险控制-风控变量查看")]
+ [MyAuthorize("风控变量查看")]
public JsonResult GetAllRiskVariables()
{
try
@@ -504,7 +504,7 @@ namespace YLErp.Web.Controllers
}
[HttpPost("risk-variables")]
- [MyAuthorize("风险控制-风控变量新增")]
+ [MyAuthorize("风控变量新增")]
public JsonResult CreateRiskVariable([FromBody] CreateRiskVariableReq req)
{
try
@@ -525,7 +525,7 @@ namespace YLErp.Web.Controllers
}
[HttpPut("risk-variables/{id}")]
- [MyAuthorize("风险控制-风控变量编辑")]
+ [MyAuthorize("风控变量编辑")]
public JsonResult UpdateRiskVariable(long id, [FromBody] UpdateRiskVariableReq req)
{
try
@@ -546,7 +546,7 @@ namespace YLErp.Web.Controllers
}
[HttpDelete("risk-variables/{id}")]
- [MyAuthorize("风险控制-风控变量删除")]
+ [MyAuthorize("风控变量删除")]
public JsonResult DeleteRiskVariable(long id)
{
try
@@ -571,7 +571,7 @@ namespace YLErp.Web.Controllers
#region Trade Types
[HttpGet("trade-types")]
- [MyAuthorize("风险控制-风控应用查看")]
+ [MyAuthorize("风控应用查看")]
public JsonResult GetTradeTypes()
{
try
@@ -600,7 +600,7 @@ namespace YLErp.Web.Controllers
#region Audit Log
[HttpGet("risk-audit-logs")]
- [MyAuthorize("风险控制-风控日志查看")]
+ [MyAuthorize("风控日志查看")]
public JsonResult QueryRiskAuditLogs(QueryRiskAuditLogReq req)
{
try
@@ -621,7 +621,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-audit-logs/{id}")]
- [MyAuthorize("风险控制-风控日志查看")]
+ [MyAuthorize("风控日志查看")]
public JsonResult GetRiskAuditLogDetail(long id)
{
try
@@ -642,7 +642,7 @@ namespace YLErp.Web.Controllers
}
[HttpGet("risk-audit-logs/export")]
- [MyAuthorize("风险控制-风控日志导出")]
+ [MyAuthorize("风控日志导出")]
public IActionResult ExportRiskAuditLogs(QueryRiskAuditLogReq req)
{
try
From eb778677e94bba9b84da30f74bfe3c459a4005ad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:02:41 +0800
Subject: [PATCH 06/17] =?UTF-8?q?Revert=20"=E4=BF=AE=E6=94=B9=E9=A3=8E?=
=?UTF-8?q?=E6=8E=A7=E8=A7=84=E5=88=99=E6=93=8D=E4=BD=9C=E6=9D=83=E9=99=90?=
=?UTF-8?q?"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit f53ef952220745e1af919ad7a90718dc8a479f8e.
---
.../Ver-5.6.0/seed_menu_risk_alert.sql | 18 ------------------
YLErpWeb/App_Data/FunctionRight.xml | 8 ++++----
2 files changed, 4 insertions(+), 22 deletions(-)
delete mode 100644 Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql
deleted file mode 100644
index 3ab5fb65..00000000
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_menu_risk_alert.sql
+++ /dev/null
@@ -1,18 +0,0 @@
--- ============================================================
--- 异常交易监控页面 - 操作权限(按钮)数据
--- 依赖:异常交易监控菜单 id=1077 (type=1) 需先插入
--- 对应 FunctionRight.xml 风险控制下风控相关操作权限(共16个按钮)
--- type: 0=目录 1=菜单 2=按钮
--- ============================================================
-
--- ----------------------------
--- 1. sys_menu 页面+按钮(type=1,2)
--- ----------------------------
-INSERT INTO `yltrs_admin`.`sys_menu` (`id`, `pid`, `pids`, `name`, `code`, `type`, `icon`, `router`, `component`, `permission`, `application`, `open_type`, `visible`, `link`, `redirect`, `weight`, `sort`, `remark`, `status`, `create_time`, `create_user`, `update_time`, `update_user`) VALUES
-(1077, 99, NULL, '异常交易监控', NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, '', 0, NULL, NULL, NULL, NULL);
-
--- ----------------------------
--- 2. sys_role_menu 角色1的按钮权限
--- ----------------------------
-INSERT INTO `yltrs_admin`.`sys_role_menu` (`id`, `role_id`, `menu_id`) VALUES
-(1097, 1, 1077);
diff --git a/YLErpWeb/App_Data/FunctionRight.xml b/YLErpWeb/App_Data/FunctionRight.xml
index ed07a284..1e03e280 100644
--- a/YLErpWeb/App_Data/FunctionRight.xml
+++ b/YLErpWeb/App_Data/FunctionRight.xml
@@ -62,21 +62,21 @@
-
+
-
+
-
+
-
+
From 7347e527a7140f912e6c5ccb3d01a1320097a3ac Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:02:43 +0800
Subject: [PATCH 07/17] =?UTF-8?q?Revert=20"=E4=BF=AE=E6=94=B9URL=E5=9C=B0?=
=?UTF-8?q?=E5=9D=80"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 5caad4d0ffa69db64530d1ab97dc8404d20e5b5d.
---
YLErpWeb/App_Data/Menus.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/YLErpWeb/App_Data/Menus.txt b/YLErpWeb/App_Data/Menus.txt
index 506f2a79..7b460406 100644
--- a/YLErpWeb/App_Data/Menus.txt
+++ b/YLErpWeb/App_Data/Menus.txt
@@ -25,7 +25,7 @@
{Name:"资金监控",Rights:["风险控制-资金监控"],Url:"client/clientRiskMonitor"},
{Name:"市场风险",Rights:["风险控制-市场风险"],Url:"risk/RiskExposureReport"},
{Name:"限额监控",Rights:["风险控制-限额监控"],Url:"risk/quotaMonitor"},
- {Name:"异常交易监控",Rights:["风险控制-异常交易监控"],Url:"v3/risk/risk-engine-config"},
+ {Name:"异常交易监控",Rights:["风险控制-异常交易监控"],Url:"v3//risk/risk-engine-config"},
{Name:"白名单券池",Rights:["风险控制-白名单券池"],Url:"v3/data/underlying-pool"},
{Name:"日终持仓风险",Rights:["风险控制-日终持仓风险"],Url:"trade/EodPositionRisks"},
{Name:"日终持仓风险_互换",Rights:["风险控制-日终持仓风险_互换"],Url:"swaptrade2/EodPositionRisks"},
From d1804710f3288548943d367edb77befee62deda2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:02:49 +0800
Subject: [PATCH 08/17] =?UTF-8?q?Revert=20"=E4=BC=98=E5=8C=96=E5=AD=97?=
=?UTF-8?q?=E6=AE=B5=E7=B1=BB=E5=9E=8B"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 10b08f8f211844d1ff8b936596ab65a3760cb3e5.
---
.../Modules/RiskEngine/RiskEngineService.cs | 2 +-
YLErpDAL/Modules/RiskEngine/RiskRule.cs | 2 +-
.../Modules/RiskEngine/RiskRuleApplication.cs | 2 +-
.../Modules/RiskEngine/RiskRuleService.cs | 103 +++++++++++-------
4 files changed, 67 insertions(+), 42 deletions(-)
diff --git a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
index 2e0e68a8..3d040b9f 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
@@ -157,7 +157,7 @@ namespace YLErp.Modules.RiskEngine
var rules = LoadRulesFromDb();
var applications = LoadApplicationsFromDb();
- List res = new List();
+ List res = new List();
foreach(var i in applications)
{
if(i.Status!= RiskRuleStatus.Active)
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRule.cs b/YLErpDAL/Modules/RiskEngine/RiskRule.cs
index bc6c6910..5558c2b4 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRule.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRule.cs
@@ -10,7 +10,7 @@ namespace YLErp.Modules.RiskEngine
public class RiskRule
{
// === 基础信息 ===
- public long Id { get; set; }
+ public int Id { get; set; }
public string RuleName { get; set; }
public string RuleText { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs
index 68219350..9e186dbf 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs
@@ -25,7 +25,7 @@ namespace YLErp.Modules.RiskEngine
/// 应用配置主键ID。
/// 用于唯一标识一条规则应用记录。
///
- public long Id { get; set; }
+ public int Id { get; set; }
///
/// 关联的规则ID列表。
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
index 7e79f074..d8f1316f 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
@@ -534,41 +534,6 @@ namespace YLErp.Modules.RiskEngine
return string.Join(", ", names);
}
- ///
- /// 构建 Scope 字段的 OR 过滤谓词(逗号分隔值精确匹配)
- ///
- private static IQueryable ApplyScopeFilter(
- IQueryable query,
- Expression> fieldSelector,
- string csvValues)
- {
- var ids = csvValues.Split(',', StringSplitOptions.RemoveEmptyEntries);
- if (ids.Length == 0)
- return query;
-
- Expression> predicate = null;
- var param = fieldSelector.Parameters[0];
- var member = fieldSelector.Body;
-
- foreach (var trimmed in ids.Select(id => id.Trim()))
- {
- var eq = Expression.Equal(member, Expression.Constant(trimmed));
- var startsExpr = Expression.Call(member, nameof(string.StartsWith), null,
- Expression.Constant(trimmed + ","));
- var endsExpr = Expression.Call(member, nameof(string.EndsWith), null,
- Expression.Constant("," + trimmed));
- var containsExpr = Expression.Call(member, nameof(string.Contains), null,
- Expression.Constant("," + trimmed + ","));
-
- var orExpr = Expression.OrElse(Expression.OrElse(eq, startsExpr),
- Expression.OrElse(endsExpr, containsExpr));
- var lambda = Expression.Lambda>(orExpr, param);
- predicate = predicate == null ? lambda : predicate.Or(lambda);
- }
-
- return predicate != null ? query.Where(predicate) : query;
- }
-
private static string GetStrategyName(RiskControlStrategy strategy)
{
return strategy switch
@@ -965,16 +930,76 @@ namespace YLErp.Modules.RiskEngine
}
if (!string.IsNullOrWhiteSpace(req.ScopeClientIds))
- query = ApplyScopeFilter(query, a => a.ScopeClientIds, req.ScopeClientIds);
+ {
+ var ids = req.ScopeClientIds.Split(',', StringSplitOptions.RemoveEmptyEntries);
+ Expression> scopePredicate = null;
+ foreach (var id in ids)
+ {
+ var idCopy = id;
+ Expression> expr = a =>
+ a.ScopeClientIds == idCopy ||
+ a.ScopeClientIds.StartsWith(idCopy + ",") ||
+ a.ScopeClientIds.EndsWith("," + idCopy) ||
+ a.ScopeClientIds.Contains("," + idCopy + ",");
+ scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
+ }
+ if (scopePredicate != null)
+ query = query.Where(scopePredicate);
+ }
if (!string.IsNullOrWhiteSpace(req.ScopeUnderlyingTypes))
- query = ApplyScopeFilter(query, a => a.ScopeUnderlyingTypes, req.ScopeUnderlyingTypes);
+ {
+ var types = req.ScopeUnderlyingTypes.Split(',', StringSplitOptions.RemoveEmptyEntries);
+ Expression> scopePredicate = null;
+ foreach (var type in types)
+ {
+ var typeCopy = type;
+ Expression> expr = a =>
+ a.ScopeUnderlyingTypes == typeCopy ||
+ a.ScopeUnderlyingTypes.StartsWith(typeCopy + ",") ||
+ a.ScopeUnderlyingTypes.EndsWith("," + typeCopy) ||
+ a.ScopeUnderlyingTypes.Contains("," + typeCopy + ",");
+ scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
+ }
+ if (scopePredicate != null)
+ query = query.Where(scopePredicate);
+ }
if (!string.IsNullOrWhiteSpace(req.ScopeTradeTypes))
- query = ApplyScopeFilter(query, a => a.ScopeTradeTypes, req.ScopeTradeTypes);
+ {
+ var types = req.ScopeTradeTypes.Split(',', StringSplitOptions.RemoveEmptyEntries);
+ Expression> scopePredicate = null;
+ foreach (var type in types)
+ {
+ var typeCopy = type;
+ Expression> expr = a =>
+ a.ScopeTradeTypes == typeCopy ||
+ a.ScopeTradeTypes.StartsWith(typeCopy + ",") ||
+ a.ScopeTradeTypes.EndsWith("," + typeCopy) ||
+ a.ScopeTradeTypes.Contains("," + typeCopy + ",");
+ scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
+ }
+ if (scopePredicate != null)
+ query = query.Where(scopePredicate);
+ }
if (!string.IsNullOrWhiteSpace(req.ScopeAssetBookIds))
- query = ApplyScopeFilter(query, a => a.ScopeAssetBookIds, req.ScopeAssetBookIds);
+ {
+ var ids = req.ScopeAssetBookIds.Split(',', StringSplitOptions.RemoveEmptyEntries);
+ Expression> scopePredicate = null;
+ foreach (var id in ids)
+ {
+ var idCopy = id;
+ Expression> expr = a =>
+ a.ScopeAssetBookIds == idCopy ||
+ a.ScopeAssetBookIds.StartsWith(idCopy + ",") ||
+ a.ScopeAssetBookIds.EndsWith("," + idCopy) ||
+ a.ScopeAssetBookIds.Contains("," + idCopy + ",");
+ scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
+ }
+ if (scopePredicate != null)
+ query = query.Where(scopePredicate);
+ }
var pagedResult = query.OrderByDescending(a => a.UpdateDate)
.Select(a => new RiskApplicationListItem
From dae112d1999904e0772d27877f01730d66501e77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:02:49 +0800
Subject: [PATCH 09/17] =?UTF-8?q?Revert=20"fix(risk-engine):=20=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E5=A4=9A=E4=B8=AA=E9=A3=8E=E6=8E=A7=E5=BC=95=E6=93=8E?=
=?UTF-8?q?=E9=97=AE=E9=A2=98"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit d7c09c793a488cec9699746fa0ce7d17ff040a81.
---
.../DBModels/glms_risk_rule_application.cs | 2 +-
.../DbUpdate/Ver-5.6.0/seed_rules.sql | 7 +-
.../RiskEngine/Compile/RuleCompiler.cs | 7 -
.../Dto/CreateRiskApplicationReq.cs | 2 +-
.../RiskEngine/Dto/QueryRiskApplicationReq.cs | 4 -
.../RiskEngine/Dto/QueryRiskVariableReq.cs | 1 -
.../RiskEngine/Dto/RiskApplicationDetail.cs | 2 +-
.../RiskEngine/Dto/RiskApplicationListItem.cs | 4 +-
.../Modules/RiskEngine/Dto/RuleCondition.cs | 3 -
.../Dto/UpdateRiskApplicationReq.cs | 2 +-
.../Modules/RiskEngine/RiskEngineService.cs | 2 +-
.../Modules/RiskEngine/RiskRuleApplication.cs | 2 +-
.../Modules/RiskEngine/RiskRuleService.cs | 161 ++----------------
YLErpWeb/App_Data/Menus.txt | 1 -
14 files changed, 27 insertions(+), 173 deletions(-)
diff --git a/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs b/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
index a1d577ac..aa5dbb6a 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
@@ -13,7 +13,7 @@ namespace YLErp.DBModels
public string ScopeClientIds { get; set; }
public string ScopeUnderlyingTypes { get; set; }
public string ScopeTradeTypes { get; set; }
- public int ScopeIsGlobal { get; set; }
+ public bool ScopeIsGlobal { get; set; }
public int Version { get; set; } = 1;
public int? UpdateOptId { get; set; }
public string UpdateOptName { get; set; }
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
index 9751a1d9..45a17cb9 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
@@ -50,7 +50,7 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
'挂钩标的到期日早于合约到期日时禁止交易',
JSON_ARRAY(JSON_OBJECT(
'VariableId', 22,
- 'Operator', '早于', 'ThresholdType', 'Variable',
+ 'Operator', '<', 'ThresholdType', 'Variable',
'ThresholdVariableId', 3
)),
'market.UnderlyingMaturityDate < trade.ExerciseDate',
@@ -87,8 +87,7 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
'保证金利率不在配置区间内(默认2%~5%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
'VariableId', 12,
- 'Operator', '不介于', 'ThresholdType', 'Fixed', 'Value', JSON_ARRAY(2, 5),
- 'IncludeLowerBound', true, 'IncludeUpperBound', true
+ 'Operator', '不介于', 'ThresholdType', 'Fixed', 'Value', JSON_ARRAY(2, 5)
)),
'!(client_marginrate.InitMarginRebateRate >= 2 && client_marginrate.InitMarginRebateRate <= 5)',
1, 1, 0, 'SYSTEM', NOW());
@@ -113,7 +112,7 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
'合约起息日早于当前日期时触发审批',
JSON_ARRAY(JSON_OBJECT(
'VariableId', 2,
- 'Operator', '早于', 'ThresholdType', 'Variable',
+ 'Operator', '<', 'ThresholdType', 'Variable',
'ThresholdVariableId', 21
)),
'trade.StartDate < sys.CurrentDate',
diff --git a/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs b/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs
index 85875f15..0d2f778f 100644
--- a/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs
+++ b/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs
@@ -304,19 +304,12 @@ namespace YLErp.Modules.RiskEngine
{
return op?.Trim() switch
{
- // 数值型 C# 符号
"=" or "==" => "==",
"!=" or "≠" => "!=",
">" => ">",
"<" => "<",
">=" => ">=",
"<=" => "<=",
- // 日期型中文语义 → C# 符号
- "早于" => "<",
- "晚于" => ">",
- "等于" => "==",
- "不早于" => ">=",
- "不晚于" => "<=",
_ => throw new ArgumentException($"不支持的操作符:{op}")
};
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs
index 65e939c4..f50d4f36 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/CreateRiskApplicationReq.cs
@@ -11,6 +11,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ScopeClientIds { get; set; }
public string ScopeUnderlyingTypes { get; set; }
public string ScopeTradeTypes { get; set; }
- public int ScopeIsGlobal { get; set; }
+ public bool ScopeIsGlobal { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs
index eec45ca7..bd494ed8 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs
@@ -9,9 +9,5 @@ namespace YLErp.Modules.RiskEngine.Dto
public RiskRuleStatus? Status { get; set; }
public RiskControlStrategy? Strategy { get; set; }
public string TriggerPoint { get; set; }
- public string ScopeClientIds { get; set; }
- public string ScopeUnderlyingTypes { get; set; }
- public string ScopeTradeTypes { get; set; }
- public string ScopeAssetBookIds { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs
index 9b8f39bd..639d9b3d 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs
@@ -6,7 +6,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public class QueryRiskVariableReq : BaseSearchReq
{
public RiskVariableCategory? Category { get; set; }
- public RiskVariableDataType? DataType { get; set; }
public string VariableName { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
index cb76b20c..52824a0d 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
@@ -14,7 +14,7 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ScopeClientIds { get; set; }
public string ScopeUnderlyingTypes { get; set; }
public string ScopeTradeTypes { get; set; }
- public int ScopeIsGlobal { get; set; }
+ public bool ScopeIsGlobal { get; set; }
public int Version { get; set; }
public string OptName { get; set; }
public DateTime OptDate { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
index 466b1d94..fcaaf7df 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
@@ -7,14 +7,14 @@ namespace YLErp.Modules.RiskEngine.Dto
{
public long Id { get; set; }
public string RuleIds { get; set; }
- public int Status { get; set; }
+ public RiskRuleStatus Status { get; set; }
public RiskControlStrategy ControlStrategy { get; set; }
public string TriggerPoints { get; set; }
public string ScopeAssetBookIds { get; set; }
public string ScopeClientIds { get; set; }
public string ScopeUnderlyingTypes { get; set; }
public string ScopeTradeTypes { get; set; }
- public int ScopeIsGlobal { get; set; }
+ public bool ScopeIsGlobal { get; set; }
public int Version { get; set; }
public string OptName { get; set; }
public DateTime OptDate { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs b/YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs
index d1e459ff..81facae9 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs
@@ -7,8 +7,5 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ThresholdType { get; set; }
public object Value { get; set; }
public long? ThresholdVariableId { get; set; }
- // 介于/不介于 的边界包含控制,默认 true
- public bool IncludeLowerBound { get; set; } = true;
- public bool IncludeUpperBound { get; set; } = true;
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
index aa290529..b9af55a9 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
@@ -11,7 +11,7 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ScopeClientIds { get; set; }
public string ScopeUnderlyingTypes { get; set; }
public string ScopeTradeTypes { get; set; }
- public int ScopeIsGlobal { get; set; }
+ public bool ScopeIsGlobal { get; set; }
public int Version { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
index 3d040b9f..845149d3 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
@@ -534,7 +534,7 @@ namespace YLErp.Modules.RiskEngine
return false;
}
- if (application.ScopeIsGlobal == 1)
+ if (application.ScopeIsGlobal)
{
return true;
}
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs
index 9e186dbf..7b741252 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleApplication.cs
@@ -67,7 +67,7 @@ namespace YLErp.Modules.RiskEngine
/// true 表示对所有交易都适用,此时通常忽略其他 Scope 字段;
/// false 表示只在指定范围内适用,需要结合下方各 Scope 字段进行过滤。
///
- public int ScopeIsGlobal { get; set; }
+ public bool ScopeIsGlobal { get; set; }
///
/// 适用的资产簿记账户范围。
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
index d8f1316f..4e082af5 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
@@ -1,7 +1,6 @@
using BaseOUDAL;
using Newtonsoft.Json;
using Qdp.Foundation.Utilities;
-using System.Linq.Expressions;
using YLErp.BLL;
using YLErp.DBModels;
using YLErp.Model;
@@ -203,7 +202,7 @@ namespace YLErp.Modules.RiskEngine
private static readonly Dictionary> ValidOperatorsByType = new Dictionary>
{
{ RiskVariableDataType.Numeric, new HashSet { ">", "<", ">=", "<=", "=", "≠", "介于", "不介于" } },
- { RiskVariableDataType.Date, new HashSet { "早于", "晚于", "等于", "不早于", "不晚于", "介于", "不介于" } },
+ { RiskVariableDataType.Date, new HashSet { "<", ">", "=", ">=", "<=", "介于", "不介于" } },
{ RiskVariableDataType.Boolean, new HashSet { "是", "否" } }
};
@@ -292,35 +291,15 @@ namespace YLErp.Modules.RiskEngine
{
if (cond.Value == null)
throw new ServiceException($"{condLabel}:固定阈值不能为空");
-
- if (cond.Operator == "介于" || cond.Operator == "不介于")
+ if (variableDef.DataType == RiskVariableDataType.Numeric)
{
- // 介于/不介于:Value 必须为双元素数组 [下限, 上限]
- if (!(cond.Value is Newtonsoft.Json.Linq.JArray arr && arr.Count == 2))
- throw new ServiceException($"{condLabel}:操作符 '{cond.Operator}' 的阈值必须为双元素数组 [下限, 上限]");
- if (variableDef.DataType == RiskVariableDataType.Numeric)
- {
- if (!decimal.TryParse(arr[0].ToString(), out _) || !decimal.TryParse(arr[1].ToString(), out _))
- throw new ServiceException($"{condLabel}:数值型介于/不介于的下限和上限必须为数字");
- }
- if (variableDef.DataType == RiskVariableDataType.Date)
- {
- if (!DateTime.TryParse(arr[0].ToString(), out _) || !DateTime.TryParse(arr[1].ToString(), out _))
- throw new ServiceException($"{condLabel}:日期型介于/不介于的起始和结束日期必须为合法日期");
- }
+ if (!decimal.TryParse(cond.Value.ToString(), out _))
+ throw new ServiceException($"{condLabel}:数值型变量的阈值必须为数字");
}
- else
+ if (variableDef.DataType == RiskVariableDataType.Date)
{
- if (variableDef.DataType == RiskVariableDataType.Numeric)
- {
- if (!decimal.TryParse(cond.Value.ToString(), out _))
- throw new ServiceException($"{condLabel}:数值型变量的阈值必须为数字");
- }
- if (variableDef.DataType == RiskVariableDataType.Date)
- {
- if (!DateTime.TryParse(cond.Value.ToString(), out _))
- throw new ServiceException($"{condLabel}:日期型变量的阈值必须为合法日期");
- }
+ if (!DateTime.TryParse(cond.Value.ToString(), out _))
+ throw new ServiceException($"{condLabel}:日期型变量的阈值必须为合法日期");
}
}
else if (cond.ThresholdType == "Variable")
@@ -377,7 +356,7 @@ namespace YLErp.Modules.RiskEngine
private void ValidateScopeFields(CreateRiskApplicationReq req)
{
- if (req.ScopeIsGlobal == 1)
+ if (req.ScopeIsGlobal)
{
if (!string.IsNullOrEmpty(req.ScopeAssetBookIds) ||
!string.IsNullOrEmpty(req.ScopeClientIds) ||
@@ -534,36 +513,6 @@ namespace YLErp.Modules.RiskEngine
return string.Join(", ", names);
}
- private static string GetStrategyName(RiskControlStrategy strategy)
- {
- return strategy switch
- {
- RiskControlStrategy.Block => "阻断",
- RiskControlStrategy.Approval => "审批",
- RiskControlStrategy.ShowTip => "提醒",
- _ => strategy.ToString()
- };
- }
-
- private static readonly Dictionary TriggerPointCnMap = new Dictionary
- {
- ["BOOK_CONFIRM"] = "交易录入确认",
- ["CLOSE_REVIEW"] = "平仓审核",
- ["UPLOAD_CONFIRMATION"] = "上传确认书",
- ["EVENT_TRIGGER"] = "事件触发",
- ["FUND_PAYMENT"] = "资金支付"
- };
-
- private static string MapTriggerPointsToChinese(string triggerPoints)
- {
- if (string.IsNullOrWhiteSpace(triggerPoints))
- return "";
-
- var parts = triggerPoints.Split(',');
- var translated = parts.Select(p => TriggerPointCnMap.TryGetValue(p.Trim(), out var cn) ? cn : p.Trim());
- return string.Join(", ", translated);
- }
-
#endregion
#region Rule Management
@@ -864,7 +813,7 @@ namespace YLErp.Modules.RiskEngine
{
Id = app.id,
RuleIds = app.RuleIds,
- Status = (int)app.Status,
+ Status = app.Status,
ControlStrategy = app.ControlStrategy,
TriggerPoints = app.TriggerPoints,
ScopeAssetBookIds = app.ScopeAssetBookIds,
@@ -929,84 +878,12 @@ namespace YLErp.Modules.RiskEngine
&& r.RuleName.Contains(req.RuleName)));
}
- if (!string.IsNullOrWhiteSpace(req.ScopeClientIds))
- {
- var ids = req.ScopeClientIds.Split(',', StringSplitOptions.RemoveEmptyEntries);
- Expression> scopePredicate = null;
- foreach (var id in ids)
- {
- var idCopy = id;
- Expression> expr = a =>
- a.ScopeClientIds == idCopy ||
- a.ScopeClientIds.StartsWith(idCopy + ",") ||
- a.ScopeClientIds.EndsWith("," + idCopy) ||
- a.ScopeClientIds.Contains("," + idCopy + ",");
- scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
- }
- if (scopePredicate != null)
- query = query.Where(scopePredicate);
- }
-
- if (!string.IsNullOrWhiteSpace(req.ScopeUnderlyingTypes))
- {
- var types = req.ScopeUnderlyingTypes.Split(',', StringSplitOptions.RemoveEmptyEntries);
- Expression> scopePredicate = null;
- foreach (var type in types)
- {
- var typeCopy = type;
- Expression> expr = a =>
- a.ScopeUnderlyingTypes == typeCopy ||
- a.ScopeUnderlyingTypes.StartsWith(typeCopy + ",") ||
- a.ScopeUnderlyingTypes.EndsWith("," + typeCopy) ||
- a.ScopeUnderlyingTypes.Contains("," + typeCopy + ",");
- scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
- }
- if (scopePredicate != null)
- query = query.Where(scopePredicate);
- }
-
- if (!string.IsNullOrWhiteSpace(req.ScopeTradeTypes))
- {
- var types = req.ScopeTradeTypes.Split(',', StringSplitOptions.RemoveEmptyEntries);
- Expression> scopePredicate = null;
- foreach (var type in types)
- {
- var typeCopy = type;
- Expression> expr = a =>
- a.ScopeTradeTypes == typeCopy ||
- a.ScopeTradeTypes.StartsWith(typeCopy + ",") ||
- a.ScopeTradeTypes.EndsWith("," + typeCopy) ||
- a.ScopeTradeTypes.Contains("," + typeCopy + ",");
- scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
- }
- if (scopePredicate != null)
- query = query.Where(scopePredicate);
- }
-
- if (!string.IsNullOrWhiteSpace(req.ScopeAssetBookIds))
- {
- var ids = req.ScopeAssetBookIds.Split(',', StringSplitOptions.RemoveEmptyEntries);
- Expression> scopePredicate = null;
- foreach (var id in ids)
- {
- var idCopy = id;
- Expression> expr = a =>
- a.ScopeAssetBookIds == idCopy ||
- a.ScopeAssetBookIds.StartsWith(idCopy + ",") ||
- a.ScopeAssetBookIds.EndsWith("," + idCopy) ||
- a.ScopeAssetBookIds.Contains("," + idCopy + ",");
- scopePredicate = scopePredicate == null ? expr : scopePredicate.Or(expr);
- }
- if (scopePredicate != null)
- query = query.Where(scopePredicate);
- }
-
var pagedResult = query.OrderByDescending(a => a.UpdateDate)
.Select(a => new RiskApplicationListItem
{
Id = a.id,
RuleIds = a.RuleIds,
- Status = (int)a.Status,
+ Status = a.Status,
ControlStrategy = a.ControlStrategy,
TriggerPoints = a.TriggerPoints,
ScopeAssetBookIds = a.ScopeAssetBookIds,
@@ -1085,7 +962,7 @@ namespace YLErp.Modules.RiskEngine
DbContext.SaveChanges();
WriteAuditLog("APP_CREATE", "APPLICATION", entity.id, ResolveRuleNames(req.RuleIds),
- $"创建应用配置:策略={GetStrategyName(req.ControlStrategy)}, 触发时点={MapTriggerPointsToChinese(req.TriggerPoints)}",
+ $"创建应用配置:策略={req.ControlStrategy}, 触发时点={req.TriggerPoints}",
snapshotData: JsonConvert.SerializeObject(new { Version = entity.Version }));
DbContext.SaveChanges();
@@ -1139,7 +1016,7 @@ namespace YLErp.Modules.RiskEngine
app.UpdateDate = DateTime.Now;
WriteAuditLog("APP_UPDATE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds),
- $"修改应用配置:策略={GetStrategyName(req.ControlStrategy)}, 触发时点={MapTriggerPointsToChinese(req.TriggerPoints)}");
+ $"修改应用配置:策略={req.ControlStrategy}, 触发时点={req.TriggerPoints}");
DbContext.SaveChanges();
TryRefreshCache();
@@ -1157,7 +1034,7 @@ namespace YLErp.Modules.RiskEngine
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
- WriteAuditLog("APP_DELETE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "删除应用配置");
+ WriteAuditLog("APPLICATION_DELETE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "删除应用配置");
DbContext.SaveChanges();
TryRefreshCache();
@@ -1250,7 +1127,7 @@ namespace YLErp.Modules.RiskEngine
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
- WriteAuditLog("APP_BATCH_DISABLE", "APPLICATION", app.id, ResolveRuleNames(app.RuleIds), "批量停用应用配置");
+ WriteAuditLog("APPLICATION_BATCH_DISABLE", "APPLICATION", app.id, ResolveRuleNames(app.RuleIds), "批量停用应用配置");
}
DbContext.SaveChanges();
@@ -1277,11 +1154,6 @@ namespace YLErp.Modules.RiskEngine
query = query.Where(v => v.Category == req.Category.Value);
}
- if (req.DataType.HasValue)
- {
- query = query.Where(v => v.DataType == req.DataType.Value);
- }
-
if (!string.IsNullOrWhiteSpace(req.VariableName))
{
query = query.Where(v => v.VariableName.Contains(req.VariableName));
@@ -1493,13 +1365,12 @@ namespace YLErp.Modules.RiskEngine
if (req.StartDate.HasValue)
{
- query = query.Where(l => l.OptDate >= req.StartDate.Value.Date);
+ query = query.Where(l => l.OptDate >= req.StartDate.Value);
}
if (req.EndDate.HasValue)
{
- var end = req.EndDate.Value.Date.AddDays(1);
- query = query.Where(l => l.OptDate < end);
+ query = query.Where(l => l.OptDate <= req.EndDate.Value);
}
if (!string.IsNullOrWhiteSpace(req.Keyword))
diff --git a/YLErpWeb/App_Data/Menus.txt b/YLErpWeb/App_Data/Menus.txt
index 7b460406..a8aea562 100644
--- a/YLErpWeb/App_Data/Menus.txt
+++ b/YLErpWeb/App_Data/Menus.txt
@@ -25,7 +25,6 @@
{Name:"资金监控",Rights:["风险控制-资金监控"],Url:"client/clientRiskMonitor"},
{Name:"市场风险",Rights:["风险控制-市场风险"],Url:"risk/RiskExposureReport"},
{Name:"限额监控",Rights:["风险控制-限额监控"],Url:"risk/quotaMonitor"},
- {Name:"异常交易监控",Rights:["风险控制-异常交易监控"],Url:"v3//risk/risk-engine-config"},
{Name:"白名单券池",Rights:["风险控制-白名单券池"],Url:"v3/data/underlying-pool"},
{Name:"日终持仓风险",Rights:["风险控制-日终持仓风险"],Url:"trade/EodPositionRisks"},
{Name:"日终持仓风险_互换",Rights:["风险控制-日终持仓风险_互换"],Url:"swaptrade2/EodPositionRisks"},
From d0e6b31d5cd376827b72b614a4a24e86fac6976f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:05:38 +0800
Subject: [PATCH 10/17] =?UTF-8?q?Revert=20"=E4=BC=98=E5=8C=96=E8=B0=83?=
=?UTF-8?q?=E6=95=B4=E8=A7=84=E5=88=99=E7=AE=A1=E7=90=86"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit e8ef5be86275cea8ce56dd8d1c8c4fb4134f5c3c.
---
.../DbUpdate/Ver-5.6.0/seed_applications.sql | 86 +++++++++----------
.../RiskEngine/Dto/RiskApplicationDetail.cs | 3 +
.../RiskEngine/Dto/RiskApplicationListItem.cs | 2 +
.../Modules/RiskEngine/RiskRuleService.cs | 76 ++++++++++++++--
YLErpWeb/Controllers/RiskRuleController.cs | 36 +-------
5 files changed, 122 insertions(+), 81 deletions(-)
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql
index 4573b7d0..8c3cf942 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql
@@ -5,131 +5,131 @@
-- 每条规则对应一条应用配置(1:1),定义"何时、对谁、怎么处理"
-- ControlStrategy: 1=Block(禁止), 2=Approval(审批), 3=Warning(提示)
-- TriggerPoints: BOOK_CONFIRM=簿记交易确认
--- ScopeIsGlobal: 1=全局适用, 0=按维度配置(Scope字段为NULL表示"全部")
+-- ScopeIsGlobal: 1=全局适用, 0=按维度配置(Scope字段为空表示"全部")
-- ============================================================
-- 规则1:挂钩标的集中度超阈值(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '挂钩标的集中度超阈值';
-- 规则2:挂钩标的到期日小于合约到期日(禁止,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '挂钩标的到期日小于合约到期日';
-- 规则3:名义本金超阈值(审批,账户/合约类型)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '名义本金超阈值';
-- 规则4:保证金支付比例超阈值(审批,账户/标的类型)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '保证金支付比例超阈值';
-- 规则5:保证金利率偏离(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '保证金利率偏离';
-- 规则6:保证金收取比例低于最低标准(审批,账户/标的类型)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '保证金收取比例低于最低标准';
-- 规则7:起息日早于当前日期(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '起息日早于当前日期';
-- 规则8:支付日为银行间交易日(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '支付日为银行间交易日';
-- 规则9:到期日为银行间交易日(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '到期日为银行间交易日';
-- 规则10:平仓日为银行间交易日(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '平仓日为银行间交易日';
-- 规则11:合约期限超阈值(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '合约期限超阈值';
-- 规则12:债券类净价偏离(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '债券类净价偏离';
-- 规则13:债券类收益率偏离(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '债券类收益率偏离';
-- 规则14:非债券类价格偏离(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '非债券类价格偏离';
-- 规则15:单一交易对手累计标的数量超阈值(审批,对手方)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '单一交易对手累计标的数量超阈值';
-- 规则16:多头支付固定端利率偏离(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '多头支付固定端利率偏离';
-- 规则17:空头利率减点借贷加权偏离(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '空头利率减点借贷加权偏离';
-- 规则18:账户授权收支方向不匹配(禁止,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '账户授权收支方向不匹配';
-- 规则19:执行价偏离超阈值(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '执行价偏离超阈值';
-- 规则20:希腊字母限额超阈值(提示,账户/标的,预留接口)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 0, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '希腊字母限额超阈值';
-- 规则21:接近/触发敲入敲出价(提示,全局,预留接口)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeAssetBookIds`, `ScopeClientIds`, `ScopeUnderlyingTypes`, `ScopeTradeTypes`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
+INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
SELECT
- CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', NULL, NULL, NULL, NULL, 1, 1, 0, 'SYSTEM', NOW()
+ CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
FROM `glms_risk_rule` r WHERE r.RuleName = '接近/触发敲入敲出价';
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
index 52824a0d..fd9f4d77 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationDetail.cs
@@ -7,6 +7,9 @@ namespace YLErp.Modules.RiskEngine.Dto
{
public long Id { get; set; }
public string RuleIds { get; set; }
+ public string RuleName { get; set; }
+ public string ConditionJson { get; set; }
+ public string RuleNames { get; set; }
public RiskRuleStatus Status { get; set; }
public RiskControlStrategy ControlStrategy { get; set; }
public string TriggerPoints { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
index fcaaf7df..25bb7f2e 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskApplicationListItem.cs
@@ -7,6 +7,8 @@ namespace YLErp.Modules.RiskEngine.Dto
{
public long Id { get; set; }
public string RuleIds { get; set; }
+ public string RuleName { get; set; }
+ public string RuleNames { get; set; }
public RiskRuleStatus Status { get; set; }
public RiskControlStrategy ControlStrategy { get; set; }
public string TriggerPoints { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
index 4e082af5..8767bfc4 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
@@ -813,6 +813,7 @@ namespace YLErp.Modules.RiskEngine
{
Id = app.id,
RuleIds = app.RuleIds,
+ RuleNames = ResolveRuleNames(app.RuleIds),
Status = app.Status,
ControlStrategy = app.ControlStrategy,
TriggerPoints = app.TriggerPoints,
@@ -878,11 +879,55 @@ namespace YLErp.Modules.RiskEngine
&& r.RuleName.Contains(req.RuleName)));
}
- var pagedResult = query.OrderByDescending(a => a.UpdateDate)
- .Select(a => new RiskApplicationListItem
+ var pagedApps = query.OrderByDescending(a => a.UpdateDate)
+ .Select(a => new
+ {
+ a.id,
+ a.RuleIds,
+ a.Status,
+ a.ControlStrategy,
+ a.TriggerPoints,
+ a.ScopeAssetBookIds,
+ a.ScopeClientIds,
+ a.ScopeUnderlyingTypes,
+ a.ScopeTradeTypes,
+ a.ScopeIsGlobal,
+ a.Version,
+ a.OptName,
+ a.OptDate,
+ a.UpdateOptName,
+ a.UpdateDate
+ });
+
+ var pagedResult = pagedApps.ToSearchList(req);
+
+ var allRuleIds = pagedResult.rows
+ .SelectMany(a => a.RuleIds.Split(','))
+ .Select(s => long.TryParse(s.Trim(), out long id) ? id : (long?)null)
+ .Where(id => id.HasValue)
+ .Select(id => id.Value)
+ .Distinct()
+ .ToList();
+
+ var ruleMap = allRuleIds.Count > 0
+ ? DbContext.glms_risk_rule
+ .Where(r => allRuleIds.Contains(r.id) && r.Status != RiskRuleStatus.Deleted)
+ .ToDictionary(r => (long)r.id, r => r.RuleName)
+ : new Dictionary();
+
+ var resultList = pagedResult.rows.Select(a =>
+ {
+ var names = a.RuleIds.Split(',')
+ .Select(s => long.TryParse(s.Trim(), out long id) ? id : (long?)null)
+ .Where(id => id.HasValue)
+ .Select(id => ruleMap.ContainsKey(id.Value) ? ruleMap[id.Value] : null)
+ .Where(n => n != null);
+
+ return new RiskApplicationListItem
{
Id = a.id,
RuleIds = a.RuleIds,
+ RuleNames = string.Join(", ", names),
Status = a.Status,
ControlStrategy = a.ControlStrategy,
TriggerPoints = a.TriggerPoints,
@@ -896,10 +941,16 @@ namespace YLErp.Modules.RiskEngine
OptDate = a.OptDate.GetValueOrDefault(),
UpdateOptName = a.UpdateOptName,
UpdateDate = a.UpdateDate ?? a.OptDate.GetValueOrDefault()
- })
- .ToSearchList(req);
+ };
+ }).ToList();
- return pagedResult;
+ return new SearchListResult
+ {
+ rows = resultList,
+ records = pagedResult.records,
+ total = pagedResult.total,
+ page = pagedResult.page
+ };
}
public RiskApplicationDetail GetApplicationDetail(long applicationId)
@@ -909,10 +960,25 @@ namespace YLErp.Modules.RiskEngine
if (app == null)
throw new ServiceException("应用配置不存在或已删除");
+ var ruleIds = app.RuleIds.Split(',')
+ .Select(s => long.TryParse(s.Trim(), out long id) ? id : (long?)null)
+ .Where(id => id.HasValue)
+ .Select(id => id.Value)
+ .ToList();
+
+ var rules = DbContext.glms_risk_rule
+ .Where(r => ruleIds.Contains(r.id) && r.Status != RiskRuleStatus.Deleted)
+ .ToList();
+
+ var ruleNames = string.Join(", ", rules.Select(r => r.RuleName));
+ var firstRule = rules.FirstOrDefault();
+
return new RiskApplicationDetail
{
Id = app.id,
RuleIds = app.RuleIds,
+ RuleNames = ruleNames,
+ ConditionJson = firstRule?.ConditionJson,
Status = app.Status,
ControlStrategy = app.ControlStrategy,
TriggerPoints = app.TriggerPoints,
diff --git a/YLErpWeb/Controllers/RiskRuleController.cs b/YLErpWeb/Controllers/RiskRuleController.cs
index 55ba98e9..9c97be3e 100644
--- a/YLErpWeb/Controllers/RiskRuleController.cs
+++ b/YLErpWeb/Controllers/RiskRuleController.cs
@@ -1,5 +1,4 @@
using Qdp.Foundation.Utilities;
-using YLErp.DBModels;
using YLErp.Modules.RiskEngine;
using YLErp.Modules.RiskEngine.Dto;
@@ -209,7 +208,7 @@ namespace YLErp.Web.Controllers
{
var service = new RiskRuleService(CurUser);
var result = service.GetRuleApplications(id);
- return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } });
+ return Json(new { success = true, data = result });
}
catch (ServiceException ex)
{
@@ -230,7 +229,7 @@ namespace YLErp.Web.Controllers
{
var service = new RiskRuleService(CurUser);
var result = service.GetAllRuleList();
- return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } });
+ return Json(new { success = true, data = result });
}
catch (ServiceException ex)
{
@@ -490,7 +489,7 @@ namespace YLErp.Web.Controllers
{
var service = new RiskRuleService(CurUser);
var result = service.GetAllVariableList();
- return Json(new { success = true, data = new { rows = result, total = result.Count, records = result.Count, page = 1 } });
+ return Json(new { success = true, data = result });
}
catch (ServiceException ex)
{
@@ -568,35 +567,6 @@ namespace YLErp.Web.Controllers
#endregion
- #region Trade Types
-
- [HttpGet("trade-types")]
- [MyAuthorize("风控应用查看")]
- public JsonResult GetTradeTypes()
- {
- try
- {
- var rows = ConsTrade.AllTradeTypes.Select(t => new { label = t, value = t }).ToList();
- var total = rows.Count;
- return Json(new {
- success = true,
- data = new {
- page = 1,
- records = total,
- rows = rows,
- total = total
- }
- });
- }
- catch (Exception ex)
- {
- _logger.Error(ex, "查询合约类型列表");
- return Json(new { success = false, message = "系统异常,请联系管理员" });
- }
- }
-
- #endregion
-
#region Audit Log
[HttpGet("risk-audit-logs")]
From 75dc6f182b98718e13984d62028c25f2b2d8bc6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:05:40 +0800
Subject: [PATCH 11/17] =?UTF-8?q?Revert=20"refactor(risk-engine):=20Condit?=
=?UTF-8?q?ionJson=20=E6=94=B9=E4=B8=BA=20RuleCondition=20=E6=95=B0?=
=?UTF-8?q?=E7=BB=84=E6=A0=BC=E5=BC=8F=EF=BC=8C=E7=B2=BE=E7=AE=80=20DTO=20?=
=?UTF-8?q?=E5=91=BD=E5=90=8D"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 3bf90e25efbbeaf20af0076b0272086f4d06f4a0.
---
.../DbUpdate/Ver-5.6.0/prod.sql | 2 +-
.../DbUpdate/Ver-5.6.0/seed_rules.sql | 111 ++++++++++--------
.../{RuleCondition.cs => FormulaCondition.cs} | 6 +-
.../RiskEngine/Dto/FormulaDefinition.cs | 10 ++
.../RiskEngine/Dto/RiskRuleSimpleItem.cs | 9 --
.../Modules/RiskEngine/RiskRuleService.cs | 60 +++++-----
YLErpWeb/Controllers/RiskRuleController.cs | 21 ----
7 files changed, 107 insertions(+), 112 deletions(-)
rename YLErpDAL/Modules/RiskEngine/Dto/{RuleCondition.cs => FormulaCondition.cs} (55%)
create mode 100644 YLErpDAL/Modules/RiskEngine/Dto/FormulaDefinition.cs
delete mode 100644 YLErpDAL/Modules/RiskEngine/Dto/RiskRuleSimpleItem.cs
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
index d9642a21..3f266be1 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
@@ -4,7 +4,7 @@ CREATE TABLE `glms_risk_rule` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
`RuleName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '规则名称',
`RuleText` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则文本',
- `ConditionJson` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '条件JSON(结构化模式, RuleCondition数组)',
+ `ConditionJson` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '条件JSON(结构化模式, FormulaCondition数组)',
`RuleExpr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '规则表达式(自由文本模式, 类C#表达式)',
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
index 45a17cb9..33b72018 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
@@ -21,9 +21,6 @@
-- 45=期初净价偏离度 46=期初收益率偏离度 47=期初价格偏离度
-- 48=利息端利率与FR007偏离度 49=利息端利率与借贷加权费率偏离度
-- 50=执行价偏离度 51=执行价 52=客户品种最低保证金率 53=参考价格
---
--- ConditionJson 精简设计:只存 VariableId/Operator/ThresholdType/Value/ThresholdVariableId
--- 展示字段(VariableName/VariableType/Unit/ThresholdVariableName)从变量接口关联获取
-- ============================================================
@@ -37,8 +34,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('挂钩标的集中度超阈值',
'挂钩标的集中度超过阈值(默认30%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 24,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 30
+ 'VariableId', 24, 'VariableName', '挂钩标的集中度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 30,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'calc.UnderlyingConcentration > 30',
1, 1, 0, 'SYSTEM', NOW());
@@ -49,9 +47,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('挂钩标的到期日小于合约到期日',
'挂钩标的到期日早于合约到期日时禁止交易',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 22,
- 'Operator', '<', 'ThresholdType', 'Variable',
- 'ThresholdVariableId', 3
+ 'VariableId', 22, 'VariableName', '挂钩标的到期日', 'VariableType', 'Date',
+ 'Operator', '<', 'ThresholdType', 'variable', 'Value', JSON_TYPE(NULL),
+ 'ThresholdVariableId', 3, 'ThresholdVariableName', '合约到期日', 'Unit', JSON_TYPE(NULL)
)),
'market.UnderlyingMaturityDate < trade.ExerciseDate',
1, 1, 0, 'SYSTEM', NOW());
@@ -62,8 +60,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('名义本金超阈值',
'合约名义本金超过阈值(默认1亿元)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 1,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 100000000
+ 'VariableId', 1, 'VariableName', '合约名义本金', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 100000000,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '元'
)),
'trade.StockEqvNotional > 100000000',
1, 1, 0, 'SYSTEM', NOW());
@@ -74,8 +73,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('保证金支付比例超阈值',
'保证金比例超过阈值(默认50%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 13,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 50
+ 'VariableId', 13, 'VariableName', '保证金比例', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 50,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'trade.MarginRate > 50',
1, 1, 0, 'SYSTEM', NOW());
@@ -86,8 +86,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('保证金利率偏离',
'保证金利率不在配置区间内(默认2%~5%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 12,
- 'Operator', '不介于', 'ThresholdType', 'Fixed', 'Value', JSON_ARRAY(2, 5)
+ 'VariableId', 12, 'VariableName', '保证金利率', 'VariableType', 'Numeric',
+ 'Operator', '不介于', 'ThresholdType', 'fixed', 'Value', JSON_ARRAY(2, 5),
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'!(client_marginrate.InitMarginRebateRate >= 2 && client_marginrate.InitMarginRebateRate <= 5)',
1, 1, 0, 'SYSTEM', NOW());
@@ -98,9 +99,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('保证金收取比例低于最低标准',
'保证金比例低于客户品种最低保证金率时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 13,
- 'Operator', '<', 'ThresholdType', 'Variable',
- 'ThresholdVariableId', 52
+ 'VariableId', 13, 'VariableName', '保证金比例', 'VariableType', 'Numeric',
+ 'Operator', '<', 'ThresholdType', 'variable', 'Value', JSON_TYPE(NULL),
+ 'ThresholdVariableId', 52, 'ThresholdVariableName', '客户品种最低保证金率', 'Unit', '%'
)),
'trade.MarginRate < config.MinMarginRate',
1, 1, 0, 'SYSTEM', NOW());
@@ -111,9 +112,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('起息日早于当前日期',
'合约起息日早于当前日期时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 2,
- 'Operator', '<', 'ThresholdType', 'Variable',
- 'ThresholdVariableId', 21
+ 'VariableId', 2, 'VariableName', '合约起息日', 'VariableType', 'Date',
+ 'Operator', '<', 'ThresholdType', 'variable', 'Value', JSON_TYPE(NULL),
+ 'ThresholdVariableId', 21, 'ThresholdVariableName', '当前日期', 'Unit', JSON_TYPE(NULL)
)),
'trade.StartDate < sys.CurrentDate',
1, 1, 0, 'SYSTEM', NOW());
@@ -124,8 +125,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('支付日为银行间交易日',
'支付日为银行间交易日时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 38,
- 'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
+ 'VariableId', 38, 'VariableName', '支付日是否银行间交易日', 'VariableType', 'Boolean',
+ 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
)),
'calc.IsSettlementDateTradingDay == true',
1, 1, 0, 'SYSTEM', NOW());
@@ -136,8 +138,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('到期日为银行间交易日',
'到期日为银行间交易日时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 36,
- 'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
+ 'VariableId', 36, 'VariableName', '到期日是否银行间交易日', 'VariableType', 'Boolean',
+ 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
)),
'calc.IsExerciseDateTradingDay == true',
1, 1, 0, 'SYSTEM', NOW());
@@ -148,8 +151,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('平仓日为银行间交易日',
'平仓日为银行间交易日时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 37,
- 'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
+ 'VariableId', 37, 'VariableName', '平仓日是否银行间交易日', 'VariableType', 'Boolean',
+ 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
)),
'calc.IsUnwindDateTradingDay == true',
1, 1, 0, 'SYSTEM', NOW());
@@ -160,8 +164,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('合约期限超阈值',
'合约期限超过阈值(默认365天)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 26,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 365
+ 'VariableId', 26, 'VariableName', '合约期限', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 365,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '天'
)),
'calc.MaturityDays > 365',
1, 1, 0, 'SYSTEM', NOW());
@@ -172,8 +177,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('债券类净价偏离',
'期初净价与上一收盘日中债估值净价偏离度超阈值(默认5%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 45,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
+ 'VariableId', 45, 'VariableName', '期初净价偏离度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'Math.Abs(swap_position.PosiNetNoFeePrice - market.CBValuationNetPrice) / market.CBValuationNetPrice * 100 > 5',
1, 1, 0, 'SYSTEM', NOW());
@@ -184,8 +190,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('债券类收益率偏离',
'期初收益率与上一收盘日中债估值收益率偏离度超阈值(默认5%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 46,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
+ 'VariableId', 46, 'VariableName', '期初收益率偏离度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'Math.Abs(trade.InitYtm - market.CBValuationYtm) / market.CBValuationYtm * 100 > 5',
1, 1, 0, 'SYSTEM', NOW());
@@ -196,8 +203,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('非债券类价格偏离',
'期初价格与上一日收盘价偏离度超阈值(默认5%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 47,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
+ 'VariableId', 47, 'VariableName', '期初价格偏离度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'Math.Abs(trade.SpotPrice - market.LastClosePrice) / market.LastClosePrice * 100 > 5',
1, 1, 0, 'SYSTEM', NOW());
@@ -208,8 +216,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('单一交易对手累计标的数量超阈值',
'对手方累计标的数量超过阈值(默认10个)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 32,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 10
+ 'VariableId', 32, 'VariableName', '对手方累计标的数量', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 10,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '个'
)),
'calc.CounterpartyUnderlyingCount > 10',
1, 1, 0, 'SYSTEM', NOW());
@@ -221,12 +230,14 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
'多头方向支付固定端场景下,利息端利率与FR007偏离度超阈值(默认3%)时触发审批',
JSON_ARRAY(
JSON_OBJECT(
- 'VariableId', 41,
- 'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
+ 'VariableId', 41, 'VariableName', '多空方向为多头', 'VariableType', 'Boolean',
+ 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
),
JSON_OBJECT(
- 'VariableId', 48,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 3
+ 'VariableId', 48, 'VariableName', '利息端利率与FR007偏离度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 3,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)
),
'calc.IsLongDirection == true && Math.Abs(calc.InterestRate - market.FR007) / market.FR007 * 100 > 3',
@@ -239,12 +250,14 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
'空头方向场景下,利息端利率与借贷加权费率偏离度超阈值(默认2%)时触发审批',
JSON_ARRAY(
JSON_OBJECT(
- 'VariableId', 42,
- 'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
+ 'VariableId', 42, 'VariableName', '多空方向为空头', 'VariableType', 'Boolean',
+ 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
),
JSON_OBJECT(
- 'VariableId', 49,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 2
+ 'VariableId', 49, 'VariableName', '利息端利率与借贷加权费率偏离度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 2,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)
),
'calc.IsShortDirection == true && Math.Abs(calc.InterestRate - market.BondLendingRate) / market.BondLendingRate * 100 > 2',
@@ -256,8 +269,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('账户授权收支方向不匹配',
'保证金收支方向与账户授权方向不匹配时禁止交易',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 43,
- 'Operator', '是', 'ThresholdType', 'Fixed', 'Value', true
+ 'VariableId', 43, 'VariableName', '保证金收支方向为支付', 'VariableType', 'Boolean',
+ 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
)),
'calc.IsMarginPay == true',
1, 1, 0, 'SYSTEM', NOW());
@@ -268,8 +282,9 @@ INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr
('执行价偏离超阈值',
'执行价与参考价格偏离度超阈值(默认5%)时触发审批',
JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 50,
- 'Operator', '>', 'ThresholdType', 'Fixed', 'Value', 5
+ 'VariableId', 50, 'VariableName', '执行价偏离度', 'VariableType', 'Numeric',
+ 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
+ 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
)),
'Math.Abs(trade.StrikePrice - market.ReferencePrice) / market.ReferencePrice * 100 > 5',
1, 1, 0, 'SYSTEM', NOW());
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs b/YLErpDAL/Modules/RiskEngine/Dto/FormulaCondition.cs
similarity index 55%
rename from YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs
rename to YLErpDAL/Modules/RiskEngine/Dto/FormulaCondition.cs
index 81facae9..5f313d70 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RuleCondition.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/FormulaCondition.cs
@@ -1,11 +1,15 @@
namespace YLErp.Modules.RiskEngine.Dto
{
- public class RuleCondition
+ public class FormulaCondition
{
public long VariableId { get; set; }
+ public string VariableName { get; set; }
+ public string VariableType { get; set; }
public string Operator { get; set; }
public string ThresholdType { get; set; }
public object Value { get; set; }
public long? ThresholdVariableId { get; set; }
+ public string ThresholdVariableName { get; set; }
+ public string Unit { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/FormulaDefinition.cs b/YLErpDAL/Modules/RiskEngine/Dto/FormulaDefinition.cs
new file mode 100644
index 00000000..cd85d0d7
--- /dev/null
+++ b/YLErpDAL/Modules/RiskEngine/Dto/FormulaDefinition.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace YLErp.Modules.RiskEngine.Dto
+{
+ public class FormulaDefinition
+ {
+ public string LogicOperator { get; set; }
+ public List Conditions { get; set; }
+ }
+}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleSimpleItem.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleSimpleItem.cs
deleted file mode 100644
index aea6a343..00000000
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleSimpleItem.cs
+++ /dev/null
@@ -1,9 +0,0 @@
-namespace YLErp.Modules.RiskEngine.Dto
-{
- public class RiskRuleSimpleItem
- {
- public long Id { get; set; }
- public string RuleName { get; set; }
- public string RuleText { get; set; }
- }
-}
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
index 8767bfc4..58c9f5e5 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
@@ -79,7 +79,6 @@ using YLErp.Modules.RiskEngine.Dto;
GetRuleVersions(long) 获取规则版本历史(从审计日志 SnapshotData 提取版本号)
BatchDeleteRules(List) 批量删除规则(逐条保护检查,单事务)
GetRuleApplications(long) 获取规则关联的应用配置列表
- GetAllRuleList() 获取所有启用规则(轻量字段,供应用配置下拉)
── 应用配置管理(9 个) ───────────────────────────────────────────
QueryApplicationList(QueryRiskApplicationReq) 查询应用列表(多条件筛选,内存关联规则名称)
@@ -260,22 +259,25 @@ namespace YLErp.Modules.RiskEngine
private void ValidateConditionJson(string conditionJson)
{
- List conditions;
+ FormulaDefinition formula;
try
{
- conditions = JsonConvert.DeserializeObject>(conditionJson);
+ formula = JsonConvert.DeserializeObject(conditionJson);
}
catch
{
throw new ServiceException("公式表达式 JSON 格式不合法");
}
- if (conditions == null || conditions.Count == 0)
+ if (formula.Conditions == null || formula.Conditions.Count == 0)
throw new ServiceException("公式条件列表不能为空");
- for (int i = 0; i < conditions.Count; i++)
+ if (formula.LogicOperator != "AND")
+ throw new ServiceException("当前仅支持 AND 逻辑运算符");
+
+ for (int i = 0; i < formula.Conditions.Count; i++)
{
- var cond = conditions[i];
+ var cond = formula.Conditions[i];
var condLabel = $"条件{i + 1}";
var variableDef = DbContext.glms_risk_variable
@@ -287,7 +289,7 @@ namespace YLErp.Modules.RiskEngine
if (!validOperators.Contains(cond.Operator))
throw new ServiceException($"{condLabel}:操作符 '{cond.Operator}' 不适用于{GetDataTypeName(variableDef.DataType)}类型变量");
- if (cond.ThresholdType == "Fixed")
+ if (cond.ThresholdType == "fixed")
{
if (cond.Value == null)
throw new ServiceException($"{condLabel}:固定阈值不能为空");
@@ -302,7 +304,7 @@ namespace YLErp.Modules.RiskEngine
throw new ServiceException($"{condLabel}:日期型变量的阈值必须为合法日期");
}
}
- else if (cond.ThresholdType == "Variable")
+ else if (cond.ThresholdType == "variable")
{
if (!cond.ThresholdVariableId.HasValue)
throw new ServiceException($"{condLabel}:变量阈值引用的变量 ID 不能为空");
@@ -315,7 +317,7 @@ namespace YLErp.Modules.RiskEngine
}
else
{
- throw new ServiceException($"{condLabel}:阈值类型 '{cond.ThresholdType}' 不合法,仅支持 Fixed/Variable");
+ throw new ServiceException($"{condLabel}:阈值类型 '{cond.ThresholdType}' 不合法,仅支持 fixed/variable");
}
}
}
@@ -443,15 +445,23 @@ namespace YLErp.Modules.RiskEngine
if (ruleName.Length > 200)
throw new ServiceException("规则名称长度不能超过200字符");
- if (string.IsNullOrWhiteSpace(ruleExpr))
- throw new ServiceException("规则表达式不能为空");
+ bool hasStructured = !string.IsNullOrWhiteSpace(conditionJson);
+ bool hasFreeText = !string.IsNullOrWhiteSpace(ruleExpr);
- if (!string.IsNullOrWhiteSpace(conditionJson))
+ if (!hasStructured && !hasFreeText)
+ throw new ServiceException("公式表达式不能为空,请提供结构化条件或自由文本表达式");
+
+ if (hasStructured && hasFreeText)
+ throw new ServiceException("结构化条件和自由文本表达式不能同时提供,请选择其中一种模式");
+
+ if (hasStructured)
{
ValidateConditionJson(conditionJson);
}
-
- ValidateRuleExpr(ruleExpr);
+ else
+ {
+ ValidateRuleExpr(ruleExpr);
+ }
}
private List ParseRuleIds(string ruleIds)
@@ -833,20 +843,6 @@ namespace YLErp.Modules.RiskEngine
return result;
}
- public List GetAllRuleList()
- {
- return DbContext.glms_risk_rule
- .Where(r => r.Status == RiskRuleStatus.Active)
- .OrderBy(r => r.id)
- .Select(r => new RiskRuleSimpleItem
- {
- Id = r.id,
- RuleName = r.RuleName,
- RuleText = r.RuleText
- })
- .ToList();
- }
-
#endregion
#region Application Management
@@ -1081,7 +1077,7 @@ namespace YLErp.Modules.RiskEngine
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
- WriteAuditLog("APP_UPDATE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds),
+ WriteAuditLog("APPLICATION_UPDATE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds),
$"修改应用配置:策略={req.ControlStrategy}, 触发时点={req.TriggerPoints}");
DbContext.SaveChanges();
@@ -1136,7 +1132,7 @@ namespace YLErp.Modules.RiskEngine
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
- WriteAuditLog("APP_DISABLE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "停用应用配置");
+ WriteAuditLog("APPLICATION_DISABLE", "APPLICATION", applicationId, ResolveRuleNames(app.RuleIds), "停用应用配置");
DbContext.SaveChanges();
TryRefreshCache();
@@ -1163,7 +1159,7 @@ namespace YLErp.Modules.RiskEngine
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
- WriteAuditLog("APP_BATCH_ENABLE", "APPLICATION", app.id, ResolveRuleNames(app.RuleIds), "批量启用应用配置");
+ WriteAuditLog("APPLICATION_BATCH_ENABLE", "APPLICATION", app.id, ResolveRuleNames(app.RuleIds), "批量启用应用配置");
}
DbContext.SaveChanges();
@@ -1362,7 +1358,7 @@ namespace YLErp.Modules.RiskEngine
variable.UpdateOptName = UserName;
variable.UpdateDate = DateTime.Now;
- WriteAuditLog("VAR_UPDATE", "VARIABLE", variableId, req.VariableName, $"修改变量:{variable.VariableName}");
+ WriteAuditLog("VARIABLE_UPDATE", "VARIABLE", variableId, req.VariableName, $"修改变量:{variable.VariableName}");
DbContext.SaveChanges();
InvalidateVariableCache();
diff --git a/YLErpWeb/Controllers/RiskRuleController.cs b/YLErpWeb/Controllers/RiskRuleController.cs
index 9c97be3e..d65997dc 100644
--- a/YLErpWeb/Controllers/RiskRuleController.cs
+++ b/YLErpWeb/Controllers/RiskRuleController.cs
@@ -221,27 +221,6 @@ namespace YLErp.Web.Controllers
}
}
- [HttpGet("risk-rules/list")]
- [MyAuthorize("风控规则查看")]
- public JsonResult GetAllRiskRules()
- {
- try
- {
- var service = new RiskRuleService(CurUser);
- var result = service.GetAllRuleList();
- return Json(new { success = true, data = result });
- }
- catch (ServiceException ex)
- {
- return Json(new { success = false, message = ex.Message });
- }
- catch (Exception ex)
- {
- _logger.Error(ex, "查询规则下拉列表");
- return Json(new { success = false, message = "系统异常,请联系管理员" });
- }
- }
-
#endregion
#region Application Management
From 4ac18c4810a75ff787c5767d3c19274c8abca1d9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:05:42 +0800
Subject: [PATCH 12/17] =?UTF-8?q?Revert=20"feat(risk-engine):=20=E5=AE=8C?=
=?UTF-8?q?=E5=96=84=E9=A3=8E=E6=8E=A7=E8=A7=84=E5=88=99=E7=A7=8D=E5=AD=90?=
=?UTF-8?q?=E6=95=B0=E6=8D=AE=E4=B8=8E=20CRUD=20=E6=8E=A5=E5=8F=A3?=
=?UTF-8?q?=E4=BC=98=E5=8C=96"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit c2fc699e5757202a0b9abd310e2ceb350d2f153c.
---
.../DbUpdate/Ver-5.6.0/seed_applications.sql | 135 --------
.../DbUpdate/Ver-5.6.0/seed_rules.sql | 306 ------------------
.../DbUpdate/Ver-5.6.0/seed_variables.sql | 14 -
.../RiskEngine/Dto/QueryRiskApplicationReq.cs | 2 +-
.../RiskEngine/Dto/QueryRiskVariableReq.cs | 2 +-
.../RiskEngine/Dto/RiskRuleListItem.cs | 2 -
.../Dto/UpdateRiskApplicationReq.cs | 2 +-
.../RiskEngine/Dto/UpdateRiskRuleReq.cs | 2 +-
.../RiskEngine/Dto/UpdateRiskVariableReq.cs | 2 +-
.../Modules/RiskEngine/RiskEngineService.cs | 2 +-
.../Modules/RiskEngine/RiskRuleService.cs | 42 ++-
11 files changed, 31 insertions(+), 480 deletions(-)
delete mode 100644 Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql
delete mode 100644 Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql
deleted file mode 100644
index 8c3cf942..00000000
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_applications.sql
+++ /dev/null
@@ -1,135 +0,0 @@
--- ============================================================
--- 规则应用初始数据(对应设计文档 §4.9.1 通用规则预置参考)
--- 依赖:seed_rules.sql(规则数据需先插入)
---
--- 每条规则对应一条应用配置(1:1),定义"何时、对谁、怎么处理"
--- ControlStrategy: 1=Block(禁止), 2=Approval(审批), 3=Warning(提示)
--- TriggerPoints: BOOK_CONFIRM=簿记交易确认
--- ScopeIsGlobal: 1=全局适用, 0=按维度配置(Scope字段为空表示"全部")
--- ============================================================
-
--- 规则1:挂钩标的集中度超阈值(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '挂钩标的集中度超阈值';
-
--- 规则2:挂钩标的到期日小于合约到期日(禁止,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '挂钩标的到期日小于合约到期日';
-
--- 规则3:名义本金超阈值(审批,账户/合约类型)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '名义本金超阈值';
-
--- 规则4:保证金支付比例超阈值(审批,账户/标的类型)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '保证金支付比例超阈值';
-
--- 规则5:保证金利率偏离(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '保证金利率偏离';
-
--- 规则6:保证金收取比例低于最低标准(审批,账户/标的类型)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '保证金收取比例低于最低标准';
-
--- 规则7:起息日早于当前日期(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '起息日早于当前日期';
-
--- 规则8:支付日为银行间交易日(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '支付日为银行间交易日';
-
--- 规则9:到期日为银行间交易日(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '到期日为银行间交易日';
-
--- 规则10:平仓日为银行间交易日(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '平仓日为银行间交易日';
-
--- 规则11:合约期限超阈值(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '合约期限超阈值';
-
--- 规则12:债券类净价偏离(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '债券类净价偏离';
-
--- 规则13:债券类收益率偏离(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '债券类收益率偏离';
-
--- 规则14:非债券类价格偏离(审批,全局)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '非债券类价格偏离';
-
--- 规则15:单一交易对手累计标的数量超阈值(审批,对手方)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '单一交易对手累计标的数量超阈值';
-
--- 规则16:多头支付固定端利率偏离(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '多头支付固定端利率偏离';
-
--- 规则17:空头利率减点借贷加权偏离(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '空头利率减点借贷加权偏离';
-
--- 规则18:账户授权收支方向不匹配(禁止,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 1, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '账户授权收支方向不匹配';
-
--- 规则19:执行价偏离超阈值(审批,账户)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 2, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '执行价偏离超阈值';
-
--- 规则20:希腊字母限额超阈值(提示,账户/标的,预留接口)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', 0, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '希腊字母限额超阈值';
-
--- 规则21:接近/触发敲入敲出价(提示,全局,预留接口)
-INSERT INTO `glms_risk_rule_application` (`RuleIds`, `Status`, `ControlStrategy`, `TriggerPoints`, `ScopeIsGlobal`, `Version`, `OptId`, `OptName`, `OptDate`)
-SELECT
- CAST(r.id AS CHAR), 1, 3, 'BOOK_CONFIRM', 1, 1, 0, 'SYSTEM', NOW()
-FROM `glms_risk_rule` r WHERE r.RuleName = '接近/触发敲入敲出价';
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
deleted file mode 100644
index 33b72018..00000000
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_rules.sql
+++ /dev/null
@@ -1,306 +0,0 @@
--- ============================================================
--- 规则初始数据(对应设计文档 §4.9.1 通用规则预置参考)
--- 依赖:seed_variables.sql(变量池数据需先插入,ID 1~44)
---
--- 变量 ID 映射(seed_variables.sql 自增):
--- 1=合约名义本金 2=合约起息日 3=合约到期日 4=合约平仓日
--- 5=合约支付日 6=期初净价 7=期初全价 8=期初收益率
--- 9=期初价格 10=期末全价 11=期末价格 12=保证金利率
--- 13=保证金比例 14=客户授信额度
--- 15=上一收盘日中债估值净价 16=上一收盘日中债估值全价 17=上一收盘日中债估值收益率
--- 18=上一日收盘价 19=借贷加权费率 20=FR007 21=当前日期
--- 22=挂钩标的到期日 23=标的发行余额
--- 24=挂钩标的集中度 25=授信占用率 26=合约期限 27=Delta
--- 28=Gamma 29=Vega 30=Theta 31=利息端利率
--- 32=对手方累计标的数量 33=同一标的累计名义本金 34=同一客户累计名义本金
--- 35=总持仓名义本金
--- 36=到期日是否银行间交易日 37=平仓日是否银行间交易日 38=支付日是否银行间交易日
--- 39=利息端/浮动端方向是否同向 40=关键业务要素是否一致
--- 41=多空方向为多头 42=多空方向为空头
--- 43=保证金收支方向为支付 44=保证金收支方向为收取
--- 45=期初净价偏离度 46=期初收益率偏离度 47=期初价格偏离度
--- 48=利息端利率与FR007偏离度 49=利息端利率与借贷加权费率偏离度
--- 50=执行价偏离度 51=执行价 52=客户品种最低保证金率 53=参考价格
--- ============================================================
-
-
--- ============================================================
--- 插入 21 条通用规则
--- ============================================================
-
--- 规则1:挂钩标的集中度超阈值(审批,全局)
--- 条件:挂钩标的集中度(ID=24) > 30%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('挂钩标的集中度超阈值',
- '挂钩标的集中度超过阈值(默认30%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 24, 'VariableName', '挂钩标的集中度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 30,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- 'calc.UnderlyingConcentration > 30',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则2:挂钩标的到期日小于合约到期日(禁止,全局)
--- 条件:挂钩标的到期日(ID=22) < 合约到期日(ID=3)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('挂钩标的到期日小于合约到期日',
- '挂钩标的到期日早于合约到期日时禁止交易',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 22, 'VariableName', '挂钩标的到期日', 'VariableType', 'Date',
- 'Operator', '<', 'ThresholdType', 'variable', 'Value', JSON_TYPE(NULL),
- 'ThresholdVariableId', 3, 'ThresholdVariableName', '合约到期日', 'Unit', JSON_TYPE(NULL)
- )),
- 'market.UnderlyingMaturityDate < trade.ExerciseDate',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则3:名义本金超阈值(审批,账户/合约类型)
--- 条件:合约名义本金(ID=1) > 100000000(1亿元)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('名义本金超阈值',
- '合约名义本金超过阈值(默认1亿元)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 1, 'VariableName', '合约名义本金', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 100000000,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '元'
- )),
- 'trade.StockEqvNotional > 100000000',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则4:保证金支付比例超阈值(审批,账户/标的类型)
--- 条件:保证金比例(ID=13) > 50%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('保证金支付比例超阈值',
- '保证金比例超过阈值(默认50%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 13, 'VariableName', '保证金比例', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 50,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- 'trade.MarginRate > 50',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则5:保证金利率偏离(审批,账户)
--- 条件:保证金利率(ID=12) 不介于 [2%, 5%]
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('保证金利率偏离',
- '保证金利率不在配置区间内(默认2%~5%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 12, 'VariableName', '保证金利率', 'VariableType', 'Numeric',
- 'Operator', '不介于', 'ThresholdType', 'fixed', 'Value', JSON_ARRAY(2, 5),
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- '!(client_marginrate.InitMarginRebateRate >= 2 && client_marginrate.InitMarginRebateRate <= 5)',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则6:保证金收取比例低于最低标准(审批,账户/标的类型)
--- 条件:保证金比例(ID=13) < 客户品种最低保证金率(ID=52)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('保证金收取比例低于最低标准',
- '保证金比例低于客户品种最低保证金率时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 13, 'VariableName', '保证金比例', 'VariableType', 'Numeric',
- 'Operator', '<', 'ThresholdType', 'variable', 'Value', JSON_TYPE(NULL),
- 'ThresholdVariableId', 52, 'ThresholdVariableName', '客户品种最低保证金率', 'Unit', '%'
- )),
- 'trade.MarginRate < config.MinMarginRate',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则7:起息日早于当前日期(审批,全局)
--- 条件:合约起息日(ID=2) < 当前日期(ID=21)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('起息日早于当前日期',
- '合约起息日早于当前日期时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 2, 'VariableName', '合约起息日', 'VariableType', 'Date',
- 'Operator', '<', 'ThresholdType', 'variable', 'Value', JSON_TYPE(NULL),
- 'ThresholdVariableId', 21, 'ThresholdVariableName', '当前日期', 'Unit', JSON_TYPE(NULL)
- )),
- 'trade.StartDate < sys.CurrentDate',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则8:支付日为银行间交易日(审批,全局)
--- 条件:支付日是否银行间交易日(ID=38) = 是
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('支付日为银行间交易日',
- '支付日为银行间交易日时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 38, 'VariableName', '支付日是否银行间交易日', 'VariableType', 'Boolean',
- 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
- )),
- 'calc.IsSettlementDateTradingDay == true',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则9:到期日为银行间交易日(审批,全局)
--- 条件:到期日是否银行间交易日(ID=36) = 是
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('到期日为银行间交易日',
- '到期日为银行间交易日时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 36, 'VariableName', '到期日是否银行间交易日', 'VariableType', 'Boolean',
- 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
- )),
- 'calc.IsExerciseDateTradingDay == true',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则10:平仓日为银行间交易日(审批,全局)
--- 条件:平仓日是否银行间交易日(ID=37) = 是
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('平仓日为银行间交易日',
- '平仓日为银行间交易日时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 37, 'VariableName', '平仓日是否银行间交易日', 'VariableType', 'Boolean',
- 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
- )),
- 'calc.IsUnwindDateTradingDay == true',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则11:合约期限超阈值(审批,账户)
--- 条件:合约期限(ID=26) > 365天
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('合约期限超阈值',
- '合约期限超过阈值(默认365天)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 26, 'VariableName', '合约期限', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 365,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '天'
- )),
- 'calc.MaturityDays > 365',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则12:债券类净价偏离(审批,全局)
--- 条件:期初净价偏离度(ID=45) > 5%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('债券类净价偏离',
- '期初净价与上一收盘日中债估值净价偏离度超阈值(默认5%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 45, 'VariableName', '期初净价偏离度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- 'Math.Abs(swap_position.PosiNetNoFeePrice - market.CBValuationNetPrice) / market.CBValuationNetPrice * 100 > 5',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则13:债券类收益率偏离(审批,全局)
--- 条件:期初收益率偏离度(ID=46) > 5%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('债券类收益率偏离',
- '期初收益率与上一收盘日中债估值收益率偏离度超阈值(默认5%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 46, 'VariableName', '期初收益率偏离度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- 'Math.Abs(trade.InitYtm - market.CBValuationYtm) / market.CBValuationYtm * 100 > 5',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则14:非债券类价格偏离(审批,全局)
--- 条件:期初价格偏离度(ID=47) > 5%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('非债券类价格偏离',
- '期初价格与上一日收盘价偏离度超阈值(默认5%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 47, 'VariableName', '期初价格偏离度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- 'Math.Abs(trade.SpotPrice - market.LastClosePrice) / market.LastClosePrice * 100 > 5',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则15:单一交易对手累计标的数量超阈值(审批,对手方)
--- 条件:对手方累计标的数量(ID=32) > 10个
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('单一交易对手累计标的数量超阈值',
- '对手方累计标的数量超过阈值(默认10个)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 32, 'VariableName', '对手方累计标的数量', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 10,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '个'
- )),
- 'calc.CounterpartyUnderlyingCount > 10',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则16:多头支付固定端利率偏离(审批,账户)
--- 条件:多空方向为多头(ID=41) AND 利息端利率与FR007偏离度(ID=48) > 3%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('多头支付固定端利率偏离',
- '多头方向支付固定端场景下,利息端利率与FR007偏离度超阈值(默认3%)时触发审批',
- JSON_ARRAY(
- JSON_OBJECT(
- 'VariableId', 41, 'VariableName', '多空方向为多头', 'VariableType', 'Boolean',
- 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
- ),
- JSON_OBJECT(
- 'VariableId', 48, 'VariableName', '利息端利率与FR007偏离度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 3,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )
- ),
- 'calc.IsLongDirection == true && Math.Abs(calc.InterestRate - market.FR007) / market.FR007 * 100 > 3',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则17:空头利率减点借贷加权偏离(审批,账户)
--- 条件:多空方向为空头(ID=42) AND 利息端利率与借贷加权费率偏离度(ID=49) > 2%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('空头利率减点借贷加权偏离',
- '空头方向场景下,利息端利率与借贷加权费率偏离度超阈值(默认2%)时触发审批',
- JSON_ARRAY(
- JSON_OBJECT(
- 'VariableId', 42, 'VariableName', '多空方向为空头', 'VariableType', 'Boolean',
- 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
- ),
- JSON_OBJECT(
- 'VariableId', 49, 'VariableName', '利息端利率与借贷加权费率偏离度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 2,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )
- ),
- 'calc.IsShortDirection == true && Math.Abs(calc.InterestRate - market.BondLendingRate) / market.BondLendingRate * 100 > 2',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则18:账户授权收支方向不匹配(禁止,账户)
--- 条件:保证金收支方向为支付(ID=43)(实际需结合账户授权方向判断,此处简化)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('账户授权收支方向不匹配',
- '保证金收支方向与账户授权方向不匹配时禁止交易',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 43, 'VariableName', '保证金收支方向为支付', 'VariableType', 'Boolean',
- 'Operator', '是', 'ThresholdType', 'fixed', 'Value', true,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', JSON_TYPE(NULL)
- )),
- 'calc.IsMarginPay == true',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则19:执行价偏离超阈值(审批,账户)
--- 条件:执行价偏离度(ID=50) > 5%
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('执行价偏离超阈值',
- '执行价与参考价格偏离度超阈值(默认5%)时触发审批',
- JSON_ARRAY(JSON_OBJECT(
- 'VariableId', 50, 'VariableName', '执行价偏离度', 'VariableType', 'Numeric',
- 'Operator', '>', 'ThresholdType', 'fixed', 'Value', 5,
- 'ThresholdVariableId', JSON_TYPE(NULL), 'ThresholdVariableName', JSON_TYPE(NULL), 'Unit', '%'
- )),
- 'Math.Abs(trade.StrikePrice - market.ReferencePrice) / market.ReferencePrice * 100 > 5',
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则20:希腊字母限额超阈值(提示,预留接口,一期不纳入)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('希腊字母限额超阈值',
- 'Delta/Gamma/Vega/Theta任一超阈值时提示(预留接口,一期不纳入)',
- NULL,
- NULL,
- 1, 1, 0, 'SYSTEM', NOW());
-
--- 规则21:接近/触发敲入敲出价(提示,预留接口,需确认具体判断逻辑)
-INSERT INTO `glms_risk_rule` (`RuleName`, `RuleText`, `ConditionJson`, `RuleExpr`, `Status`, `Version`, `OptId`, `OptName`, `OptDate`) VALUES
-('接近/触发敲入敲出价',
- '标的价格接近敲入/敲出价时提示(预留接口,需确认具体判断逻辑)',
- NULL,
- NULL,
- 1, 1, 0, 'SYSTEM', NOW());
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql
index 934a3a27..050d5470 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql
@@ -45,20 +45,6 @@ INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`
('同一标的累计名义本金', 3, 1, '元', '≥ 0', 'SUM(该标的所有存续交易的 StockEqvNotional),含本笔', 'calc.SameUnderlyingTotalNotional', 310, 0, 'SYSTEM', NOW()),
('同一客户累计名义本金', 3, 1, '元', '≥ 0', 'SUM(该客户所有存续交易的 StockEqvNotional),含本笔', 'calc.SameClientTotalNotional', 311, 0, 'SYSTEM', NOW()),
('总持仓名义本金', 3, 1, '元', '≥ 0', 'SUM(所有存续交易的 StockEqvNotional)', 'calc.TotalPositionNotional', 312, 0, 'SYSTEM', NOW());
--- 新增变量(ID 45~53):
--- 45=期初净价偏离度 46=期初收益率偏离度 47=期初价格偏离度
--- 48=利息端利率与FR007偏离度 49=利息端利率与借贷加权费率偏离度
--- 50=执行价偏离度 51=执行价 52=客户品种最低保证金率 53=参考价格
-INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
-('期初净价偏离度', 3, 1, '%', '≥ 0', 'ABS(期初净价-中债估值净价)/中债估值净价*100', 'Math.Abs(swap_position.PosiNetNoFeePrice - market.CBValuationNetPrice) / market.CBValuationNetPrice * 100', 313, 0, 'SYSTEM', NOW()),
-('期初收益率偏离度', 3, 1, '%', '≥ 0', 'ABS(期初收益率-中债估值收益率)/中债估值收益率*100', 'Math.Abs(trade.InitYtm - market.CBValuationYtm) / market.CBValuationYtm * 100', 314, 0, 'SYSTEM', NOW()),
-('期初价格偏离度', 3, 1, '%', '≥ 0', 'ABS(期初价格-上一日收盘价)/上一日收盘价*100', 'Math.Abs(trade.SpotPrice - market.LastClosePrice) / market.LastClosePrice * 100', 315, 0, 'SYSTEM', NOW()),
-('利息端利率与FR007偏离度', 3, 1, '%', '≥ 0', 'ABS(利息端利率-FR007)/FR007*100', 'Math.Abs(calc.InterestRate - market.FR007) / market.FR007 * 100', 316, 0, 'SYSTEM', NOW()),
-('利息端利率与借贷加权费率偏离度', 3, 1, '%', '≥ 0', 'ABS(利息端利率-借贷加权费率)/借贷加权费率*100', 'Math.Abs(calc.InterestRate - market.BondLendingRate) / market.BondLendingRate * 100', 317, 0, 'SYSTEM', NOW()),
-('执行价偏离度', 3, 1, '%', '≥ 0', 'ABS(执行价-参考价格)/参考价格*100', 'Math.Abs(trade.StrikePrice - market.ReferencePrice) / market.ReferencePrice * 100', 318, 0, 'SYSTEM', NOW()),
-('执行价', 1, 1, '元', '≥ 0', 'trade.StrikePrice', 'trade.StrikePrice', 115, 0, 'SYSTEM', NOW()),
-('客户品种最低保证金率', 1, 1, '%', '0~100', '客户品种最低保证金率(由账户/标的配置决定)', 'config.MinMarginRate', 116, 0, 'SYSTEM', NOW()),
-('参考价格', 2, 1, '元', '≥ 0', '执行价参考价格(行情数据)', 'market.ReferencePrice', 210, 0, 'SYSTEM', NOW());
-- 4.4.4 布尔判断类(Category=4)
INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs
index bd494ed8..f195ee7c 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskApplicationReq.cs
@@ -5,7 +5,7 @@ namespace YLErp.Modules.RiskEngine.Dto
{
public class QueryRiskApplicationReq : BaseSearchReq
{
- public string RuleName { get; set; }
+ public string Keyword { get; set; }
public RiskRuleStatus? Status { get; set; }
public RiskControlStrategy? Strategy { get; set; }
public string TriggerPoint { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs
index 639d9b3d..cc9dc45a 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/QueryRiskVariableReq.cs
@@ -6,6 +6,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public class QueryRiskVariableReq : BaseSearchReq
{
public RiskVariableCategory? Category { get; set; }
- public string VariableName { get; set; }
+ public string Keyword { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs
index 988f55c4..ec0c3610 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/RiskRuleListItem.cs
@@ -8,8 +8,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public long Id { get; set; }
public string RuleName { get; set; }
public string RuleText { get; set; }
- public string ConditionJson { get; set; }
- public string RuleExpr { get; set; }
public RiskRuleStatus Status { get; set; }
public int Version { get; set; }
public string OptName { get; set; }
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
index b9af55a9..73cafe4f 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskApplicationReq.cs
@@ -12,6 +12,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public string ScopeUnderlyingTypes { get; set; }
public string ScopeTradeTypes { get; set; }
public bool ScopeIsGlobal { get; set; }
- public int Version { get; set; }
+ public int ExpectedVersion { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs
index 85521bac..466286c8 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskRuleReq.cs
@@ -6,6 +6,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public string RuleText { get; set; }
public string ConditionJson { get; set; }
public string RuleExpr { get; set; }
- public int Version { get; set; }
+ public int ExpectedVersion { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskVariableReq.cs b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskVariableReq.cs
index 2990b7c1..1c19502b 100644
--- a/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskVariableReq.cs
+++ b/YLErpDAL/Modules/RiskEngine/Dto/UpdateRiskVariableReq.cs
@@ -12,6 +12,6 @@ namespace YLErp.Modules.RiskEngine.Dto
public string Description { get; set; }
public string VariableExpr { get; set; }
public int SortOrder { get; set; }
- public int Version { get; set; }
+ public int ExpectedVersion { get; set; }
}
}
diff --git a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
index 845149d3..9669c869 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskEngineService.cs
@@ -122,7 +122,7 @@ namespace YLErp.Modules.RiskEngine
public static RiskEngineService GetInstance() => _instance.Value;
- private RiskEngineService() : base(OptUserInfo.SystemUser)
+ private RiskEngineService() : base((OptUserInfo)null)
{
}
diff --git a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
index 58c9f5e5..e12cdf1d 100644
--- a/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
+++ b/YLErpDAL/Modules/RiskEngine/RiskRuleService.cs
@@ -185,6 +185,7 @@ namespace YLErp.Modules.RiskEngine
public class RiskRuleService : YLBaseService
{
private readonly IYcLogger _logger = LogFactory.GetLogger("RiskRuleService");
+ private readonly RiskEngineService _riskEngineService;
private HashSet _variableExprCache;
private DateTime _variableCacheUpdateTime;
@@ -207,14 +208,17 @@ namespace YLErp.Modules.RiskEngine
public RiskRuleService(OptUserInfo userInfo) : base(userInfo)
{
+ _riskEngineService = RiskEngineService.GetInstance();
}
public RiskRuleService(YLBaseService baseService) : base(baseService)
{
+ _riskEngineService = RiskEngineService.GetInstance();
}
public RiskRuleService(OptUserInfo optUser, YLContext dbContext) : base(optUser, dbContext)
{
+ _riskEngineService = RiskEngineService.GetInstance();
}
#region Private Helpers
@@ -395,7 +399,7 @@ namespace YLErp.Modules.RiskEngine
{
try
{
- RiskEngineService.GetInstance().RefreshCache();
+ _riskEngineService.RefreshCache();
}
catch (Exception ex)
{
@@ -556,8 +560,6 @@ namespace YLErp.Modules.RiskEngine
Id = r.id,
RuleName = r.RuleName,
RuleText = r.RuleText,
- ConditionJson = r.ConditionJson,
- RuleExpr = r.RuleExpr,
Status = r.Status,
Version = r.Version,
OptName = r.OptName,
@@ -651,7 +653,7 @@ namespace YLErp.Modules.RiskEngine
{
var rule = GetRuleOrThrow(ruleId);
- if (rule.Version != req.Version)
+ if (rule.Version != req.ExpectedVersion)
throw new ServiceException("规则已被其他用户修改,请重新加载后再编辑");
ValidateRuleParams(req.RuleName, req.ConditionJson, req.RuleExpr);
@@ -702,11 +704,13 @@ namespace YLErp.Modules.RiskEngine
throw new ServiceException("仅已停用的规则可以启用");
rule.Status = RiskRuleStatus.Active;
+ rule.Version = rule.Version + 1;
rule.UpdateOptId = UserId;
rule.UpdateOptName = UserName;
rule.UpdateDate = DateTime.Now;
- WriteAuditLog("RULE_ENABLE", "RULE", ruleId, rule.RuleName, "启用规则");
+ WriteAuditLog("RULE_ENABLE", "RULE", ruleId, rule.RuleName, "启用规则",
+ snapshotData: JsonConvert.SerializeObject(new { Version = rule.Version }));
DbContext.SaveChanges();
TryRefreshCache();
@@ -719,6 +723,7 @@ namespace YLErp.Modules.RiskEngine
throw new ServiceException("仅已生效的规则可以停用");
rule.Status = RiskRuleStatus.Disabled;
+ rule.Version = rule.Version + 1;
rule.UpdateOptId = UserId;
rule.UpdateOptName = UserName;
rule.UpdateDate = DateTime.Now;
@@ -867,14 +872,6 @@ namespace YLErp.Modules.RiskEngine
query = query.Where(a => a.TriggerPoints.Contains(req.TriggerPoint));
}
- if (!string.IsNullOrWhiteSpace(req.RuleName))
- {
- query = query.Where(a => DbContext.glms_risk_rule
- .Any(r => r.Status != RiskRuleStatus.Deleted
- && a.RuleIds.Contains(r.id.ToString())
- && r.RuleName.Contains(req.RuleName)));
- }
-
var pagedApps = query.OrderByDescending(a => a.UpdateDate)
.Select(a => new
{
@@ -940,6 +937,13 @@ namespace YLErp.Modules.RiskEngine
};
}).ToList();
+ if (!string.IsNullOrWhiteSpace(req.Keyword))
+ {
+ resultList = resultList
+ .Where(a => a.RuleNames.Contains(req.Keyword))
+ .ToList();
+ }
+
return new SearchListResult
{
rows = resultList,
@@ -1046,7 +1050,7 @@ namespace YLErp.Modules.RiskEngine
{
var app = GetApplicationOrThrow(applicationId);
- if (app.Version != req.Version)
+ if (app.Version != req.ExpectedVersion)
throw new ServiceException("应用配置已被其他用户修改,请重新加载后再编辑");
if (!string.IsNullOrWhiteSpace(req.RuleIds))
@@ -1111,6 +1115,7 @@ namespace YLErp.Modules.RiskEngine
ValidateRuleIdsActive(app.RuleIds);
app.Status = RiskRuleStatus.Active;
+ app.Version = app.Version + 1;
app.UpdateOptId = UserId;
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
@@ -1128,6 +1133,7 @@ namespace YLErp.Modules.RiskEngine
throw new ServiceException("仅已生效的应用配置可以停用");
app.Status = RiskRuleStatus.Disabled;
+ app.Version = app.Version + 1;
app.UpdateOptId = UserId;
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
@@ -1155,6 +1161,7 @@ namespace YLErp.Modules.RiskEngine
foreach (var app in apps)
{
app.Status = RiskRuleStatus.Active;
+ app.Version = app.Version + 1;
app.UpdateOptId = UserId;
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
@@ -1185,6 +1192,7 @@ namespace YLErp.Modules.RiskEngine
foreach (var app in apps)
{
app.Status = RiskRuleStatus.Disabled;
+ app.Version = app.Version + 1;
app.UpdateOptId = UserId;
app.UpdateOptName = UserName;
app.UpdateDate = DateTime.Now;
@@ -1216,9 +1224,9 @@ namespace YLErp.Modules.RiskEngine
query = query.Where(v => v.Category == req.Category.Value);
}
- if (!string.IsNullOrWhiteSpace(req.VariableName))
+ if (!string.IsNullOrWhiteSpace(req.Keyword))
{
- query = query.Where(v => v.VariableName.Contains(req.VariableName));
+ query = query.Where(v => v.VariableName.Contains(req.Keyword));
}
var result = query.OrderBy(v => v.SortOrder).ThenBy(v => v.VariableName)
@@ -1326,7 +1334,7 @@ namespace YLErp.Modules.RiskEngine
{
var variable = GetVariableOrThrow(variableId);
- if (variable.Version != req.Version)
+ if (variable.Version != req.ExpectedVersion)
throw new ServiceException("变量已被其他用户修改,请重新加载后再编辑");
if (string.IsNullOrWhiteSpace(req.VariableName))
From d01253a5daeb272b6d460d905763ab965796160d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=BC=A0=E5=90=8D=E9=94=90?= <1565842059@qq.com>
Date: Thu, 2 Jul 2026 16:13:41 +0800
Subject: [PATCH 13/17] =?UTF-8?q?Revert=20"feat:=20=E8=A7=84=E5=88=99?=
=?UTF-8?q?=E5=8F=8C=E6=A8=A1=E5=BC=8F=E5=85=AC=E5=BC=8F=E8=A1=A8=E8=BE=BE?=
=?UTF-8?q?=E5=BC=8F=EF=BC=88RuleExpr=EF=BC=89&=20=E5=AD=97=E6=AE=B5?=
=?UTF-8?q?=E7=B2=BE=E7=AE=80=E9=87=8D=E6=9E=84"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 28ed20e527e97eaf1b97e06f7c351d4779d89536.
---
.../YLErp.Core/DBModels/glms_risk_rule.cs | 7 +-
.../DBModels/glms_risk_rule_application.cs | 3 +-
.../DBModels/glms_risk_rule_audit_log.cs | 1 +
.../YLErp.Core/DBModels/glms_risk_variable.cs | 5 +-
.../DbUpdate/Ver-5.6.0/prod.sql | 22 +-
.../DbUpdate/Ver-5.6.0/seed_variables.sql | 59 --
.../RiskEngine/Compile/RuleCompiler.cs | 124 ++--
.../Dto/CreateRiskApplicationReq.cs | 2 +-
.../RiskEngine/Dto/CreateRiskRuleReq.cs | 6 +-
.../RiskEngine/Dto/CreateRiskVariableReq.cs | 5 +-
.../RiskEngine/Dto/FormulaCondition.cs | 4 +-
.../RiskEngine/Dto/QueryRiskRuleReq.cs | 2 +-
.../RiskEngine/Dto/RiskApplicationDetail.cs | 8 +-
.../RiskEngine/Dto/RiskApplicationListItem.cs | 6 +-
.../RiskEngine/Dto/RiskAuditLogDetail.cs | 1 +
.../RiskEngine/Dto/RiskAuditLogListItem.cs | 1 +
.../Dto/RiskRuleApplicationSummary.cs | 1 +
.../Modules/RiskEngine/Dto/RiskRuleDetail.cs | 7 +-
.../RiskEngine/Dto/RiskRuleListItem.cs | 4 +-
.../RiskEngine/Dto/RiskVariableDetail.cs | 5 +-
.../RiskEngine/Dto/RiskVariableListItem.cs | 3 +-
.../RiskEngine/Dto/RiskVariableSimpleItem.cs | 2 +-
.../Dto/UpdateRiskApplicationReq.cs | 1 -
.../RiskEngine/Dto/UpdateRiskRuleReq.cs | 6 +-
.../RiskEngine/Dto/UpdateRiskVariableReq.cs | 4 +-
.../Modules/RiskEngine/RiskEngineService.cs | 182 ++---
YLErpDAL/Modules/RiskEngine/RiskResult.cs | 4 +-
YLErpDAL/Modules/RiskEngine/RiskRule.cs | 21 +-
.../Modules/RiskEngine/RiskRuleService.cs | 650 ++++++++----------
YLErpWeb/App_Data/Config/otcformat.js | 125 +---
YLErpWeb/Common/BaseController.cs | 8 -
31 files changed, 512 insertions(+), 767 deletions(-)
delete mode 100644 Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql
diff --git a/Framework/YLErp.Core/DBModels/glms_risk_rule.cs b/Framework/YLErp.Core/DBModels/glms_risk_rule.cs
index 1581b02f..cdb5896d 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_rule.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_rule.cs
@@ -5,10 +5,11 @@ namespace YLErp.DBModels
[Table("glms_risk_rule")]
public class glms_risk_rule : DBModelWithOperator
{
+ public string RuleCode { get; set; }
public string RuleName { get; set; }
- public string RuleText { get; set; }
- public string ConditionJson { get; set; }
- public string RuleExpr { get; set; }
+ public string RuleDescription { get; set; }
+ public string FormulaJson { get; set; }
+ public string FormulaText { get; set; }
public RiskRuleStatus Status { get; set; } = RiskRuleStatus.Active;
public int Version { get; set; } = 1;
public int? UpdateOptId { get; set; }
diff --git a/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs b/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
index aa5dbb6a..0c731e27 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_rule_application.cs
@@ -5,7 +5,8 @@ namespace YLErp.DBModels
[Table("glms_risk_rule_application")]
public class glms_risk_rule_application : DBModelWithOperator
{
- public string RuleIds { get; set; }
+ public string ApplicationCode { get; set; }
+ public long RuleId { get; set; }
public RiskRuleStatus Status { get; set; } = RiskRuleStatus.Active;
public RiskControlStrategy ControlStrategy { get; set; }
public string TriggerPoints { get; set; }
diff --git a/Framework/YLErp.Core/DBModels/glms_risk_rule_audit_log.cs b/Framework/YLErp.Core/DBModels/glms_risk_rule_audit_log.cs
index fca43e2b..660927b0 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_rule_audit_log.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_rule_audit_log.cs
@@ -9,6 +9,7 @@ namespace YLErp.DBModels
public string TargetType { get; set; }
public long TargetId { get; set; }
public string TargetName { get; set; }
+ public string TargetCode { get; set; }
public string OperationDetail { get; set; }
public string Result { get; set; }
public string SnapshotData { get; set; }
diff --git a/Framework/YLErp.Core/DBModels/glms_risk_variable.cs b/Framework/YLErp.Core/DBModels/glms_risk_variable.cs
index 099312ae..8eff1191 100644
--- a/Framework/YLErp.Core/DBModels/glms_risk_variable.cs
+++ b/Framework/YLErp.Core/DBModels/glms_risk_variable.cs
@@ -5,13 +5,16 @@ namespace YLErp.DBModels
[Table("glms_risk_variable")]
public class glms_risk_variable : DBModelWithOperator
{
+ public string VariableCode { get; set; }
public string VariableName { get; set; }
public RiskVariableCategory Category { get; set; }
public RiskVariableDataType DataType { get; set; }
public string Unit { get; set; }
public string ValueDomain { get; set; }
public string Description { get; set; }
- public string VariableExpr { get; set; }
+ public string ImplementationScript { get; set; }
+ public string SourceExpression { get; set; }
+ public bool IsImplemented { get; set; }
public int Version { get; set; } = 1;
public int SortOrder { get; set; }
public int? UpdateOptId { get; set; }
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
index 3f266be1..8ba5327f 100644
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
+++ b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/prod.sql
@@ -2,10 +2,11 @@ SET FOREIGN_KEY_CHECKS=0;
CREATE TABLE `glms_risk_rule` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
+ `RuleCode` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '规则编码(RISK-YYYYMMDD-NNNN)',
`RuleName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '规则名称',
- `RuleText` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则文本',
- `ConditionJson` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '条件JSON(结构化模式, FormulaCondition数组)',
- `RuleExpr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '规则表达式(自由文本模式, 类C#表达式)',
+ `RuleDescription` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '规则描述',
+ `FormulaJson` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '公式JSON表达式',
+ `FormulaText` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '公式可读文本',
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
`OptId` int NULL DEFAULT NULL COMMENT '创建人Id',
@@ -15,12 +16,14 @@ CREATE TABLE `glms_risk_rule` (
`UpdateOptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '最后修改人名称',
`UpdateDate` datetime NULL DEFAULT NULL COMMENT '最后修改时间',
PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_rule_code`(`RuleCode` ASC) USING BTREE,
INDEX `idx_status`(`Status` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控规则定义表' ROW_FORMAT = Dynamic;
CREATE TABLE `glms_risk_rule_application` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
- `RuleIds` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '关联规则Id列表(逗号分隔)',
+ `ApplicationCode` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '应用编码(APP-YYYYMMDD-NNNN)',
+ `RuleId` bigint NOT NULL COMMENT '关联规则Id',
`Status` tinyint NOT NULL DEFAULT 1 COMMENT '状态: 1=Active, 2=Disabled, 3=Deleted',
`ControlStrategy` tinyint NOT NULL COMMENT '控制策略: 1=Block, 2=Approval, 3=Warning',
`TriggerPoints` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '触发时点(逗号分隔)',
@@ -37,6 +40,8 @@ CREATE TABLE `glms_risk_rule_application` (
`UpdateOptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '最后修改人名称',
`UpdateDate` datetime NULL DEFAULT NULL COMMENT '最后修改时间',
PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_application_code`(`ApplicationCode` ASC) USING BTREE,
+ INDEX `idx_rule_id`(`RuleId` ASC) USING BTREE,
INDEX `idx_status`(`Status` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控规则应用配置表' ROW_FORMAT = Dynamic;
@@ -46,6 +51,7 @@ CREATE TABLE `glms_risk_rule_audit_log` (
`TargetType` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '目标类型(RULE/APPLICATION/VARIABLE)',
`TargetId` bigint NOT NULL COMMENT '目标记录Id',
`TargetName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '目标名称',
+ `TargetCode` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '目标编码',
`OperationDetail` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '操作详情',
`Result` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '操作结果',
`SnapshotData` longtext CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '快照数据(JSON)',
@@ -61,13 +67,16 @@ CREATE TABLE `glms_risk_rule_audit_log` (
CREATE TABLE `glms_risk_variable` (
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键Id',
+ `VariableCode` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '变量编码',
`VariableName` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '变量名称',
`Category` tinyint NOT NULL COMMENT '分类: 1=BookingElement, 2=MarketData, 3=SystemCalc, 4=BooleanCheck',
`DataType` tinyint NOT NULL COMMENT '数据类型: 1=Numeric, 2=Date, 3=Boolean',
`Unit` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '单位',
`ValueDomain` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '值域描述',
`Description` varchar(500) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
- `VariableExpr` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '变量表达式(C#表达式)',
+ `ImplementationScript` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '实现脚本(C#表达式)',
+ `SourceExpression` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT '来源表达式',
+ `IsImplemented` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否已实现: 0=否, 1=是',
`Version` int NOT NULL DEFAULT 1 COMMENT '版本号(乐观锁)',
`SortOrder` int NOT NULL DEFAULT 0 COMMENT '排序',
`OptId` int NULL DEFAULT NULL COMMENT '创建人Id',
@@ -76,7 +85,8 @@ CREATE TABLE `glms_risk_variable` (
`UpdateOptId` int NULL DEFAULT NULL COMMENT '最后修改人Id',
`UpdateOptName` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '最后修改人名称',
`UpdateDate` datetime NULL DEFAULT NULL COMMENT '最后修改时间',
- PRIMARY KEY (`id`) USING BTREE
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_variable_code`(`VariableCode` ASC) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '风控变量池定义表' ROW_FORMAT = Dynamic;
SET FOREIGN_KEY_CHECKS=1;
diff --git a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql b/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql
deleted file mode 100644
index 050d5470..00000000
--- a/Framework/YLErp.Resources/DbUpdate/Ver-5.6.0/seed_variables.sql
+++ /dev/null
@@ -1,59 +0,0 @@
--- ============================================================
--- 变量池初始数据(对应设计文档 §4.4 变量池完整清单)
--- ============================================================
-
--- 4.4.1 簿记要素类(Category=1)
-INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
-('合约名义本金', 1, 1, '元', '≥ 0', 'trade.StockEqvNotional 或 swap_position.PosiNotionalValue', 'trade.StockEqvNotional', 101, 0, 'SYSTEM', NOW()),
-('合约起息日', 1, 2, NULL, NULL, 'trade.StartDate 或 swap_position.PosiStartDate', 'trade.StartDate', 102, 0, 'SYSTEM', NOW()),
-('合约到期日', 1, 2, NULL, NULL, 'trade.ExerciseDate 或 swap_position.PosiMatuirityDate', 'trade.ExerciseDate', 103, 0, 'SYSTEM', NOW()),
-('合约平仓日', 1, 2, NULL, NULL, 'trade.UnWindDate', 'trade.UnWindDate', 104, 0, 'SYSTEM', NOW()),
-('合约支付日', 1, 2, NULL, NULL, 'trade.SettlementDate', 'trade.SettlementDate', 105, 0, 'SYSTEM', NOW()),
-('期初净价', 1, 1, '元', '≥ 0', 'swap_position.PosiNetNoFeePrice(债券 TRS)', 'swap_position.PosiNetNoFeePrice', 106, 0, 'SYSTEM', NOW()),
-('期初全价', 1, 1, '元', '≥ 0', 'swap_position.PosiNetFeePrice(债券 TRS)/ trade.SpotPrice(其他)', 'swap_position.PosiNetFeePrice', 107, 0, 'SYSTEM', NOW()),
-('期初收益率', 1, 1, '%', NULL, 'trade.InitYtm 或 swap_position.InitYtm', 'trade.InitYtm', 108, 0, 'SYSTEM', NOW()),
-('期初价格', 1, 1, '元', '≥ 0', 'trade.SpotPrice(非债券类)', 'trade.SpotPrice', 109, 0, 'SYSTEM', NOW()),
-('期末全价', 1, 1, '元', '≥ 0', 'eod_swap_position.UnderlyingPrice(债券 TRS)', 'eod_swap_position.UnderlyingPrice', 110, 0, 'SYSTEM', NOW()),
-('期末价格', 1, 1, '元', '≥ 0', 'trade.FinalPrice', 'trade.FinalPrice', 111, 0, 'SYSTEM', NOW()),
-('保证金利率', 1, 1, '%', NULL, 'client_marginrate.InitMarginRebateRate', 'client_marginrate.InitMarginRebateRate', 112, 0, 'SYSTEM', NOW()),
-('保证金比例', 1, 1, '%', '0~100', 'trade.MarginRate', 'trade.MarginRate', 113, 0, 'SYSTEM', NOW()),
-('客户授信额度', 1, 1, '元', '≥ 0', 'credit.Credit', 'credit.Credit', 114, 0, 'SYSTEM', NOW());
-
--- 4.4.2 行情类(Category=2,统一取上一交易日收盘价)
-INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
-('上一收盘日中债估值净价', 2, 1, '元', '≥ 0', '资讯数据', 'market.CBValuationNetPrice', 201, 0, 'SYSTEM', NOW()),
-('上一收盘日中债估值全价', 2, 1, '元', '≥ 0', '资讯数据', 'market.CBValuationFullPrice', 202, 0, 'SYSTEM', NOW()),
-('上一收盘日中债估值收益率', 2, 1, '%', NULL, '资讯数据', 'market.CBValuationYtm', 203, 0, 'SYSTEM', NOW()),
-('上一日收盘价', 2, 1, '元', '≥ 0', '行情数据,按标的区分', 'market.LastClosePrice', 204, 0, 'SYSTEM', NOW()),
-('借贷加权费率', 2, 1, '%', NULL, 'CMDM 标的债券借贷费率行情表', 'market.BondLendingRate', 205, 0, 'SYSTEM', NOW()),
-('FR007', 2, 1, '%', NULL, '上一交易日收盘价', 'market.FR007', 206, 0, 'SYSTEM', NOW()),
-('当前日期', 2, 2, NULL, NULL, 'DateTime.Today', 'sys.CurrentDate', 207, 0, 'SYSTEM', NOW()),
-('挂钩标的到期日', 2, 2, NULL, NULL, '资讯数据', 'market.UnderlyingMaturityDate', 208, 0, 'SYSTEM', NOW()),
-('标的发行余额', 2, 1, '元', '≥ 0', '资讯数据', 'market.UnderlyingIssueBalance', 209, 0, 'SYSTEM', NOW());
-
--- 4.4.3 系统计算值类(Category=3)
-INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
-('挂钩标的集中度', 3, 1, '%', '0~100', '同一标的存续交易总名义本金 ÷ 标的发行余额 × 100', 'calc.UnderlyingConcentration', 301, 0, 'SYSTEM', NOW()),
-('授信占用率', 3, 1, '%', '0~100', '(已占用授信 + 本笔授信占用) ÷ 授信总额 × 100', 'calc.CreditUsageRate', 302, 0, 'SYSTEM', NOW()),
-('合约期限', 3, 1, '天', '≥ 0', '(ExerciseDate - StartDate).Days', 'calc.MaturityDays', 303, 0, 'SYSTEM', NOW()),
-('Delta', 3, 1, NULL, NULL, 'realtime_trade_risk.Delta(预留接口,一期不纳入)', 'realtime_trade_risk.Delta', 304, 0, 'SYSTEM', NOW()),
-('Gamma', 3, 1, NULL, NULL, 'realtime_trade_risk.Gamma(预留接口,一期不纳入)', 'realtime_trade_risk.Gamma', 305, 0, 'SYSTEM', NOW()),
-('Vega', 3, 1, NULL, NULL, 'realtime_trade_risk.Vega(预留接口,一期不纳入)', 'realtime_trade_risk.Vega', 306, 0, 'SYSTEM', NOW()),
-('Theta', 3, 1, NULL, NULL, 'realtime_trade_risk.Theta(预留接口,一期不纳入)', 'realtime_trade_risk.Theta', 307, 0, 'SYSTEM', NOW()),
-('利息端利率', 3, 1, '%', NULL, '固定利率 或 FR007 ± 加点', 'calc.InterestRate', 308, 0, 'SYSTEM', NOW()),
-('对手方累计标的数量', 3, 1, '个', '≥ 0', 'COUNT(DISTINCT UnderlyingId) 该对手方所有存续交易,含本笔', 'calc.CounterpartyUnderlyingCount', 309, 0, 'SYSTEM', NOW()),
-('同一标的累计名义本金', 3, 1, '元', '≥ 0', 'SUM(该标的所有存续交易的 StockEqvNotional),含本笔', 'calc.SameUnderlyingTotalNotional', 310, 0, 'SYSTEM', NOW()),
-('同一客户累计名义本金', 3, 1, '元', '≥ 0', 'SUM(该客户所有存续交易的 StockEqvNotional),含本笔', 'calc.SameClientTotalNotional', 311, 0, 'SYSTEM', NOW()),
-('总持仓名义本金', 3, 1, '元', '≥ 0', 'SUM(所有存续交易的 StockEqvNotional)', 'calc.TotalPositionNotional', 312, 0, 'SYSTEM', NOW());
-
--- 4.4.4 布尔判断类(Category=4)
-INSERT INTO `glms_risk_variable` (`VariableName`, `Category`, `DataType`, `Unit`, `ValueDomain`, `Description`, `VariableExpr`, `SortOrder`, `OptId`, `OptName`, `OptDate`) VALUES
-('到期日是否银行间交易日', 4, 3, NULL, NULL, '查询银行间交易日历', 'calc.IsExerciseDateTradingDay', 401, 0, 'SYSTEM', NOW()),
-('平仓日是否银行间交易日', 4, 3, NULL, NULL, '查询银行间交易日历', 'calc.IsUnwindDateTradingDay', 402, 0, 'SYSTEM', NOW()),
-('支付日是否银行间交易日', 4, 3, NULL, NULL, '查询银行间交易日历', 'calc.IsSettlementDateTradingDay', 403, 0, 'SYSTEM', NOW()),
-('利息端/浮动端方向是否同向', 4, 3, NULL, NULL, '利息端"收取"↔浮动端"多头",利息端"支付"↔浮动端"空头"', 'calc.IsInterestFloatSameDirection', 404, 0, 'SYSTEM', NOW()),
-('关键业务要素是否一致', 4, 3, NULL, NULL, '交易确认书 vs 簿记要素(大模型方案)', 'calc.IsKeyElementsConsistent', 405, 0, 'SYSTEM', NOW()),
-('多空方向为多头', 4, 3, NULL, NULL, 'trade.BuySell == "买入" 或浮动端为多头', 'calc.IsLongDirection', 406, 0, 'SYSTEM', NOW()),
-('多空方向为空头', 4, 3, NULL, NULL, '与多头互斥', 'calc.IsShortDirection', 407, 0, 'SYSTEM', NOW()),
-('保证金收支方向为支付', 4, 3, NULL, NULL, '保证金方向为支付', 'calc.IsMarginPay', 408, 0, 'SYSTEM', NOW()),
-('保证金收支方向为收取', 4, 3, NULL, NULL, '与支付互斥', 'calc.IsMarginReceive', 409, 0, 'SYSTEM', NOW());
diff --git a/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs b/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs
index 0d2f778f..55115803 100644
--- a/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs
+++ b/YLErpDAL/Modules/RiskEngine/Compile/RuleCompiler.cs
@@ -32,7 +32,8 @@ namespace YLErp.Modules.RiskEngine
/// - 可调试:生成的脚本代码可直接阅读和理解
///
/// 示例:
- /// RuleExpr: Convert.ToDecimal(((YLErp.DBModels.trade)DataMap["trade"]).StockEqvNotional) > 100000000m
+ /// FormulaJson: { "conditions": [{"variableCode":"trade.StockEqvNotional","operator":">","value":100000000}] }
+ /// 生成脚本:Convert.ToDecimal(((YLErp.DBModels.trade)DataMap["trade"]).StockEqvNotional) > 100000000m
/// 编译结果:Func<RiskContext, bool>(内部通过 Roslyn 编译缓存)
///
public static class RuleCompiler
@@ -62,48 +63,51 @@ namespace YLErp.Modules.RiskEngine
///
public static void Compile(this RiskRule rule)
{
- var result = ValidateAndCompileRule(rule);
- if (!result.Success)
+ if (string.IsNullOrWhiteSpace(rule.FormulaJson))
{
- throw new InvalidOperationException(result.ErrorMessage);
+ throw new ArgumentException("规则 FormulaJson 不能为空", nameof(rule.FormulaJson));
}
+
+ // 1. 解析 FormulaJson
+ var conditions = ParseFormulaJson(rule.FormulaJson);
+
+ // 2. 生成 Roslyn C# 脚本代码
+ string scriptCode = BuildScriptCode(conditions);
+
+ // 3. 编译脚本(只编译一次,后续直接执行)
+ var compiled = CompileScript(scriptCode);
+
+ // 4. 写入规则(不持久化,仅内存缓存)
+ rule.CompiledScript = compiled;
}
///
- /// 校验并编译规则表达式。
- /// 当前 RuleExpr 要求是 Roslyn 可直接执行的 bool 表达式。
+ /// 解析 FormulaJson,提取条件列表
///
- public static RuleCompileResult ValidateAndCompileFormula(string formulaExp)
+ private static List<(string variableCode, string op, object value, string variableType)> ParseFormulaJson(string formulaJson)
{
- if (string.IsNullOrWhiteSpace(formulaExp))
+ var result = new List<(string, string, object, string)>();
+ var jObj = JObject.Parse(formulaJson);
+ var conditions = jObj["conditions"] as JArray;
+
+ if (conditions == null || !conditions.Any())
{
- return RuleCompileResult.Fail("规则 RuleExpr 不能为空");
+ throw new ArgumentException("FormulaJson 中缺少 conditions");
}
try
{
- var compiled = CompileScript(formulaExp);
- return RuleCompileResult.Ok(compiled);
- }
- catch (Exception ex)
- {
- return RuleCompileResult.Fail(ex.Message);
- }
- }
+ string variableCode = cond["variableCode"]?.Value();
+ string op = cond["operator"]?.Value();
+ object value = cond["value"]?.Value |