Files
zszq-trs/YLErpDAL/Modules/TradeModule/DocGenerateModule/ConfirmationGenerateContext.cs
T

1980 lines
86 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
using YLErp.Modules.SwapModule;
namespace YLErp.Modules.TradeModule.DocGenerateModule
{
public class ConfirmationGenerateContext : YLBaseService, ITradeDocGeneratorContext, ITradeConfirmationGeneratotContext
{
/// <summary>
/// 生成确认书时,用户选择的资金记录
/// </summary>
public IEnumerable<int> UserTradeCashIds { get; }
/// <summary>
/// 同步锁
/// </summary>
private static readonly object _syncLock = new object();
/// <summary>
/// 确认书编号缓存 处理 确认书生成出重复编号问题,浙期已修改,如果其他公司有类似问题请参照这次提交代码
/// key 是合约编号
/// value[tradecashid,当前时间] 过期时间1h
/// 汤旺
/// </summary>
private static Dictionary<string, long[]> ContractCodeCache = new Dictionary<string, long[]>();
/// <summary>
/// [必需]交易记录
/// </summary>
public OtcTradeBase Trade { get; }
public IEnumerable<OtcTradeBase> SubTrades { get; }
private readonly trade_cash _tradeCash;
private readonly List<trade_cash> _subTradeCashes = new List<trade_cash>();
/// <summary>
/// [必需]合约业务接口
/// </summary>
public IContractBLL ContractBLL { get; }
/// <summary>
/// 浮动平仓事件集
/// </summary>
public readonly List<swap_flow_event> FlowEvents;
/// <summary>
/// 平仓事件集
/// </summary>
public readonly List<swap_flow_event> AllFlowEvents = new List<swap_flow_event>();
/// <summary>
/// 交易持仓腿集合
/// </summary>
public readonly List<swap_position> SwapPositions = new List<swap_position>();
/// <summary>
/// [必需]期权数据提供接口
/// </summary>
public ITradeExtendDataProvider TradeDataProvider { get; }
readonly string _contractType;
public ConfirmationGenerateContext(IEnumerable<int> tradeCashIds, IEnumerable<trade> 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<trade>();
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;
}
/// <summary>
/// 构造函数
/// </summary>
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<OtcTradeBase>() { 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<int, List<trade_cash>>() { { tradeObj.id, new List<trade_cash> { _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<swap_flow_event> flowEvents, List<swap_flow_event> allFlowEvents, List<trade> trades, List<swap_position> 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;
}
/// <summary>
/// 获取系统配置接口对象
/// </summary>
public IErpConfig GetErpConfig()
{
return PS.GetErpConfig();
}
/// <summary>
/// 转换word文档为pdf文档
/// </summary>
public void ConvertDocToPDF(string wordDocPath, string targetPdfPath)
{
OfficeFileConverter.ConvertFileFormat(wordDocPath, targetPdfPath);
}
/// <summary>
/// 根据Excel文档模板生成文档
/// </summary>
public void GenerateExcelFromTemplate(string templatePath, Dictionary<string, JToken> 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<string, object> 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);
}
}
/// <summary>
/// 根据Word文档模板生成文档
/// </summary>
public void GenerateDocFromTemplate(string templatePath, Dictionary<string, JToken> 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));
}
}
/// <summary>
/// 获取合成价差期权的商品标的名称
/// </summary>
public string GetSyntheticUnderlyingName(string underlyingCode)
{
return synthetic_underlyingBLL.GetUnderlyingTipsInfo(underlyingCode);
}
/// <summary>
/// 获取亚式期权行权价
/// </summary>
/// <param name="trade"></param>
/// <returns></returns>
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;
}
/// <summary>
/// 获取亚式期权现价
/// </summary>
/// <param name="trade"></param>
/// <returns></returns>
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();
}
/// <summary>
/// 保存文档生成数据
/// </summary>
public ITradeContractDocument SaveContractDocument(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null)
{
var documents = new List<ITradeContractDocument>();
var savedOutputFileName = isPdf ? outPutFileName : outPutFileName.Replace(".pdf", ".docx");
var fileType = isPdf ? FileTypeEnum.Pdf : FileTypeEnum.Word;
var tradecashDict = _subTradeCashes.Count == 0 ? new Dictionary<int, List<int>>() { { Trade.id, new List<int>() { (_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<int>() { _tradeCash.id };
}
var trades = new List<OtcTradeBase>() { Trade };
if (Trade.TradeType == "结构化交易" && SubTrades.Count() > 1)
{ trades.AddRange(SubTrades); }
documents = SaveContractDocuments(trades, tradecashDict, contractCode, savedOutputFileName, fileType);
ContractCodeCache.Remove(contractCode);
return documents[0];
}
/// <summary>
/// 保存文档生成数据
/// </summary>
public List<ITradeContractDocument> SaveContractDocuments(string outPutFileName, string contractCode, bool isPdf = false, string outPath = null)
{
var documents = new List<ITradeContractDocument>();
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<int, List<int>>();
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<int>() { 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;
}
/// <summary>
/// 保存文档生成数据
/// </summary>
public List<ITradeContractDocument> 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;
}
/// <summary>
/// 保存文档生成数据
/// </summary>
/// <param name="trade"></param>
/// <param name="trades"></param>
/// <param name="tradeCashIds"></param>
/// <param name="contractCode"></param>
/// <param name="fileName"></param>
/// <param name="fileType"></param>
/// <returns></returns>
private List<ITradeContractDocument> SaveContractDocuments(IEnumerable<OtcTradeBase> trades, Dictionary<int, List<int>> tradeCashIds, string contractCode, string fileName, string fileType)
{
lock (_syncLock)
{
var documents = new List<ITradeContractDocument>();
var firstTrade = trades.First();
var isGJBuyer = firstTrade.BuySell == "买入";
var nowDate = DateTime.Now;
var db = DbContextFactory.GetYLDbContext();
#region 清理历史数据
var tcIds = new List<int>();
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;
}
}
/// <summary>
/// 保存文档生成数据
/// </summary>
/// <param name="trade"></param>
/// <param name="trades"></param>
/// <param name="tradeCashIds"></param>
/// <param name="contractCode"></param>
/// <param name="fileName"></param>
/// <param name="fileType"></param>
/// <returns></returns>
private List<ITradeContractDocument> SaveContractDocumentsByEventIds(IEnumerable<OtcTradeBase> trades, List<swap_flow_event> flow_Events, string contractCode, string fileName, string fileType)
{
lock (_syncLock)
{
var documents = new List<ITradeContractDocument>();
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;
}
}
/// <summary>
/// 获取生成文档的输出路径(物理路径)
/// </summary>
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<int, NameValueCollection> _tradeMetas;
/// <summary>
/// 获取交易关联的客户信息
/// </summary>
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;
}
/// <summary>
/// 获取交易关联的结算资金信息
/// </summary>
public ClientSettleBalance GetClientBalance(DateTime date)
{
var client = GetClient();
var clientbalances = ClientBalanceUtility.GetClientBanlances(new List<int>() { client.id }, DateTime.MinValue, date);
return clientbalances.FirstOrDefault();
}
public ClientSettleBalance GetClientBalanceByReal(DateTime date)
{
var client = GetClient();
var clientbalances = new RealTimeClientBanlanceService(UserInfo).GetBanlances(new List<int>() { client.id }, date, calcDate: date);
return clientbalances.FirstOrDefault();
}
/// <summary>
/// 获取交易关联的标的
/// </summary>
public underlying_manager GetTradeUnderlying()
{
return GetTradeUnderlying(Trade.UnderlyingCode);
}
/// <summary>
/// 获取交易关联的标的
/// </summary>
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;
}
/// <summary>
/// 获取组合标的信息
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
public SyntheticUnderlying GetSyntheticUnderlying(string code)
{
return DataCacheProvider.GetUnderlyingDataSource().GetSyntheticUnderlying(code);
}
/// <summary>
/// 获取交易关联的市场信息
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 获取交易关联的标的对应的品种信息
/// </summary>
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;
}
/// <summary>
/// 获取交易关联的标的对应的品种信息
/// </summary>
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;
}
/// <summary>
/// 获取客户银行卡
/// </summary>
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;
}
/// <summary>
/// 获取机构客户职责联系人信息
/// </summary>
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;
}
/// <summary>
/// 获取客户法人/联系人
/// </summary>
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;
}
/// <summary>
/// 获取客户法人/联系人
/// </summary>
public List<ClientDuty> 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 List<contactype> GetContractTypes()
{
var result = DbContextFactory.GetClientDbContext(OptUser).contactype.ToList();
return result;
}
/// <summary>
/// 获取工作日天数
/// </summary>
public int GetWorkDayCount(DateTime from, DateTime to)
{
return QdpCalendarHelper.GetWorkDayCount(from, to);
}
/// <summary>
/// 获取交易记录元数据
/// </summary>
/// <param name="tradeId"></param>
/// <returns></returns>
public NameValueCollection GetTradeMetas(int tradeId)
{
if (_tradeMetas == null)
{
_tradeMetas = new Dictionary<int, NameValueCollection>();
}
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];
}
/// <summary>
/// 获取结构化交易所有行权价
/// </summary>
/// <returns></returns>
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();
}
/// <summary>
/// 获取交易的初始预付金
/// </summary>
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;
}
/// <summary>
/// 确认书文档生成后的处理
/// </summary>
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;
}
/// <summary>
/// 获取主交易的资金信息
/// </summary>
/// <returns></returns>
public trade_cash GetTradeCash()
{
return _tradeCash;
}
public trade_cash GetTradeCashById(int cashId)
{
return DbContext.trade_cash.Where(O => O.id == cashId).FirstOrDefault();
}
public IEnumerable<KeyValuePair<OtcTrade, trade_cash>> 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<trade_cash> cashes = DbContext.trade_cash.Where(O => tradeIds.Contains(O.TradeId) && O.ValidState != ConsGlobal.InValid && !O.IsDeleted).ToList();
var result = new List<KeyValuePair<OtcTrade, trade_cash>>();
var dates = cashes.Select(O => O.ValueDate).ToArray();
foreach (var c in cashes)
{
result.Add(new KeyValuePair<OtcTrade, trade_cash>(
new TradeDalService(this).GetTradeOrEodTrade(new[] { c.TradeId }, c.ValueDate).First(),
c));
}
return result;
}
public IEnumerable<OtcTrade> 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<trade_cash> GetGroupTradeCashs(int parentTradeCashId)
{
return DbContext.trade_cash.Where(x => x.ParentTradeCashId == parentTradeCashId && x.ValidState != "InValid").ToList();
}
/// <summary>
/// 累计期权id获取转远期的tradecash记录
/// </summary>
/// <param name="tradeId"></param>
/// <returns></returns>
public List<trade_cash> 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;
}
/// <summary>
/// 获取子交易的资金信息
/// </summary>
/// <returns></returns>
public IEnumerable<trade_cash> 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<string>();
foreach (var ContractCodeCache in ContractCodeCache)
{
if (ContractCodeCache.Value[1] - guoqitime < 0)
{
liststr.Add(ContractCodeCache.Key);
}
}
liststr.ForEach(o => ContractCodeCache.Remove(o));
#endregion
contractNo = GenerateGuolianContractNo();
return contractNo;
}
/// <summary>
/// 生成国联确认书编号
/// </summary>
private string GenerateGuolianContractNo()
{
if (_contractType != ContractTypeEnum.Trade)
{
return UniqueTimeId.GetStr();
}
return Trade.TradeNumber;
}
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<KeyValuePair<OtcTrade, trade_cash>> 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;
}
/// <summary>
/// 获取价差期权 组合标的最大价格
/// </summary>
/// <returns></returns>
public double GetDifferenceMaxPrice()
{
var query = DbContext.TradeMeta.Where(O => O.TradeId == Trade.id && O.MetaKey == "组合标的").FirstOrDefault();
var syntheticPrice = JsonHelper.Deserialize<SyntheticPriceModel>(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<trade_cash>() { cash });
}
/// <summary>
/// 当前了结次数
/// </summary>
public int UnwindCount(List<trade_cash> cashes = null)
{
var num = 0;
if (cashes == null)
{
if (Trade.TradeType != "结构化交易")
{ cashes = new List<trade_cash>() { GetTradeCash() }; }
else
{ cashes = GetSubTradeCashes().ToList(); }
}
var action = new List<string>() { "系统操作-平仓费", "系统操作-行权费" };
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<OtcTrade> Trades { get; private set; }
/// <summary>
/// 一笔交易存在多次平仓记录
/// </summary>
public IReadOnlyDictionary<int, List<trade_cash>> TradeCashes { get; private set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
//public IClient Client => _client;
public List<OtcTradeBase> GetClientTrades()
{
var result = new List<OtcTradeBase>();
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<string>() { "系统操作-行权费", "系统操作-平仓费" };
query = query.Where(O => actions.Contains(O.tc.Action));
break;
default:
break;
}
//result = query.Select(O => O.t).ToList().Cast<OtcTradeBase>().ToList();
var tradeIds = query.Select(O => O.t.id).Distinct().ToList();//.Cast<OtcTradeBase>().ToList();
result = new TradeDalService(this).GetTradeOrEodTrade(tradeIds, SystemValueDate).Cast<OtcTradeBase>().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<trade_span> CalcMargin(OtcTradeBase trade, double? price)
{
if (!(trade is trade))
{
throw new DocGenerateException("计算预付金时Trade不存在");
}
var req = new RunMarginCalculationReq(UserInfo)
{
tradeList = new List<trade> { (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<client_file> GetClient_file()
{
var result = new List<client_file>();
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;
}
/// <summary>
/// 3.15删掉
/// </summary>
/// <returns></returns>
[Obsolete]
public trade_swap GetTrade_Swap()
{
trade_swap result;
result = DbContextFactory.GetYLDbContext().trade_swap.Where(m => m.TradeId == Trade.id).FirstOrDefault();
return result;
}
/// <summary>
/// 3.15删掉
/// </summary>
/// <returns></returns>
[Obsolete]
public trade_snowball Gettrade_snowball()
{
trade_snowball result;
result = DbContextFactory.GetYLDbContext().trade_snowball.Where(m => m.TradeId == Trade.id).FirstOrDefault();
return result;
}
/// <summary>
/// 3.15删掉
/// </summary>
/// <returns></returns>
[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');
}
/// <summary>
///
/// </summary>
/// <param name="Rule">规则</param>
/// <param name="contractIndex">返回的数据</param>
/// <param name="totalWidth"> 结果字符串中的字符数,等于原始字符数加上任何其他填充字符</param>
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;
}
/// <summary>
/// 获取货币对汇率
/// </summary>
/// <param name="baseCurrency">计价货币</param>
/// <param name="quoteCurrency">结算货币</param>
/// <param name="date"></param>
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<trade_cash_detail> 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);
}
/// <summary>
/// 3.15删掉
/// </summary>
/// <returns></returns>
[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<DictionaryItems> 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;
}
/// <summary>
/// 人民币转大写
/// <para>该方法直接调用NumberHelper.CmycurD(num)</para>
/// </summary>
/// <param name="num"></param>
/// <returns></returns>
public string CmycurD(double num)
{
var str = NumberHelper.CmycurD(num);
if (str.EndsWith("整") && !str.EndsWith("元整"))
{
str = str.Remove(str.Length - 1);
}
return str;
}
/// <summary>
/// 当前所有了结次数,包含全部了结
/// </summary>
/// <param name="cashes"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public int AllUnwindCount(List<trade_cash> cashes = null)
{
var num = 0;
if (cashes == null)
{
if (Trade.TradeType != "结构化交易")
{ cashes = new List<trade_cash>() { GetTradeCash() }; }
else
{ cashes = GetSubTradeCashes().ToList(); }
}
var action = new List<string>() { "系统操作-平仓费", "系统操作-行权费" };
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;
}
/// <summary>
/// 计算TTM
/// </summary>
public double CalculateTTMDays(DateTime from, DateTime to, int varietyid, bool precisionOfMinute)
{
return TradeCalcHelper.CalculateTTMDays(from, to, varietyid, precisionOfMinute);
}
/// <summary>
/// 获取某交易日之后的交易日
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public DateTime GetTradeDate(DateTime date)
{
return BLL.valuedateBLL.GetNonHoliday(date);
}
/// <summary>
/// 获取系统参数配置
/// </summary>
/// <returns></returns>
public valuedate GetValuedate()
{
return DbContext.valuedate.FirstOrDefault();
}
public List<swap_event> GetSwapEvents(int tradeId)
{
return DbContext.swap_event.Where(x => x.SwapTradeId == tradeId && x.Invalid == true).ToList();
}
public List<swap_position> 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<swap_position> GetSwapPositions(List<int> 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<swap_flow_event> GetFlowEvents()
{
return FlowEvents;
}
public List<swap_flow_event> GetAllFlowEvents()
{
return AllFlowEvents;
}
public List<swap_position> 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<swap_flow> GetSwapFlows(int tradeId)
{
return DbContext.swap_flow.Where(x => x.SwapTradeId == tradeId && x.DataState == (int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList();
}
public List<underlying_manager> GetUnderlyings(List<string> underlyingCodes)
{
return DbContext.underlying_manager.Where(x => underlyingCodes.Contains(x.UnderlyingCode)).AsNoTracking().ToList();
}
public List<trade_extend> GetTrade_Extends(List<int> tradeIds)
{
return DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList();
}
public List<swap_flow_event> GetFlowEvents(int tradeId, List<int> eventTypes)
{
return DbContext.swap_flow_event.Where(x => eventTypes.Contains(x.EventType) && x.SwapTradeId == tradeId && x.DataState == (int)SwapFlowDateStateEnum.完成).AsNoTracking().ToList();
}
public List<eod_swap_position> GetEodPositions(int tradeId, DateTime valueDate)
{
return DbContext.eod_swap_position.ActiveByTradeAndDate(tradeId, valueDate).AsNoTracking().ToList();
}
public List<SwapFlowDeal> 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);
}
}
}