修改成仅期权确认书页面

This commit is contained in:
锦麟 王
2026-03-24 13:41:50 +08:00
parent 9bbd512707
commit 9be15621f5
8 changed files with 218 additions and 10 deletions
@@ -177,6 +177,9 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule
{
foreach (var tradeContractGroup in tradeDic.Values)
{
//判断是否为期权交易(非收益互换的交易强制走默认逻辑V1,不走插件)
var isOptionTrade = tradeContractGroup.trade.TradeType != "收益互换";
//插件版本(期权交易强制使用V1默认逻辑)
if ((tradeContractGroup.trade.TradeType != "结构化交易" && tradeContractGroup.trade.TradeType != "收益互换" && tradeContractGroup.trade_cash == null)
|| (tradeContractGroup.trade.TradeType == "结构化交易" && tradeContractGroup.trade.IsGroup == 0 && tradeContractGroup.trade.SubTrades.Any(O => O.trade_cash == null)))
{
@@ -185,8 +188,7 @@ namespace YLErp.Modules.TradeModule.DocGenerateModule
ErrorMessage = "缺少现金交割记录"
});
}
//插件版本
else if (generatorV2 != null)
else if (generatorV2 != null && !isOptionTrade)
{
var result = GenerateSingleV2(generatorV2, tradeContractGroup, docType);
resultList.Add(result);
+1
View File
@@ -79,6 +79,7 @@
<FunctionSub Name="交易确认书" Title="交易确认书"></FunctionSub>
<FunctionSub Name="交易确认书生成" Title="交易确认书生成" Type="Operate" Note="是否有交易确认书生成权限" ></FunctionSub>
<FunctionSub Name="交易确认书邮件发送" Title="交易确认书邮件发送" Type="Operate" Note="是否有交易确认书邮件发送权限" ></FunctionSub>
<FunctionSub Name="交易确认书-期权" Title="交易确认书-期权" Note="期权交易确认书页面访问权限"></FunctionSub>
<FunctionSub Name="结算确认书" Title="结算确认书"></FunctionSub>
<FunctionSub Name="结算确认书生成" Title="结算确认书生成" Type="Operate" Note="是否有结算确认书生成权限" ></FunctionSub>
<FunctionSub Name="结算确认书重置" Title="结算确认书重置" Type="Operate" Note="是否有结算确认书重置权限" ></FunctionSub>
+1
View File
@@ -42,6 +42,7 @@
{Name:"资金审批",Rights:["结算管理-资金审批页面"],Url:"entryexit/entryexitApproval"},
{Name:"收盘操作",Rights:["结算管理-收盘操作"],Url:"eod_trade_value/eodExec"},
{Name:"交易确认书",Rights:["结算管理-交易确认书"],Url:"TradeConfirmBook/ConfirmBookListByClient"},
{Name:"交易确认书_期权",Rights:["结算管理-交易确认书-期权"],Url:"TradeConfirmBook/IndexOption"},
{Name:"结算确认书",Rights:["结算管理-结算确认书"],Url:"swaptrade2/tradeEndConfirmList"},
{Name:"每日估值报告",Rights:["结算管理-每日估值报告"],Url:"clientbalance/TradeMarketReport"},
{Name:"其他报告",Rights:["结算管理-其他报告"],Url:"supervise_report/ExtendReport"},
+1
View File
@@ -636,6 +636,7 @@ namespace YLErp.Web
public bool _交易确认书生成 => HasRight("结算管理-交易确认书生成");
public bool _交易确认书查看 => HasRight("结算管理-交易确认书");
public bool _交易确认书邮件发送 => HasRight("结算管理-交易确认书邮件发送");
public bool _交易确认书期权查看 => HasRight("结算管理-交易确认书-期权");
public bool _结算确认书生成 => HasRight("结算管理-结算确认书生成");
public bool _结算确认书重置 => HasRight("结算管理-结算确认书重置");
public bool _结算确认书邮件发送 => HasRight("结算管理-结算确认书邮件发送");
@@ -64,6 +64,37 @@ namespace YLErp.Web.Controllers
return View();
}
// GET - 期权交易确认书页面
[MyAuthorize("结算管理-交易确认书-期权")]
public ActionResult IndexOption()
{
ViewBag.ValueDate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd");
if (GlobalConfig.SelectConfirmationBookTemplate)
{
try
{
if (string.IsNullOrWhiteSpace(GlobalConfig.PluginFolder))
{ throw new Exception("未找到插件路径"); }
var dirPath = Path.Combine(GlobalConfig.PluginFolder, "App_Docs", ContractTypeEnum.Trade);
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}
var paths = Directory.GetFiles(dirPath, "*.docx");
for (var i = 0; i < paths.Length; i++)
{
paths[i] = Path.GetFileName(paths[i]);
}
ViewBag.TemplateNames = paths;
}
catch (Exception ex)
{
LogFactory.GetLogger("SelectConfirmationBookTemplate").Error(ex);
}
}
return View("~/Views/TradeConfirmBookOption/Index.cshtml");
}
public JsonResult ToPdf(string enid)
{
var intid = DataProtectHelper.DecryptInt(enid);
@@ -87,6 +118,74 @@ namespace YLErp.Web.Controllers
return Json(result);
}
/// <summary>
/// 期权确认书查询(排除收益互换)
/// </summary>
public JsonResult OptionQuery(TradeReq req)
{
req.AssetIdList = AssetUnitModel.IntersectAssetUnits(req.AssetIdGroupList, req.AssetIdList).ToList();
req.UserAssets = CurUser.GetAssetUnitIds();
req.UserClients = CurUser.GetClientIdsByCurUser(CurUser._查看所有交易);
req.CurUserTradeIds = CurUser.GetTradeIdsByCurUser();
// 排除收益互换
req.NotInTradeTypes = new List<string> { "收益互换" };
var sList = new tradeBLL().SearchListForTradeConfirm(req);
var rowList = sList.rows;
// 增加交易确认书编号
if (rowList != null && rowList.Any())
{
var tradeIds = rowList.Select(x => x.id).ToList();
var tradeContractCodeList = (from tradeContractR in yldb.trade_contract_r
join tradeContractDoc in (from tradeContractDocTemp in yldb.trade_contract_document where ContractTypeEnum.Trade == tradeContractDocTemp.Type select tradeContractDocTemp)
on tradeContractR.ContractCode equals tradeContractDoc.Code into tradeContractDoc1
from tradeContractDoc2 in tradeContractDoc1.DefaultIfEmpty()
where tradeIds.Contains(tradeContractR.TradeId) && ContractTypeEnum.Trade == tradeContractR.Type && tradeContractR.Type == tradeContractDoc2.Type && tradeContractR.IsValid
select new
{
tradeContractR.id,
tradeContractR.TradeId,
tradeContractR.ContractCode,
tradeContractR.send_email_result,
tradeContractDoc = tradeContractDoc2
}).ToList();
foreach (var trade in rowList)
{
if (trade.TradeType == "合成价差期权")
{
trade.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(trade.UnderlyingCode);
}
var tradeContractinfo = tradeContractCodeList.FirstOrDefault(t => t.TradeId == trade.id);
trade.MetaDic["send_email_result"] = "";
if (tradeContractinfo != null)
{
trade.ContractCode = tradeContractinfo.ContractCode;
if (null != tradeContractinfo.tradeContractDoc)
{
trade.MetaDic["ContractEncryptId"] = tradeContractinfo.tradeContractDoc.EncryptId;
trade.MetaDic["ContractRId"] = tradeContractinfo.id.ToString();
trade.MetaDic["ContractDocUrl"] = tradeContractinfo.tradeContractDoc.RelativePath;
trade.MetaDic["HasGeneratedConfirmBook"] = "True";
trade.MetaDic["send_email_result"] = tradeContractinfo.send_email_result;
}
else
{
trade.MetaDic["ContractEncryptId"] = "";
trade.MetaDic["ContractRId"] = tradeContractinfo.id.ToString();
trade.MetaDic["HasGeneratedConfirmBook"] = "False";
}
}
else
{
trade.MetaDic["ContractEncryptId"] = "";
trade.MetaDic["ContractRId"] = "";
trade.MetaDic["HasGeneratedConfirmBook"] = "False";
}
}
}
return Json(sList);
}
public async Task<ActionResult> SentMail(string enid, List<string> reciver)
{
var result = await DoSendMailSywg(enid, reciver);
+9 -7
View File
@@ -1464,6 +1464,8 @@ namespace YLErp.Web.Controllers
for (var i = 0; i < Request.Form.Files.Count; i++)
{
var file = Request.Form.Files[i];
// 安全处理:使用 Path.GetFileName 提取纯文件名,防止路径遍历攻击
var safeFileName = Path.GetFileName(file.FileName);
var protocolTypes = new List<string>() { "主协议附件(PDF)", "补充协议附件(PDF)", "履约协议附件(PDF)", "代签产品附件(PDF)" };
var filePath = isSuitably == "true" ? $"~/App_Docs/ClientFiles/SuitablyFiles/{clientPath}" : $"~/App_Docs/ClientFiles/{clientPath}";
if (!Directory.Exists(filePath))
@@ -1471,13 +1473,13 @@ namespace YLErp.Web.Controllers
Directory.CreateDirectory(Server.MapPath(filePath));
}
var oldName = $"{fileDesc}-{file.FileName}";
var oldName = $"{fileDesc}-{safeFileName}";
//check fileName protocol
if (!string.IsNullOrWhiteSpace(ProtocolNumber))
{
var OtherClientFilesName = clientDB.client_file.Where(o => o.ApprovalOrder < 1 && o.ClientId != client.id && o.ProtocolNumber != null && o.ProtocolNumber != "" && o.IsValid).Select(o => new { o.FileName, o.FileDesc }).ToList();
if (OtherClientFilesName.Where(o => o.FileName.ToUpper() == oldName.ToUpper() || o.FileName.ToUpper() == file.FileName.ToUpper()).Any())
if (OtherClientFilesName.Where(o => o.FileName.ToUpper() == oldName.ToUpper() || o.FileName.ToUpper() == safeFileName.ToUpper()).Any())
{
return JsonError("其他客户有协议使用的文件与该文件重名,请修改文件名后上传。");
}
@@ -1491,7 +1493,7 @@ namespace YLErp.Web.Controllers
{
return JsonError("该协议编号已存在,且已废弃删除,请修改协议编号后上传。");
}
if (clientDB.client_file.Where(O => O.ApprovalOrder < 1 && (O.FileName == file.FileName || O.FileName == oldName) && O.ProtocolNumber != null && O.ProtocolNumber != "" && O.ProtocolNumber != ProtocolNumber && O.IsValid).Any())
if (clientDB.client_file.Where(O => O.ApprovalOrder < 1 && (O.FileName == safeFileName || O.FileName == oldName) && O.ProtocolNumber != null && O.ProtocolNumber != "" && O.ProtocolNumber != ProtocolNumber && O.IsValid).Any())
{
return JsonError("该文件已属于其他协议,请上传未使用的文件。");
}
@@ -1554,22 +1556,22 @@ namespace YLErp.Web.Controllers
clientFile.MainProtocolNumber = MainProtocolNumber;
}
clientFile.FileName = file.FileName;
clientFile.FileName = safeFileName;
clientFile.FileDesc = fileDesc;
clientFile.ClientId = client.id;
clientFile.FileDesc = fileDesc;
clientFile.OptId = CurUser.UserId;
clientFile.OptName = CurUser.UserName;
clientFile.OptDate = optDateTime; // DateTime.Now
clientFile.OptDate = optDateTime; // DateTime.Now
clientFile.ProtocolNumber = ProtocolNumber;
clientFile.HasSent = false;
clientFile.FilePath = Path.Combine(filePath.TrimStart('~'), file.FileName);
clientFile.FilePath = Path.Combine(filePath.TrimStart('~'), safeFileName);
clientFile.IsValid = true;
var ret = new ClientFileService(CurUser).UploadFile(clientFile);
if (string.IsNullOrWhiteSpace(ret) || ret == "修改成功")
{
file.SaveAs(Path.Combine(Server.MapPath(filePath), file.FileName));
file.SaveAs(Path.Combine(Server.MapPath(filePath), safeFileName));
LogFactory.GetLogger<ClientController>().Info($"客户{client.Name}(id:{client.id})上传文件({file.FileName}),真实上传时间:{DateTime.Now},客户选择的日期:{optDateTime}");
if (ret == "修改成功")
{
@@ -0,0 +1,102 @@
@{
ViewBag.Title = "交易确认书_期权";
Layout = "~/Views/Shared/_MainLayout.cshtml";
var pageObj = new
{
isGDGZ = YLErp.PS.Config.Company == CompanyEnum.光大光子,
isGTJA = YLErp.PS.Config.Company == CompanyEnum.国泰君安,
isHaiTong = YLErp.PS.Config.Company == YLErp.Configuration.CompanyEnum.海通,
isRuiDa = YLErp.PS.Config.Company == YLErp.Configuration.CompanyEnum.瑞达,
isBoHai = YLErp.PS.Config.Company == YLErp.Configuration.CompanyEnum.渤海,
isWuChan = YLErp.PS.Config.Company == YLErp.Configuration.CompanyEnum.物产中大,
ConfirmBookStampStatus = PS.Config.ErpElement.ConfirmBookStampStatus,
valuedate = valuedateBLL.ValueDate.ToString("yyyy-MM-dd"),
configcolumn = configcolumn_data.交易确认书,
SettleDocModeMultiple = valuedate.SettleDocModeMultiple.Equals(valuedateBLL.SystemDate.SettleDocMode),
BrokerMode = YLErp.PS.Config.ComponentVersion == YLErp.Configuration.ComponentVersion.Broker,
MarketMaker = YLErp.PS.Config.ComponentVersion == YLErp.Configuration.ComponentVersion.MarketMaker,
reqTradeStatus = $"{ConsTrade.确认成交},{ConsTrade.已到期},{ConsTrade.已平仓},{ConsTrade.已执行}",
SelectConfirmationBookTemplate = GlobalConfig.SelectConfirmationBookTemplate == true,
templateNames = ViewBag.TemplateNames,
//初始化时使用空页面(清楚预置查询条件及初始不加载数据)
initEmptyView = YLErp.PS.Config.Company == YLErp.Configuration.CompanyEnum.弘业,
IsAutoSealAndUploadFiles = YLErp.PS.GetErpConfig().IsAutoSealAndUploadFiles,
IsZheQi = PS.Config.Is浙期,
IsAutoSealAfterGeneratedBook = PS.GetErpConfig().IsAutoSealAfterGeneratedBook,
canGenerate = CurUser.结算管理_交易确认书生成,
canSendEmail = CurUser.结算管理_交易确认书邮件发送,
// 标识为期权确认书页面
isOptionPage = true
};
// 期权交易类型:排除收益互换、远期、掉期等非期权类型
var tradeTypes = ConsTrade.AllTradeTypes
.Except(new List<string> { "场内期权", "股票", "收益互换", "远期", "掉期", "商品期货", "商品现货" })
.Concat(new List<string> { "黑箱结构" });
}
@section CSS{
<style>
table input[type=text][disabled] {
border: none;
background-color: transparent !important;
text-align: left;
}
.no-skin {
position: static !important;
}
</style>
}
@section JS{
<script src="~/statics/libs/signalr/dist/browser/signalr.min.js"></script>
<script src="~/Scripts/app/tradeHelper.js?v=@HtmlUtil.JsVersion"></script>
<script type="text/javascript">
var page = @Json.Serialize(pageObj);
</script>
<script src="~/Scripts/app/trade/tradeConfirmBook.js?v=@(HtmlUtil.JsVersion)"></script>
}
<div class="searchdiv">
@Html.ShortInput("TradeNumber", "交易编号")
@Html.ShortInput("ContractCode", "合约编号")
@Html.MyAceDropdownInput("ClientId", "客户名称", ClientDataModel.GetAllClient())
@Html.MyAceDropdownInput("AssetId", "簿记账户", AssetunitController.GetClientassetunit())
@Html.MyAceDropdownInput("GroupId", "簿记账户组", AssetUnitModel.GetAllAssetUnitGroupItem())
<div class="search-group">
<span class="search-label">标的代码</span>
<select class="" data-placeholder="请选择 标的代码" id="UnderlyingId" name="UnderlyingId" multiple></select>
</div>
@Html.MyAceDropdownInput2("BuySell", "交易方向", GlobalData.GetSelectItems(new List<string> { "买入", "卖出" }))
@Html.SearchDateRange("ExerciseDate", "到期日期")
@Html.SearchDateRange("TradeDate", "交易日期")
@Html.MyAceDropdownInput("TradeStatus", "交易状态", GlobalData.TradeStatusAfterConfirm(), true)
@if (pageObj.IsAutoSealAndUploadFiles){
@Html.MyAceDropdownInput("SealResults", "用印结果", GlobalData.GetSealResultItems())
@Html.SearchDateRange("SealDate", "用印日期")
}
@Html.ShortInput("Comments", "备注")
<br />
@MyControls.SearchBtn()
@if (pageObj.canGenerate)
{
@MyControls.Btn("批量生成交易确认书", "BatchCreateContracts()")
}
@MyControls.Btn("批量下载交易确认书", "BatchDownLoadDoc()")
<button class="btn btn-primary" id="batchSendEmail" style="margin-left:16px;">批量发送邮件</button>
@if (PS.GetErpConfig().IsAutoSealAndUploadFiles && !PS.GetErpConfig().IsAutoSealAfterGeneratedBook)
{
@MyControls.Btn("批量确认书用印", "BatchSealContracts()")
}
<div style="width:30px;display:inline;" onclick="showcolumnChooser();return false;">
<img src="~/Images/configure.png" />
</div>
</div>
@Html.Raw(JqGridSimple.OutTable())
<a download="" href="" target="_blank" id="downPdf"></a>
@await Html.PartialAsync("/Views/Common/_chooseContractType.cshtml", "sendReport()")
@@ -420,7 +420,7 @@ function __initJqGrid() {
onJqgridPaging: typeof onJqgridPaging !== 'undefined' ? onJqgridPaging : void 0
};
var grid = jQuery('#listGrid').jqGrid({
url: '/trade/tradeConfirmEmailQuery',
url: page.isOptionPage ? '/TradeConfirmBook/OptionQuery' : '/trade/tradeConfirmEmailQuery',
datatype: page.initEmptyView ? 'local' : 'json',
height: 'auto',
width: '90%',