using System.Data; using YieldChain.Helpers; using YLErp.BLL; using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.Modules.SuperviseReportModule.SAC.Common; using YLErp.Modules.SuperviseReportModule.SAC.Model; using static YLErp.DBModels.Consts.ConsReport; namespace YLErp.Modules.SuperviseReportModule.SAC.Service { class ReportSwapConfirmationAttService : ReportBaseService { public ReportSwapConfirmationAttService(OptUserInfo optUser) : base(optUser) { } protected override string _excelDataSourcePath => "交易相关\\"; protected override string _excelDataSourceFileName => "import_SwapConfirmationAtt_template.xlsx"; protected override DataFlagsEnum BusiDataType => DataFlagsEnum.A1017; private List _validOperationType = null; public override List ValidOperationType { get { if (_validOperationType == null) { _validOperationType = new List() { OptFlagsEnum.A, OptFlagsEnum.U, OptFlagsEnum.D, }; } return _validOperationType; } } protected override SuperviseReportTypeEnum ReportType => SuperviseReportTypeEnum.SAC_ConfirmationAtt; List noteList = new List(); protected override BodyModel GenerateBody(out bool noData, out List fileList) { fileList = new List(); BodyModel model = new BodyModel(); var cacheKey = $"{BusiDataType}"; List dataList = new List(); if ((PS.Config.ErpElement.SAC_ReportDataSource & SAC_ReportDataSourceEnum.Template) == SAC_ReportDataSourceEnum.Template) { dataList = GetSwapConfirmationAttModel(out fileList); } if ((PS.Config.ErpElement.SAC_ReportDataSource & SAC_ReportDataSourceEnum.System) == SAC_ReportDataSourceEnum.System) { var nextDate = _reqInfo.ReportDate.AddDays(1); var nextDataDate = _reqInfo.DataDate.AddDays(1); using (var db = new YLContext()) { var codeList = ReportStatus.GetCacheInfo(cacheKey); var query = (from t in db.trade join tc in db.trade_cash on t.id equals tc.TradeId join tr in db.trade_contract_r on tc.id equals tr.TradeCashId join td in db.trade_contract_document on tr.ContractCode equals td.Code join ts in db.trade_swap on t.id equals ts.TradeId where ((_operationType == OptFlagsEnum.A && t.TradeDate >= _reqInfo.DataDate && t.TradeDate < nextDataDate)//新增时使用交易日期判断 || (_operationType != OptFlagsEnum.A && tc.OptDate >= _reqInfo.ReportDate && tc.OptDate < nextDate)//补正和废止时使用操作日期判断 || tr.OptDate >= _reqInfo.DataDate) && (_operationType == OptFlagsEnum.D || (t.ValidState != "InValid" && tc.ValidState != "InValid" && !tc.IsDeleted && tr.IsValid)) && /*t.UnderlyingInstrumentType == "Stock" &&*/ t.TradeType == "收益互换" && tc.Action == "系统操作-期权费" select new { tcId = tc.id, tc.OptDate, tradeValid = t.ValidState != "InValid", tradecashValid = tc.ValidState != "InValid" && !tc.IsDeleted, tradeContractRValid = tr.IsValid, t.id, t.ClientId, t.TradeDate, t.ExerciseDate, t.SettlementDate, t.ExerciseMode, t.BuySell, TradeType = t.StructureType ?? t.TradeType, t.OptionType, t.OriginalStockEqvNotional, t.StockEqvNotionalReal, t.IsMoneynessOption, t.SpotPrice, t.Strike, t.MarginTemplateName, t.MarginType, t.InitialMargin, t.UnderlyingCode, t.AnnualizeFactor, ts.IsGetFloatingProfit, ts.IsPayFloatingProfit, ts.GetVarietyId, ts.PayVarietyId, ts.GetUnderlyingCode, ts.PayUnderlyingCode, ts.GetLongShort, ts.PayLongShort, ts.GetSpotPrice, ts.PaySpotPrice, ts.GetTradePrice, ts.PayTradePrice, ts.GetSwapTimeAndRate, ts.PaySwapTimeAndRate, ts.GetFixedProfit, ts.PayFixedProfit, ts.GetMarginRate, ts.PayMarginRate, ts.GetTradeAmount, ts.PayTradeAmount, tr.ContractCode, td.Paths, td.StampDocumentFileName, t.QuoteCurrency, t.SettlementCurrency, ts.GetUnAnnualRate, ts.GetSingleFee, ts.PayUnAnnualRate, ts.PaySingleFee, }).OrderBy(O => O.OptDate).ToArray().Where(O => !codeList.Contains(O.id + "")).ToArray(); List ids = query.Select(O => O.id).ToList(); List delIds = new List(); if (_operationType == OptFlagsEnum.D) { delIds = DbContext.TradeAuditLog.Where(O => ids.Contains(O.TradeId) && O.OptDate >= _reqInfo.ReportDate && O.OptDate < nextDate && O.OptType == "删除交易").Select(O => O.TradeId).ToList(); } Dictionary> metaDic = DbContext.TradeMeta.Where(O => ids.Contains(O.TradeId)).AsEnumerable().GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.ToDictionary(K1 => K1.MetaKey, V1 => V1.MetaValue)); Dictionary reportDescDic = DbContext.AppConfig.Where(O => O.PGroup == ConsAppConfig.ReportDescSwap).ToDictionary(K => K.PName, V => V.PValue); foreach (var item in query) { var cacheValue = item.id.ToString(); if (ReportStatus.CheckCacheInfo(cacheKey, cacheValue)) { continue; } //如果存在重复数据,则始终用较新的数据 SwapConfirmationAttModel info = new SwapConfirmationAttModel(); info.ConfirmationNo = item.ContractCode; var confirmationNote = base.GetReportNotes(SuperviseReportTypeEnum.SAC_SwapConfirmation, $"_{info.ConfirmationNo.Replace("_", "-")}_").FirstOrDefault(); var currentCodes = ReportStatus.GetCacheInfo(DataFlagsEnum.A1005.ToString());//取出这一次报送交易要素的交易编号 if (!currentCodes.Contains(item.id.ToString()) && (confirmationNote == null || !confirmationNote.ReportResponse)) { continue;//跳过交易要素还没报送的确认书附件; } SACReportNotes note = base.GetReportNotes(formatInfoTag(info)).FirstOrDefault(); if (note == null && _operationType == OptFlagsEnum.A) { info.OperationType = OptFlagsEnum.A; note = new SACReportNotes() { IsValid = true, }; } else { if (note == null) { continue; } switch (_operationType) { case OptFlagsEnum.A: continue;//新增数据已报送,跳过 case OptFlagsEnum.U: if (!note.changeStatus) { continue;//交易没有被修改过,跳过 } info.OperationType = OptFlagsEnum.U; note.IsValid = true; break; case OptFlagsEnum.D: if (!delIds.Contains(item.id)) { continue;//交易没有被删除,跳过 } info.OperationType = OptFlagsEnum.D; note.IsValid = false; break; case OptFlagsEnum.NONE: default: throw new ServiceException("未知操作类型"); } } Dictionary reportCacheDic = JsonHelper.ToObject>(note.InfoCache) ?? new Dictionary(); if (info.OperationType != _operationType) { continue; } if (info.OperationType != OptFlagsEnum.D && (!item.tradeValid || !item.tradecashValid || !item.tradeContractRValid)) {//非废止报送中,应跳过所有存在无效数据的数据 continue; } if (metaDic.ContainsKey(item.id)) { var metaInfo = metaDic[item.id]; var tradingPlace = metaInfo.ContainsKey(ConsTradeMetaKey.TradingPlace) ? TradingPlaceMap[metaInfo[ConsTradeMetaKey.TradingPlace]] : ""; if (tradingPlace == "1")//跳过交易场所为报价系统的交易; { continue; } } if (info.OperationType != OptFlagsEnum.A) { info.BizID = note.BizId;//确认书编号; } string path = item.StampDocumentFileName ?? item.Paths; if (!path.StartsWith("\\") || path.StartsWith("/")) { path = "\\" + path; } var absolutePath = OtcAppContext.MapPath(path); absolutePath = Path.ChangeExtension(absolutePath, "pdf"); info.ConfirmationFilesTuple = new List() { new ConfirmationFilesTupleModel() { ConfirmationFiles = Path.GetFileName(absolutePath) } }; info.ExceID = base.formatExceID(); if (!ReportStatus.CheckFileLength(absolutePath)) { break; } fileList.Add(absolutePath); ReportStatus.AddCacheInfo(cacheKey, cacheValue); dataList.Add(info); note.id = 0; note.InfoCache = $"{{\"DueDate\":\"{item.OptDate?.ToString("yyyy-MM-dd")}\",\"Tag\":\"{info.ConfirmationNo}\",\"Source\":\"System\"}}"; note.ExceId = info.ExceID; note.CreateTime = DateTime.Now; note.FileTag = FileTag; note.ReportType = ReportType; note.ReportDate = _reqInfo.ReportDate; note.InfoTag = formatInfoTag(info, true); note.OptTime = note.CreateTime; note.RetCode = ""; note.RetMsg = ""; note.ReportResponse = false; note.DataId = item.tcId.ToString(); note.BizId = ""; note.changeStatus = false; noteList.Add(note); } } } if ((PS.Config.ErpElement.SAC_ReportDataSource & SAC_ReportDataSourceEnum.KingstarView) == SAC_ReportDataSourceEnum.KingstarView) { dataList.AddRange(GetSwapConfirmationAttModelFromView(out fileList)); } var subsystemDataList = loadSubsystemDataSource(fileList, AddSubsystemNote); if (subsystemDataList != null && subsystemDataList.Count > 0) dataList.AddRange(subsystemDataList); noData = dataList.Count == 0; model.ConfirmationAtt = dataList; return model; } public bool AddSubsystemNote(SwapConfirmationAttModel model, List fileList, string tag) { SACReportNotes note = base.GetReportNotes(ReportType, formatInfoTag(model, true)).FirstOrDefault();//参数true要加,要不A和D会查到同一条记录,在D时候,就会和A相同的数据 if (note == null) { note = new SACReportNotes() { InfoCache = $"{{\"Tag\":\"{model.ConfirmationNo}\",\"Source\":\"Subsystem\",\"SubFileTag\":\"{tag}\",\"ExceID\":\"{model.ExceID}\"}}", IsValid = true, }; } else { switch (model.OperationType) { case OptFlagsEnum.A: return false;//新增数据已报送,跳过 case OptFlagsEnum.U: //多次U的时候,每次用最新的tag来赋值SubFileTag note.InfoCache = $"{{\"Tag\":\"{model.ConfirmationNo}\",\"Source\":\"Subsystem\",\"SubFileTag\":\"{tag}\",\"ExceID\":\"{model.ExceID}\"}}"; note.IsValid = true; break; case OptFlagsEnum.D: note.IsValid = false; break; case OptFlagsEnum.NONE: default: throw new ServiceException("未知操作类型"); } } if (model.ConfirmationFilesTuple != null && model.ConfirmationFilesTuple.Count > 0) { fileList.AddRange(model.ConfirmationFilesTuple.Select(x => x.ConfirmationFiles)); } model.ExceID = base.formatExceID(); note.id = 0; note.ExceId = model.ExceID; note.CreateTime = DateTime.Now; note.FileTag = FileTag; note.ReportType = ReportType; note.ReportDate = _reqInfo.ReportDate; note.InfoTag = formatInfoTag(model, true); note.OptTime = note.CreateTime; note.RetCode = ""; note.RetMsg = ""; note.ReportResponse = false; note.BizId = ""; note.changeStatus = false; noteList.Add(note); return true; } private List GetSwapConfirmationAttModel(out List fileList) { fileList = new List(); List result = new List(); if (_excelDataSource != null && _excelDataSource.Tables.Contains("收益互换确认书附件明细")) { var cacheKey = $"{BusiDataType}"; DataTable dt = _excelDataSource.Tables["收益互换确认书附件明细"]; string sourcePath = Path.Combine(_excelDataSourceRootPath, "附件"); for (int i = 1; i < dt.Rows.Count; i++) { if (string.IsNullOrWhiteSpace(dt.Rows[i][0]?.ToString())) { //第一列空白说明数据结束了; break; } var optType = OptFlagsEnum.NONE; switch (dt.Rows[i][1]?.ToString()) { case "首次": optType = OptFlagsEnum.A; break; case "变更": optType = OptFlagsEnum.U; break; case "废止": optType = OptFlagsEnum.D; break; } if (optType != _operationType) { continue; } SwapConfirmationAttModel model = new SwapConfirmationAttModel(); model.ConfirmationNo = GetDataSetValue(dt, i, 0); model.OperationType = optType; var cacheValue = model.ConfirmationNo; if (ReportStatus.CheckCacheInfo(cacheKey, cacheValue)) { continue; } model.ConfirmationFilesTuple = new List(); var files = GetDataSetValue(dt, i, 2).Split(','); foreach (var f in files) { if (!string.IsNullOrWhiteSpace(f)) { var path = Path.Combine(sourcePath, f); if (!ReportStatus.CheckFileLength(path)) { break; } fileList.Add(path); model.ConfirmationFilesTuple.Add(new ConfirmationFilesTupleModel() { ConfirmationFiles = f }); } } List notes = base.GetReportNotes(ReportType, formatInfoTag(model)); var note = notes.LastOrDefault(O => O.InfoCache.Contains(cacheValue)); if (note == null && _operationType == OptFlagsEnum.A) { note = new SACReportNotes() { InfoCache = $"{{\"Tag\":\"{model.ConfirmationNo}\",\"Source\":\"Template\"}}", IsValid = true, }; } else { if (note == null) { continue; } switch (_operationType) { case OptFlagsEnum.A: continue;//新增数据已报送,跳过 case OptFlagsEnum.U: note.IsValid = true; break; case OptFlagsEnum.D: note.IsValid = false; break; case OptFlagsEnum.NONE: default: throw new ServiceException("未知操作类型"); } } if (_operationType != OptFlagsEnum.A) { model.BizID = note.BizId; } model.ExceID = base.formatExceID(); result.Add(model); ReportStatus.AddCacheInfo(cacheKey, cacheValue); note.id = 0; note.ExceId = model.ExceID; note.CreateTime = DateTime.Now; note.FileTag = FileTag; note.ReportType = ReportType; note.ReportDate = _reqInfo.ReportDate; note.InfoTag = formatInfoTag(model, true); note.OptTime = note.CreateTime; note.RetCode = ""; note.RetMsg = ""; note.ReportResponse = false; note.BizId = ""; note.DataId = ""; note.changeStatus = false; noteList.Add(note); } } return result; } private List GetSwapConfirmationAttModelFromView(out List fileList) { fileList = new List(); List result = new List(); if (_viewDataSource != null && _viewDataSource.Tables.Contains("交易确认书附件")) { var ftpHelper = new FtpHelper(PS.Config.ErpElement.KingstarView_RemotePath, PS.Config.ErpElement.KingstarView_RemoteUser, PS.Config.ErpElement.KingstarView_RemotePassword, PS.Config.ErpElement.KingstarView_FtpUsePassive, 3000, PS.Config.ErpElement.KingstarView_EnableSsl); var cacheKey = $"{BusiDataType}"; DataTable dt = _viewDataSource.Tables["交易确认书附件"]; for (int i = 0; i < dt.Rows.Count; i++) { var optType = OptFlagsEnum.NONE; switch (GetDataSetValue(dt, i, "OPERATIONTYPE")) { case "A": optType = OptFlagsEnum.A; break; case "U": optType = OptFlagsEnum.U; break; case "D": optType = OptFlagsEnum.D; break; } if (optType != _operationType) { continue; } SwapConfirmationAttModel model = new SwapConfirmationAttModel(); model.IgnoreCheck = true; model.ConfirmationNo = GetDataSetValue(dt, i, "CONFIRMATIONNO"); model.OperationType = optType; var cacheValue = model.ConfirmationNo; if (ReportStatus.CheckCacheInfo(cacheKey, cacheValue)) { continue; } model.ConfirmationFilesTuple = new List(); ; var files = GetDataSetValue(dt, i, "CONFIRMATIONFILES").Split(','); foreach (var f in files) { if (!string.IsNullOrWhiteSpace(f)) { var downloadRet = ftpHelper.DownloadFile(CreateViewAttDownloadPath(f), ViewLocalAttFileDir + @"\kingstar\", out string message); LogFactory.GetLogger("ftpHelper.DownloadFile").Info($"下载结果:{ViewLocalAttFileDir},{f},{downloadRet}"); var path = downloadRet; if (!ReportStatus.CheckFileLength(path)) { break; } fileList.Add(path); model.ConfirmationFilesTuple.Add(new ConfirmationFilesTupleModel() { ConfirmationFiles = Path.GetFileName(path) }); } } List notes = base.GetReportNotes(ReportType, formatInfoTag(model)); var note = notes.LastOrDefault(O => O.InfoCache.Contains(cacheValue)); if (note == null && _operationType == OptFlagsEnum.A) { note = new SACReportNotes() { InfoCache = $"{{\"Tag\":\"{model.ConfirmationNo}\",\"Source\":\"KingstarView\"}}", IsValid = true, }; } else { if (note == null) { continue; } switch (_operationType) { case OptFlagsEnum.A: continue;//新增数据已报送,跳过 case OptFlagsEnum.U: note.IsValid = true; break; case OptFlagsEnum.D: note.IsValid = false; break; case OptFlagsEnum.NONE: default: throw new ServiceException("未知操作类型"); } } if (_operationType != OptFlagsEnum.A) { model.BizID = note.BizId; } model.ExceID = base.formatExceID(); result.Add(model); ReportStatus.AddCacheInfo(cacheKey, cacheValue); note.id = 0; note.ExceId = model.ExceID; note.CreateTime = DateTime.Now; note.FileTag = FileTag; note.ReportType = ReportType; note.ReportDate = _reqInfo.ReportDate; note.InfoTag = formatInfoTag(model, true); note.OptTime = note.CreateTime; note.RetCode = ""; note.RetMsg = ""; note.ReportResponse = false; note.BizId = ""; note.DataId = ""; note.changeStatus = false; noteList.Add(note); } } return result; } private string formatInfoTag(SwapConfirmationAttModel model, bool suffixType = false) { string result = $"{BusiDataType}_{model.ConfirmationNo.Replace("_", "-")}_成交_确认书_"; if (suffixType) { result = $"{result}{_operationType}"; } return result; } protected override List CheckBodyValue(BodyModel model, out bool checkStatus) { List result = new List(); if (model?.ConfirmationAtt != null) { CheckHelper helper = new CheckHelper(); for (int i = 0; i < model.ConfirmationAtt.Count; i++) { List listRoot = new List(); var item = model.ConfirmationAtt[i]; if (item.IgnoreCheck) continue; helper.ExecuteCheck(item, (name, value, msg) => { listRoot.Add(new SacInfo(name, value, msg)); }); if (listRoot.Count > 0) { var errMsg = new SacInfo("SwapConfirmationAtt", i); errMsg.SubMaps = new List(listRoot); result.Add(errMsg); } } } checkStatus = result.Count > 0; return result; } public override bool BeforeOfGenerated(out string errMsg) { errMsg = ""; foreach (var file in xmlAttachmentList) { try { File.Delete(file); } catch (Exception e) { LogFactory.GetLogger().Error(e); }; } for (int i = 0; i < noteList.Count; i++) { base.SaveReportNotes(noteList[i]); } return true; } } }