using System.Text; using System.Text.RegularExpressions; using OfficeOpenXml; using YLErp.BLL; using YLErp.BLL.EodSettlement; using YLErp.Enums; using YLErp.Helpers; using YLErp.Model; using YLErp.Modules.ClientModule; using YLErp.Modules.DataCacheModule; using YLErp.Modules.ReportModule.SettlementReportModule; using YLErp.Modules.TradeModule.QueryModule; using YLErp.Office; using YLErp.QdpModule; //using OfficeOpenXml.Style; //using YLErp.BLL; //using YLErp.Configuration; //using YLErp.Modules.EodModule; //using YLErp.QdpModule; namespace YLErp.Modules.ReportModule { /// /// 结算报告服务 /// public class SettlementReportFotGTService : YLBaseService { public SettlementReportFotGTService(OptUserInfo userInfo) : base(userInfo) { } /// /// from:trade_spancontroller.GetReportData /// public ClientDingShiReport_GT GetReportData(DingShiReportEmail emailData, IEnumerable userAssetUnits, string template = "") { var report = new ClientDingShiReport_GT() { ReportFrom = emailData.From, ReportEnd = emailData.To }; report.client = DataCacheProvider.GetClientDataSource().GetData(emailData.ClientId); report.CurUserName = emailData.CurUserName; if (emailData.SendContent.Contains("账户状况")) { var clientBalance = ClientBalanceUtility.GetClientBanlances(new List { emailData.ClientId }, emailData.From, emailData.To, IsClientBalanceGap: false, IsGetOuterMarginGap: false, ParentFlag: emailData.ParentFlag).FirstOrDefault(); report.reportModel = new ReportModel_GT() { ClientName = report.client.Name, ReportDate = report.ReportEnd, LastDayRemainFund = clientBalance?.LastDayRemainFund ?? 0, CashInChange = clientBalance?.InFund ?? 0, CashOutChange = clientBalance?.OutFund ?? 0, WinLoss = clientBalance?.WinLoss ?? 0, ToEndBalance = clientBalance?.ToEndBalance ?? 0, ToDayRemainFund = clientBalance?.AmountFund ?? 0, WorstCastClientPayable = clientBalance?.MinusPayableMarginTotal ?? 0, EodPremium = clientBalance?.EodPremium ?? 0, OptionPremiumAndSwapSum = clientBalance?.OptionPremiumAndSwapSum ?? 0, AvailableFund = clientBalance?.AvailableAmount ?? 0, Credit = clientBalance?.TotalCredit ?? 0, DesirableFund = clientBalance?.DesirableFund ?? 0, WinLossSum = clientBalance?.WinLossSum ?? 0, PositionPnl =((PS.Config.IsPVRounded ? clientBalance?.RoundedPositionPnl : clientBalance?.PositionPnl ) ?? 0), AmountFundWithPositionPnl = clientBalance?.AmountFundWithPositionPnl ?? 0, }; } if (emailData.SendContent.Contains("持仓明细")) { var spanReq = new TradeSpanReq { ClientId = emailData.ClientId, ValueDate = emailData.To, ParentFlag = emailData.ParentFlag }; report.eodPositions = clientTradePositionQueryList(spanReq, userAssetUnits); } if (emailData.SendContent.Contains("历史交易")) { var treq = new TradeReq() { ClientId = emailData.ClientId, ValueDateStart = emailData.From, ValueDateEnd = emailData.To, ParentFlag = emailData.ParentFlag }; report.unwindTrades = SearchHistoryListOnly(treq, true); } //txt报告特殊处理用到 var desc = DBCacheManager.Single.GetStr(CacheTable.DingShiDesc, template: template); if (string.IsNullOrWhiteSpace(desc)) { desc = DBCacheManager.Single.GetStr(CacheTable.DingShiDesc); } var descList = Regex.Split(desc, "

", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); var newDescList = new List(); descList.ForEach(x => { x = Regex.Replace(x, "<[^>]+>", ""); x = Regex.Replace(x, "&[^;]+;", ""); newDescList.Add(x); }); report.downloadFilePath = emailData.DownloadFilePath; if (string.IsNullOrWhiteSpace(emailData.Title)) { emailData.Title = DBCacheManager.Single.GetStr(CacheTable.ClientBalanceReportTiltle, template: template); } report.Title = ReplaceWildcard(emailData.Title, report); return report; } public string ReplaceWildcard(string input, ClientDingShiReport_GT report) { if (!string.IsNullOrEmpty(input)) { input = Regex.Replace(input, @"\{\{(.*?)\}\}", m => { switch (m.Groups[1].Value) { case "客户名称": return report.client.Name; case "客户编号": return report.client.Number; case "追保金额": return report.reportModel.WorstCastClientPayable.ToString("0.00"); case "大写追保金额": return NumberHelper.CmycurD(report.reportModel.WorstCastClientPayable); case "支付截止时间": return QdpCalendarHelper.GetNonHoliday(DateTime.Now < DateTime.Now.Date.AddHours(9).AddMinutes(30) ? DateTime.Now : DateTime.Now.AddDays(1)).ToString("yyyy年MM月dd日") + "上午9:30"; case "发送日期": return DateTime.Now.ToString("yyyy-MM-dd"); case "起始日期": return report.ReportFrom.ToString("yyyy-MM-dd"); case "结束日期": return report.ReportEnd.ToString("yyyy-MM-dd"); case "开户行": if (report.ClientBank.Any()) { var Bank = new StringBuilder(); report.ClientBank.ForEach(x => { Bank.Append(x.Bank).Append(","); }); return Bank.ToString().Substring(0, Bank.ToString().Length - 1); } return string.Empty; case "户名": if (report.ClientBank.Any()) { var ClientName = new StringBuilder(); report.ClientBank.ForEach(x => { ClientName.Append(x.ClientName).Append(","); }); return ClientName.ToString().Substring(0, ClientName.ToString().Length - 1); } return string.Empty; case "账号": if (report.ClientBank.Any()) { var Card = new StringBuilder(); report.ClientBank.ForEach(x => { Card.Append(x.Card).Append(","); }); return Card.ToString().Substring(0, Card.ToString().Length - 1); } return string.Empty; default: return string.Empty; } }); } return input; } public string GenerateFileEntry(ClientDingShiReport_GT report, string type) { var tempFolder = OtcAppContext.MapPath("~/App_Docs/Temp/结算报告"); var targetPath = string.IsNullOrEmpty(report.downloadFilePath) ? Path.Combine(tempFolder, report.ReportEnd.ToString("yyyyMMdd")) : report.downloadFilePath; if (!Directory.Exists(targetPath)) { Directory.CreateDirectory(targetPath); } var clientName = report.client.Name; var fileName = $"结算报告_{clientName}_{report.ReportEnd:yyyy-MM-dd}"; var targetFileName = Path.Combine(targetPath, $"{fileName}.xlsx"); var modelDict = new Dictionary(); if (report.reportModel != null) { modelDict.Add("客户权益信息", report.reportModel); } var positionSheetModels = new PositionSheetModels(); if (report.eodPositions != null) { modelDict.Add("客户持仓明细", report.eodPositions); } var historySheetModels = new HistorySheetModels(); if (report.unwindTrades != null) { modelDict.Add("到期平仓明细", report.unwindTrades); } var sourcePath = OtcAppContext.MapPath("~/App_Docs/导出模板"); var sourceFileName = Path.Combine(sourcePath, "结算报告模板_国投安信场外期权.xlsx"); var pdffile = ExcelTemplate.GeneratePDFFromExeclTemplate(sourcePath, sourceFileName, modelDict, targetPath, targetFileName , shouldDeleteSheet: true, needToPdf: false, callback: new GenerateExcelCallback(this) { report = report }.Callback); string path = Path.Combine(targetPath, targetFileName); //if (type == "PDF") //{ // path = GeneratePDFReport(path); //} return path; } /// /// 没引用 /// /// /// //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)) // { // MsOfficeHelper.ConvertExcelToPDF(excelfilepath2, pdfFilePath); // } // else // { // WordHelper.ConvertToFormat(wordfilepath, pdfFilePath, Microsoft.Office.Interop.Word.WdExportFormat.wdExportFormatPDF); // } // return pdfFilePath; //} class GenerateExcelCallback : YLBaseService { public ClientDingShiReport_GT report; public GenerateExcelCallback(YLBaseService baseService) : base(baseService) { } public void Callback(ExcelWorksheets sheets) { } } public (EmailTradeConfirmResultType status, string message) SendSettlementReports(DingShiReportEmail emailData, ClientDingShiReport_GT report, string template, bool IsSkipCheckMarginCall = false, List recevier = null) { string message = null; var attachFiles = new List(); var IsNeedMarginCall = false; if (!IsSkipCheckMarginCall) { IsNeedMarginCall = CheckIsNeedMarginCall(report.client, emailData.PayableFund > 0 ? emailData.PayableFund : report.reportModel.WorstCastClientPayable); } emailData.FileTypes.ForEach(type => { if (type.@checked) { var filepath = GenerateFileEntry(report, type.type); if (!string.IsNullOrEmpty(filepath)) { attachFiles.Add(filepath); } } }); // 要向该客户的所有订阅了邮件通知的人员发送邮件 var emails = ClientDataQueryService.GetClientEmails(report.client.id, false, recevier); var status = EmailTradeConfirmResultType.Succeed; if (emails.All(o => string.IsNullOrWhiteSpace(o))) { status = EmailTradeConfirmResultType.NoEmailSetting; } else { emails = emails.Where(o => !string.IsNullOrWhiteSpace(o)); var title = string.Empty; var detail = string.Empty; if (IsNeedMarginCall) { title = $"【追保通知】{report.Title}"; detail = emailData.MarginDetail; detail = ReplaceWildcard(detail, report); } else { title = report.Title; detail = emailData.Detail; } var mailFrom = DBCacheManager.Single.GetStr(CacheTable.TradeMarketSendUser, template); if (string.IsNullOrWhiteSpace(mailFrom)) { mailFrom = DBCacheManager.Single.GetStr(CacheTable.TradeMarketSendUser); } message = EmailHelper.SendMail(string.Join(";", emails), title, detail, true, attachFiles, emailData.CCEmail, mailFrom); if (!string.IsNullOrEmpty(message)) { status = EmailTradeConfirmResultType.EmailSentFailed; } } return (status, message); } public bool CheckIsNeedMarginCall(int ClientId, DateTime start, DateTime end, double payableFund = -1, bool IsGap = false, bool IsOuter = false, bool ParentFlag = false) { var client = DataCacheProvider.GetClientDataSource().GetData(ClientId); var clientBalance = ClientBalanceUtility.GetClientBanlances(new List { ClientId }, start, end, IsGap, IsOuter, ParentFlag).FirstOrDefault(); return CheckIsNeedMarginCall(client, payableFund > 0 ? payableFund : clientBalance?.MinusPayableMarginTotal ?? 0); } private bool CheckIsNeedMarginCall(Client client, double payableFund) { var SamePeerMarginCallStarting = valuedateBLL.SystemDate.SamePeerMarginCallPoint; if (client.SamePeer == 0 && payableFund > SamePeerMarginCallStarting) { return true; } if (client.SamePeer == 1 && payableFund > 1) { return true; } return false; } //from:trade_spancontroller.clientTradePositionQueryList private List clientTradePositionQueryList(TradeSpanReq req, IEnumerable userAssetUnits) { if (req.ClientId == null || req.ValueDate == null) { return new List(0); } var positionList = new ClientPositionQueryService(this).SearchPositionListAll(req, userAssetUnits); var underlying = DataCacheProvider.GetUnderlyingDataSource(); int i = 1; var result = positionList.Select(x => { var model = new EodPositionReportModel_GT() { id = i++, trade = x.trade, ValueDate = x.ValueDate ?? DateTime.Today }; model.ExerciseMode = x.trade.ExerciseMode == "European" ? "欧式" : "美式"; model.BuySell = x.trade.BuySell == "买入" ? "卖出" : "买入"; var isMoneyness = x.trade.IsMoneynessOption == "是"; model.Strike = x.trade.Strike.OtcFormatUmPrice(isMoneyness); model.Strike2 = "\\"; model.Strike3 = "\\"; switch (model.trade.TradeType) { case "双鲨期权": model.Strike2 = x.trade.trade_double_sharkfin_option.StrikeHigh.OtcFormatUmPrice(isMoneyness); break; case "凤凰期权": model.Strike2 = x.trade.trade_autocall.SpreadStrike1.OtcFormatUmPrice(isMoneyness); model.Strike3 = x.trade.trade_autocall.SpreadStrike.OtcFormatUmPrice(isMoneyness); break; case "雪球期权": { switch (x.trade.trade_snowball.KOPayoffType) { case KOPayoffTypeEnum.ToOption: model.Strike2 = x.trade.trade_snowball.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; case KOPayoffTypeEnum.ToSpreadOption: model.Strike2 = x.trade.trade_snowball.SpreadStrikeAtKO.OtcFormatUmPrice(isMoneyness); model.Strike3 = x.trade.trade_snowball.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; } switch (x.trade.trade_snowball.KIPayoffType) { case KIPayoffTypeEnum.ToPutOption: case KIPayoffTypeEnum.ToCallOption: model.Strike2 = x.trade.trade_snowball.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToPutSpreadOption: case KIPayoffTypeEnum.ToCallSpreadOption: model.Strike2 = x.trade.trade_snowball.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness); model.Strike3 = x.trade.trade_snowball.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; } } break; } var un = underlying.GetData(model.trade.UnderlyingCode); if (un != null && un.IsCommodity()) { model.UnderlyingCode = un.MarketCode == null || un.MarketCode == "" ? un.UnderlyingCode : un.UnderlyingCode + "." + un.MarketCode; } else { model.UnderlyingCode = model.trade.UnderlyingCode; } model.UnderlyingPrice = x.UnderlyingPrice; model.CurrentPrice = Math.Abs(x.CurrentPrice ?? 0); model.TradeSinglePrice = Math.Abs( x.TradeSinglePrice ?? 0); model.TradePrice = Math.Abs(x.TradePrice ?? 0); model.CurrentPriceSum = Math.Abs((x.CurrentPrice ?? 0) * x.trade.Notional); model.Pnl = PS.Config.IsPVRounded ? x.RoundedPnl : x.Pnl; model.Margin = x.Margin; return model; }).ToList(); return result; } /// /// 查询所有历史交易数据 /// private static List SearchHistoryListOnly(TradeReq req, bool isFromTradeMarketReport = false) { var historyList = new TradeHistoryQueryService(OptUserInfo.SystemUser) .SearchHistoryListOnly(req, isFromTradeMarketReport); var underlying = DataCacheProvider.GetUnderlyingDataSource(); int i = 1; var sList = historyList.Select(x => { var model = new UnwindTradeModel_GT() { id = i++, trade = x.trade, tc = x.trade_cash, }; model.ExerciseMode = x.trade.ExerciseMode == "European" ? "欧式" : "美式"; model.BuySell = x.trade.BuySell == "买入" ? "卖出" : "买入"; var un = underlying.GetData(model.trade.UnderlyingCode); if (un != null && un.IsCommodity()) { model.UnderlyingCode = un.MarketCode == null || un.MarketCode == "" ? un.UnderlyingCode : un.UnderlyingCode + "." + un.MarketCode; } else { model.UnderlyingCode = model.trade.UnderlyingCode; } model.TradeSinglePrice = Math.Abs(x.trade.TradeSinglePrice ?? 0); model.TradePrice = Math.Abs(x.TradePrice ?? 0); model.UnwindPrice = Math.Abs(x.trade_cash.UnwindPrice ?? 0); model.Amount = Math.Abs(x.trade_cash.Amount); model.WinLoss = x.WinLoss; return model; }).ToList(); return sList; } } }