diff --git a/YLErpDAL/Modules/TradeModule/OAModels.cs b/YLErpDAL/Modules/TradeModule/OAModels.cs index 80a22e4c..35dab7a2 100644 --- a/YLErpDAL/Modules/TradeModule/OAModels.cs +++ b/YLErpDAL/Modules/TradeModule/OAModels.cs @@ -22,4 +22,23 @@ namespace YLErp.Modules.TradeModule public string url { get; set; } public string fileid { get; set; } } + + /// + /// 国联OA接口响应模型 + /// + public class GuoLianOAResponse + { + public int code { get; set; } + public GuoLianOAData data { get; set; } + public string status { get; set; } + } + + /// + /// 国联OA接口响应数据模型 + /// + public class GuoLianOAData + { + public string msg { get; set; } + public string requestid { get; set; } + } } \ No newline at end of file diff --git a/YLErpDAL/Modules/TradeModule/TradeOAService.cs b/YLErpDAL/Modules/TradeModule/TradeOAService.cs index 6ded3413..37d86d24 100644 --- a/YLErpDAL/Modules/TradeModule/TradeOAService.cs +++ b/YLErpDAL/Modules/TradeModule/TradeOAService.cs @@ -75,17 +75,16 @@ namespace YLErp.Modules.TradeModule // 调用OA接口 var oaResp = await CallOAInterfaceAsync(trade, tcr?.ContractCode, tdoc, oaResult.id); - if (oaResp != null && oaResp.success) + if (oaResp != null && oaResp.code == 0) { oaResult.status = "提交成功"; - oaResult.oa_fileid = oaResp.data?.fileid; - oaResult.oa_msg = oaResp.message; - oaResult.oa_url = oaResp.data?.url; + oaResult.oa_fileid = oaResp.data?.requestid; + oaResult.oa_msg = oaResp.data?.msg ?? "提交成功"; } else { oaResult.status = "提交失败"; - oaResult.oa_msg = oaResp?.message ?? "OA接口调用失败"; + oaResult.oa_msg = oaResp?.data?.msg ?? "OA接口调用失败"; } await DbContext.SaveChangesAsync(); @@ -106,7 +105,7 @@ namespace YLErp.Modules.TradeModule /// 交易确认书文档 /// OA结果记录ID /// 是否成功 - private async Task CallOAInterfaceAsync(trade trade, string contractCode, trade_contract_document tdoc, int oaResultId) + private async Task CallOAInterfaceAsync(trade trade, string contractCode, trade_contract_document tdoc, int oaResultId) { try { @@ -114,33 +113,24 @@ namespace YLErp.Modules.TradeModule var oaConfigSection = AppManager.GetConfiguration().GetSection("oa_confg"); var baseUrl = oaConfigSection["BaseUrl"]; var subUrl = oaConfigSection["SubUrl"]; - var loginName = string.Empty; - using (var adminDb = new ErpBaseContext()) - { - var userInfo = adminDb.SystemUsers.FirstOrDefault(x => x.Id == UserInfo.UserId); - loginName = userInfo?.OaAccount; - } - var systemKey = oaConfigSection["SystemKey"]; - var objectClass = oaConfigSection["ObjectClass"]; - var tradeType = oaConfigSection["TradeType"] ?? "2"; - var businessType = oaConfigSection["BusinessType"] ?? "7"; - var urgent = int.Parse(oaConfigSection["Urgent"] ?? "1"); - var issend = int.Parse(oaConfigSection["Issend"] ?? "0"); + var systemToken = oaConfigSection["SystemToken"]; + var systemName = oaConfigSection["SystemName"]; + var isNextFlow = oaConfigSection["IsNextFlow"] ?? "0"; - if (string.IsNullOrEmpty(loginName)) - { - logger.Error("OA账号未配置"); - return new OAResponse() { data = null, success = false, message = "OA账号未配置" }; - - } if (string.IsNullOrEmpty(baseUrl)) { logger.Error("OA接口配置中BaseUrl为空"); - return new OAResponse() { data = null, success = false, message = "OA接口配置中地址为空" }; + return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "OA接口配置中地址为空" } }; + } + if (string.IsNullOrEmpty(systemToken)) + { + logger.Error("OA接口配置中SystemToken为空"); + return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "OA接口配置中SystemToken为空" } }; } // 处理附件 - var attachments = new List(); + string attachmentBase64 = null; + string attachmentFileName = null; if (tdoc != null && !string.IsNullOrEmpty(tdoc.AbsolutePath)) { try @@ -148,131 +138,85 @@ namespace YLErp.Modules.TradeModule if (File.Exists(tdoc.AbsolutePath)) { var fileBytes = await File.ReadAllBytesAsync(tdoc.AbsolutePath); - var base64Content = Convert.ToBase64String(fileBytes); - var fileName = Path.GetFileName(tdoc.AbsolutePath); - - attachments.Add(new - { - nrtitle = fileName, - nrtype = "1", - content = base64Content - }); - + attachmentBase64 = Convert.ToBase64String(fileBytes); + attachmentFileName = Path.GetFileName(tdoc.AbsolutePath); logger.Info($"成功读取附件文件:{tdoc.AbsolutePath},文件大小:{fileBytes.Length} 字节"); } else { logger.Error($"附件文件不存在:{tdoc.AbsolutePath}"); - return new OAResponse() { data = null, success = false, message = $"附件文件不存在" }; - + return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "附件文件不存在" } }; } } catch (Exception ex) { logger.Error($"读取附件文件失败:{tdoc.AbsolutePath},错误:{ex.Message}", ex); - return new OAResponse() { data = null, success = false, message = $"读取附件文件失败" }; + return new GuoLianOAResponse() { code = -1, data = new GuoLianOAData { msg = "读取附件文件失败" } }; } } - // 计算同一客户、同一交易日期、同一多空方向名义本金汇总 - // 1. 先获取当前交易的多空方向 - var currentPosition = DbContext.swap_position.AsNoTracking() - .Where(sp => sp.SwapTradeId == trade.id && sp.IsInitial && sp.PositionType > 0 && !sp.Invalid) - .FirstOrDefault(); - var currentPositionType = currentPosition.PositionType; - // 2. 查询同一客户、同一交易日期的所有有效交易 - var sameClientTrades = DbContext.trade.AsNoTracking() - .Where(t => t.ClientId == trade.ClientId - && t.TradeDate == trade.TradeDate - && t.ValidState != "InValid"); - - var exerciseDate = sameClientTrades.Select(x => x.ExerciseDate).OrderBy(o => o).FirstOrDefault(); - // 3. 关联持仓表,筛选相同多空方向的持仓 - var matchingPositions = from t in sameClientTrades - join sp in DbContext.swap_position.AsNoTracking() - on t.id equals sp.SwapTradeId - where sp.PositionType == currentPositionType - && sp.IsInitial && sp.PositionType > 0 && !sp.Invalid - select t; - - // 4. 计算名义本金汇总和加权平均保证金率 - var totalNotionalPrincipal = matchingPositions.Sum(x => x.OriginalStockEqvNotional); - - // 计算加权平均保证金率 - decimal marginRate = 0; - if (totalNotionalPrincipal > 0) + // 构建dataMap + var dataMap = new { - decimal weightedMarginSum = 0; - foreach (var t in matchingPositions) + title = $"固定收益部申请【{contractCode}】TRS交易确认书", + urgentLevel = "正常", + applyDate = DateTime.Now.ToString("yyyyMMdd"), + applicant = UserInfo.UserName, + applicantComp = "国联民生证券总部", + contractType = "业务", + businessType = "金融交易类合同(除股票质押式回购业务部分购回、购回协议)", + contractSecretLevel = "一般", + contractUrgentLevel = "一般", + //去除后缀 + contractName = Path.GetFileNameWithoutExtension(tdoc.FileName), + isRelatedTransaction = "否", + partyAType = "企业", + partyA = trade.ClientName, + partyBType = "企业", + partyB = "国联民生证券股份有限公司", + partyASmsNotify = "否", + partyBSmsNotify = "否", + contractAmount = trade.OriginalStockEqvNotional, + contractBeginDate = trade.StartDate?.ToString("yyyyMMdd"), + contractEndDate = trade.ExerciseDate?.ToString("yyyyMMdd"), + currency = "人民币", + contractSignDate = DateTime.Now.ToString("yyyyMMdd"), + signIntegrityAgreement = "无需签订", + contractBackground = $"我司与{trade.ClientName}已完成NAFMII协议签署,并开展TRS交易:{contractCode},参与标的{trade.UnderlyingCode} {trade.UnderlyingName},参与标的数量面额{trade.OriginalStockEqvNotional}元人民币", + attachments = string.IsNullOrEmpty(attachmentBase64) ? null : new[] { - var marginDetail = UnderlyingHelper.GetApplicableMarginRate(t.ClientId, t.UnderlyingCode, t.TradeDate.Value); - var rate = marginDetail?.init_rate ?? 0; - weightedMarginSum += rate * Convert.ToDecimal(t.OriginalStockEqvNotional); + new + { + fileName = attachmentFileName, + fileBytes = attachmentBase64 + } } - marginRate = weightedMarginSum / Convert.ToDecimal(totalNotionalPrincipal); - // marginRate=Math.Round(marginRate, 4); // 保留四位小数 - } + }; - var posiTypeStr = currentPositionType == (int)PositionTypeFlag.Long ? "买入" : "卖出"; - var underlyingType = sameClientTrades.Count() > 0 ? "利率债" : trade.UnderlyingInstrumentTypeCn; - string bgContent = @$"

各位领导:

-

经友好协商,我司拟与交易对手开展以下场外利率收益互换交易:

-

浮动收益支付方: 浙商证券

-

浮动收益接收方: {trade.ClientName}

-

标的: {underlyingType}

-

方向: {posiTypeStr}

-

起始日: {trade.StartDate?.ToString("yyyy/M/d")}

-

到期日: {exerciseDate?.ToString("yyyy/M/d")}

-

合约名义本金: {totalNotionalPrincipal:N0}元

-

保证金支付方: {trade.ClientName}

-

交易标的满足浙商证券标的池管理要求,交易对手方为非交易商,提供【{(marginRate * 100).ToString("0.##")}%】名义本金的履约担保品作为初始保证金。保证金预警线与盯市追保符合内外规要求。

"; // 构建OA请求参数 var oaRequest = new { - loginname = loginName, - systemkey = systemKey, - objectclass = objectClass, - title = $"关于场外利率债收益互换交易的审批盖章申请({trade.StartDate.Value.ToString("yyyyMMdd")}-{trade.ClientName})", - urgent = urgent, - issend = issend, - copyattfileid = "", - je = (double)totalNotionalPrincipal, - filerela = new object[0], - groupno = "", - extinfo = new - { - busdata = new - { - BM1 = "", - BM2 = "", - BGRQ = trade.TradeDate.Value.ToString("yyyy-MM-dd"), - NGR1 = "", - NGR2 = "", - CKDX1 = "", - CKDX2 = "", - LB = "", - JYLX = tradeType,//自主对冲 - YWLX = businessType,//收益互换 - QSBGNR = bgContent, - MX = new object[0], - SQMX = new object[0] - }, - attachments = attachments.ToArray() - } + isnextflow = isNextFlow, + systemToken = systemToken, + systemName = systemName, + dataMap = JsonHelper.Serialize(dataMap) }; - logger.Info($"OA接口参数:{JsonHelper.Serialize(oaRequest)}"); - // 调用OA接口 + + logger.Info($"国联OA接口参数: {JsonHelper.Serialize(oaRequest)}"); + + // 调用OA接口 (GET请求) var httpClient = new HttpClientWrap(baseUrl); - var response = httpClient.PostJson(subUrl, oaRequest, null);// fileDraft - logger.Info($"OA接口返回:{response}"); + var response = httpClient.PostJson(subUrl, oaRequest,null); + logger.Info($"国联OA接口返回: {response}"); + // 解析响应 - var responseObj = JsonHelper.Deserialize(response); + var responseObj = JsonHelper.Deserialize(response); return responseObj; } catch (Exception ex) { logger.Error($"调用OA接口时发生异常,交易ID:{trade.id},异常信息:{ex.Message}", ex); - return new OAResponse() { data = null, success = false, message = $"调用OA接口时发生异常" }; + return new GuoLianOAResponse() { code = -2, data = new GuoLianOAData { msg = $"调用OA接口时发生异常: {ex.Message}" } }; } } }