using BaseOUDAL; using System.Text.RegularExpressions; using YieldChain.Helpers; using YLErp.Enums; using YLErp.Helpers; using YLErp.Modules.DataCacheModule; using YLErp.MsOffice; using YLErp.Office; using YLErp.Office.Converters; namespace YLErp.Modules.TradeModule.QueryModule { public class TradeSwapDetailsQueryService : YLBaseService { public TradeSwapDetailsQueryService(OptUserInfo userInfo) : base(userInfo) { } public TradeSwapDetailsQueryService(YLBaseService baseService) : base(baseService) { } public TradeSwapDetailsReport TradeSwapDetailsReport { private set; get; } public string ExportReport(TradeDetailsReq req, string biaoTou = null, string biaoWei = null) { var client = DataCacheProvider.GetClientDataSource().GetData(req.ClientId != 0 ? req.ClientId : req.ClientIdsInt[0]); if (client == null) { throw new ServiceException("系统中没有此客户,clientId:" + req.ClientId); } var resultList = SearchFlowMoreDetails(req); return ConfirmDanzhang(resultList, client, req, biaoTou, biaoWei); } private string ConfirmDanzhang(SearchListResult resultList, Client client, TradeDetailsReq req, string biaoTou = null, string biaoWei = null) { if (!resultList.rows.Any()) { throw new ServiceException(client.Name + "没有交易明细"); } var report = new TradeSwapDetailsReport(); report.TradeFlowListAll = resultList.rows.ToList(); report.TradeFlowListSum = (TradeFlowMoreSum)resultList.Sum; report.ClientId = client.id; report.ClientName = string.IsNullOrEmpty(client.Abbreviation) ? client.Name : client.Abbreviation; report.ClientFullName = client.Name; report.ClientNumber = client.Number; report.ClientAbbreviation = client.Abbreviation; report.CompanyName = PS.Config.CompanyFullName; report.ReportStart = req.StartDate == null ? DateTime.MinValue : req.StartDate.Value; report.ReportEnd = req.EndDate.Value; // 主 客户编号+A; 补充 客户编号+B;履约 客户编号+D; 主确认书:客户编号 + W report.ClientNumberA = client.Number + "A"; report.ClientNumberB = client.Number + "B"; report.ClientNumberD = client.Number + "D"; report.ClientNumberW = client.Number + "W"; var startDate = report.ReportStart; if (startDate == DateTime.MinValue) { report.TradeDetailsCode = client.Number + "_" + report.ReportEnd.ToString("yyyyMMdd"); } else { report.TradeDetailsCode = client.Number + "_" + report.ReportStart.ToString("yyyyMMdd") + "_" + report.ReportEnd.ToString("yyyyMMdd"); } #region 处理表头表尾 var biaoTouList = Regex.Split(biaoTou, "

", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); var newBiaoTouList = new List(); biaoTouList.ForEach(x => { x = Regex.Replace(x, "<[^>]+>", ""); x = Regex.Replace(x, "&[^;]+;", ""); newBiaoTouList.Add(x); }); report.BiaoTouLines = newBiaoTouList; report.BiaoTou = string.Join("\n", newBiaoTouList); var biaoWeiList = Regex.Split(biaoWei, "

", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); var newBiaoWeiList = new List(); biaoWeiList.ForEach(x => { x = Regex.Replace(x, "<[^>]+>", ""); x = Regex.Replace(x, "&[^;]+;", ""); newBiaoWeiList.Add(x); }); report.BiaoWeiLines = newBiaoWeiList; report.BiaoWei = string.Join("\n", newBiaoWeiList); #endregion report.OutputFolder = req.OutputFolder; TradeSwapDetailsReport = report; return GenerateTradeDetailsReportV2(report, client); } private string GenerateTradeDetailsReportV2(TradeSwapDetailsReport report, Client client) { //获取盯市报告模板信息 var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/收益互换明细模板-单章.xlsx"); //if (client.ConfirmBookMode == "双章版") var targetFolder = report.OutputFolder; if (string.IsNullOrEmpty(targetFolder)) { var date = report.ReportEnd; targetFolder = OtcAppContext.MapPath($"~/App_Docs/Download/{date:yyyyMM}/"); } string excelFileName; var startDate = report.ReportStart; if (startDate == DateTime.MinValue) { excelFileName = $"收益互换交易结算确认书_{report.ReportEnd:MMdd}_{report.ClientName}.xlsx"; } else { excelFileName = $"收益互换交易结算确认书_{startDate:MMdd}_{report.ReportEnd:MMdd}_{report.ClientName}.xlsx"; } var excelFilePath = Path.Combine(targetFolder, excelFileName); Directory.CreateDirectory(targetFolder); ExcelTemplate.GeneratePDFFromExeclTemplateV2(templateFile, excelFilePath, new Dictionary { { "交易明细", report } }, shouldDeleteSheet: true, needToPdf: false); return excelFilePath; } public SearchListResult SearchFlowMoreDetails(TradeDetailsReq req) { if (req.ClientId < 1 && string.IsNullOrWhiteSpace(req.ClientIds)) { return new SearchListResult(); } if (req.EndDate == null) { throw new ServiceException("请选择结束日期"); } if (req.StartDate != null && req.StartDate > req.EndDate) { throw new ServiceException("起始日期不能大于结束日期"); } var clientIdsInt = new List(); if (!string.IsNullOrWhiteSpace(req.ClientIds)) { clientIdsInt.AddRange(req.ClientIdsInt); } else if (req.ClientId > 0) { clientIdsInt.Add(req.ClientId); } if (req.ParentFlag) { var clientIdList = DataCacheProvider.GetClientDataSource().AsQueryable(O => clientIdsInt.Contains(O.ParentId)).Select(O => O.id).ToList().ToHashSet(); clientIdsInt.AddRange(clientIdList); } var query = from source in DbContext.trade_swap_flow_more join tradecashswap in DbContext.trade_cash_swap on source.id equals tradecashswap.FlowId into tradecashswap from swap in tradecashswap.DefaultIfEmpty() where !source.IsDelete && source.IsCompose && clientIdsInt.Contains(source.ClientId) select new TradeFlowMoreDetails { id = source.id, BuySell = source.BuySell, TradeNumber = source.TradeNumber, UnderlyingCode = source.UnderlyingCode, TradeDate = source.TradeDate, ExerciseDate = source.ExerciseDate, Price = source.Price, Notional = -source.Notional, AnnualRate = -source.AnnualRate, CurrencyRate = source.BuySell == "开仓" ? null : source.CurrencyRate, UnwindDate = source.BuySell == "开仓" ? null : source.UnwindDate, UnwindPrice = source.BuySell == "开仓" ? null : source.UnwindPrice, UnwindNotional = source.BuySell == "开仓" ? null : -source.UnwindNotional, TradeId = swap.TradeId, TradeCashId = swap.TradeCashId, TradeType = source.BuySell, TotalFee = (source.TotalFee ?? 0), StockEqvNotional = Math.Abs(source.Notional) * source.Price, LongShort = source.LongShort, OrderbyDate = source.BuySell == "开仓" ? source.TradeDate : source.UnwindDate, OrderbyNumber = source.TradeNumber.Length >= 5 ? source.TradeNumber.Substring(source.TradeNumber.Length - 5, 5) : source.TradeNumber }; if (req.DetailStatuses == "成交") { query = query.Where(x => x.BuySell == "开仓"); if (req.StartDate.HasValue) { query = query.Where(x => x.TradeDate >= req.StartDate); } if (req.EndDate.HasValue) { DateTime TradeDateTemp = req.EndDate.Value.AddDays(1); query = query.Where(x => x.TradeDate < TradeDateTemp); } } else if (req.DetailStatuses == "了结") { query = query.Where(x => x.BuySell == "平仓"); if (req.StartDate.HasValue) { query = query.Where(x => x.UnwindDate >= req.StartDate); } if (req.EndDate.HasValue) { DateTime TradeDateTemp = req.EndDate.Value.AddDays(1); query = query.Where(x => x.UnwindDate < TradeDateTemp); } } else { if (req.StartDate.HasValue) { query = query.Where(x => (x.BuySell == "开仓" && x.TradeDate >= req.StartDate) || (x.BuySell == "平仓" && x.UnwindDate >= req.StartDate)); } if (req.EndDate.HasValue) { DateTime TradeDateTemp = req.EndDate.Value.AddDays(1); query = query.Where(x => (x.BuySell == "开仓" && x.TradeDate < TradeDateTemp) || (x.BuySell == "平仓" && x.UnwindDate < TradeDateTemp)); } } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "OrderbyDate,OrderbyNumber"; req.sord = "asc"; } var retListResult = query.ToSearchList(req); var tcids = retListResult.rows.Select(x => x.TradeCashId).ToHashSet(); var tradedetail = DbContext.trade_cash_detail.Where(x => tcids.Contains(x.TradeCashId)).ToList(); var tradenumbers = retListResult.rows.Select(x => x.TradeNumber).ToHashSet(); var opentradeswapflowmore = DbContext.trade_swap_flow_more.Where(x => tradenumbers.Contains(x.TradeNumber) && x.BuySell == "开仓" && !x.IsDelete && x.IsCompose).ToList(); var underlying = DataCacheProvider.GetUnderlyingDataSource(); var instrumentTypeArr = new List() { ConsGlobal.InstrumentType.Stock, ConsGlobal.InstrumentType.StockIF }; foreach (var item in retListResult.rows) { var un = underlying.GetData(item.UnderlyingCode); if (un != null && un.IsCommodity()) { item.UnderlyingCode = un.MarketCode == null || un.MarketCode == "" ? un.UnderlyingCode : un.UnderlyingCode + "." + un.MarketCode; } var detail = tradedetail.Where(x => x.TradeCashId == item.TradeCashId); if (detail.Any() && item.BuySell == "平仓") { //item.FloatIncome = (-detail.FirstOrDefault(x => x.TradeCashType == TradeCashTypeEnum.浮动收益.ToString())?.Amount ?? 0); item.FixedIncome = (-detail.FirstOrDefault(x => x.TradeCashType == TradeCashTypeEnum.利息.ToString())?.Amount ?? 0); item.Amount = (-detail.Sum(x => x.Amount) ?? 0); item.FloatIncome = item.Amount - item.FixedIncome; } if (item.BuySell == "开仓") { var totalFee = (item.TotalFee / Math.Abs(item.Notional)).Normalize() * (item.LongShort == "多头" ? -1 : 1); item.Price += totalFee; } else { var openflow = opentradeswapflowmore.Where(x => x.TradeNumber == item.TradeNumber).FirstOrDefault(); var optotalFee = ((openflow.TotalFee ?? 0) / Math.Abs(item.Notional)).Normalize() * (openflow.LongShort == "多头" ? -1 : 1); var totalFee = (item.TotalFee / Math.Abs(item.UnwindNotional ?? 0)).Normalize() * (openflow.LongShort == "多头" ? 1 : -1); item.Price += optotalFee; item.UnwindPrice += totalFee; } item.TradeNumber = item.OrderbyNumber; } TradeFlowMoreSum sum = new TradeFlowMoreSum(); if (retListResult.rows.Any()) { sum.FloatIncomeSum = retListResult.rows.Sum(x => (x.FloatIncome ?? 0)); sum.FixedIncomeSum = retListResult.rows.Sum(x => (x.FixedIncome ?? 0)); sum.AmountSum = retListResult.rows.Sum(x => (x.Amount ?? 0)); } retListResult.Sum = sum; return retListResult; } public SendTradeDetailReportResult SendTradeDetailReport(TradeDetailsReq req, TradeSwapDetailsReport report, string luoKuan, string reportFilePath, string template, List receiver = null, bool skip = false) { var AppendixType = DBCacheManager.Single.GetStr(CacheTable.TradeSwapDerailsNeedAppendix, template); var path = string.Empty; if (AppendixType == "PDF") { path = FileHelper.ReplaceExtension(reportFilePath, ".pdf"); path = GeneratePDFReport(reportFilePath); } else { path = reportFilePath; } var filePathes = new List() { path }; var clientContacts = new ClientDBContext().clientduty.Where(x => x.ApprovalOrder < 1 && x.ClientId == req.ClientId && (x.DeadLine == null || x.DeadLine > DateTime.Now) && x.IsReceiveEmail.HasValue && x.IsReceiveEmail == 1).ToList(); var clientContactMails = new List(); if (receiver != null && receiver.Count > 0) { foreach (var item in clientContacts) { var ids = item.ContactTypeId.Split(','); if (ids.Intersect(receiver).Count() != 0) { clientContactMails.Add(item.Email); } } } else { clientContactMails = clientContacts.Select(o => o.Email).ToList(); } var emails = DataConvert.EmailsSplitByComma(clientContactMails); // var attachFiles = new List { reportFilePath }; var startstr = req.StartDate.HasValue ? req.StartDate.Value.ToString("yyyy-MM-dd") : ""; var gh = req.StartDate.HasValue && req.EndDate.HasValue ? "-" : ""; var endstr = req.EndDate.HasValue ? req.EndDate.Value.ToString("yyyy-MM-dd") : ""; var endPart = (startstr == endstr) ? startstr : (startstr + gh + endstr); //邮件标题格式 "【当前公司】"+ 客户名称 + "-场外交易确认-" + 确认日期或区间 var title = $"【国君风管】{report.ClientName}-场外商品互换交易确认-{endPart}"; if (PS.Config.IsGuoJun) { title = $"【国君风管】{report.ClientName}-场外商品互换交易确认-{endPart}"; } var status = EmailTradeConfirmResultType.Succeed; string sendMailMsg = null; var ccemail = DBCacheManager.Single.GetStr(CacheTable.CCEmail, template); var sendUser = DBCacheManager.Single.GetStr(CacheTable.TradeDetailsSendUser, template); if (emails.All(o => string.IsNullOrWhiteSpace(o))) { status = EmailTradeConfirmResultType.NoEmailSetting; } else { emails = emails.Where(o => !string.IsNullOrWhiteSpace(o)); if (!string.IsNullOrWhiteSpace(AppendixType)) { sendMailMsg = EmailHelper.SendMail(string.Join(";", emails), $"{report.ClientAbbreviation ?? ""}{title}", $"{luoKuan}", true, filePathes, ccemail, mailFrom: sendUser); } else { sendMailMsg = EmailHelper.SendMail(string.Join(";", emails), $"{report.ClientAbbreviation ?? ""}{title}", $"{luoKuan}", true, null, ccemail, mailFrom: sendUser); } if (!string.IsNullOrEmpty(sendMailMsg)) { status = EmailTradeConfirmResultType.EmailSentFailed; } } return new SendTradeDetailReportResult { ResultType = status, ErrorMsg = sendMailMsg }; } private string GeneratePDFReport(string excelPath) { var tempFolder = OtcAppContext.MapPath("~/App_Docs/Temp"); if (!Directory.Exists(tempFolder)) { Directory.CreateDirectory(tempFolder); } var tempExcelFilePath = FileHelper.GetTargetFilePath(excelPath, tempFolder, true); File.Copy(excelPath, tempExcelFilePath); var pdfFilePath = FileHelper.ReplaceExtension(excelPath, ".pdf"); var excelfilepath2 = FileHelper.ReplaceExtension(excelPath, ".xlsx"); var wordfilepath = FileHelper.ReplaceExtension(excelPath, ".docx"); if (File.Exists(excelfilepath2)) { OfficeFileConverter.ConvertFileFormat(excelfilepath2, pdfFilePath); } else { OfficeFileConverter.ConvertDocxToPDF(wordfilepath, pdfFilePath); } return pdfFilePath; } } public class TradeSwapDetailsReport { public YLErp.Configuration.IErpConfig Config => PS.Config.ErpElement; public string CompanyName { get; set; } public string TradeDetailsCode { get; set; } public string ClientNumber { get; set; } /// /// 主 客户编号+A; 补充 客户编号+B;履约 客户编号+D; 主确认书:客户编号 + W /// public string ClientNumberA { get; set; } public string ClientNumberB { get; set; } public string ClientNumberD { get; set; } public string ClientNumberW { get; set; } public int? ClientId { get; set; } /// /// 有简称则用简称(应该是国君的需求) /// public string ClientName { get; set; } /// /// 客户全称 /// public string ClientFullName { get; set; } /// /// 客户简称 /// public string ClientAbbreviation { get; set; } public DateTime ReportStart { get; set; } public DateTime ReportEnd { get; set; } public string ReportEndString => (ReportStart != DateTime.MinValue ? ($"{ReportStart.ToString("yyyy年M月d日")}至{ReportEnd.ToString("yyyy年M月d日")}") : ReportEnd.ToString("yyyy年M月d日")); public DateTime ReportNow { get; set; } public string ReportDateRange { get { var startDate = ReportStart; if (startDate == DateTime.MinValue) { return $"{ReportEnd:yyyy/MM/dd}"; } return $"{startDate:yyyy/MM/dd}-{ReportEnd:yyyy/MM/dd}"; } } public string BiaoTou { get; set; } public string BiaoWei { get; set; } /// /// 用于Excel导出模板(交易明细) /// public IEnumerable BiaoTouLines { get; set; } /// /// 用于Excel导出模板(交易明细) /// public IEnumerable BiaoWeiLines { get; set; } public string LuoKuan { get; set; } public string Today => DateTime.Now.ToString("yyyy年M月d日"); /// /// 导出文件输出文件夹路径 /// public string OutputFolder { get; set; } public List TradeFlowListAll { get; set; } public TradeFlowMoreSum TradeFlowListSum { get; set; } } public class TradeFlowMoreDetails { public int id { get; set; } public string TradeNumber { get; set; } /// /// 交易编号 /// public string BuySell { get; set; } /// /// 标的代码 /// public string UnderlyingCode { get; set; } /// /// 交易日期 /// public DateTime? TradeDate { get; set; } /// /// 到期日期 /// public DateTime? ExerciseDate { get; set; } public string TradeDateString { get { return TradeDate?.ToString("yyyy/MM/dd"); } } public string ExerciseString { get { return ExerciseDate?.ToString("yyyy/MM/dd"); } } /// /// 标的价格 /// public double Price { get; set; } public string PriceString { get { return Price.ToString("0.000000"); } } /// /// 份额 /// public double Notional { get; set; } public string NotionalString { get { return (double.TryParse(Notional.ToString(), out double c) == true ? c.ToString() : 0.ToString()); } } /// /// 利率 /// public double? AnnualRate { get; set; } public string AnnualRateString { get { return AnnualRate?.ToString("0.0000"); } } /// /// 汇率 /// public double? CurrencyRate { get; set; } public string CurrencyRateString { get { return BuySell == "开仓" ? "--" : CurrencyRate?.ToString("0.0000"); } } /// /// 平仓日期 /// public DateTime? UnwindDate { get; set; } public string UnwindDateString { get { return BuySell == "开仓" ? "--" : UnwindDate?.ToString("yyyy/MM/dd"); } } /// /// 平仓价格 /// public double? UnwindPrice { get; set; } public string UnwindPriceString { get { return BuySell == "开仓" ? "--" : UnwindPrice?.ToString("0.000000"); } } /// /// 平仓数量 /// public double? UnwindNotional { get; set; } public string UnwindNotionalString { get { return BuySell == "开仓" ? "--" : (int.TryParse(UnwindNotional?.ToString(), out int c) == true ? c.ToString() : 0.ToString()); } } /// /// 浮动收益 /// public double? FloatIncome { get; set; } public string FloatIncomeString { get { return BuySell == "开仓" ? "--" : FloatIncome?.ToString("0.00"); } } /// /// 固定收益 /// public double? FixedIncome { get; set; } public string FixedIncomeString { get { return BuySell == "开仓" ? "--" : FixedIncome?.ToString("0.00"); } } /// /// 平仓总额 /// public double? Amount { get; set; } public string AmountString { get { return BuySell == "开仓" ? "--" : Amount?.ToString("0.00"); } } public string TradeType { get; set; } public double StockEqvNotional { get; set; } public string StockEqvNotionalString { get { return StockEqvNotional.ToString("0.00"); } } public string PayType { get { if (TradeNumber.Contains("W")) { return AnnualRate > 0 ? "商品互换\r\n收固定付浮动" : "商品互换\r\n付固定收浮动"; } else if (TradeNumber.Contains("S")) { return AnnualRate > 0 ? "权益互换\r\n收固定付浮动" : "权益互换\r\n付固定收浮动"; } else if (TradeNumber.Contains("F")) { return AnnualRate > 0 ? "仓单互换\r\n收固定付浮动" : "仓单互换\r\n付固定收浮动"; } else { return AnnualRate > 0 ? "收固定付浮动" : "付固定收浮动"; } } } public int? TradeId { get; set; } public int? TradeCashId { get; set; } /// /// 手续费 /// public double TotalFee { get; set; } public string LongShort { get; set; } /// /// 排序规则时间 /// public DateTime? OrderbyDate { get; set; } public string OrderbyNumber { get; set; } } public class TradeFlowMoreSum { public double FloatIncomeSum { get; set; } public double FixedIncomeSum { get; set; } public double AmountSum { get; set; } } }