using BaseOUDAL; using Newtonsoft.Json.Linq; using OfficeOpenXml; using Qdp.Foundation.Utilities; using Qdp.Pricing.Base.Enums; using Qdp.Pricing.Library.Common.Interfaces; using Qdp.Pricing.Library.Options.Products.Asian; using System; using System.Collections.Specialized; using System.Diagnostics.Contracts; using System.Text; using System.Web; using YieldChain.Helpers; using YLErp.Abstract; using YLErp.BLL; using YLErp.BLL.Eod; using YLErp.BLL.EodSettlement; using YLErp.BLL.MarginCalculation; using YLErp.Commons; using YLErp.Configuration; using YLErp.DBModels; using YLErp.DBModels.Abstract; using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.Helpers; using YLErp.Model; using YLErp.Models; using YLErp.Modules.ApiModule.ExportModule; using YLErp.Modules.CalculationModule; using YLErp.Modules.DataProviderModule; using YLErp.Modules.TradeDalModule; using YLErp.Office; using YLErp.Office.Converters; using YLErp.Plugins.TradeDocGenerator; using YLErp.Plugins.TradeDocGenerator.Abstracts; using YLErp.QdpModule; namespace YLErp.Modules.TradeModule.DocGenerateModule { public class ConfirmationGenerateContext : YLBaseService, ITradeDocGeneratorContext, ITradeConfirmationGeneratotContext { /// /// 生成确认书时,用户选择的资金记录 /// public IEnumerable UserTradeCashIds { get; } /// /// 同步锁 /// private static readonly object _syncLock = new object(); /// /// 确认书编号缓存 处理 确认书生成出重复编号问题,浙期已修改,如果其他公司有类似问题请参照这次提交代码 /// key 是合约编号 /// value[tradecashid,当前时间] 过期时间1h /// 汤旺 /// private static Dictionary ContractCodeCache = new Dictionary(); /// /// [必需]交易记录 /// public OtcTradeBase Trade { get; } public IEnumerable SubTrades { get; } private readonly trade_cash _tradeCash; private readonly List _subTradeCashes = new List(); /// /// [必需]合约业务接口 /// public IContractBLL ContractBLL { get; } /// /// 浮动平仓事件集 /// public readonly List FlowEvents; /// /// 平仓事件集 /// public readonly List AllFlowEvents = new List(); /// /// 交易持仓腿集合 /// public readonly List SwapPositions = new List(); /// /// [必需]期权数据提供接口 /// public ITradeExtendDataProvider TradeDataProvider { get; } readonly string _contractType; public ConfirmationGenerateContext(IEnumerable tradeCashIds, IEnumerable trades, string contractType, OptUserInfo userInfo, DateTime? startDate, DateTime? endDate) : this(((tradeCashIds?.FirstOrDefault()) ?? 0), trades.First(), contractType, userInfo) { Trades = trades.GroupBy(O => O.id).Select(O => O.First()).ToList() ?? throw new ArgumentNullException(nameof(trades)); TradeCashes = trades.GroupBy(O => O.id).ToDictionary(K => K.Key, V => V.Where(O => O.trade_cash != null).Select(O => O.trade_cash).ToList()); var structureTrades = trades.Where(O => O.TradeType == "结构化交易"); var subTrade = new List(); foreach (var item in structureTrades) { if (item.SubTrades != null) { subTrade.AddRange(item.SubTrades); var idArr = TradeCashes[item.id].Select(O => O.id); var obj = item.SubTrades.Where(O => O.trade_cash != null && !idArr.Contains(O.trade_cash.id)).Select(O => O.trade_cash); TradeCashes[item.id].AddRange(obj); } TradeCashes[item.id].RemoveAll(O => O == null); } subTrade = subTrade.GroupBy(O => O.id).Select(O => O.FirstOrDefault()).ToList(); if (tradeCashIds == null || tradeCashIds.Count() == 0) { tradeCashIds = trades.Select(O => (O.trade_cash?.id) ?? 0).Concat(subTrade.Select(O => (O.trade_cash?.id) ?? 0)).ToArray(); } SubTrades = subTrade; UserTradeCashIds = tradeCashIds; StartDate = startDate; EndDate = endDate; } /// /// 构造函数 /// public ConfirmationGenerateContext(int tradeCashId, trade tradeObj, string contractType, OptUserInfo userInfo) : base(userInfo) { Trade = tradeObj ?? throw new ArgumentNullException(nameof(tradeObj)); Trades = new[] { tradeObj }; if (tradeObj.TradeType == "结构化交易") { SubTrades = tradeObj.SubTrades; if (tradeObj.SubTrades != null) { foreach (var trade in tradeObj.SubTrades) { _subTradeCashes.Add(trade.trade_cash ?? throw new ArgumentNullException("trade.SubTrades[].trade_cash")); } } var checkCash = _subTradeCashes.GroupBy(O => $"{O.Action}_{O.Notional}_{O.UnwindNotional}").ToDictionary(K => K.Key, V => 1); if (tradeObj.StructureType == "蝶式组合") { var tradecash = _subTradeCashes.GroupBy(o => new { Action = o.Action, TradeType = o.TradeType }).Select(o => new { Action = o.Key.Action, TradeType = o.Key.TradeType, Notional = o.Sum(s => s.Notional), UnwindNotional = o.Sum(s => s.UnwindNotional) }); checkCash = tradecash.GroupBy(O => $"{O.Action}_{O.Notional}_{O.UnwindNotional}").ToDictionary(K => K.Key, V => 1); } //浙期存在参与率不一致的组合交易,会导致有效数量不一致,黑箱不参与资金检查,例如子交易有现金流交易notioal为0 if (checkCash.Count > 1 && !PS.Config.Is浙期 && tradeObj.IsGroup != 1 && tradeObj.StructureType != "风险逆转" && tradeObj.TradeType != "三领口") { throw new InvalidOperationException("子交易资金记录不匹配!"); } if (tradeCashId == 0) { tradeCashId = _subTradeCashes.FirstOrDefault()?.id ?? 0; } _tradeCash = _subTradeCashes.Where(O => O.id == tradeCashId).FirstOrDefault(); if (tradeObj.IsGroup == 1) { _tradeCash = tradeObj.trade_cash ?? throw new ArgumentNullException(nameof(trade.trade_cash)); } } //else if (tradeObj.TradeType == "结构化交易" && tradeObj.IsGroup == 1) //{ // _tradeCash = tradeObj.trade_cash ?? throw new ArgumentNullException(nameof(trade.trade_cash)); // if (tradeCashId == 0) // { // tradeCashId = tradeObj.trade_cash.id; // } // SubTrades = tradeObj.SubTrades; // foreach (var trade in tradeObj.SubTrades) // { // _subTradeCashes.Add(trade.trade_cash ?? throw new ArgumentNullException("trade.SubTrades[].trade_cash")); // } // var checkCash = _subTradeCashes.GroupBy(O => $"{O.Action}_{O.Notional}_{O.UnwindNotional}").ToDictionary(K => K.Key, V => 1); // if (checkCash.Count > 1) // { // throw new InvalidOperationException("子交易资金记录不匹配!"); // } //} else { // _tradeCash = tradeObj.trade_cash ?? throw new ArgumentNullException(nameof(trade.trade_cash)); // if (tradeCashId == 0) // { tradeCashId = tradeObj.trade_cash.id; } SubTrades = new List() { Trade }; } // UserTradeCashIds = new[] { tradeCashId }; _client = DataCacheProvider.GetClientDataSource().GetData(tradeObj.ClientId) ?? throw new ArgumentNullException(nameof(tradeObj.ClientId)); _contractType = contractType ?? throw new ArgumentNullException(nameof(contractType)); ContractBLL = new TradeContractBLL(this); TradeDataProvider = new TradeExtendDataProvider(this); // TradeCashes = new Dictionary>() { { tradeObj.id, new List { _tradeCash } } }; // TradeCashes[Trade.id].AddRange(_subTradeCashes); // TradeCashes[Trade.id].RemoveAll(O => O == null); string fixing = null; //亚式期权 if (tradeObj.TradeType == "亚式期权") { fixing = AsianOptionFixingService.GetFixingString(tradeObj.trade_cash.ValueDate, tradeObj); fixing = FixingService.AddOrReplaceLastDateSpotPrice(fixing, tradeObj.trade_cash.ValueDate, tradeObj.trade_cash.FinalPrice ?? 0.0); if (PS.Config.Is润和 && tradeObj.trade_cash.CreateTime != null && tradeObj.trade_cash.ValueDate.ToString("yyyy-MM-dd").Equals(tradeObj.trade_cash.CreateTime.OtcFormatDate()) && tradeObj.trade_cash.CreateTime.Value.Hour < 15) { var index = fixing.IndexOf(tradeObj.trade_cash.ValueDate.ToString("yyyy-MM-dd")); if (index >= 0) { fixing = fixing.Remove(index).TrimEnd(';'); } } } Trade.Fixing = fixing; } public ConfirmationGenerateContext(Client client, List flowEvents, List allFlowEvents, List trades, List swapPositions, string contractType, OptUserInfo userInfo) : base(userInfo) { _client = client; _contractType = contractType ?? throw new ArgumentNullException(nameof(contractType)); ContractBLL = new TradeContractBLL(this); TradeDataProvider = new TradeExtendDataProvider(this); Trades = trades; FlowEvents = flowEvents; AllFlowEvents = allFlowEvents; SwapPositions = swapPositions; } /// /// 获取系统配置接口对象 /// public IErpConfig GetErpConfig() { return PS.GetErpConfig(); } /// /// 转换word文档为pdf文档 /// public void ConvertDocToPDF(string wordDocPath, string targetPdfPath) { OfficeFileConverter.ConvertFileFormat(wordDocPath, targetPdfPath); } /// /// 根据Excel文档模板生成文档 /// public void GenerateExcelFromTemplate(string templatePath, Dictionary modelDic, string outputFilePath, bool genPdf = true) { var templaExt = Path.GetExtension(templatePath); var outputExt = Path.GetExtension(outputFilePath); var tmpOutputFilePath = outputFilePath; if (templaExt == ".xlsx") { //特殊处理:使用excel模板生成文档。 tmpOutputFilePath = outputFilePath.Replace(".docx", ".xlsx").Replace(".pdf", ".xlsx"); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; new ExcelTemplateGenerator() .SetTemplateFile(templatePath) .SetTemplateData(modelDic.ToDictionary(n => n.Key, n => (object)n.Value)) .OutputToFile(tmpOutputFilePath); } else { //new ExcelTemplateGenerator().SetTemplateFile(templatePath).SetTemplateData(modelDic).OutputToFile(outputFilePath); } if (genPdf) { var outputPdfFile = FileHelper.ReplaceExtension(tmpOutputFilePath, ".pdf"); OfficeFileConverter.ConvertFileFormat(tmpOutputFilePath, outputPdfFile); } } public void GenerateExcelFromTemplate(string templatePath, Dictionary modelDic, string outputFilePath, bool genPdf = true) { var templaExt = Path.GetExtension(templatePath); var outputExt = Path.GetExtension(outputFilePath); var tmpOutputFilePath = outputFilePath; if (templaExt == ".xlsx") { //特殊处理:使用excel模板生成文档。 tmpOutputFilePath = outputFilePath.Replace(".doc", ".xlsx").Replace(".docx", ".xlsx").Replace(".pdf", ".xlsx"); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; new ExcelTemplateGenerator() .SetTemplateFile(templatePath) .SetTemplateData(modelDic) .OutputToFile(tmpOutputFilePath); } else { //new ExcelTemplateGenerator().SetTemplateFile(templatePath).SetTemplateData(modelDic).OutputToFile(outputFilePath); } if (genPdf) { var outputPdfFile = FileHelper.ReplaceExtension(tmpOutputFilePath, ".pdf"); OfficeFileConverter.ConvertFileFormat(tmpOutputFilePath, outputPdfFile); } } /// /// 根据Word文档模板生成文档 /// public void GenerateDocFromTemplate(string templatePath, Dictionary modelDic, string outputFilePath, bool genPdf = true) { //WordHelper.GenerateFromTemplate(templatePath, modelDic, outputFilePath); var varDic = new JsonVarDic(modelDic); var _outputFilePath = outputFilePath.Replace(".pdf", ".docx"); LogFactory.GetLogger("Word生成").Info($"生成Word文档:{_outputFilePath}"); OfficeFileConverter.ConvertByUsingDocTemplate(templatePath, _outputFilePath, varDic, false); var toPDF = outputFilePath.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase); if (genPdf && toPDF) { LogFactory.GetLogger("Word生成").Info($"转换Word文档为PDF:{_outputFilePath}"); ConvertToPdfHelper.ConvertPDFByApi(HttpUtility.UrlEncode(_outputFilePath), HttpUtility.UrlEncode(outputFilePath)); } } /// /// 获取合成价差期权的商品标的名称 /// public string GetSyntheticUnderlyingName(string underlyingCode) { return synthetic_underlyingBLL.GetUnderlyingTipsInfo(underlyingCode); } /// /// 获取亚式期权行权价 /// /// /// public double? GetAsianStrikePrice(OtcTradeBase trade, DateTime valueDate) { var t = trade as trade; if (trade == null) { throw new TradeDocGenerateException($"交易信息出错 {trade?.TradeNumber}"); } if (t.TradeType == "亚式期权" && t.trade_asian_option == null) { tradeBLL.SetFieldsByTradeType(new[] { t }); } if (t.TradeType != "亚式期权" || t.trade_asian_option.StrikeType == StrikeStyle.Fixed.ToString()) { return trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike; } t.trade_asian_option.Fixings = AsianOptionFixingService.GetFixingString(valueDate, t); var QdpTrade = TradeCalcHelper.GetQdpTrade(t); if (QdpTrade != null && QdpTrade.Instrument != null && QdpTrade.Instrument is IOption opt) { var asianOpt = opt as AsianOption; return asianOpt.ActualStrike; } return null; } /// /// 获取亚式期权现价 /// /// /// public double? GetAsianFinalPrice(OtcTradeBase trade, trade_asian_option asian_option, DateTime valueDate) { if (trade == null || asian_option == null) { throw new TradeDocGenerateException($"交易信息出错 {trade?.TradeNumber}"); } if (trade.TradeType != "亚式期权" || asian_option.StrikeType == StrikeStyle.Fixed.ToString()) { return trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike; } asian_option.Fixings = AsianOptionFixingService.GetFixingString(valueDate, trade, asian_option); var QdpTrade = QdpTradeBuilder.GetAsianOptionTrade(trade, asian_option); if (QdpTrade != null && QdpTrade.Instrument != null && QdpTrade.Instrument is IOption opt) { var asianOpt = opt as AsianOption; return asianOpt.FinalPrice(); } return null; } public DateTime? GetAveragingPeriodStartDate(OtcTradeBase trade) { if (trade.TradeType == "亚式期权") { var asianTrade = DbContext.trade_asian_option.Where(O => O.TradeId == trade.id).FirstOrDefault(); if (asianTrade != null) { return asianTrade.AveragingPeriodStartDate; } } if (trade.TradeType == "远期") { var forwardTrade = DbContext.trade_forward.Where(O => O.TradeId == trade.id).FirstOrDefault(); if (forwardTrade != null) { if (string.IsNullOrWhiteSpace(forwardTrade.ObservationDates)) { //如果为空返回到期日 return trade.ExerciseDate; } var observationDates = forwardTrade.ObservationDates.Split(',').OrderBy(o => o); if (DateTime.TryParse(observationDates.FirstOrDefault(), out var startDate)) { return startDate; } } } return null; } public void DelContractDocument(ITradeContractDocument contractDoc) { var db = DbContextFactory.GetYLDbContext(); var datas = db.trade_contract_r.Where(n => n.ContractCode == contractDoc.Code && n.Type == contractDoc.Type && n.IsValid).ToList(); //db.trade_contract_r.RemoveRange(datas); datas.ForEach(O => O.IsValid = false); var contractDocs = db.trade_contract_document.Where(x => x.Code == contractDoc.Code && x.Type == contractDoc.Type).ToArray(); db.trade_contract_document.RemoveRange(contractDocs); db.SaveChanges(); } /// /// 保存文档生成数据 /// public ITradeContractDocument SaveContractDocument(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null) { var documents = new List(); var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".docx"); var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Word; var tradecashDict = _subTradeCashes.Count == 0 ? new Dictionary>() { { Trade.id, new List() { (_tradeCash?.id ?? 0) } } } : _subTradeCashes.GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); if (Trade.IsGroup == 1) // 黑箱交易需要传主交易和子交易 { tradecashDict[Trade.id] = new List() { _tradeCash.id }; } var trades = new List() { Trade }; if (Trade.TradeType == "结构化交易" && SubTrades.Count() > 1) { trades.AddRange(SubTrades); } documents = SaveContractDocuments(trades, tradecashDict, contractCode, savedOutputFileName, fileType); ContractCodeCache.Remove(contractCode); return documents[0]; } /// /// 保存文档生成数据 /// public List SaveContractDocuments(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null) { var documents = new List(); var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".xlsx"); var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Excel; //var tradecashDict = TradeCashes.ToDictionary(K => K.Key, V => V.Value.Select(O => O.id).ToList()); var tradecashDict = new Dictionary>(); foreach (var item in TradeCashes) { for (var i = 0; i < item.Value.Count; i++) { if (!tradecashDict.TryGetValue(item.Value[i].TradeId, out var value)) { tradecashDict[item.Value[i].TradeId] = new List() { item.Value[i].id }; } else { value.Add(item.Value[i].id); } } } var trades = Trades.ToList(); var structureTrades = Trades.Where(O => O.TradeType == "结构化交易" && O.IsGroup != 1).ToList(); foreach (trade item in structureTrades) { trades.AddRange(item.SubTrades); } documents = SaveContractDocuments(trades, tradecashDict, contractCode, savedOutputFileName, fileType); ContractCodeCache.Remove(contractCode); return documents; } /// /// 保存文档生成数据 /// public List SaveContractDocumentsByEventId(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null) { var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".xlsx"); var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Excel; var documents = SaveContractDocumentsByEventIds(Trades, FlowEvents, contractCode, savedOutputFileName, fileType); ContractCodeCache.Remove(contractCode); return documents; } /// /// 保存文档生成数据 /// /// /// /// /// /// /// /// private List SaveContractDocuments(IEnumerable trades, Dictionary> tradeCashIds, string contractCode, string fileName, string fileType) { lock (_syncLock) { var documents = new List(); var firstTrade = trades.First(); var isGJBuyer = firstTrade.BuySell == "买入"; var nowDate = DateTime.Now; var db = DbContextFactory.GetYLDbContext(); #region 清理历史数据 var tcIds = new List(); foreach (var item in tradeCashIds) { tcIds.AddRange(item.Value); } var tradeIds = trades.Select(x => x.id); //当生成分组主交易确认书时,没有tradeCashId if (_contractType == "交易确认书") { var datas = db.trade_contract_r.Where(O => tradeIds.Contains(O.TradeId) && O.IsValid && O.Type == _contractType).ToList(); datas.ForEach(O => O.IsValid = false); } else { var datas = db.trade_contract_r.Where(O => tcIds.Contains(O.TradeCashId ?? 0) && O.IsValid).ToList(); datas.ForEach(O => O.IsValid = false); } //db.trade_contract_r.RemoveRange(datas); //var codes = datas.Select(O => O.ContractCode); //var contractDocs = db.trade_contract_document.Where(O => codes.Contains(O.Code)).ToArray(); //db.trade_contract_document.RemoveRange(contractDocs); #endregion var contractRecord = db.trade_contract_document.Where(O => O.Code == contractCode && O.Type == _contractType).FirstOrDefault(); if (contractRecord == null) { contractRecord = new trade_contract_document(); db.trade_contract_document.Add(contractRecord); } contractRecord.Code = contractCode; contractRecord.ValueDate = SystemValueDate; contractRecord.BuyerId = isGJBuyer ? 0 : firstTrade.ClientId; contractRecord.BuyerName = isGJBuyer ? (PS.Config.CompanyName ?? "") : firstTrade.ClientName; contractRecord.SellerId = isGJBuyer ? firstTrade.ClientId : 0; contractRecord.SellerName = isGJBuyer ? firstTrade.ClientName : (PS.Config.CompanyName ?? ""); contractRecord.FileType = fileType; contractRecord.Status = ContractStatusEnum.Draft; contractRecord.SourceType = 1; // 系统生成 contractRecord.Paths = "/App_Docs/contractdoc/output/" + fileName; contractRecord.FileName = fileName; contractRecord.StampDocumentFileName = null; contractRecord.SealErrMsg = null; contractRecord.SealResult = null; contractRecord.Comments = null; contractRecord.DayNumber = null; contractRecord.ContractVersion = null; contractRecord.Type = _contractType; contractRecord.OptId = UserId; contractRecord.OptName = UserName; contractRecord.OptDate = nowDate; contractRecord.ClientId = firstTrade.ClientId; contractRecord.StampDocumentFileName = null; contractRecord.SealResult = null; foreach (var item in trades) { if (item.TradeType == "结构化交易" && item.IsGroup == 0) { //var cTrade = trades.First(O => O.ParentTradeId == item.id); //var contractTradeRelation = new trade_contract_r(); //db.trade_contract_r.Add(contractTradeRelation); //contractTradeRelation.TradeId = item.id; //contractTradeRelation.TradeNumber = item.TradeNumber; //contractTradeRelation.ContractCode = contractRecord.Code; //contractTradeRelation.TradeClearCode = contractRecord.Code; //contractTradeRelation.Type = _contractType; //contractTradeRelation.OptId = UserId; //contractTradeRelation.OptName = UserName; //contractTradeRelation.OptDate = nowDate; //contractTradeRelation.TradeCashId = tradeCashIds[cTrade.id][0]; //contractTradeRelation.IsValid = true; //documents.Add(contractRecord); continue; } else { if (tradeCashIds.Any()) { var tcList = tradeCashIds[item.id].Distinct().ToList(); for (var i = 0; i < tcList.Count; i++) { var contractTradeRelation = new trade_contract_r(); db.trade_contract_r.Add(contractTradeRelation); contractTradeRelation.TradeId = item.id; contractTradeRelation.TradeNumber = item.TradeNumber; contractTradeRelation.ContractCode = contractRecord.Code; contractTradeRelation.TradeClearCode = contractRecord.Code; contractTradeRelation.Type = _contractType; contractTradeRelation.OptId = UserId; contractTradeRelation.OptName = UserName; contractTradeRelation.OptDate = nowDate; contractTradeRelation.TradeCashId = tcList[i]; contractTradeRelation.IsValid = true; documents.Add(contractRecord); } } else { var contractTradeRelation = new trade_contract_r(); db.trade_contract_r.Add(contractTradeRelation); contractTradeRelation.TradeId = item.id; contractTradeRelation.TradeNumber = item.TradeNumber; contractTradeRelation.ContractCode = contractRecord.Code; contractTradeRelation.TradeClearCode = contractRecord.Code; contractTradeRelation.Type = _contractType; contractTradeRelation.OptId = UserId; contractTradeRelation.OptName = UserName; contractTradeRelation.OptDate = nowDate; contractTradeRelation.IsValid = true; documents.Add(contractRecord); } } } //var parentIds = trades.Where(O => O.TradeType == "结构化交易").Select(O => O.id).ToHashSet(); ////解决生成子交易确认书时,主交易编号查询不到的问题,在此使用主交易编号创建一条记录; //if (parentIds.Any()) //{ // foreach (var item in parentIds) // { // OtcTradeBase parentTrade = trades.First(O => O.id == item); // var contractTradeRelation = new trade_contract_r(); // db.trade_contract_r.Add(contractTradeRelation); // contractTradeRelation.TradeId = parentTrade.id; // contractTradeRelation.TradeNumber = parentTrade.TradeNumber; // contractTradeRelation.ContractCode = contractRecord.Code; // contractTradeRelation.TradeClearCode = contractRecord.Code; // contractTradeRelation.Type = _contractType; // contractTradeRelation.OptId = OptId; // contractTradeRelation.OptName = OptName; // contractTradeRelation.OptDate = nowDate; // contractTradeRelation.TradeCashId = tradeCashIds[item][0]; // documents.Add(contractRecord); // } //} db.SaveChanges(); return documents; } } /// /// 保存文档生成数据 /// /// /// /// /// /// /// /// private List SaveContractDocumentsByEventIds(IEnumerable trades, List flow_Events, string contractCode, string fileName, string fileType) { lock (_syncLock) { var documents = new List(); var firstTrade = trades.First(); var isGJBuyer = firstTrade.BuySell == "买入"; var nowDate = DateTime.Now; var db = DbContextFactory.GetYLDbContext(); #region 清理历史数据 var flowEventIds = flow_Events.Select(s => s.id).ToList(); var eventDate = flow_Events.First().UnwindDate.Value; var tradeIds = trades.Select(x => x.id); if (_contractType == "交易确认书") { var datas = db.trade_contract_r.Where(O => tradeIds.Contains(O.TradeId) && O.IsValid && O.Type == _contractType).ToList(); datas.ForEach(O => O.IsValid = false); } else { var datas = db.trade_contract_r.Where(O => flowEventIds.Contains(O.SwapFlowEventId ?? 0) && O.IsValid).ToList(); datas.ForEach(O => O.IsValid = false); } #endregion var contractRecord = db.trade_contract_document.Where(O => O.Code == contractCode && O.Type == _contractType).FirstOrDefault(); if (contractRecord == null) { contractRecord = new trade_contract_document(); db.trade_contract_document.Add(contractRecord); } contractRecord.Code = contractCode; contractRecord.ValueDate = eventDate; contractRecord.BuyerId = isGJBuyer ? 0 : firstTrade.ClientId; contractRecord.BuyerName = isGJBuyer ? (PS.Config.CompanyName ?? "") : firstTrade.ClientName; contractRecord.SellerId = isGJBuyer ? firstTrade.ClientId : 0; contractRecord.SellerName = isGJBuyer ? firstTrade.ClientName : (PS.Config.CompanyName ?? ""); contractRecord.FileType = fileType; contractRecord.Status = ContractStatusEnum.Draft; contractRecord.SourceType = 1; // 系统生成 contractRecord.Paths = "/App_Docs/contractdoc/output/" + fileName; contractRecord.FileName = fileName; contractRecord.StampDocumentFileName = null; contractRecord.SealErrMsg = null; contractRecord.SealResult = null; contractRecord.Comments = null; contractRecord.DayNumber = null; contractRecord.ContractVersion = null; contractRecord.Type = _contractType; contractRecord.OptId = UserId; contractRecord.OptName = UserName; contractRecord.OptDate = nowDate; contractRecord.ClientId = firstTrade.ClientId; contractRecord.StampDocumentFileName = null; contractRecord.SealResult = null; foreach (var item in flow_Events) { var contractTradeRelation = new trade_contract_r(); db.trade_contract_r.Add(contractTradeRelation); contractTradeRelation.TradeId = item.SwapTradeId; contractTradeRelation.TradeNumber = item.SwapTradeNo; contractTradeRelation.ContractCode = contractRecord.Code; contractTradeRelation.TradeClearCode = contractRecord.Code; contractTradeRelation.Type = _contractType; contractTradeRelation.OptId = UserId; contractTradeRelation.OptName = UserName; contractTradeRelation.OptDate = nowDate; contractTradeRelation.SwapFlowEventId = item.id; contractTradeRelation.IsValid = true; documents.Add(contractRecord); } db.SaveChanges(); return documents; } } /// /// 获取生成文档的输出路径(物理路径) /// public string GetOutputFilePath(string fileName) { var folder = Path.Combine(OtcAppContext.AppDocsPath, "contractdoc", "output"); if (!Directory.Exists(folder)) { Directory.CreateDirectory(folder); } return Path.Combine(folder, fileName); } //-------------------------------------- // 方法定义--数据获取 //-------------------------------------- Variety _variety; underlying_manager _underlying; Market _market; ClientBankCard _bankcard; ClientDuty _clientduty; Client _client; Dictionary _tradeMetas; /// /// 获取交易关联的客户信息 /// public Client GetClient() { if (_client == null) { _client = DataCacheProvider.GetClientDataSource().GetData(Trade.ClientId); if (_client == null) { throw new ServiceException($"客户(id:{Trade.ClientId},名称:{Trade.ClientName})信息未找到"); } } if (_client.IsDocShowParentName == 1 && _client.ParentId > 0) { var client = DataCacheProvider.GetClientDataSource().GetData(_client.ParentId); _client.Name = client.Name; } return _client; } public Client GetParentClient(int clientId) { var parentClient = new Client(); var client = DataCacheProvider.GetClientDataSource().GetData(clientId); if (client == null) { throw new ServiceException($"客户(id:{clientId})信息未找到"); } if (client.ParentId > 0) { parentClient = DataCacheProvider.GetClientDataSource().GetData(client.ParentId); if (_client == null) { throw new ServiceException($"父客户(id:{client.ParentId})信息未找到"); } } return parentClient; } /// /// 获取交易关联的结算资金信息 /// public ClientSettleBalance GetClientBalance(DateTime date) { var client = GetClient(); var clientbalances = ClientBalanceUtility.GetClientBanlances(new List() { client.id }, DateTime.MinValue, date); return clientbalances.FirstOrDefault(); } public ClientSettleBalance GetClientBalanceByReal(DateTime date) { var client = GetClient(); var clientbalances = new RealTimeClientBanlanceService(UserInfo).GetBanlances(new List() { client.id }, date, calcDate: date); return clientbalances.FirstOrDefault(); } /// /// 获取交易关联的标的 /// public underlying_manager GetTradeUnderlying() { return GetTradeUnderlying(Trade.UnderlyingCode); } /// /// 获取交易关联的标的 /// public underlying_manager GetTradeUnderlying(string underlyingCode) { if (_underlying == null || _underlying.UnderlyingCode != underlyingCode) { _underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode); if (_underlying == null) { throw new ServiceException("标的资产信息未找到:" + Trade.UnderlyingCode); } } return _underlying; } /// /// 获取组合标的信息 /// /// /// public SyntheticUnderlying GetSyntheticUnderlying(string code) { return DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(code); } /// /// 获取交易关联的市场信息 /// /// public Market GetMarketInfo() { if (_market == null) { var underlying = GetTradeUnderlying(); _market = DbContext.market.Where(O => O.MarketName == underlying.MarketName).FirstOrDefault(); } if (_market == null) { throw new ServiceException($"标的{GetTradeUnderlying().MarketName}对应的市场信息未找到"); } return _market; } /// /// 获取交易关联的标的对应的品种信息 /// public Variety GetUnderlyingVariety() { if (_variety == null) { var UnderlyingTypeId = GetTradeUnderlying().UnderlyingTypeId; _variety = DbContext.variety.AsNoTracking().FirstOrDefault(x => x.id == UnderlyingTypeId); } if (_variety == null) { throw new ServiceException($"标的{GetTradeUnderlying().UnderlyingCode}对应的品种信息未找到"); } return _variety; } /// /// 获取交易关联的标的对应的品种信息 /// public Variety GetUnderlyingVariety(string underlyingCode) { _variety = null; var UnderlyingTypeId = GetTradeUnderlying(underlyingCode).UnderlyingTypeId; _variety = DbContext.variety.AsNoTracking().FirstOrDefault(x => x.id == UnderlyingTypeId); if (_variety == null) { throw new ServiceException($"标的{GetTradeUnderlying(underlyingCode).UnderlyingCode}对应的品种信息未找到"); } return _variety; } /// /// 获取客户银行卡 /// public ClientBankCard GetClientBankCard(bool throwExceptionIfNotFound = true) { var client = GetClient(); if (_bankcard == null) { _bankcard = DbContextFactory.GetClientDbContext(OptUser).bankcard.OrderByDescending(x => x.OptDate).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && x.ValidState != "InValid"); } if (_bankcard == null && throwExceptionIfNotFound) { throw new ServiceException($"客户{client.Name}对应的银行帐户信息未找到"); } return _bankcard; } /// /// 获取机构客户职责联系人信息 /// public ClientDuty GetClientDuty(bool throwExceptionIfNotFound = true) { var client = GetClient(); if (_clientduty == null) { _clientduty = DbContextFactory.GetClientDbContext(OptUser).clientduty.OrderBy(x => x.id).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && (x.DeadLine == null || x.DeadLine >= valuedateBLL.SystemDate.ValueDate) && x.ContactTypeId.Contains("1")); } if (_clientduty == null) { _clientduty = DbContextFactory.GetClientDbContext(OptUser).clientduty.OrderBy(x => x.id).FirstOrDefault(x => x.ApprovalOrder < 1 && x.ClientId == client.id && (x.DeadLine == null || x.DeadLine >= valuedateBLL.SystemDate.ValueDate) && x.ContactTypeId.Contains("2")); } if (_clientduty == null && throwExceptionIfNotFound) { throw new ServiceException($"客户{client.Name}对应的机构联系人信息未找到"); } return _clientduty; } /// /// 获取客户法人/联系人 /// public ClientDuty GetClientDuty(int ContactTypeid) { var client = GetClient(); var ClientDuty = DbContextFactory.GetClientDbContext(OptUser).clientduty.Where(x => x.ApprovalOrder < 1 && x.ClientId == client.id && x.ContactTypeId.Contains(ContactTypeid.ToString()) && (x.DeadLine > DateTime.Now || x.DeadLine == null)).FirstOrDefault(); return ClientDuty; } /// /// 获取客户法人/联系人 /// public List GetClientDuties() { var client = GetClient(); var result = DbContextFactory.GetClientDbContext(OptUser).clientduty.Where(x => x.ApprovalOrder < 1 && x.ClientId == client.id && (x.DeadLine > DateTime.Now || x.DeadLine == null)).ToList(); return result; } /// /// 获取工作日天数 /// public int GetWorkDayCount(DateTime from, DateTime to) { return QdpCalendarHelper.GetWorkDayCount(from, to); } /// /// 获取交易记录元数据 /// /// /// public NameValueCollection GetTradeMetas(int tradeId) { if (_tradeMetas == null) { _tradeMetas = new Dictionary(); } if (!_tradeMetas.ContainsKey(tradeId)) { _tradeMetas[tradeId] = new NameValueCollection(); var datas = DbContext.TradeMeta.Where(n => n.TradeId == tradeId).Select(n => new { n.MetaKey, n.MetaValue }).ToArray(); foreach (var data in datas) { _tradeMetas[tradeId][data.MetaKey] = data.MetaValue; } } return _tradeMetas[tradeId]; } /// /// 获取结构化交易所有行权价 /// /// public double[] GetStructureStrikes() { if (Trade.TradeType != "结构化交易") { return new double[0]; } //var arr = DbContext.trade.Where(n => n.ParentTradeId == Trade.id).Select(n => n.Strike).ToArray(); var arr = new TradeDalService(this).GetStructTradeFromTradeOrEodTrade(new[] { Trade.id }, SystemValueDate).Select(n => n.Strike).ToArray(); return arr.Select(n => n ?? 0).OrderBy(O => O).ToArray(); } /// /// 获取交易的初始预付金 /// public double GetInitialMargin() { //好像并没有使用,暂时注释掉代码逻辑,改为抛出异常。在V3.3及以后版本可以删除 throw new NotImplementedException(); //if (Trade.BuySell == "卖出") //{ // return 0; //} //var variety = GetUnderlyingVariety(); //var underlying = GetTradeUnderlying(); //underlying.QuotationDate = Trade.TradeDate; //var spotPrices = new double[] { Trade.SpotPrice ?? 0 }; //volatility vols = volatilityBLL.GetVols("交易", underlying); //if (!Trade.NoRiskRate.HasValue) //{ // Trade.NoRiskRate = (valuedateBLL.SystemDate.RiskFreeRate ?? 0) * 0.01; //} //var tradeObj = (trade)Trade; //if (tradeObj.TradeType == "结构化交易") //{ // tradeObj.SubTrades = DbContext.trade.Where(n => n.ParentTradeId == Trade.id).ToList(); //} //VolSurfaceInitializerSingleton.InitializeMarketProxy(underlying, vols.VolSurfaceMode, vols.VolTable, OptId.ToString(), false, 0, vols.InterpolationMethod); //var optionValue = OptionCalculator.GetOptionValueResult(OptId.ToString(), underlying, tradeObj, spotPrices, preciseTimeMode: true); ////预付金初始价值=期初期权价值+CashDelta(t)*预付金初始比例(预付金初始比例:两个涨跌停版) ////OTC-8856 Start //var UpLimitValue = variety.UpLimitValue; ////var UpLimitValue = ((Math.Abs(underlying.UpDownLimitValue) > 1e-5) ? underlying.UpDownLimitValue : variety.UpLimitValue); ////End //return (Trade.TradePrice ?? 0) + Math.Abs(optionValue == null ? 0 : optionValue.DeltaCash) * UpLimitValue; } /// /// 确认书文档生成后的处理 /// public bool OnConfirmationGenerated() { //var trade = DbContext.trade.Find(Trade.id); //var childTds = DbContext.trade.Where(x => x.ParentTradeId == Trade.id); //HasGeneratedConfirmBook 已经转换成 Function 不需要修改数据库 验证后可删除 //TradeDalService service = new TradeDalService(this); //var trade = service.GetTradeOrEodTrade(new[] { Trade.id }, ValueDate, true).FirstOrDefault(); //var childTds = service.GetStructTradeFromTradeOrEodTrade(new[] { Trade.id }, ValueDate, true); //trade.HasGeneratedConfirmBook = 1; //foreach (var child in childTds) //{ // child.HasGeneratedConfirmBook = 1; //} return true; } /// /// 获取主交易的资金信息 /// /// public trade_cash GetTradeCash() { return _tradeCash; } public trade_cash GetTradeCashById(int cashId) { return DbContext.trade_cash.Where(O => O.id == cashId).FirstOrDefault(); } public IEnumerable> GetTradeCashes(int tradeId) { //var tradeIds = DbContext.trade.Where(O => O.id == tradeId || O.ParentTradeId == tradeId).Select(O => O.id).ToList(); var tradeIds = new TradeDalService(this).GetTradeOrEodTradeOfTidAPid(new[] { tradeId }, SystemValueDate).Select(O => O.id).ToList(); if (GetErpConfig().Company == CompanyEnum.东莞) { var subTrades = GetSubTrades(tradeId); tradeIds.AddRange(subTrades.Select(n => n.id).ToList()); } IEnumerable cashes = DbContext.trade_cash.Where(O => tradeIds.Contains(O.TradeId) && O.ValidState != ConsGlobal.InValid && !O.IsDeleted).ToList(); var result = new List>(); var dates = cashes.Select(O => O.ValueDate).ToArray(); foreach (var c in cashes) { result.Add(new KeyValuePair( new TradeDalService(this).GetTradeOrEodTrade(new[] { c.TradeId }, c.ValueDate).First(), c)); } return result; } public IEnumerable GetSubTrades(int parentTradeId) { var trades = new TradeDalService(this).GetStructTradeFromTradeOrEodTrade(new[] { parentTradeId }, SystemValueDate).ToList(); return trades; } public OtcTradeBase GetParentTrade(int parentTradeId) { return DbContext.trade.Find(parentTradeId); } public List GetGroupTradeCashs(int parentTradeCashId) { return DbContext.trade_cash.Where(x => x.ParentTradeCashId == parentTradeCashId && x.ValidState != "InValid").ToList(); } /// /// 累计期权id获取转远期的tradecash记录 /// /// /// public List GetConvForwardTradeCash(int tradeId) { var forwardTradeNumberList = DbContext.autocall_observation.Where(n => n.TradeId == tradeId && n.SettlementMode.Contains("转远期")).Select(n => n.ConvTradeNumber).ToList(); var tradeCash = (from cash in DbContext.trade_cash join trade in DbContext.trade on cash.TradeId equals trade.id where trade.ValidState != "InValid" && cash.ValidState != "InValid" && forwardTradeNumberList.Contains(trade.TradeNumber) select cash).ToList(); return tradeCash; } /// /// 获取子交易的资金信息 /// /// public IEnumerable GetSubTradeCashes() { return _subTradeCashes; } public string DateFormat(DateTime date) { var month = date.Month.ToString(); if (date.Month == 10) { month = "A"; } else if (date.Month == 11) { month = "B"; } else if (date.Month == 12) { month = "C"; } var day = date.Day.ToString().PadLeft(2, '0'); return month + day; } public string DoubleFormat(double? value) { if (value == null) { return "0"; } if (Math.Floor(value.Value) == value) { return ((int)value).ToString(); } return value.Value.ToString("f1").Replace('.', 'd'); } public virtual string GenerateContractNo(out string contractIndex) { contractIndex = ""; string contractNo; #region 移除过期缓存 var guoqitime = DateTime.Now.AddHours(-1).Ticks; var liststr = new List(); foreach (var ContractCodeCache in ContractCodeCache) { if (ContractCodeCache.Value[1] - guoqitime < 0) { liststr.Add(ContractCodeCache.Key); } } liststr.ForEach(o => ContractCodeCache.Remove(o)); #endregion switch (GetErpConfig().Company) { case CompanyEnum.长江: contractNo = GenerateCJContractNo(); break; case CompanyEnum.宏源: contractNo = GenerateHYContractNo(); break; case CompanyEnum.海通: contractNo = GenerateHTContractNo(); break; case CompanyEnum.中财资本: contractNo = GenerateZCContractNo(out contractIndex); break; case CompanyEnum.国泰君安: contractNo = GenerateGTJAContractNo(out contractIndex); break; case CompanyEnum.上期资本: contractNo = GenerateSQContractNo(out contractIndex); break; case CompanyEnum.瑞达: contractNo = GenerateRDXKContractNo(); break; case CompanyEnum.东方财富: contractNo = GenerateDFCFContractNo(out contractIndex); break; case CompanyEnum.国海: contractNo = GenerateGHContractNo(out contractIndex); break; case CompanyEnum.山西: contractNo = GenerateSXContractNo(out contractIndex); break; case CompanyEnum.东莞: contractNo = GenerateDongGuanContractNo(out contractIndex); break; case CompanyEnum.天风: contractNo = GenerateTFContractNo(out contractIndex); break; case CompanyEnum.广期资本: contractNo = GenerateGQContractNo(out contractIndex); break; case CompanyEnum.中粮: contractNo = GenerateGTJAContractNo(out contractIndex); break; case CompanyEnum.浙期: contractNo = GenerateZheQiContractNo(out contractIndex); break; case CompanyEnum.国信金阳: contractNo = GenerateGXJYContractNo(out contractIndex); break; case CompanyEnum.华安: contractNo = GenerateHuaAniContractNo(); break; case CompanyEnum.华西: contractNo = GenerateHuaXiContractNo(); break; case CompanyEnum.国贸启润: contractNo = GenerateGuoMaoContractNo(); break; case CompanyEnum.物产中大: contractNo = GenerateWCZDContractNo(); break; case CompanyEnum.招证: contractNo = GenerateZhaoZhengContractNo(); break; case CompanyEnum.默认: case CompanyEnum.红塔众鑫: contractNo = "yilian-" + UniqueTimeId.GetStr(); break; case CompanyEnum.山西固收: contractNo = GenerateShanXiGuShouContractNo(); break; case CompanyEnum.浙商: contractNo = GenerateZheShangContractNo(); break; case CompanyEnum.国联: contractNo = GenerateGuolianContractNo(); break; default: throw new ContextMarshalException("未实现"); } return contractNo; } /// /// 山西固收交易确认书编号 /// /// private string GenerateShanXiGuShouContractNo() { if (_contractType != ContractTypeEnum.Trade) { return UniqueTimeId.GetStr(); } return Trade.TradeNumber; string prefix = $"SAC-{Trade.TradeDate:yyyyMMdd}-GSTRS-"; string contractNo = string.Empty; lock (_syncLock) { var query = from r in DbContext.trade_contract_r join t in DbContext.trade on r.TradeId equals t.id where r.Type == ContractTypeEnum.Trade && r.ContractCode.StartsWith(prefix) select r; var codeList = query.Select(s=>s.ContractCode).ToList(); var count = codeList.Count; do { count++; contractNo = $"{prefix}{count:0000}"; } while (codeList.Contains(contractNo)); } return contractNo; } /// /// 浙商交易确认书编号 /// /// private string GenerateZheShangContractNo() { if (_contractType != ContractTypeEnum.Trade) { return UniqueTimeId.GetStr(); } if (Trade.TradeType == "收益互换") { var posi = GetSwapPositions(Trade.id, true).FirstOrDefault(p => p.PositionType > 0); var isLong = posi?.PositionType == (int)PositionTypeFlag.Short ? false : true; return "GLMS-" + _client.Number + "-" + Trade.TradeDate?.ToString("yyyyMMdd") + (isLong ? "-L" : "-S"); } return Trade.TradeNumber; } private string GenerateGuolianContractNo() { if (_contractType != ContractTypeEnum.Trade) { return UniqueTimeId.GetStr(); } if (Trade.TradeType == "收益互换") { var posi = GetSwapPositions(Trade.id, true).FirstOrDefault(p => p.PositionType > 0); var isLong = posi?.PositionType == (int)PositionTypeFlag.Short ? false : true; return "GLMS-" + _client.Number + "-" + Trade.TradeNumber; } return Trade.TradeNumber; } /// /// 生成国贸确认书编号 /// /// /// private string GenerateGuoMaoContractNo() { var contractNo = ""; var sb = new StringBuilder($"{GetClient().Number}"); var builder = PredicateBuilder.Create(O => true); switch (_contractType) { case ContractTypeEnum.Trade: sb.Append("-JY-"); sb.Append(Trade.TradeDate.Value.ToString("yyyyMMdd")); builder = builder.And(O => O.Type == ContractTypeEnum.Trade); break; case ContractTypeEnum.UnWind: case ContractTypeEnum.Clearing: default: builder = builder.And(O => O.Type != ContractTypeEnum.Trade); sb.Append("-JS-"); sb.Append(GetTradeCash().ValueDate.ToString("yyyyMMdd")); break; } var prefix = sb.ToString(); var codeList = DbContext.trade_contract_r.AsNoTracking().Where(builder).Where(O => O.ContractCode.StartsWith(prefix)).Select(O => O.ContractCode).ToList(); var count = codeList.Count; do { count++; contractNo = $"{prefix}{count:000}"; } while (codeList.Contains(contractNo)); return contractNo; } /// /// 生成招证确认书编号 /// /// /// private string GenerateZhaoZhengContractNo() { var service = new TradeMetaService(OptUser); var tc = GetTradeCash(); var contractNo = ""; var suffix = ""; var sb = new StringBuilder($"SAC-{GetClient().Number}-"); var builder = PredicateBuilder.Create(O => true); switch (_contractType) { case ContractTypeEnum.Trade: sb.Append(Trade.TradeDate.Value.ToString("yyyyMMdd")); builder = builder.And(O => O.Type == ContractTypeEnum.Trade); break; case ContractTypeEnum.UnWind: case ContractTypeEnum.Clearing: default: builder = builder.And(O => O.Type != ContractTypeEnum.Trade); sb.Append(tc.ValueDate.ToString("yyyyMMdd")); suffix = "QS"; break; } switch (Trade.TradeType) { case "收益互换": sb.Append("SW"); break; case "远期": sb.Append("FW"); break; case "现金流交易": sb.Append("OT"); break; default: sb.Append("OP"); break; } var prefix = sb.ToString(); var codeList = DbContext.trade_contract_r.AsNoTracking().Where(builder).Where(O => O.ContractCode.StartsWith(prefix)).Select(O => O.ContractCode).ToList(); var count = codeList.Count; do { count++; contractNo = $"{prefix}{count:00}{suffix}"; } while (codeList.Contains(contractNo)); //var metaKey = "期货报送成交编号" + tc.id; //if (service.GetTradeMeta(Trade.id, metaKey).IsNullOrWhiteSpace()) //{ // var dealNumber = GenerateZhaoZhengDealNumber(prefix); // new TradeMetaService(OptUser).AddTradeMeta(Trade.id, metaKey, dealNumber); //} return contractNo; } /// /// 生成招证期货报送成交编号 /// /// /// //private string GenerateZhaoZhengDealNumber(string contractNoPrefix) //{ // var contractNo = ""; // string tradeType = ""; // switch (Trade.TradeType) // { // case "收益互换": // tradeType = "SW"; // break; // case "远期": // tradeType = "FW"; // break; // case "现金流交易": // tradeType = "OT"; // break; // default: // tradeType = "OP"; // break; // } // StringBuilder tradeNumberStr = new StringBuilder($"{tradeType}-{GetClient().Number}-"); // switch (_contractType) // { // case ContractTypeEnum.Trade: // tradeNumberStr.Append(Trade.TradeDate.Value.ToString("yyyyMMdd")); // break; // case ContractTypeEnum.UnWind: // case ContractTypeEnum.Clearing: // default: // tradeNumberStr.Append(GetTradeCash().ValueDate.ToString("yyyyMMdd")); // break; // } // string prefix = tradeNumberStr.ToString(); // var list = DbContext.TradeMeta.Where(O => O.MetaKey.StartsWith("期货报送成交编号") && O.MetaValue.StartsWith(prefix)).Select(O => O.MetaValue).ToArray(); // var count = DbContext.trade_contract_r.AsNoTracking().Where(O => O.ContractCode.StartsWith(contractNoPrefix)).Count(); // do // { // count++; // contractNo = $"{prefix}{count:0000}"; // } while (list.Contains(contractNo)); // return contractNo; //} /// /// 仅支持生成提前终止和到期结算确认书编号 /// /// /// private string GenerateHuaXiContractNo() { var contractNo = ""; const string company = "华西证券-"; var year = Trade.TradeDate?.ToString("yyyy") + "-"; var leftPart = "SACOE-" + company + year; if (Trade.TradeType == "收益互换") { leftPart = "SACTE-" + company + year; } var rule = Trade.TradeNumber.Split('-')?[3]; var prefix = leftPart + rule; var contractCode = DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefix) && O.IsValid).OrderByDescending(x => x.ContractCode)?.FirstOrDefault()?.ContractCode; var code = contractCode == null ? "0" : contractCode.Substring(contractCode.Length - 1, 1); var count = Convert.ToInt32(code) + 1; contractNo = $"{prefix}-{count}"; return contractNo; } /// /// 仅支持生成提前终止和到期结算确认书编号 /// /// /// private string GenerateHuaAniContractNo() { var client = GetClient(); var prefix = Trade.TradeNumber + "-JS"; var contractNo = ""; var contractCode = DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefix) && O.IsValid).OrderByDescending(x => x.ContractCode)?.FirstOrDefault()?.ContractCode; var code = contractCode == null ? "0" : contractCode.Substring(contractCode.Length - 2, 2); var count = Convert.ToInt32(code) + 1; contractNo = $"{prefix}{count.ToString().PadLeft(2, '0')}"; return contractNo; } /// /// 仅支持生成提前终止和到期结算确认书编号 /// /// /// private string GenerateZheQiContractNo(out string contractIndex) { contractIndex = ""; var tradeCash = TradeCashes[Trade.id].FirstOrDefault(); var db = DbContextFactory.GetYLDbContext(); var tradeQuery = db.trade.Where(O => O.ValidState != "InValid" && O.TradeDate == Trade.TradeDate); var tradeTypeEn = ""; if (Trade.TradeType == "远期") { tradeQuery = tradeQuery.Where(O => O.TradeType == "远期"); if (Trade.StructureType == "掉期") { tradeTypeEn = "SW"; tradeQuery = tradeQuery.Where(O => O.StructureType == "掉期" || O.TradeType == "收益互换"); } else { tradeTypeEn = "FW"; tradeQuery = tradeQuery.Where(O => O.StructureType != "掉期"); } } else if (Trade.TradeType == "收益互换") { tradeTypeEn = "SW"; tradeQuery = tradeQuery.Where(O => O.StructureType == "掉期" || O.TradeType == "收益互换"); } else { var tradeTypes = new[] { "远期", "收益互换" }; tradeQuery = tradeQuery.Where(O => !tradeTypes.Contains(O.TradeType)); tradeTypeEn = "OP"; } var actions = new[] { "系统操作-平仓费", "系统操作-行权费" }; var codeInfos = (from tc in db.trade_cash join t in tradeQuery on tc.TradeId equals t.id join tr in db.trade_contract_r on tc.id equals tr.TradeCashId into tempTr from tr in tempTr.DefaultIfEmpty() where tr.IsValid && tc.ValidState != "InValid" && tc.IsDeleted == false && tc.id != tradeCash.id && (actions.Contains(tc.Action) || tc.IsLastAction) select new { tcId = tc.id, ContractCode = tr.ContractCode }).ToArray(); var tradeTag = ""; var client = DataCacheProvider.GetClientDataSource().GetData(Trade.ClientId); tradeTag = $"{tradeTypeEn}{Trade.TradeDate?.ToString("yyMMdd")}"; var count = codeInfos.Count(O => O.tcId < tradeCash.id); var tradeNumber = ""; do { count++; tradeNumber = $"{client.Number}{tradeTag}{count.ToString("000")}Q"; } while (codeInfos.Any(O => O.ContractCode == tradeNumber) || ContractCodeCache.ContainsKey(tradeNumber)); var tcId = GetTradeCash().id; ContractCodeCache[tradeNumber] = new[] { tcId, DateTime.Now.Ticks }; return tradeNumber; } /// /// 检查生成的确认书编号是否存在 /// /// /// private bool CheckContractNo(string contractNo) { return DbContext.trade_contract_r.Any(O => O.ContractCode == contractNo); } private string GenerateRDXKContractNo() { var client = GetClient(); if (string.IsNullOrWhiteSpace(client.Code)) { throw new TradeDocGenerateException("客户代码不应为空"); } var prefix = $"RDXK-{client.Code}-"; if (Trade.TradeType == "远期") { if (Trade.StructureType == "掉期") { prefix += "SW-"; } else { prefix += "FW-"; } } else if (Trade.TradeType == "亚式期权") { prefix += "AS-"; } prefix += GetTradeCash().ValueDate.ToString("yyyyMMdd") + "-"; var contractNo = ""; var codes = DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefix) && O.IsValid).Select(O => O.ContractCode).ToHashSet(); var count = codes.Count; do { count++; contractNo = prefix + count; } while (codes.Contains(contractNo)); return contractNo; } private string GenerateZCContractNo(out string contractIndex) { var client = GetClient(); var ruleId = ""; var suffix = ""; switch (_contractType) { case ContractTypeEnum.Trade: ruleId = "ZC"; break; case ContractTypeEnum.Clearing: ruleId = "ZCSettlement"; suffix = "S"; break; case ContractTypeEnum.UnWind: ruleId = "ZCUnWind"; suffix = " - 01"; break; default: break; } string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{client.Number}C{contractIndex}{suffix}"; } while (CheckContractNo(code)); return code; } private string GenerateGTJAContractNo(out string contractIndex) { var client = GetClient(); var ruleId = ""; var suffix = ""; var instrumentTypeArr = new List() { ConsGlobal.InstrumentType.Stock, ConsGlobal.InstrumentType.StockIF, ConsGlobal.InstrumentType.StockIndex }; if (instrumentTypeArr.Contains(GetTradeUnderlying().UnderlyingInstrumentType) || Trade.TradeType == "雪球期权") { var date = GetTradeCash().ValueDate.ToString("yyyyMMdd"); if (StartDate != null && EndDate != null && StartDate != EndDate) { date = $"{StartDate.Value.ToString("yyyyMMdd")}-{EndDate.Value.ToString("yyyyMMdd")}"; } contractIndex = date; return $"{client.Number}-{date}-0"; } else { switch (_contractType) { case ContractTypeEnum.Trade: ruleId = "GTJA"; break; case ContractTypeEnum.Clearing: ruleId = "GTJASettlement"; suffix = "S"; break; case ContractTypeEnum.UnWind: ruleId = "GTJAUnWind"; suffix = " - 01"; break; default: break; } string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{client.Number}C{contractIndex}{suffix}"; } while (CheckContractNo(code)); return code; } } private string GenerateHTContractNo() { string contractNo; var date = GetTradeCash().ValueDate; var valueDates = new List(); foreach (var item in TradeCashes.Values) { valueDates.AddRange(item.Select(O => O.ValueDate).ToList()); } if (valueDates.ToHashSet().Count > 1) { throw new ArgumentException((_contractType == ContractTypeEnum.Trade ? "交易" : "结算") + "日期不正确"); } var prefix = $"{_client.Number}{date:yyyyMMdd}"; switch (_contractType) { case ContractTypeEnum.Trade: prefix += "T"; break; case ContractTypeEnum.Clearing: case ContractTypeEnum.UnWind: prefix += "S"; break; default: break; } var codes = DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefix) && O.IsValid).Select(O => O.ContractCode).ToHashSet(); var count = codes.Count; do { count++; contractNo = prefix + count; } while (codes.Contains(contractNo)); return contractNo; } private string GenerateWCZDContractNo() { var prefix = GetClient().Number + "-" + DateTime.Now.ToString("yyyyMMdd"); var contractNo = ""; var contracts = DbContext.trade_contract_r.Where(_ => Trade.id == (_.TradeId) && _.Type == _contractType && _.IsValid); if (contracts != null && contracts.Any()) { contractNo = contracts.First().ContractCode; } else { var codes = DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefix) && O.IsValid).Select(O => O.ContractCode).ToHashSet(); var count = codes.Count; do { count++; contractNo = prefix + count.ToString("D3"); } while (codes.Contains(contractNo)); } return contractNo; } public string GenerateWCZDChildrenContractNo(int tId, int tcId) { //所有确认书编号都在trademate里面存取 var contractNo = ""; var showcontractNo = ""; var prefix = GetClient().Number + "-"; var endFlag = ""; var contractC = DbContext.trade_contract_r_number.Where(_ => tId == (_.TradeId) && _.TradeConfirmNumber.StartsWith(prefix) && _.TradeConfirmNumberType == "C"); var currentTrade = DbContext.trade.Where(t => t.id == tId).First(); var tParentId = currentTrade.ParentTradeId > 0 ? currentTrade.ParentTradeId : 0; switch (_contractType) { case ContractTypeEnum.Trade: endFlag = "C"; //是否有父交易 if (currentTrade.ParentTradeId > 0) { contractC = DbContext.trade_contract_r_number.Where(_ => tParentId == (_.TradeParentId) && _.TradeConfirmNumber.StartsWith(prefix) && _.TradeConfirmNumberType == "C"); } if (contractC != null && contractC.Any()) { contractNo = contractC.First().TradeConfirmNumber; break; } else { var endPreFix = ""; //累计转远期特殊处理 if (currentTrade.TradeType == "远期" && (currentTrade.Comments ?? "").Contains("累计期权")) { var AcctradeFirst = DbContext.trade.Where(l => l.TradeNumber == currentTrade.Comments.Replace("累计期权:", "")).First(); //获取父数据的交易确认书编号 var AccParent = DbContext.trade_contract_r_number.Where(_ => AcctradeFirst.id == (_.TradeId) && _.TradeConfirmNumberType == endFlag); if (AccParent != null && AccParent.Any()) { prefix = AccParent.First().TradeConfirmNumber; prefix += "-"; if (AcctradeFirst?.ParentTradeId > 0) { var legs = DbContext.trade.Where(l => l.ParentTradeId == AcctradeFirst.ParentTradeId && AcctradeFirst.id >= l.id).Count(); endPreFix = "-yleg" + legs; } } else { throw new Exception("累计未生成交易确认书,导致远期找不到当前累计确认书编号!"); } } var codes = DbContext.trade_contract_r_number.Where(O => O.TradeConfirmNumber.StartsWith(prefix) && O.TradeConfirmNumber.EndsWith(endPreFix) && O.TradeConfirmNumberType == endFlag).Select(O => O.TradeConfirmNumber).ToHashSet(); var count = codes.Any() ? codes.Select(x => new { number = x.Substring(prefix.Length, (endPreFix).Length) }).Max(x => int.TryParse(x.number, out var num) ? num : 0) : 0; do { count++; contractNo = prefix + (count > 999 ? count.ToString("D4") : count.ToString("D3")) + endPreFix; } while (codes.Where(c => c.StartsWith(prefix) && c.Contains(contractNo) && c.EndsWith(endPreFix)).Any()); break; } case ContractTypeEnum.Clearing: case ContractTypeEnum.UnWind: endFlag = _contractType == ContractTypeEnum.Clearing ? "S" : "U"; if (contractC != null && contractC.Any()) { var contractS_Or_U = DbContext.trade_contract_r_number.Where(O => O.TradeId == tId && O.TradeCashId == tcId && O.TradeConfirmNumber.StartsWith(prefix) && O.TradeConfirmNumberType == endFlag); //是否有父交易 if (currentTrade.ParentTradeId > 0) { contractC = DbContext.trade_contract_r_number.Where(_ => tParentId == (_.TradeParentId) && _.TradeConfirmNumber.StartsWith(prefix) && _.TradeConfirmNumberType == "C"); } if (contractS_Or_U != null && contractS_Or_U.Any()) { contractNo = contractS_Or_U.First().TradeConfirmNumber; showcontractNo = contractS_Or_U.First().ShowTradeConfirmNumber; break; } var tradeCash = GetTradeCash(); if (currentTrade.IsGroup != 2 && currentTrade.ParentTradeId > 0) { //全部平仓一腿 var legs = DbContext.trade.Where(l => l.ParentTradeId == currentTrade.ParentTradeId && currentTrade.id >= l.id).Count(); contractNo = contractC.First().TradeConfirmNumber + "-leg" + legs; } else { contractNo = contractC.First().TradeConfirmNumber; } IEnumerable> trade_Cashes = GetTradeCashes(tId).Where(l => ((l.Value.UnwindType ?? "").Contains("部分") || (l.Value.UnwindType ?? "").Contains("全部")) && l.Value.id < tcId).OrderBy(l => l.Value.id); if (trade_Cashes != null && trade_Cashes.Any()) { showcontractNo = contractNo + "-" + (trade_Cashes.Count() + 1); } else { if (currentTrade.ParentTradeId == 0 || GetTradeCashes(tId).Where(l => (l.Value.UnwindType ?? "").Contains("部分")).Any()) { showcontractNo = contractNo + "-" + 1; } else { showcontractNo = contractNo; } } } else { throw new Exception("交易确认书未生成!"); } break; default: break; } if ((DbContext.trade_contract_r_number.Where(O => O.TradeId == tId && O.TradeParentId == tParentId && O.TradeCashId == tcId && O.TradeConfirmNumberType == endFlag).FirstOrDefault()) == null) { var trade_Contract_R_Number = new trade_contract_r_number() { TradeId = tId, TradeCashId = tcId, TradeConfirmNumber = contractNo, TradeConfirmNumberType = endFlag, TradeParentId = tParentId, ShowTradeConfirmNumber = String.IsNullOrWhiteSpace(showcontractNo) ? contractNo : showcontractNo, }; trade_Contract_R_Number.SetOpt(UserInfo); DbContext.trade_contract_r_number.Add(trade_Contract_R_Number); DbContext.SaveChanges(); } if (_contractType == "交易确认书") { //持仓编号[123,123C],[123,123U] var metaValue = contractNo; var legStr = ""; if (currentTrade.ParentTradeId == 0 && !metaValue.Contains("leg"))//)Trade.ParentTradeId == 0 && !Trade.Comments.Contains("累计期权")) { if ((currentTrade.Comments ?? "").Contains("累计期权")) { legStr += "-yleg1"; } else { legStr += "-leg1"; } } else if (currentTrade.ParentTradeId > 0 && !metaValue.Contains("leg")) { var legs = DbContext.trade.Where(l => l.ParentTradeId == currentTrade.ParentTradeId && tId >= l.id).Count(); legStr += "-leg" + legs; } metaValue += legStr; TradeMeta meta = null; if ((meta = DbContext.TradeMeta.Where(O => O.TradeId == tId && O.MetaKey == ConsTradeMetaKey.ContractCode).FirstOrDefault()) == null) { meta = new TradeMeta { TradeId = tId, MetaKey = ConsTradeMetaKey.ContractCode, MetaValue = metaValue, CreateTime = DateTime.Now }; DbContext.TradeMeta.Add(meta); DbContext.SaveChanges(); } } return ContractTypeEnum.Trade == _contractType ? contractNo : showcontractNo; } public string GetWCZDConfirmNumber(int tId, int tcId, string type) { return DbContext.trade_contract_r_number.Where(O => O.TradeId == tId && O.TradeCashId == tcId && O.TradeConfirmNumberType == type).FirstOrDefault().TradeConfirmNumber; } private string GenerateHYContractNo() { if (string.IsNullOrWhiteSpace(_client.Code)) { throw new TradeDocGenerateException("生成合同编号失败,请先添加客户代码!"); } if (string.IsNullOrWhiteSpace(_client.Abbreviation)) { throw new TradeDocGenerateException("生成合同编号失败,请先添加客户简称!"); } if (!_client.ProtocolSignDate.HasValue) { throw new TradeDocGenerateException("生成合同编号失败,请先添加客户商品类协议签署日期!"); } var tradeCount = DbContext.trade .Where(O => O.ClientId == _client.id && O.ParentTradeId == 0 && O.ValidState != "InValid" && O.id < Trade.id).Count(); string code; do { tradeCount += 1; code = $"HL-{_client.Code}-{_client.ProtocolSignDate?.ToString("yyyy")}-{_client.Abbreviation}-SAC-01-1-TC{tradeCount:000}"; } while (CheckContractNo(code)); return code; } private string GenerateCJContractNo() { var contractNo = ""; var tradeIndex = 1; var groupIndex = 1; var tradeId = 0; var date = DateTime.MinValue; var unwindCount = ""; var query = DbContext.trade.Where(O => O.ValidState != "InValid"); if (Trade.GroupId.HasValue) { var trades = query.Where(O => O.GroupName == Trade.GroupName).OrderBy(O => O.id).ToList(); groupIndex = trades.Where(O => O.id <= Trade.id).Count(); tradeId = trades[0].id; } query = query.Where(O => ConsTrade.OptionTradeTypes.Contains(O.TradeType)); switch (_contractType) { case ContractTypeEnum.Trade: date = Trade.TradeDate ?? date; query = query.Where(O => O.TradeDate == Trade.TradeDate); break; case ContractTypeEnum.UnWind: date = Trade.UnWindDate ?? date; query = query.Where(O => O.UnWindDate == Trade.UnWindDate); unwindCount = UnwindCount().ToString(); break; case ContractTypeEnum.Clearing: date = Trade.ExerciseDate ?? date; query = query.Where(O => O.ExerciseDate == Trade.ExerciseDate); break; default: return contractNo; } var prefixStr = $"CJ{date:yyyyMMdd}"; var codes = DbContext.trade_contract_r.Where(O => O.IsValid).Join(query, TCR => TCR.TradeId, T => T.id, (TCR, T) => TCR.ContractCode).ToList(); codes = codes.Union(DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefixStr) && O.IsValid).Select(O => O.ContractCode).ToList()).ToList(); var metaKey = $"{date:yyyy-MM-dd}_{_contractType}{unwindCount}"; TradeMeta meta = null; if ((meta = DbContext.TradeMeta.Where(O => O.TradeId == Trade.id && O.MetaKey == metaKey).FirstOrDefault()) != null) { contractNo = meta.MetaValue; } else { meta = new TradeMeta { TradeId = Trade.id, MetaKey = metaKey, CreateTime = DateTime.Now }; DbContext.TradeMeta.Add(meta); } if (string.IsNullOrWhiteSpace(contractNo) || codes.Contains(contractNo)) { var prefix = date.ToString("yyyy-MM-dd_"); codes.AddRange( DbContext.TradeMeta .Where(O => O.MetaKey.StartsWith(prefix)) .Select(O => O.MetaValue).ToList()); if (query.Where(O => O.id == tradeId).Count() == 0) { tradeId = Trade.id; } if (Trade.GroupId.HasValue) { query = query.Where(O => O.GroupId != Trade.GroupId); } query = query.Where(O => O.id < tradeId); tradeIndex = query.Where(O => O.GroupId != null).AsEnumerable().GroupBy(O => O.GroupId).Count(); tradeIndex += query.Where(O => O.GroupId == null).Count(); do { tradeIndex++; contractNo = $"{prefixStr}{tradeIndex:D2}{groupIndex:D3}"; } while (codes.Contains(contractNo)); meta.MetaValue = contractNo; DbContext.SaveChanges(); } return contractNo; } private string GenerateSQContractNo(out string contractIndex) { var code = ""; contractIndex = ""; var clientObj = GetClient(); var date = DateTime.MinValue; var unwindCount = ""; var query = DbContext.trade.Where(O => O.ValidState != "InValid"); switch (_contractType) { case ContractTypeEnum.Trade: date = Trade.TradeDate ?? date; query = query.Where(O => O.TradeDate == Trade.TradeDate); break; case ContractTypeEnum.UnWind: date = Trade.UnWindDate ?? date; query = query.Where(O => O.UnWindDate == Trade.UnWindDate); unwindCount = UnwindCount().ToString(); break; case ContractTypeEnum.Clearing: date = Trade.ExerciseDate ?? date; query = query.Where(O => O.ExerciseDate == Trade.ExerciseDate); break; default: return code; } var prefix = $"{clientObj.Number}-JY-{date:yyyyMMdd}"; var codes = DbContext.trade_contract_r.Where(O => O.ContractCode.StartsWith(prefix) && O.IsValid).Select(O => O.ContractCode).ToList(); var metaKey = $"{date:yyyy-MM-dd}_{_contractType}{unwindCount}"; TradeMeta meta = null; if ((meta = DbContext.TradeMeta.Where(O => O.TradeId == Trade.id && O.MetaKey == metaKey).FirstOrDefault()) != null) { code = meta.MetaValue; } else { meta = new TradeMeta { TradeId = Trade.id, MetaKey = metaKey, CreateTime = DateTime.Now }; DbContext.TradeMeta.Add(meta); } if (string.IsNullOrWhiteSpace(code) || codes.Contains(code)) { var tradeCodes = codes .Where(O => O.Contains(prefix)) .OrderByDescending(O => O); var tradeCode = tradeCodes.FirstOrDefault(); if (string.IsNullOrWhiteSpace(tradeCode) || !int.TryParse(tradeCode.Substring(prefix.Length).TrimEnd(), out var tradeCount)) { tradeCount = 0; } do { tradeCount++; contractIndex = tradeCount.ToString("00"); code = $"{prefix}{contractIndex}"; } while (codes.Contains(code)); meta.MetaValue = code; DbContext.SaveChanges(); } return code; } private string GenerateDFCFContractNo(out string contractIndex) { var client = GetClient(); var Abbreviation = client != null ? client.Abbreviation : ""; if (client.ClientType == "产品") Abbreviation = client != null ? client.AdminFullName : ""; var date = DateTime.Now.ToString("yyyy"); var ruleId = "DFCF-" + Abbreviation + "-" + date; string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(3, '0'); code = $"{ruleId}-{contractIndex}"; } while (CheckContractNo(code)); return code; } private string GenerateGHContractNo(out string contractIndex) { var date = DateTime.Now.ToString("yyyy"); var client = GetClient(); var Abbreviation = client != null ? client.Abbreviation : ""; if (client.ClientType == "产品") Abbreviation = client != null ? client.AdminFullName : ""; var ruleId = "GH-" + Abbreviation + "-" + date; string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{ruleId}-{contractIndex}"; } while (CheckContractNo(code)); return code; } private string GenerateDongGuanContractNo(out string contractIndex) { var code = string.Empty; var codes = DbContext.trade_contract_r.Where(n => n.TradeId == Trade.id && n.Type == "交易确认书") .OrderBy(n => n.id).Select(n => new { n.ContractCode, n.IsValid }).ToArray(); if (codes.Length > 0) { code = (codes.FirstOrDefault(n => n.IsValid) ?? codes[0]).ContractCode; var index = code.LastIndexOf('-'); contractIndex = index > 0 ? code.Substring(index + 1) : string.Empty; } else { var date = DateTime.Now.ToString("yyyy"); var client = GetClient(); var Abbreviation = client != null ? client.Abbreviation : ""; if (client.ClientType == "产品") Abbreviation = client != null ? client.AdminFullName : ""; var ruleId = "DG-" + Abbreviation + "-" + date; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{ruleId}-{contractIndex}"; } while (CheckContractNo(code)); } return code; } private string GenerateTFContractNo(out string contractIndex) { var date = DateTime.Now.ToString("yyyy"); var client = GetClient(); var Abbreviation = client != null ? client.Abbreviation : ""; if (client.ClientType == "产品") Abbreviation = client != null ? client.AdminFullName : ""; var ruleId = "TF-" + Abbreviation + "-" + date; string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{ruleId}-{contractIndex}"; } while (CheckContractNo(code)); return code; } private string GenerateSXContractNo(out string contractIndex) { var date = DateTime.Now.ToString("yyyy"); var client = GetClient(); var Abbreviation = client != null ? client.Abbreviation : ""; if (client.ClientType == "产品") Abbreviation = client != null ? client.AdminFullName : ""; var ruleId = "SX-" + Abbreviation + "-" + date; string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{ruleId}-{contractIndex}"; } while (CheckContractNo(code)); return code; } private string GenerateGQContractNo(out string contractIndex) { var date = DateTime.Now.ToString("yyyyMMdd"); var ruleId = "GQZB" + date + "FUT"; string code; do { contractIndex = ContractBLL.GetRuleIndex(ruleId).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); code = $"{ruleId}-{contractIndex}"; } while (CheckContractNo(code)); return code; } private string GenerateGXJYContractNo(out string contractIndex) { contractIndex = ""; var tc = GetTradeCash(); var date = tc.ValueDate; if (string.IsNullOrEmpty(_client.MainProtocolCode)) { throw new ServiceException("找不到该数据主协议编号"); } var clientMainProtocolCode = _client.MainProtocolCode; var preTag = clientMainProtocolCode ?? "N"; //合并起来作为获取递增序号的取值条件 var leftPart = preTag; var fullSize = leftPart.Length + 3; var db = DbContextFactory.GetYLDbContext(); var tradeNumbers = db.trade.Where(x => x.TradeNumber.StartsWith(leftPart) && x.TradeNumber.Length >= fullSize) .OrderByDescending(x => x.TradeNumber).Select(n => n.TradeNumber).ToList(); var numberStrings = tradeNumbers.Select(x => x.Substring(leftPart.Length).IndexOf('-') > 0 ? x.Substring(leftPart.Length).Remove(x.Substring(leftPart.Length).IndexOf('-')) : x.Substring(leftPart.Length)).Where(x => int.TryParse(x, out var num)); var number = numberStrings.LongCount() > 0 ? numberStrings.Max(x => int.TryParse(x, out var a) ? a : 0) : 0; //获取总的该用户最大的交易编号记录 var newNumber = number == 0 ? 1 : (number + 1); //获取提前终止数量 var tradeUnwindConfirmationNumbers = db.trade_contract_r.Where(l => l.TradeNumber.StartsWith(leftPart) && l.TradeNumber.Length >= fullSize && l.Type == "提前终止确认书" && l.IsValid).Select(n => n.ContractCode).ToList(); var tradeUnwindConfirmationNumberStrings = tradeUnwindConfirmationNumbers.Select(x => x.Contains(leftPart) ? (x.Substring(leftPart.Length).IndexOf('-') > 0 ? x.Substring(leftPart.Length).Remove(x.Substring(leftPart.Length).IndexOf('-')) : x.Substring(leftPart.Length)) : "1").Where(x => int.TryParse(x, out var num)); var tradeUnwindConfirmationCount = tradeUnwindConfirmationNumberStrings.Max(x => x); if (newNumber > (string.IsNullOrWhiteSpace(tradeUnwindConfirmationCount) ? 0 : (int.Parse(tradeUnwindConfirmationCount) + 1))) { return getTradeNumber(newNumber, leftPart, db); } else { return getTradeNumber(int.Parse(tradeUnwindConfirmationCount) + 1, leftPart, db); } } private string getTradeNumber(int newNumber, string leftPart, YLContext db) { if (newNumber < 1e3) { var childTradeNumberPart = leftPart + newNumber.ToString("D3"); if (db.trade.Any(x => x.TradeNumber.Contains(childTradeNumberPart) && db.trade_contract_r.Any(l => l.ContractCode.Contains(childTradeNumberPart)) && x.ValidState != "InValid")) { return getTradeNumber(newNumber + 1, leftPart, db); } else { return leftPart + newNumber.ToString("D3"); } } else { var childTradeNumberPart = leftPart + newNumber; if (db.trade.Any(x => x.TradeNumber.Contains(childTradeNumberPart) && db.trade_contract_r.Any(l => l.ContractCode.Contains(childTradeNumberPart)) && x.ValidState != "InValid")) { return getTradeNumber(newNumber + 1, leftPart, db); } else { return childTradeNumberPart; } } } /// /// 获取价差期权 组合标的最大价格 /// /// public double GetDifferenceMaxPrice() { var query = DbContext.TradeMeta.Where(O => O.TradeId == Trade.id && O.MetaKey == "组合标的").FirstOrDefault(); var syntheticPrice = JsonHelper.Deserialize(query.MetaValue); var differenceMaxPrice = syntheticPrice.SuList.Select(l => l.Price * l.Coefficient).Max(); return differenceMaxPrice; } public int UnwindCount(trade_cash cash) { return UnwindCount(new List() { cash }); } /// /// 当前了结次数 /// public int UnwindCount(List cashes = null) { var num = 0; if (cashes == null) { if (Trade.TradeType != "结构化交易") { cashes = new List() { GetTradeCash() }; } else { cashes = GetSubTradeCashes().ToList(); } } var action = new List() { "系统操作-平仓费", "系统操作-行权费" }; var cashIds = cashes.Select(O => O.TradeId).ToList(); var query = DbContext.trade_cash .Where(O => cashIds.Contains(O.TradeId) && action.Contains(O.Action) && (O.Notional - O.UnwindNotional) > 0.0001 && O.ValidState != ConsGlobal.InValid && !O.IsDeleted); if (cashIds.Count > 1) { #region 检查子交易资金信息 //if (query.GroupBy(O => O.TradeId).Count() != cashIds.Count) //{ throw new ArgumentException("子交易资金记录不匹配"); } var id = cashIds[0]; var tempNum = query.Where(O => O.TradeId == id).Count(); for (var i = 1; i < cashIds.Count; i++) { id = cashIds[i]; var n = query.Where(O => O.TradeId == id).Count(); if (tempNum != n) { throw new ArgumentException("子交易资金记录不匹配"); } } #endregion } if (query.Any()) { var cash = cashes[0]; num = query.Where(O => O.ValueDate <= cash.ValueDate && O.id < cash.id).Count() + 1; } return num; } public IEnumerable Trades { get; private set; } /// /// 一笔交易存在多次平仓记录 /// public IReadOnlyDictionary> TradeCashes { get; private set; } public DateTime? StartDate { get; set; } public DateTime? EndDate { get; set; } //public IClient Client => _client; public List GetClientTrades() { var result = new List(); var cash = GetTradeCash(); var query = from t in DbContext.trade join tc in DbContext.trade_cash on t.id equals tc.TradeId where t.ClientId == _client.id && tc.ValueDate == cash.ValueDate && !tc.IsDeleted select new { t, tc }; switch (_contractType) { case ContractTypeEnum.Trade: query = query.Where(O => O.tc.Action == "系统操作-期权费"); break; case ContractTypeEnum.Clearing: case ContractTypeEnum.UnWind: var actions = new List() { "系统操作-行权费", "系统操作-平仓费" }; query = query.Where(O => actions.Contains(O.tc.Action)); break; default: break; } //result = query.Select(O => O.t).ToList().Cast().ToList(); var tradeIds = query.Select(O => O.t.id).Distinct().ToList();//.Cast().ToList(); result = new TradeDalService(this).GetTradeOrEodTrade(tradeIds, SystemValueDate).Cast().ToList(); return result; } public BaseSystemUser GetTraderUserInfo() { return DbContextFactory.GetErpBaseContext().SystemUsers.Where(O => O.Id == Trade.TraderId).FirstOrDefault(); } public ClientLevel GetClientLevel() { var client = GetClient(); return client == null || client.LevelId == null ? null : DbContextFactory.GetClientDbContext(OptUser).clientlevel.Where(O => O.id == (client.LevelId ?? 0)).FirstOrDefault(); } public client_variety_config GetClient_Variety_Config(int ClientId, int varietyId, DateTime valuedate) { var config = DbContext.client_variety_config.Where(o => o.ClientId == ClientId && o.VarietyId == varietyId && o.ValueDate <= valuedate).OrderByDescending(o => o.ValueDate).FirstOrDefault(); if (config != null) { return config; } config = DbContext.client_variety_config.Where(o => o.ClientId == 0 && o.VarietyId == varietyId && o.ValueDate <= valuedate).OrderByDescending(o => o.ValueDate).FirstOrDefault(); if (config != null) { return config; } throw new ServiceException("该品种在 " + valuedate.ToString("yyyy/MM/dd") + "未维护费率"); } public List CalcMargin(OtcTradeBase trade, double? price) { if (!(trade is trade)) { throw new DocGenerateException("计算预付金时Trade不存在"); } var req = new RunMarginCalculationReq(UserInfo) { tradeList = new List { (trade)trade }, settleDate = trade.UnWindDate.Value, PriceProvider = new SinglePriceProvider(trade.UnderlyingCode, price ?? 0) }; if (trade.IsGroup == 1) { req.tradeList = DbContext.trade.Where(x => x.ParentTradeId == trade.id).ToList(); } return MarginDefault.RunMarginCalculation(req); } public trade_cash_swap GetTradecashswap(int tradecashid) { var trade_cash_swap = DbContext.trade_cash_swap.Where(c => c.TradeCashId == tradecashid).FirstOrDefault(); return trade_cash_swap; } public List GetClient_file() { var result = new List(); result = DbContextFactory.GetClientDbContext(OptUser).client_file.Where(m => m.ApprovalOrder < 1 && m.ClientId == Trade.ClientId && (m.FileTypeName == "主协议附件(PDF)" || m.FileTypeName == "补充协议附件(PDF)" || m.FileTypeName == "履约协议附件(PDF)")).ToList(); return result; } /// /// 3.15删掉 /// /// [Obsolete] public trade_swap GetTrade_Swap() { trade_swap result; result = DbContextFactory.GetYLDbContext().trade_swap.Where(m => m.TradeId == Trade.id).FirstOrDefault(); return result; } /// /// 3.15删掉 /// /// [Obsolete] public trade_snowball Gettrade_snowball() { trade_snowball result; result = DbContextFactory.GetYLDbContext().trade_snowball.Where(m => m.TradeId == Trade.id).FirstOrDefault(); return result; } /// /// 3.15删掉 /// /// [Obsolete] public trade_forward Gettrade_forward() { trade_forward result; result = DbContextFactory.GetYLDbContext().trade_forward.Where(m => m.TradeId == Trade.id).FirstOrDefault(); return result; } public string Gettrade_contract_r() { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == Trade.id && m.Type == "交易确认书" && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public string Gettrade_contract_r(string type) { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == Trade.id && m.Type == type && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public string Gettrade_contract_r(int tradeId, string type) { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == tradeId && m.Type == type && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public string Gettrade_contract_r(string type, int tradeCashId) { var r = DbContextFactory.GetYLDbContext().trade_contract_r.Where(m => m.TradeId == Trade.id && m.TradeCashId == tradeCashId && m.Type == type && m.IsValid == true).FirstOrDefault(); return r != null ? r.ContractCode : ""; } public Owner_info GetOwner_info(string Condition) { try { var r = DbContextFactory.GetYLDbContext().Owner_Info.Where(m => m.Condition == Condition).FirstOrDefault(); return r; } catch { throw new ServiceException("admin页面没配账户信息"); } } public void GetcontractIndex(string Rule, out string contractIndex) { contractIndex = ContractBLL.GetRuleIndex(Rule).ToString(); contractIndex = contractIndex.ToString().PadLeft(4, '0'); } /// /// /// /// 规则 /// 返回的数据 /// 结果字符串中的字符数,等于原始字符数加上任何其他填充字符 public void GetcontractIndex01(string Rule, out string contractIndex, int totalWidth = 2) { contractIndex = ContractBLL.GetRuleIndex(Rule).ToString(); if (totalWidth == 0) { contractIndex = contractIndex.ToString(); } else { contractIndex = contractIndex.ToString().PadLeft(totalWidth, '0'); } } public string TransToForeignWord(string CnWord, string Key) { var result = DbContextFactory.GetYLDbContext().dicForTranslation.Where(o => o.From == CnWord && o.Key == Key).FirstOrDefault(); if (result != null) { return result.To; } return CnWord; } public Currency GetCurrency(string currencyCode) { if (string.IsNullOrWhiteSpace(currencyCode)) { throw new ServiceException("计价币种或结算币种不能为空!"); } var currency = DbContext.currency.Where(o => o.CurrencyCode == currencyCode).FirstOrDefault(); return currency; } public trade_cash_swap GetTradeCash_Swap(int tradeCashId) { if (tradeCashId <= 0) { return null; } var tcs = DbContext.trade_cash_swap.Where(o => o.TradeCashId == tradeCashId).FirstOrDefault(); return tcs; } /// /// 获取货币对汇率 /// /// 计价货币 /// 结算货币 /// public eod_currency_rate GetCurrencyRate(string quoteCurrency, string settlementCurrency, DateTime date) { var rate = new EodModule.EodCurrencyRateService(UserInfo).GetEodCurrencyRate(quoteCurrency, settlementCurrency, date); return rate ?? throw new ServiceException($"未找到货币对'{quoteCurrency}{settlementCurrency}'的结算汇率,取值日期:{date:yyyy/MM/dd}"); } public List GetTradeCashDetails(int tradeCashId) { return DbContext.trade_cash_detail.Where(x => x.TradeCashId == tradeCashId).ToList(); } public DateTime ShiftTradeDate(DateTime now, int shiftDays, string calendarName, bool NeedBothTradeDay = false) { try { var date = QdpCalendarHelper.BizDayShift(now, shiftDays, calendarName); if (NeedBothTradeDay) { date = getBothTradeDay(date); } return date; } catch (Exception e) { throw new ServiceException(now.ToShortDateString() + "未在日历中,请维护日历" + calendarName, e); } } private DateTime getBothTradeDay(DateTime now) { try { var ishoilday = QdpCalendarHelper.IsHoliday(now) || QdpCalendarHelper.IsHoliday(now, "NYB"); if (ishoilday) { var tradeDate = now.AddDays(1); return getBothTradeDay(tradeDate); } return now; } catch (Exception e) { throw new ServiceException(e.Message); } } public ClientMeta GetClientMeta(int ClientId, string MetaKey) { return DbContextFactory.GetClientDbContext(OptUser).ClientMeta.FirstOrDefault(o => o.ClientId == ClientId && o.MetaKey == MetaKey); } /// /// 3.15删掉 /// /// [Obsolete] public trade_swap GetTrade_Swap(int tradeId) { trade_swap result; result = DbContextFactory.GetYLDbContext().trade_swap.Where(m => m.TradeId == tradeId).FirstOrDefault(); return result; } public List GetDictionaryItemList(string dictName) { using (var db = new ErpBaseContext()) { var query = from i in db.DictionaryItems join d in db.Dictionaries on i.DictId equals d.Id where d.Name == dictName orderby i.IndexNum, i.Name select new Models.DictionaryItems { Name = i.Name, ShortName = i.ShortName, IndexNum = i.IndexNum, }; var list = query.ToList(); return list; } } public trade_swap_flow GetSwapFlow(int flowId) { trade_swap_flow result; result = DbContextFactory.GetYLDbContext().trade_swap_flow.Where(m => m.id == flowId).FirstOrDefault(); return result; } /// /// 人民币转大写 /// 该方法直接调用NumberHelper.CmycurD(num) /// /// /// public string CmycurD(double num) { var str = NumberHelper.CmycurD(num); if (str.EndsWith("整") && !str.EndsWith("元整")) { str = str.Remove(str.Length - 1); } return str; } /// /// 当前所有了结次数,包含全部了结 /// /// /// /// public int AllUnwindCount(List cashes = null) { var num = 0; if (cashes == null) { if (Trade.TradeType != "结构化交易") { cashes = new List() { GetTradeCash() }; } else { cashes = GetSubTradeCashes().ToList(); } } var action = new List() { "系统操作-平仓费", "系统操作-行权费" }; var cashIds = cashes.Select(O => O.TradeId).ToList(); var query = DbContext.trade_cash .Where(O => cashIds.Contains(O.TradeId) && action.Contains(O.Action) && O.ValidState != ConsGlobal.InValid && !O.IsDeleted); if (cashIds.Count > 1) { #region 检查子交易资金信息 //if (query.GroupBy(O => O.TradeId).Count() != cashIds.Count) //{ throw new ArgumentException("子交易资金记录不匹配"); } var id = cashIds[0]; var tempNum = query.Where(O => O.TradeId == id).Count(); for (var i = 1; i < cashIds.Count; i++) { id = cashIds[i]; var n = query.Where(O => O.TradeId == id).Count(); if (tempNum != n) { throw new ArgumentException("子交易资金记录不匹配"); } } #endregion } if (query.Any()) { var cash = cashes[0]; num = query.Where(O => O.ValueDate <= cash.ValueDate && O.id < cash.id).Count() + 1; } return num; } /// /// 计算TTM /// public double CalculateTTMDays(DateTime from, DateTime to, int varietyid, bool precisionOfMinute) { return TradeCalcHelper.CalculateTTMDays(from, to, varietyid, precisionOfMinute); } /// /// 获取某交易日之后的交易日 /// /// /// public DateTime GetTradeDate(DateTime date) { return BLL.valuedateBLL.GetNonHoliday(date); } /// /// 获取系统参数配置 /// /// public valuedate GetValuedate() { return DbContext.valuedate.FirstOrDefault(); } public List GetSwapEvents(int tradeId) { return DbContext.swap_event.Where(x => x.SwapTradeId == tradeId && x.Invalid == true).ToList(); } public List GetSwapPositions(int tradeId,bool? IsInitial) { var query = DbContext.swap_position.Where(x => x.SwapTradeId == tradeId&&!x.Invalid); if (IsInitial.HasValue) { query = query.Where(x=>x.IsInitial== IsInitial); } return query.ToList(); } public List GetSwapPositions(List tradeIds, bool? IsInitial) { var query = DbContext.swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && !x.Invalid); if (IsInitial.HasValue) { query = query.Where(x => x.IsInitial == IsInitial); } return query.ToList(); } public client_marginrate GetClientMarginRate(int clientId) { var clientMarginRateDbSet = DbContext.client_marginrate; var clientMarginRate = clientMarginRateDbSet.Where(x => x.ClientId == clientId)?.FirstOrDefault(); if (clientMarginRate == null) { var client = DataCacheProvider.GetClientDataSource().GetData(clientId); clientMarginRate = clientMarginRateDbSet.Where(x => x.ClientId == 0)?.FirstOrDefault(); } return clientMarginRate; } public List GetFlowEvents() { return FlowEvents; } public List GetAllFlowEvents() { return AllFlowEvents; } public List GetSwapPositions() { return SwapPositions; } public int GetDMASelttementCount(int clientId, DateTime valueDate) { var query = from r in DbContext.trade_contract_r.Where(x => x.Type == ContractTypeEnum.Clearing && x.IsValid == true) join d in DbContext.trade_contract_document.Where(x => x.ValueDate == valueDate && x.ClientId == clientId) on r.ContractCode equals d.Code select r.ContractCode; return query.Distinct().Count(); } public List GetSwapFlows(int tradeId) { return DbContext.swap_flow.Where(x=>x.SwapTradeId==tradeId&&x.DataState==(int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList(); } public List GetUnderlyings(List underlyingCodes) { return DbContext.underlying_manager.Where(x => underlyingCodes.Contains(x.UnderlyingCode)).AsNoTracking().ToList(); } public List GetTrade_Extends(List tradeIds) { return DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList(); } public List GetFlowEvents(int tradeId, List eventTypes) { return DbContext.swap_flow_event.Where(x => eventTypes.Contains(x.EventType)&&x.SwapTradeId==tradeId&&x.DataState==(int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList(); } public List GetEodPositions(int tradeId, DateTime valueDate) { return DbContext.eod_swap_position.Where(x=> x.SwapTradeId==tradeId && !x.Invalid&&x.ValueDate==valueDate).AsNoTracking().ToList(); } public List GetSwapFlowDeals(int tradeId) { return DbContext.swap_flow_deal.Where(x => x.SwapTradeId == tradeId).AsNoTracking().ToList(); } public swap_event GetEvent(long eventId) { return DbContext.swap_event.FirstOrDefault(x => x.id == eventId); } } }