Merge remote-tracking branch 'dest/glms/feature/1.4.2' into feature/p132_74-risk-engine
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
using Org.BouncyCastle.Ocsp;
|
||||
using Newtonsoft.Json;
|
||||
using YLErp.Helpers;
|
||||
using YLErp.DBModels.Enums;
|
||||
using YLErp.Model.Enum;
|
||||
using YLErp.Modules.AppModule;
|
||||
@@ -43,7 +45,7 @@ namespace YLErp.Web.Controllers
|
||||
[HttpPost]
|
||||
public ActionResult AddProcess(string type, List<ApprovalProcessAddRequest> data)
|
||||
{
|
||||
if (type == "TradeProcess" && data != null && data.Count > 0)
|
||||
if ((type == "TradeProcess" || type == "CloseProcess") && data != null && data.Count > 0)
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
@@ -54,6 +56,25 @@ namespace YLErp.Web.Controllers
|
||||
}
|
||||
}
|
||||
|
||||
// 校验节点触发条件 JSON 格式,避免非法数据入库
|
||||
if (data != null)
|
||||
{
|
||||
foreach (var item in data)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(item.triggerCondition))
|
||||
{
|
||||
try
|
||||
{
|
||||
JsonConvert.DeserializeObject<ConditionExpressionConfig>(item.triggerCondition);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return JsonError("触发条件格式非法,请检查括号与条件是否完整");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new ApprovalProcessService(CurUser).AddProcess(type, data);
|
||||
return JsonSuccess("设置成功");
|
||||
}
|
||||
@@ -66,10 +87,13 @@ namespace YLErp.Web.Controllers
|
||||
|
||||
var tradeProcess = list.Where(s => s.processType == "TradeProcess").OrderBy(s => s.order).ThenBy(s => s.parentNode).ThenBy(s => s.node).ToList();
|
||||
|
||||
// 需求②:了结/平仓/行权审批流程
|
||||
var closeProcess = list.Where(s => s.processType == "CloseProcess").OrderBy(s => s.order).ThenBy(s => s.parentNode).ThenBy(s => s.node).ToList();
|
||||
|
||||
var creditProcess = list.Where(s => s.processType == "CreditProcess").OrderBy(s => s.order).ToList();
|
||||
var outCashProcess = list.Where(s => s.processType == "OutCashProcess").OrderBy(s => s.order).ToList();
|
||||
var clientProcess = list.Where(s => s.processType == "ClientProcess").OrderBy(s => s.order).ThenBy(s => s.parentNode).ThenBy(s => s.node).ToList();
|
||||
return Json(new { OpenProcess = openProcess, TradeProcess = tradeProcess, CreditProcess = creditProcess, OutCashProcess= outCashProcess,ClientProcess = clientProcess });
|
||||
return Json(new { OpenProcess = openProcess, TradeProcess = tradeProcess, CloseProcess = closeProcess, CreditProcess = creditProcess, OutCashProcess= outCashProcess,ClientProcess = clientProcess });
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using YLErp.DBModels;
|
||||
using YLErp.Core;
|
||||
using YLErp.DBModels;
|
||||
using YLErp.Modules.EodModule;
|
||||
|
||||
namespace YLErp.Web.Controllers
|
||||
@@ -54,9 +55,13 @@ namespace YLErp.Web.Controllers
|
||||
|
||||
public ActionResult EodFuturePriceEdit(string enid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(enid) || enid == "0")
|
||||
bool isNew = string.IsNullOrEmpty(enid) || enid == "0";
|
||||
ViewBag.IsNew = isNew;
|
||||
if (isNew)
|
||||
{
|
||||
return View(new eod_commodity_future_price());
|
||||
// 新建:手工输入标的代码,失焦时调 LookupUnderlyingForEod 校验并带出市场/UnderlyingId。
|
||||
// 默认估值日期=今天:避免未填日期时落库为 0001-01-01、落在列表默认窗口(今天)之外而查不出。
|
||||
return View(new eod_commodity_future_price { ValueDate = DateTime.Today });
|
||||
}
|
||||
var intid = DecryptInt(enid);
|
||||
var dbmodel = yldb.eod_commodity_future_price.Find(intid);
|
||||
@@ -70,9 +75,12 @@ namespace YLErp.Web.Controllers
|
||||
|
||||
public ActionResult EodStockPriceEdit(string enid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(enid) || enid == "0")
|
||||
bool isNew = string.IsNullOrEmpty(enid) || enid == "0";
|
||||
ViewBag.IsNew = isNew;
|
||||
if (isNew)
|
||||
{
|
||||
return View(new eod_stock_price());
|
||||
// 新建:手工输入标的代码,失焦时调 LookupUnderlyingForEod 校验并带出市场。
|
||||
return View(new eod_stock_price { ValueDate = DateTime.Today });
|
||||
}
|
||||
var intid = DecryptInt(enid);
|
||||
var dbmodel = yldb.eod_stock_price.Find(intid);
|
||||
@@ -85,9 +93,13 @@ namespace YLErp.Web.Controllers
|
||||
}
|
||||
public ActionResult EodBondPriceEdit(string enid)
|
||||
{
|
||||
if (string.IsNullOrEmpty(enid) || enid == "0")
|
||||
bool isNew = string.IsNullOrEmpty(enid) || enid == "0";
|
||||
ViewBag.IsNew = isNew;
|
||||
if (isNew)
|
||||
{
|
||||
return View(new ChinaBondValuation());
|
||||
// 新建:手工输入债券代码(bond_id),失焦时调 LookupUnderlyingForEod 校验并带出市场。
|
||||
// 默认估值日期=今天:避免未填日期时落库为 0001-01-01、落在列表默认窗口(今天)之外而查不出。
|
||||
return View(new ChinaBondValuation { valuation_date = DateTime.Today });
|
||||
}
|
||||
var intid = DecryptLong(enid);
|
||||
var dbmodel = yldb.china_bond_valuation.Find(intid);
|
||||
@@ -98,6 +110,129 @@ namespace YLErp.Web.Controllers
|
||||
ViewData["市场"] = DataCacheProvider.GetUnderlyingDataSource().GetData(dbmodel.bond_id)?.MarketName;
|
||||
return View(dbmodel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新建日终价格时,按用户手工输入的标的代码精确查一条标的,带出名称/市场/Id。
|
||||
/// 只返回已上市(LaunchState=="1")且类型匹配的标的——与列表查询 inner join 的过滤对齐,
|
||||
/// 从源头杜绝"新增能存但查不出"的幽灵记录。前端在输入框失焦时调用,不依赖任何下拉/补全插件。
|
||||
/// </summary>
|
||||
/// <param name="code">标的代码(用户手工输入)</param>
|
||||
/// <param name="kind">bond | future | stock,决定允许的标的类型集合</param>
|
||||
[HttpPost]
|
||||
public JsonResult LookupUnderlyingForEod(string code, string kind)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(code))
|
||||
{
|
||||
return JsonError("请输入标的代码");
|
||||
}
|
||||
code = code.Trim();
|
||||
|
||||
string[] types = kind switch
|
||||
{
|
||||
"future" => new[]
|
||||
{
|
||||
ConsGlobal.InstrumentType.CommodityFutures,
|
||||
ConsGlobal.InstrumentType.GoldFutures,
|
||||
ConsGlobal.InstrumentType.TBFutures,
|
||||
ConsGlobal.InstrumentType.OtherFutures,
|
||||
ConsGlobal.InstrumentType.AbroadFutures,
|
||||
},
|
||||
"stock" => new[]
|
||||
{
|
||||
ConsGlobal.InstrumentType.Stock,
|
||||
ConsGlobal.InstrumentType.StockIndex,
|
||||
ConsGlobal.InstrumentType.StockIF,
|
||||
ConsGlobal.InstrumentType.HKStock,
|
||||
ConsGlobal.InstrumentType.HKStockIndex,
|
||||
ConsGlobal.InstrumentType.NewOtcStock,
|
||||
ConsGlobal.InstrumentType.AbroadStock,
|
||||
ConsGlobal.InstrumentType.AbroadStockIndex,
|
||||
},
|
||||
_ => new[]
|
||||
{
|
||||
ConsGlobal.InstrumentType.Bonds,
|
||||
ConsGlobal.InstrumentType.TBonds,
|
||||
ConsGlobal.InstrumentType.CreditBonds,
|
||||
ConsGlobal.InstrumentType.OtherBonds,
|
||||
},
|
||||
};
|
||||
var set = new HashSet<string>(types);
|
||||
|
||||
var u = yldb.underlying_manager
|
||||
.Where(n => n.UnderlyingCode == code && n.LaunchState == "1" && set.Contains(n.UnderlyingInstrumentType))
|
||||
.Select(n => new { n.id, n.UnderlyingCode, n.UnderlyingName, n.MarketName })
|
||||
.FirstOrDefault();
|
||||
|
||||
if (u == null)
|
||||
{
|
||||
return JsonError("未找到该标的(不存在、未上市或类型不匹配),无法录入");
|
||||
}
|
||||
|
||||
return JsonSuccess("", new
|
||||
{
|
||||
Id = u.id,
|
||||
Code = u.UnderlyingCode,
|
||||
Name = u.UnderlyingName,
|
||||
Market = u.MarketName,
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 新建日终价格时,按手工输入的片段做服务端模糊联想(代码或名称包含匹配),只回前 20 条。
|
||||
/// 与 LookupUnderlyingForEod 同样只返回已上市(LaunchState=="1")且类型匹配的标的。
|
||||
/// 用原生下拉渲染(不依赖 jQuery UI,bundle 未打包),避免几十万标的全量渲染卡死。
|
||||
/// </summary>
|
||||
[HttpPost]
|
||||
public JsonResult SuggestUnderlyingForEod(string q, string kind)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(q))
|
||||
{
|
||||
return JsonSuccess("", new List<object>());
|
||||
}
|
||||
q = q.Trim();
|
||||
|
||||
string[] types = kind switch
|
||||
{
|
||||
"future" => new[]
|
||||
{
|
||||
ConsGlobal.InstrumentType.CommodityFutures,
|
||||
ConsGlobal.InstrumentType.GoldFutures,
|
||||
ConsGlobal.InstrumentType.TBFutures,
|
||||
ConsGlobal.InstrumentType.OtherFutures,
|
||||
ConsGlobal.InstrumentType.AbroadFutures,
|
||||
},
|
||||
"stock" => new[]
|
||||
{
|
||||
ConsGlobal.InstrumentType.Stock,
|
||||
ConsGlobal.InstrumentType.StockIndex,
|
||||
ConsGlobal.InstrumentType.StockIF,
|
||||
ConsGlobal.InstrumentType.HKStock,
|
||||
ConsGlobal.InstrumentType.HKStockIndex,
|
||||
ConsGlobal.InstrumentType.NewOtcStock,
|
||||
ConsGlobal.InstrumentType.AbroadStock,
|
||||
ConsGlobal.InstrumentType.AbroadStockIndex,
|
||||
},
|
||||
_ => new[]
|
||||
{
|
||||
ConsGlobal.InstrumentType.Bonds,
|
||||
ConsGlobal.InstrumentType.TBonds,
|
||||
ConsGlobal.InstrumentType.CreditBonds,
|
||||
ConsGlobal.InstrumentType.OtherBonds,
|
||||
},
|
||||
};
|
||||
var set = new HashSet<string>(types);
|
||||
|
||||
var list = yldb.underlying_manager
|
||||
.Where(n => n.LaunchState == "1" && set.Contains(n.UnderlyingInstrumentType)
|
||||
&& (n.UnderlyingCode.Contains(q) || n.UnderlyingName.Contains(q)))
|
||||
.OrderBy(n => n.UnderlyingCode)
|
||||
.Take(20)
|
||||
.Select(n => new { n.id, Code = n.UnderlyingCode, Name = n.UnderlyingName, Market = n.MarketName })
|
||||
.ToList();
|
||||
|
||||
return JsonSuccess("", list);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public JsonResult EodFuturePriceEditJson(eod_commodity_future_price req)
|
||||
{
|
||||
|
||||
@@ -283,9 +283,12 @@ namespace YLErp.Web.Controllers
|
||||
/// <param name="tradeId"></param>
|
||||
/// <param name="closePercent"></param>
|
||||
/// <returns></returns>
|
||||
public JsonResult GetUnwindInterestList(DateTime valueDate,DateTime unwindDate, int tradeId, decimal closePercent, int eventType)
|
||||
public JsonResult GetUnwindInterestList(DateTime valueDate,DateTime unwindDate, int tradeId, decimal closePercent, int eventType, decimal notionalValue = 0, decimal posiNotionalValue = 0)
|
||||
{
|
||||
var interests = new SwapDealService(CurUser).GetUnwindInterests(valueDate, unwindDate, tradeId, closePercent, eventType);
|
||||
// 前端按"占期初(original)"语义传 closePercent(A);后端 GetUnwindInterests 按"占剩余(remaining)"语义(B)计算。
|
||||
// 多空互换前端不传 notionalValue/posiNotionalValue(默认 0),则跳过转换保持原行为。
|
||||
var convertedClosePercent = SwapDealService.ToRemainingClosePercent(closePercent, notionalValue, posiNotionalValue);
|
||||
var interests = new SwapDealService(CurUser).GetUnwindInterests(valueDate, unwindDate, tradeId, convertedClosePercent, eventType);
|
||||
foreach (var interest in interests)
|
||||
{
|
||||
interest.TdInterestAmount=Math.Round(interest.TdInterestAmount, ConsGlobal.MoneyRound,MidpointRounding.AwayFromZero);
|
||||
|
||||
@@ -296,5 +296,13 @@ namespace YLErp.Web.Controllers
|
||||
CalendarBLL.ResetCalendarForQdp();
|
||||
return JsonSuccess("删除成功");
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public JsonResult Reset()
|
||||
{
|
||||
CalendarBLL.IsListOld = true;
|
||||
CalendarBLL.ResetCalendarForQdp();
|
||||
return JsonSuccess("重置成功");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6370,14 +6370,17 @@ namespace YLErp.Web.Controllers
|
||||
return ShowError("请选择文档类型!");
|
||||
}
|
||||
|
||||
if (req.TradeDateStart == null) { req.TradeDateStart = DateTime.MinValue; }
|
||||
if (req.TradeDateEnd == null) { req.TradeDateEnd = DateTime.MaxValue; }
|
||||
var db_trade_contract_r = yldb.trade_contract_r.AsQueryable();
|
||||
var documentQuery = TradeConfirmationDocumentQuery.Create(
|
||||
yldb.trade_contract_document,
|
||||
yldb.trade_contract_r,
|
||||
yldb.trade,
|
||||
req.TradeDateStart,
|
||||
req.TradeDateEnd);
|
||||
|
||||
var query = from doc in yldb.trade_contract_document
|
||||
join r in db_trade_contract_r
|
||||
on doc.Code equals r.ContractCode
|
||||
where doc.Type == ContractTypeEnum.Trade && doc.ValueDate >= req.TradeDateStart && doc.ValueDate <= req.TradeDateEnd && r.IsValid
|
||||
var query = from item in documentQuery
|
||||
let doc = item.Document
|
||||
let r = item.Relation
|
||||
where doc.Type == ContractTypeEnum.Trade
|
||||
select new
|
||||
{
|
||||
doc.ClientId,
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace YLErp.Web.Controllers
|
||||
{
|
||||
valueDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate);
|
||||
}
|
||||
if (!EodPriceQueryService.TryGetEodPrice(valueDate, td.UnderlyingCode, out _))
|
||||
if (!EodPriceQueryService.TryGetSettlementEodPrice(valueDate, td.UnderlyingCode, out _))
|
||||
{
|
||||
return JsonError($"交易日{valueDate:yyyy-MM-dd}的结算价或收盘价未找到!");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user