Files
zszq-trs/YLErpDAL/Modules/TradeModule/QueryModule/TradeDetailsQueryService.cs
T
2024-05-09 14:06:26 +08:00

1456 lines
79 KiB
C#

using BaseOUDAL;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using System.Dynamic;
using System.Linq.Expressions;
using System.Text.RegularExpressions;
using YieldChain.Helpers;
using YLErp.BLL;
using YLErp.DBModels.Consts;
using YLErp.Enums;
using YLErp.Helpers;
using YLErp.Model;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.DataCacheModule;
using YLErp.MsOffice;
using YLErp.Office;
using YLErp.Office.Converters;
namespace YLErp.Modules.TradeModule
{
/// <summary>
/// 交易明细查询服务
/// </summary>
public class TradeDetailsQueryService : YLBaseService
{
public TradeDetailsQueryService(OptUserInfo userInfo) : base(userInfo)
{
}
public TradeDetailsQueryService(YLBaseService baseService) : base(baseService)
{
}
public TradeDetailsReport TradeDetailsReport { private set; get; }
private void BuildTradePredicate(TradeDetailsReq req, int groupTradeId,
out Expression<Func<trade, bool>> tradPredicate,
out Expression<Func<trade_cash, bool>> tradeCashPredicate)
{
if (groupTradeId > 0)
{
tradPredicate = PredicateBuilder.True<trade>().And(x => x.ParentTradeId == groupTradeId);
}
else
{
//交易明细页面:组合互换 提前终止和到期都按照子交易展示
if (req.DetailStatuses == "提前终止" || req.DetailStatuses == "到期")
{
tradPredicate = PredicateBuilder.True<trade>().And(x => x.IsGroup == 0 || x.IsGroup == 1 || (x.IsGroup == 2 && x.TradeType == "收益互换"));
}
//交易明细页面:组合互换 成交按照主交易可展开形式展示
else if (req.DetailStatuses == "成交")
{
tradPredicate = PredicateBuilder.True<trade>().And(x => x.IsGroup == 0 || x.IsGroup == 1);
}
//交易明细导出:组合互换都按照子交易展示
else
{
tradPredicate = PredicateBuilder.True<trade>().And(x => x.IsGroup == 0 || (x.IsGroup == 1 && x.TradeType == "结构化交易") || (x.IsGroup == 2 && x.TradeType == "收益互换"));
}
}
if (req.UserAssetUnits != null && req.UserAssetUnits.Any())
{
tradPredicate = tradPredicate.And(t => req.UserAssetUnits.Contains(t.AssetId));
}
var endDate = req.EndDate.Value;
tradPredicate = tradPredicate.And(t => t.TradeDate <= endDate && t.ValidState != "InValid");
if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n)))
{
var types = req.TradeTypes;
tradPredicate = tradPredicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType));
}
if (!string.IsNullOrWhiteSpace(req.StructureType))
{
tradPredicate = tradPredicate.And(t => t.StructureType.Contains(req.StructureType));
}
var clientIdsInt = new List<int>();
if (!string.IsNullOrWhiteSpace(req.ClientIds))
{
clientIdsInt.AddRange(req.ClientIdsInt);
}
else if (req.ClientId > 0)
{
clientIdsInt.Add(req.ClientId);
}
if (req.ParentFlag)
{
var clientIdList = DataCacheProvider.GetClientDataSource().AsQueryable(O => clientIdsInt.Contains(O.ParentId)).Select(O => O.id).ToList().ToHashSet();
clientIdsInt.AddRange(clientIdList);
}
tradPredicate = tradPredicate.And(t => clientIdsInt.Contains(t.ClientId));
//-----------------------------------------------
// trade_cash predicate
//-----------------------------------------------
var detailStatuses = req.DetailStatuses.TrimToEmpty();
var tradCashPredicates = new Expression<Func<trade_cash, bool>>[3];
if (detailStatuses.Contains("成交"))
{
var tcPredicate = PredicateBuilder.Create<trade_cash>(tc => tc.Action == ClientCashInCashOut.系统操作_期权费);
if (req.StartDate != null)
{
tcPredicate = tcPredicate.And(t => t.ValueDate >= req.StartDate);
}
tradCashPredicates[0] = tcPredicate;
}
if (detailStatuses.Contains("提前终止"))
{
var tcPredicate = PredicateBuilder.Create<trade_cash>(tc => ((tc.ValueDate <= endDate && tc.HappenedDate == null) || tc.HappenedDate <= endDate)
&& (tc.Action == ClientCashInCashOut.系统操作_平仓费 || (tc.Action == ClientCashInCashOut.系统操作_行权费
&& tc.ExerciseWay == TradeCashExerciseWayEnum.提前终止行权) || (tc.ExerciseWay != TradeCashExerciseWayEnum.到期行权 && tc.IsLastAction)));
if (req.StartDate != null)
{
tcPredicate = tcPredicate.And(tc => tc.ValueDate >= req.StartDate);
}
tradCashPredicates[1] = tcPredicate;
}
if (detailStatuses.Contains("到期"))
{
var tcPredicate = PredicateBuilder.Create<trade_cash>(tc => ((tc.ValueDate <= endDate && tc.HappenedDate == null) || tc.HappenedDate <= endDate)
&& (tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_互换) && tc.ExerciseWay == TradeCashExerciseWayEnum.到期行权);
if (req.StartDate != null)
{
tcPredicate = tcPredicate.And(tc => tc.ValueDate >= req.StartDate);
}
tradCashPredicates[2] = tcPredicate;
}
tradeCashPredicate = PredicateBuilder.False<trade_cash>();
for (var i = 0; i < tradCashPredicates.Length; i++)
{
if (tradCashPredicates[i] != null)
{
tradeCashPredicate = tradeCashPredicate.Or(tradCashPredicates[i]);
}
}
tradeCashPredicate = PredicateBuilder.Create<trade_cash>(
tradeCash => tradeCash.ValidState != ConsGlobal.InValid && !tradeCash.IsDeleted).And(tradeCashPredicate);
}
/// <summary>
/// 查询客户交易明细
/// </summary>
public SearchListResult<OtcTradeDetail> SearchTradeDetails(TradeDetailsReq req, int groupTradeId = 0)
{
if (req.ClientId < 1 && string.IsNullOrWhiteSpace(req.ClientIds))
{
return new SearchListResult<OtcTradeDetail>();
}
if (req.EndDate == null)
{
throw new ServiceException("请选择结束日期");
}
if (req.StartDate != null && req.StartDate > req.EndDate)
{
throw new ServiceException("起始日期不能大于结束日期");
}
BuildTradePredicate(req, groupTradeId, out var tradPredicate, out var tradeCashPredicate);
var query = from td in DbContext.trade.Where(tradPredicate)
join tc in DbContext.trade_cash.Where(tradeCashPredicate) on td.id equals tc.TradeId
join et in DbContext.eod_trade.Where(O => O.ValueDate == req.EndDate.Value) on td.id equals et.TradeId into tempEt
from et in tempEt.DefaultIfEmpty()
select new
{
et,
OtcTradeDetail = new OtcTradeDetail
{
id = td.id,
TradeNumber = td.TradeNumber,
BuySell = td.BuySell,
TradeDate = td.TradeDate,
ExerciseDate = td.ExerciseDate,
TradeType = td.IsGroup == 1 ? td.StructureType : td.TradeType,
UnderlyingCode = td.UnderlyingCode,
SpotPrice = td.SpotPrice,
TradeSinglePrice = td.TradeSinglePrice,
TradePrice = td.TradePrice,
Lots = td.Lots,
OriginalNotional = td.OriginalNotional,
Strike = td.Strike,
IsMoneynessOption = td.IsMoneynessOption,
BasisUnderlyingCode = td.BasisUnderlyingCode,
BasisGap = td.BasisGap,
UnderlyingInstrumentType = td.UnderlyingInstrumentType,
StockEqvNotional = td.StockEqvNotional,
OriginalStockEqvNotional = td.OriginalStockEqvNotional,
IsUsePremiumRate = td.IsUsePremiumRate,
TradeStatus = td.TradeStatus,
StructureType = td.StructureType,
PremiumRate = td.PremiumRate,
ExerciseMode = td.ExerciseMode,
OptionType = td.OptionType,
AnnualizeFactor = td.AnnualizeFactor,
TcId = tc.id,
TcValueDate = tc.ValueDate,
TcAction = tc.Action,
TcAmount = tc.Amount,
TcNotional = tc.Notional,
TcTradeAmount = tc.TradeAmount,
TcUnwindPrice = tc.UnwindPrice,
TcUnwindPricePercent = tc.UnwindPricePercentRate,
TcUnwindNotional = tc.UnwindNotional,
TcUnwindTradeAmount = tc.UnwindTradeAmount,
TcUnwindPercent = tc.UnwindPercentRate,
TcExerciseWay = tc.ExerciseWay,
TcFinalPrice = tc.FinalPrice,
ParticipationRate = td.ParticipationRate,
PrincipalRate = td.PrincipalRate,
NoRiskRate = td.NoRiskRate,
UnderlyingAssetName = td.UnderlyingAssetName,
IsGroup = td.IsGroup,
ClientName = td.ClientName,
ExtendInfo = td.ExtendInfo,
IsLastAction = tc.IsLastAction
//ActualStrike = td.ActualStrike,
}
};
if (req.sidx.IsNullOrWhiteSpace())
{
req.sidx = "OtcTradeDetail.TcValueDate,OtcTradeDetail.TcId";
req.sord = "desc";
}
var tempRetListResult = query.ToSearchList(req);
foreach (var item in tempRetListResult.rows)
{
if (item.OtcTradeDetail.IsLastAction)
{
if (item.OtcTradeDetail.TradeType == "凤凰期权" || item.OtcTradeDetail.IsGroup == 1)
{
var tradeCashs = DbContext.trade_cash.Where(y => y.ValidState != "InValid" && y.TradeId == item.OtcTradeDetail.id && y.Action == "系统操作-票息" && y.id != item.OtcTradeDetail.TcId);
if (tradeCashs.Any())
{
item.OtcTradeDetail.TcAmount += tradeCashs.Sum(y => y.Amount);
}
}
else if (item.OtcTradeDetail.TradeType == "收益互换")
{
var tradeCashs = DbContext.trade_cash.Where(y => y.ValidState != "InValid" && y.TradeId == item.OtcTradeDetail.id && y.Action == "系统操作-互换" && y.id != item.OtcTradeDetail.TcId);
if (tradeCashs.Any())
{
item.OtcTradeDetail.TcAmount += tradeCashs.Sum(y => y.Amount);
}
}
}
if (item.OtcTradeDetail.IsGroup == 1)
{
var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeCashId == item.OtcTradeDetail.TcId).ToList();
var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList();
var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList();
item.OtcTradeDetail.TcTradePrice = 0;
childTradeCashs.ForEach(x =>
{
var trade = childTrades.FirstOrDefault(y => y.id == x.TradeId);
item.OtcTradeDetail.TcTradePrice += (x.UnwindPercentRate * trade?.TradePrice * (trade?.BuySell == "买入" ? -1 : 1)) ?? 0;
});
}
item.OtcTradeDetail.TradeSinglePrice = Math.Abs(item.OtcTradeDetail.TradeSinglePrice ?? 0);
if (item.et == null)
{
continue;
}
item.OtcTradeDetail.SpotPrice = item.et.trade.SpotPrice;
item.OtcTradeDetail.TradeSinglePrice = Math.Abs(item.et.trade.TradeSinglePrice ?? 0);
item.OtcTradeDetail.TradePrice = item.et.trade.TradePrice;
item.OtcTradeDetail.OriginalNotional = item.et.trade.OriginalNotional;
item.OtcTradeDetail.Strike = item.et.trade.Strike;
item.OtcTradeDetail.OriginalStockEqvNotional = item.et.trade.OriginalStockEqvNotional;
}
var retListResult = new SearchListResult<OtcTradeDetail>
{
Msg = tempRetListResult.Msg,
page = tempRetListResult.page,
records = tempRetListResult.records,
rows = tempRetListResult.rows.Select(O => O.OtcTradeDetail),
total = tempRetListResult.total
};
dynamic sum = new ExpandoObject();
if (retListResult.rows.Any())
{
sum.WinLossSum = retListResult.rows.Sum(a => a.WinLoss);
sum.TradePriceSum = retListResult.rows.Sum(a => a.TradePrice * (a.BuySell == "买入" && a.TradeType != "远期" ? -1 : 1));
sum.MinusAmountSum = retListResult.rows.Sum(a => a.TcAmount);
sum.StockEqvNotionalSum = retListResult.rows.Select(x => new { x.id, x.OriginalStockEqvNotional })
.Distinct().Sum(q => q.OriginalStockEqvNotional);
}
retListResult.Sum = sum;
var underlyinglist = underlying_managerBLL.GetQuery();
foreach (var td in retListResult.rows)
{
if (td.TradeType == "亚式期权")
{
var baseReq = FixingService.GetRequestBase(valuedateBLL.ValueDate, td);
var strikeReq = new AsianOptionStrikeRequest(baseReq)
{
IsMoneynessOption = td.IsMoneynessOption == "是",
SpotPrice = td.SpotPrice,
Strike = td.Strike,
};
td.ActualStrike = trade_asian_optionBLL.GetAsianStrikePrice(strikeReq, null);
}
else
{
td.ActualStrike = td.IsMoneynessOption == "是" ? (td.SpotPrice * td.Strike) : td.Strike;
}
var CountRatio = UnderlyingDataProvider.GetCountRatio(td.UnderlyingCode);
if (!ConsTrade.TradeTypesForHedge.Contains(td.TradeType))
{
td.TradeOriginalAmount = td.OriginalNotional / CountRatio;
}
td.CountRatio = CountRatio;
if (td.TradeType == "合成价差期权")
{
td.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(td.UnderlyingCode);
}
}
return retListResult;
}
private string ConfirmYesDanzhang(SearchListResult<OtcTradeDetail> tradelist, Client client, TradeDetailsReq req, string biaoTou = null, string biaoWei = null)
{
var dic = new Dictionary<string, object>();
var table1 = new List<Dictionary<string, string>>();
var table2 = new List<Dictionary<string, string>>();
var table3 = new List<Dictionary<string, string>>();
var contractGroupList1 = tradelist.rows.Where(q => q.TcAction == ClientCashInCashOut.系统操作_期权费).ToList();
var contractGroupList2 = tradelist.rows.Where(q => q.TcAction == ClientCashInCashOut.系统操作_平仓费
|| (q.TcAction == ClientCashInCashOut.系统操作_行权费 && q.TcExerciseWay == TradeCashExerciseWayEnum.提前终止行权)).ToList();
var contractGroupList3 = tradelist.rows.Where(q => (q.TcAction == ClientCashInCashOut.系统操作_行权费 || q.TcAction == ClientCashInCashOut.系统操作_互换)
&& q.TcExerciseWay == TradeCashExerciseWayEnum.到期行权).ToList();
foreach (var td in contractGroupList1)
{
var row1 = new Dictionary<string, string>();
var va = new TradeSingleDetailReport(td);
row1["{{table1.交易编号}}"] = td.TradeNumber;
row1["{{table1.交易方向}}"] = va.BuySell;
row1["{{table1.交易日期}}"] = $"{td.TradeDate:yyyy/MM/dd}";
row1["{{table1.到期日期}}"] = $"{td.ExerciseDate:yyyy/MM/dd}";
row1["{{table1.期权类型}}"] = va.TradeMultipleType;
row1["{{table1.标的代码}}"] = td.UnderlyingCode;
row1["{{table1.期初价格}}"] = $"{va.InitialSpotPrice_Calc}";
row1["{{table1.执行价格}}"] = $"{va.StrikeString}";
row1["{{table1.权利金}}"] = $"{va.TradeSinglePriceString}";
row1["{{table1.交易数量}}"] = $"{va.TradeOriginalAmount:F2}";
row1["{{table1.交易总额}}"] = $"{va.TradePrice:F2}";
table1.Add(row1);
}
foreach (var td in contractGroupList2)
{
var row2 = new Dictionary<string, string>();
var va = new TradeSingleDetailReport(td);
row2["{{table2.交易编号}}"] = td.TradeNumber;
row2["{{table2.交易方向}}"] = va.BuySell;
row2["{{table2.交易日期}}"] = $"{td.TradeDate:yyyy/MM/dd}";
row2["{{table2.到期日期}}"] = $"{td.ExerciseDate:yyyy/MM/dd}";
row2["{{table2.期权类型}}"] = va.TradeMultipleType;
row2["{{table2.标的代码}}"] = td.UnderlyingCode;
row2["{{table2.执行价格}}"] = $"{va.StrikeString}";
row2["{{table2.权利金}}"] = $"{va.TradeSinglePriceString}";
row2["{{table2.交易数量}}"] = $"{va.TradeOriginalAmount:F2}";
row2["{{table2.交易总额}}"] = $"{va.TradePrice:F2}";
row2["{{table2.提前终止类型}}"] = va.UnwindType;
row2["{{table2.提前终止日期}}"] = $"{va.UnwindDate}";
row2["{{table2.提前终止数量}}"] = $"{va.UnwindTradeAmount}";
row2["{{table2.平仓标的价格}}"] = $"{va.FinalPrice}";
row2["{{table2.平仓价格行权收益}}"] = $"{va.SingleMinusAmountString}";
row2["{{table2.提前终止总额}}"] = $"{va.MinusAmount:F2}";
row2["{{table2.实现盈亏}}"] = $"{va.WinLoss:F2}";
table2.Add(row2);
}
foreach (var td in contractGroupList3)
{
var row3 = new Dictionary<string, string>();
var va = new TradeSingleDetailReport(td);
row3["{{table3.交易编号}}"] = td.TradeNumber;
row3["{{table3.交易方向}}"] = va.BuySell;
row3["{{table3.交易日期}}"] = $"{td.TradeDate:yyyy/MM/dd}";
row3["{{table3.到期日期}}"] = $"{td.ExerciseDate:yyyy/MM/dd}";
row3["{{table3.期权类型}}"] = va.TradeMultipleType;
row3["{{table3.标的代码}}"] = td.UnderlyingCode;
row3["{{table3.执行价格}}"] = $"{va.StrikeString}";
row3["{{table3.权利金}}"] = $"{va.TradeSinglePriceString}";
row3["{{table3.交易数量}}"] = $"{va.TradeOriginalAmount:F2}";
row3["{{table3.交易总额}}"] = $"{va.TradePrice:F2}";
row3["{{table3.到期状态}}"] = va.ExerciseType;
row3["{{table3.到期数量}}"] = $"{va.UnwindTradeAmount:F2}";
row3["{{table3.到期标的价格}}"] = $"{va.FinalPrice:F2}";
row3["{{table3.到期收益}}"] = $"{va.SingleMinusAmountString:F2}";
row3["{{table3.到期收益总额}}"] = $"{va.MinusAmount:F2}";
row3["{{table3.实现盈亏}}"] = $"{va.WinLoss:F2}";
table3.Add(row3);
}
dic["{{客户编号}}"] = client.Number;
dic["{{公司名称}}"] = client.Name;
dic["{{甲方}}"] = PS.Config.CompanyFullName;
dic["{{table1."] = table1;
dic["{{table2."] = table2;
dic["{{table3."] = table3;
dic["{{合同日期}}"] = $"{DateTime.Now.ToString("yyyy年MM月dd日")}";//ValueDate
dic["{{了结日期1}}"] = $"{req.StartDate:yyyy/MM/dd}";
dic["{{了结日期2}}"] = $"{req.EndDate:yyyy/MM/dd}";
var targetFolder = req.OutputFolder;
if (string.IsNullOrEmpty(targetFolder))
{
var date = req.EndDate;
targetFolder = OtcAppContext.MapPath($"~/App_Docs/Download/{date:yyyyMM}");
}
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/单章-场外衍生品交易结算确认书(交易明细).docx");
string FileName;
var startDate = req.StartDate;
if (startDate == DateTime.MinValue)
{
FileName = $"交易明细_{req.EndDate:MMdd}_{client.Name}.docx";
}
else
{
FileName = $"交易明细_{startDate:MMdd}_{req.EndDate:MMdd}_{client.Name}.docx";
}
var excelFilePath = Path.Combine(targetFolder, FileName);
MsWordTempalteHelper.GenerateFromTemplate(templateFile, dic, excelFilePath, true);
var report = new TradeDetailsReport
{
CreatedModel = new TradeDetailsModel(),
FinishedModel = new TradeDetailsModel(),
MatureModel = new TradeDetailsModel(),
ClientId = client.id,
ClientName = client.Name,
ClientFullName = client.Name,
ClientNumber = client.Number,
ClientAbbreviation = client.Abbreviation,
CompanyName = PS.Config.CompanyFullName,
ReportStart = req.StartDate == null ? DateTime.MinValue : req.StartDate.Value,
ReportEnd = req.EndDate.Value
};
var contractGroupList = tradelist.rows.Where(q => q.TcAction == ClientCashInCashOut.系统操作_期权费).ToList();
contractGroupList.ForEach(x =>
{
if (x.TradeType == "结构化交易" && x.IsGroup == 1)
{
x.TradeType = x.StructureType;
}
});
new TradeExtendService(this).SetTradeExtendWithCnKey(contractGroupList, true);
var tradeTypes = contractGroupList.Select(x => x.TradeType).ToHashSet();
report.CreatedModel.TradeList = contractGroupList.Select(g => new TradeSingleDetailReport(g)).ToList();
report.CreatedModel.Tradelist_Vanilla = contractGroupList.Where(c => c.TradeType == "香草期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("香草期权");
report.CreatedModel.Tradelist_Forward = contractGroupList.Where(c => c.TradeType == "远期").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("远期");
report.CreatedModel.Tradelist_Asian = contractGroupList.Where(c => c.TradeType == "亚式期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("亚式期权");
report.CreatedModel.TradeList_Binary = contractGroupList.Where(c => c.TradeType == "二元期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("二元期权");
report.CreatedModel.TradeList_Barrier = contractGroupList.Where(c => c.TradeType == "障碍期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("障碍期权");
report.CreatedModel.TradeList_DbShark = contractGroupList.Where(c => c.TradeType == "双鲨期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("双鲨期权");
report.CreatedModel.TradeList_Autocall = contractGroupList.Where(c => c.TradeType == "凤凰期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("凤凰期权");
report.CreatedModel.TradeList_Snowball = contractGroupList.Where(c => c.TradeType == "雪球期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("雪球期权");
report.CreatedModel.TradeList_RangeAcc = contractGroupList.Where(c => c.TradeType == "区间累积期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("区间累积期权");
report.CreatedModel.TradeList_AirBag = contractGroupList.Where(c => c.TradeType == "气囊结构").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("气囊结构");
report.CreatedModel.TradeList_PayoffSwap = contractGroupList.Where(c => c.TradeType == "收益互换").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("收益互换");
report.CreatedModel.TradeList_Custom = contractGroupList.Where(c => c.TradeType == "自定义交易").Select(g => new TradeSingleDetailReport(g)).ToList();
var extendInfos = report.CreatedModel.TradeList_Custom.Where(x => x.TdDetail.ExtendInfo != null).Select(x => x.TdDetail).ToList();
var propertys = new List<ExtendInfoModel>();
extendInfos.ForEach(x =>
{
propertys.AddRange(x.Propertys);
});
report.CreatedModel.PropertyNames_Custom = propertys.Select(x => x.name).Distinct().ToList();
tradeTypes.Remove("自定义交易");
report.CreatedModel.TradeList_SSpread = contractGroupList.Where(c => c.TradeType == "合成价差期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("合成价差期权");
report.CreatedModel.TradeList_Enhance = contractGroupList.Where(c => c.TradeType == "收益增强结构").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("收益增强结构");
report.CreatedModel.TradeList_Cashflow = contractGroupList.Where(c => c.TradeType == "现金流交易").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("现金流交易");
report.CreatedModel.TradeList_Accumulator = contractGroupList.Where(c => c.TradeType == "累计期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("累计期权");
report.CreatedModel.Tradelist_Risky = contractGroupList.Where(c => c.TradeType == "Risky期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("Risky期权");
report.CreatedModel.TradeList_Others = contractGroupList.Where(c => tradeTypes.Contains(c.TradeType)).Select(g => new TradeSingleDetailReport(g)).ToList();
Func<TradeSingleDetailReport, double> sumf = q => q.TradePrice;
report.CreatedModel.VanillaTradePriceSum = report.CreatedTradeList_Vanilla.Sum(sumf);
report.CreatedModel.AsianTradePriceSum = report.CreatedTradeList_Asian.Sum(sumf);
report.CreatedModel.BinaryTradePriceSum = report.CreatedTradeList_Binary.Sum(sumf);
report.CreatedModel.BarrierTradePriceSum = report.CreatedTradeList_Barrier.Sum(sumf);
report.CreatedModel.DbSharkTradePriceSum = report.CreatedTradeList_DbShark.Sum(sumf);
report.CreatedModel.AutocallTradePriceSum = report.CreatedTradeList_Autocall.Sum(sumf);
report.CreatedModel.SnowballTradePriceSum = report.CreatedTradeList_Snowball.Sum(sumf);
report.CreatedModel.RangeAccTradePriceSum = report.CreatedTradeList_RangeAcc.Sum(sumf);
report.CreatedModel.AirBagTradePriceSum = report.CreatedTradeList_AirBag.Sum(sumf);
report.CreatedModel.CustomTradePriceSum = report.CreatedTradeList_Custom.Sum(sumf);
report.CreatedModel.SSpreadTradePriceSum = report.CreatedTradeList_SSpread.Sum(sumf);
report.CreatedModel.CashflowTradePriceSum = report.CreatedTradeList_Cashflow.Sum(sumf);
report.CreatedModel.AccumulatorTradePriceSum = report.CreatedTradeList_Accumulator.Sum(sumf);
contractGroupList = tradelist.rows.Where(q => q.TcAction == ClientCashInCashOut.系统操作_平仓费
|| (q.TcAction == ClientCashInCashOut.系统操作_行权费 && q.TcExerciseWay == TradeCashExerciseWayEnum.提前终止行权)).ToList();
report.FinishedModel.TradePriceSum = contractGroupList.Select(x => new { x.id, x.TradePrice, x.BuySell })
.Distinct().Sum(q => (q.TradePrice ?? 0) * ("卖出".Equals(q.BuySell) ? -1 : 1));
report.FinishedModel.MinusAmountSum = contractGroupList.Sum(q => q.TcAmount ?? 0);
report.FinishedModel.WinLossSum = (contractGroupList.Sum(q => q.WinLoss)) ?? 0;
report.FinishedModel.TradeList = contractGroupList.Select(g => new TradeSingleDetailReport(g)).ToList();
contractGroupList = tradelist.rows.Where(q => (q.TcAction == ClientCashInCashOut.系统操作_行权费 || q.TcAction == ClientCashInCashOut.系统操作_互换)
&& q.TcExerciseWay == TradeCashExerciseWayEnum.到期行权).ToList();
report.MatureModel.TradePriceSum = contractGroupList.Select(x => new { x.id, x.TradePrice, x.BuySell })
.Distinct().Sum(q => (q.TradePrice ?? 0) * ("卖出".Equals(q.BuySell) ? -1 : 1));
report.MatureModel.MinusAmountSum = contractGroupList.Sum(q => q.TcAmount ?? 0);
report.MatureModel.WinLossSum = (contractGroupList.Sum(q => q.WinLoss)) ?? 0;
report.MatureModel.TradeList = contractGroupList.Select(g => new TradeSingleDetailReport(g)).ToList();
#region 处理表头表尾
var biaoTouList = Regex.Split(biaoTou, "</p>", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
var newBiaoTouList = new List<string>();
biaoTouList.ForEach(x =>
{
x = Regex.Replace(x, "<[^>]+>", "");
x = Regex.Replace(x, "&[^;]+;", "");
newBiaoTouList.Add(x);
});
report.BiaoTouLines = newBiaoTouList;
report.BiaoTou = string.Join("\n", newBiaoTouList);
var biaoWeiList = Regex.Split(biaoWei, "</p>", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
var newBiaoWeiList = new List<string>();
biaoWeiList.ForEach(x =>
{
x = Regex.Replace(x, "<[^>]+>", "");
x = Regex.Replace(x, "&[^;]+;", "");
newBiaoWeiList.Add(x);
});
report.BiaoWeiLines = newBiaoWeiList;
report.BiaoWei = string.Join("\n", newBiaoWeiList);
#endregion
report.OutputFolder = req.OutputFolder;
TradeDetailsReport = report;
return excelFilePath;
}
private string ConfirmDanzhang(SearchListResult<OtcTradeDetail> resultList, Client client, TradeDetailsReq req, string biaoTou = null, string biaoWei = null, bool isCreateConfirmBookModeDirectory = false, bool GenerateTradeDetails = true)
{
//国君要求如果没有交易明细就不要生成
//20210416王锦麟注释掉了这三行
//20211014国君沈小杨+镒链翁敏华要求改回来
//如果要注释下面这三行代码请写出理由
if (!resultList.rows.Any())
{
throw new ServiceException(client.Name + "没有交易明细");
}
var report = new TradeDetailsReport
{
CreatedModel = new TradeDetailsModel(),
FinishedModel = new TradeDetailsModel(),
MatureModel = new TradeDetailsModel()
};
var contractGroupList = resultList.rows.Where(q => q.TcAction == ClientCashInCashOut.系统操作_期权费).ToList();
contractGroupList.ForEach(x =>
{
if (x.TradeType == "结构化交易" && x.IsGroup == 1)
{
x.TradeType = x.StructureType;
}
});
new TradeExtendService(this).SetTradeExtendWithCnKey(contractGroupList, true);
var tradeTypes = contractGroupList.Select(x => x.TradeType).ToHashSet();
report.CreatedModel.TradeList = contractGroupList.Select(g => new TradeSingleDetailReport(g)).ToList();
report.CreatedModel.Tradelist_Vanilla = contractGroupList.Where(c => c.TradeType == "香草期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("香草期权");
report.CreatedModel.Tradelist_Forward = contractGroupList.Where(c => c.TradeType == "远期").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("远期");
report.CreatedModel.Tradelist_Asian = contractGroupList.Where(c => c.TradeType == "亚式期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("亚式期权");
report.CreatedModel.TradeList_Binary = contractGroupList.Where(c => c.TradeType == "二元期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("二元期权");
report.CreatedModel.TradeList_Barrier = contractGroupList.Where(c => c.TradeType == "障碍期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("障碍期权");
report.CreatedModel.TradeList_DbShark = contractGroupList.Where(c => c.TradeType == "双鲨期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("双鲨期权");
report.CreatedModel.TradeList_Autocall = contractGroupList.Where(c => c.TradeType == "凤凰期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("凤凰期权");
report.CreatedModel.TradeList_Snowball = contractGroupList.Where(c => c.TradeType == "雪球期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("雪球期权");
report.CreatedModel.TradeList_RangeAcc = contractGroupList.Where(c => c.TradeType == "区间累积期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("区间累积期权");
report.CreatedModel.TradeList_AirBag = contractGroupList.Where(c => c.TradeType == "气囊结构").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("气囊结构");
report.CreatedModel.TradeList_PayoffSwap = contractGroupList.Where(c => c.TradeType == "收益互换").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("收益互换");
report.CreatedModel.TradeList_Custom = contractGroupList.Where(c => c.TradeType == "自定义交易").Select(g => new TradeSingleDetailReport(g)).ToList();
var extendInfos = report.CreatedModel.TradeList_Custom.Where(x => x.TdDetail.ExtendInfo != null).Select(x => x.TdDetail).ToList();
var propertys = new List<ExtendInfoModel>();
extendInfos.ForEach(x =>
{
propertys.AddRange(x.Propertys);
});
report.CreatedModel.PropertyNames_Custom = propertys.Select(x => x.name).Distinct().ToList();
tradeTypes.Remove("自定义交易");
report.CreatedModel.TradeList_SSpread = contractGroupList.Where(c => c.TradeType == "合成价差期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("合成价差期权");
report.CreatedModel.TradeList_Enhance = contractGroupList.Where(c => c.TradeType == "收益增强结构").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("收益增强结构");
report.CreatedModel.TradeList_Cashflow = contractGroupList.Where(c => c.TradeType == "现金流交易").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("现金流交易");
var accumulatorOptionIds = DbContext.trade_accumulator_option.Where(l => l.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented).Select(l => l.TradeId).ToList();
report.CreatedModel.TradeList_Accumulator = contractGroupList.Where(c => c.TradeType == "累计期权" && !accumulatorOptionIds.Contains(c.id)).Select(g => new TradeSingleDetailReport(g)).ToList();
report.CreatedModel.TradeList_AccumulatorSegmented = contractGroupList.Where(c => c.TradeType == "累计期权" && accumulatorOptionIds.Contains(c.id)).Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("累计期权");
report.CreatedModel.Tradelist_Risky = contractGroupList.Where(c => c.TradeType == "Risky期权").Select(g => new TradeSingleDetailReport(g)).ToList();
tradeTypes.Remove("Risky期权");
report.CreatedModel.TradeList_Others = contractGroupList.Where(c => tradeTypes.Contains(c.TradeType)).Select(g => new TradeSingleDetailReport(g)).ToList();
Func<TradeSingleDetailReport, double> sumf = q => q.TradePrice;
report.CreatedModel.VanillaTradePriceSum = report.CreatedTradeList_Vanilla.Sum(sumf);
report.CreatedModel.AsianTradePriceSum = report.CreatedTradeList_Asian.Sum(sumf);
report.CreatedModel.BinaryTradePriceSum = report.CreatedTradeList_Binary.Sum(sumf);
report.CreatedModel.BarrierTradePriceSum = report.CreatedTradeList_Barrier.Sum(sumf);
report.CreatedModel.DbSharkTradePriceSum = report.CreatedTradeList_DbShark.Sum(sumf);
report.CreatedModel.AutocallTradePriceSum = report.CreatedTradeList_Autocall.Sum(sumf);
report.CreatedModel.SnowballTradePriceSum = report.CreatedTradeList_Snowball.Sum(sumf);
report.CreatedModel.RangeAccTradePriceSum = report.CreatedTradeList_RangeAcc.Sum(sumf);
report.CreatedModel.AirBagTradePriceSum = report.CreatedTradeList_AirBag.Sum(sumf);
report.CreatedModel.CustomTradePriceSum = report.CreatedTradeList_Custom.Sum(sumf);
report.CreatedModel.SSpreadTradePriceSum = report.CreatedTradeList_SSpread.Sum(sumf);
report.CreatedModel.CashflowTradePriceSum = report.CreatedTradeList_Cashflow.Sum(sumf);
report.CreatedModel.AccumulatorTradePriceSum = report.CreatedTradeList_Accumulator.Sum(sumf);
report.CreatedModel.RiskyTradePriceSum = report.CreatedTradeList_Risky.Sum(sumf);
report.CreatedModel.AccumulatorTradeSegmentedPriceSum = report.CreatedTradeList_AccumulatorSegmented.Sum(sumf);
contractGroupList = resultList.rows.Where(q => q.TcAction == ClientCashInCashOut.系统操作_平仓费
|| (q.TcAction == ClientCashInCashOut.系统操作_行权费 && q.TcExerciseWay == TradeCashExerciseWayEnum.提前终止行权) || (q.TcExerciseWay != TradeCashExerciseWayEnum.到期行权 && q.IsLastAction)).ToList();
report.FinishedModel.TradePriceSum = contractGroupList.Sum(q => (q.TradePrice ?? 0) * ((q.BuySell == "买入" && q.TradeType != "远期") ? -1 : 1) * -1);
report.FinishedModel.MinusAmountSum = contractGroupList.Sum(q => (q.TcAmount ?? 0) * -1);
report.FinishedModel.WinLossSum = contractGroupList.Sum(q => (q.WinLoss ?? 0) * -1);
report.FinishedModel.TradeList = contractGroupList.Select(g => new TradeSingleDetailReport(g)).ToList();
contractGroupList = resultList.rows.Where(q => (q.TcAction == ClientCashInCashOut.系统操作_行权费 || q.TcAction == ClientCashInCashOut.系统操作_互换)
&& q.TcExerciseWay == TradeCashExerciseWayEnum.到期行权).ToList();
report.MatureModel.TradePriceSum = contractGroupList.Sum(q => (q.TradePrice ?? 0) * ((q.BuySell == "买入" && q.TradeType != "远期") ? -1 : 1) * -1);
report.MatureModel.MinusAmountSum = contractGroupList.Sum(q => (q.TcAmount ?? 0) * -1);
report.MatureModel.WinLossSum = contractGroupList.Sum(q => (q.WinLoss ?? 0) * -1);
report.MatureModel.TradeList = contractGroupList.Select(g => new TradeSingleDetailReport(g)).ToList();
report.ClientId = client.id;
report.ClientName = client.Name;
report.ClientFullName = client.Name;
report.ClientNumber = client.Number;
report.ClientAbbreviation = client.Abbreviation;
report.CompanyName = PS.Config.CompanyFullName;
report.ReportStart = req.StartDate == null ? DateTime.MinValue : req.StartDate.Value;
report.ReportEnd = req.EndDate.Value;
#region 处理表头表尾
var biaoTouList = Regex.Split(biaoTou, "</p>", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
var newBiaoTouList = new List<string>();
biaoTouList.ForEach(x =>
{
x = Regex.Replace(x, "<[^>]+>", "");
x = Regex.Replace(x, "&[^;]+;", "");
newBiaoTouList.Add(x);
});
report.BiaoTouLines = newBiaoTouList;
report.BiaoTou = string.Join("\n", newBiaoTouList);
var biaoWeiList = Regex.Split(biaoWei, "</p>", RegexOptions.IgnoreCase).Where(x => !string.IsNullOrWhiteSpace(x)).ToList();
var newBiaoWeiList = new List<string>();
biaoWeiList.ForEach(x =>
{
x = Regex.Replace(x, "<[^>]+>", "");
x = Regex.Replace(x, "&[^;]+;", "");
newBiaoWeiList.Add(x);
});
report.BiaoWeiLines = newBiaoWeiList;
report.BiaoWei = string.Join("\n", newBiaoWeiList);
#endregion
report.OutputFolder = req.OutputFolder;
TradeDetailsReport = report;
if (GenerateTradeDetails)
{
return GenerateTradeDetailsReportV2(report, client, req.fileType?.ToUpper() == "PDF", isCreateConfirmBookModeDirectory);
}
else
{
return "";
}
}
public List<string> ExportReport(TradeDetailsReq req, string biaoTou = null, string biaoWei = null, bool isCreateConfirmBookModeDirectory = false)
{
var client = DataCacheProvider.GetClientDataSource().GetData(req.ClientId != 0 ? req.ClientId : req.ClientIdsInt[0]);
if (client == null)
{
throw new ServiceException("系统中没有此客户,clientId:" + req.ClientId);
}
var files = new List<string>();
var resultList = SearchTradeDetails(req);
if (client.SupProtocolDate != null && resultList.rows.Where(x => (x.TcValueDate ?? x.TradeDate) > client.SupProtocolDate).Any() && resultList.rows.Where(x => (x.TcValueDate ?? x.TradeDate) < client.SupProtocolDate).Any())
{
var req1 = req.Clone();
req1.EndDate = client.SupProtocolDate.Value.AddDays(-1);
var resultList1 = SearchTradeDetails(req1);
var file1 = ConfirmDanzhang(resultList1, client, req1, biaoTou, biaoWei, isCreateConfirmBookModeDirectory);
files.Add(file1);
var req2 = req.Clone();
req2.StartDate = client.SupProtocolDate;
var resultList2 = SearchTradeDetails(req2);
var file2 = ConfirmDanzhang(resultList2, client, req2, biaoTou, biaoWei, isCreateConfirmBookModeDirectory);
files.Add(file2);
}
//发送邮件的时候邮件内容是所有交易,只是文件拆分
if (!files.Any())
{
var file = ConfirmDanzhang(resultList, client, req, biaoTou, biaoWei, isCreateConfirmBookModeDirectory);
files.Add(file);
}
else
{
ConfirmDanzhang(resultList, client, req, biaoTou, biaoWei, isCreateConfirmBookModeDirectory, false);
}
return files;
}
private string GenerateTradeDetailsReportV2(TradeDetailsReport report, Client client, bool needToPdf = false, bool isCreateConfirmBookModeDirectory = false)
{
//获取盯市报告模板信息
var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/交易明细模板V2双章.xlsx");
var UseSingerBook = client.SupProtocolDate != null && (client.SupProtocolDate <= report.ReportStart || client.SupProtocolDate <= report.ReportEnd);
if (UseSingerBook)
{
templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/交易明细模板V3单章.xlsx");
}
var targetFolder = report.OutputFolder;
if (string.IsNullOrEmpty(targetFolder))
{
var date = report.ReportEnd;
targetFolder = OtcAppContext.MapPath($"~/App_Docs/Download/{date:yyyyMM}/");
}
if (isCreateConfirmBookModeDirectory)
{
if (UseSingerBook)
{
targetFolder = Path.Combine(targetFolder, "单章版");
}
else
{
targetFolder = Path.Combine(targetFolder, "双章版");
}
}
string excelFileName;
var startDate = report.ReportStart;
if (startDate == DateTime.MinValue)
{
excelFileName = $"交易结算确认书_{report.ReportEnd:MMdd}_{report.ClientName}.xlsx";
}
else
{
excelFileName = $"交易结算确认书_{startDate:MMdd}_{report.ReportEnd:MMdd}_{report.ClientName}.xlsx";
}
var excelFilePath = Path.Combine(targetFolder, excelFileName);
Directory.CreateDirectory(targetFolder);
var dic = new Dictionary<string, IEnumerable<TradeSingleDetailReport>> {
{ "香草期权",report.CreatedTradeList_Vanilla},
{ "合成价差期权",report.CreatedTradeList_SSpread},
{ "亚式期权",report.CreatedTradeList_Asian},
{ "二元期权",report.CreatedTradeList_Binary},
{ "障碍期权",report.CreatedTradeList_Barrier},
{ "双鲨期权",report.CreatedTradeList_DbShark},
{ "凤凰",report.CreatedTradeList_Autocall},
{ "雪球",report.CreatedTradeList_Snowball},
{ "区间累积",report.CreatedTradeList_RangeAcc},
{ "气囊结构",report.CreatedTradeList_AirBag},
{ "收益增强结构",report.CreatedTradeList_Enhance},
{ "现金流交易",report.CreatedTradeList_Cashflow},
{ "累计期权",report.CreatedTradeList_Accumulator},
{ "累计期权三段式",report.CreatedTradeList_AccumulatorSegmented},
{ "自定义交易",report.CreatedTradeList_Custom},
{ "远期",report.CreatedTradeList_Forward},
{ "收益互换",report.CreatedTradeList_PayoffSwap},
{ "Risky期权",report.CreatedTradeList_Risky},
{ "提前终止",report.FinishedTradeList},
{ "到期",report.MatureTradeList},
{ "黑箱",report.CreatedTradeList_Others},//暂时取个名字
};
void generateExcelCallback(ExcelWorksheets sheets)
{
foreach (var sheet in sheets)
{
//删除空列表
if (sheet.Name == "交易明细")
{
var emptyRows = 0;
var startRowIndex = 0;
for (var i = 10; i < 100000 && emptyRows < 100; i++)
{
var str = sheet.GetValue(i, 1)?.ToString();
if (string.IsNullOrWhiteSpace(str))
{
emptyRows++;
}
else
{
emptyRows = 0;
if (str == "自定义交易")
{
if (dic.TryGetValue(str, out var em))
{
if (!em.Any())
{
sheet.DeleteRow(i, 4);
i--;
startRowIndex = i;
}
else
{
var titleColumnDic = new Dictionary<string, int>();
var n = 1;
foreach (var item in em)
{
n++;
if (item.TdDetail.Propertys != null)
{
foreach (var property in item.TdDetail.Propertys)
{
if (titleColumnDic.ContainsKey(property.name))
{
sheet.Cells[i + n, titleColumnDic[property.name]].Value = property.value;
sheet.Cells[i + n, titleColumnDic[property.name]].Style.Font.Name = "微软雅黑";
sheet.Cells[i + n, titleColumnDic[property.name]].Style.Font.Size = 10;
sheet.Cells[i + n, titleColumnDic[property.name]].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
}
else
{
sheet.Cells[i + 1, titleColumnDic.Count() + 15].Value = property.name;
sheet.Cells[i + 1, titleColumnDic.Count() + 15].Style.Font.Bold = true;
sheet.Cells[i + 1, titleColumnDic.Count() + 15].Style.Font.Name = "微软雅黑";
sheet.Cells[i + 1, titleColumnDic.Count() + 15].Style.Font.Size = 10;
sheet.Cells[i + 1, titleColumnDic.Count() + 15].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
sheet.Cells[i + n, titleColumnDic.Count() + 15].Value = property.value;
sheet.Cells[i + n, titleColumnDic.Count() + 15].Style.Font.Name = "微软雅黑";
sheet.Cells[i + n, titleColumnDic.Count() + 15].Style.Font.Size = 10;
sheet.Cells[i + n, titleColumnDic.Count() + 15].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
titleColumnDic.Add(property.name, titleColumnDic.Count() + 15);
}
}
}
}
startRowIndex = i + n + 2;
}
}
if (report.CreatedTradeList_Others.Any())
{
startRowIndex += 1;
var positionCount = report.CreatedTradeList_Vanilla.Count() + report.CreatedTradeList_SSpread.Count() + report.CreatedTradeList_Asian.Count()
+ report.CreatedTradeList_Binary.Count() + report.CreatedTradeList_Barrier.Count() + report.CreatedTradeList_DbShark.Count() + report.CreatedTradeList_Autocall.Count()
+ report.CreatedTradeList_Snowball.Count() + report.CreatedTradeList_RangeAcc.Count() + report.CreatedTradeList_AirBag.Count() + report.CreatedTradeList_Enhance.Count()
+ report.CreatedTradeList_Cashflow.Count() + report.CreatedTradeList_Accumulator.Count() + report.CreatedTradeList_AccumulatorSegmented.Count() + report.CreatedTradeList_Custom.Count() + report.CreatedTradeList_Forward.Count() + report.CreatedTradeList_PayoffSwap.Count();
var tradeTypes = report.CreatedTradeList_Others.Select(x => x.TdDetail.TradeType).ToHashSet();
foreach (var tradeType in tradeTypes)
{
var eod_positionList_others = report.CreatedTradeList_Others.Where(x => x.TdDetail.TradeType == tradeType).ToList();
setPositionCell(sheet, startRowIndex, eod_positionList_others);
startRowIndex += eod_positionList_others.Count + 4;
}
}
else
{
dic.Remove("黑箱");//把暂时加的去掉
}
}
else
{
if (str == "成交")
{
var isEmpty = true;
foreach (var item in dic)
{
if (item.Value.Count() > 0 && item.Key != "提前终止" && item.Key != "到期")
{
isEmpty = false;
break;
}
}
if (isEmpty)
{
sheet.DeleteRow(i, 1);
i--;
}
}
else if (dic.TryGetValue(str, out var em) && !em.Any())
{
sheet.DeleteRow(i, 4);
i--;
}
else if (dic.TryGetValue(str, out var em2) && em2.Any())
{
i += em2.Count();
}
}
}
}
}
}
};
string text = FileHelper.ReplaceExtension(excelFilePath, ".pdf");
if (File.Exists(text))
{
File.Delete(text);
}
var typeFileName = ExcelTemplate.GeneratePDFFromExeclTemplateV2(templateFile, excelFilePath,
new Dictionary<string, object> { { "交易明细", report } },
shouldDeleteSheet: true, needToPdf: needToPdf, callback: generateExcelCallback);
return typeFileName;
}
private void setPositionCell(ExcelWorksheet sheet, int startRowIndex, List<TradeSingleDetailReport> eod_positionList_others)
{
var defaultPosition = eod_positionList_others.FirstOrDefault();
sheet.InsertRow(startRowIndex, eod_positionList_others.Count() + 4);
sheet.Cells[startRowIndex, 1].Value = defaultPosition.TdDetail.StructureType;
sheet.Cells[startRowIndex, 1].Style.Font.Bold = true;
sheet.Cells[startRowIndex, 1].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex, 1].Style.Font.Size = 10;
sheet.Cells[startRowIndex, 1].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
sheet.Cells[startRowIndex + 1, 1].Value = "交易编号";
sheet.Cells[startRowIndex + 1, 2].Value = "交易方向";
sheet.Cells[startRowIndex + 1, 3].Value = "交易日期";
sheet.Cells[startRowIndex + 1, 4].Value = "到期日期";
sheet.Cells[startRowIndex + 1, 5].Value = "交易总额";
sheet.Cells[startRowIndex + 1, 6].Value = "名义本金";
sheet.Cells[startRowIndex + 1, 7].Value = "标的代码";
sheet.Cells[startRowIndex + 1, 8].Value = "标的名称";
sheet.Cells[startRowIndex + 1, 9].Value = "期初价格";
for (var col = 1; col <= 9; col++)
{
sheet.Cells[startRowIndex + 1, col].Style.Font.Bold = true;
sheet.Cells[startRowIndex + 1, col].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex + 1, col].Style.Font.Size = 10;
sheet.Cells[startRowIndex + 1, col].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
}
var titleColumnDic = new Dictionary<string, int>();
var j = 0;
double totalTradePrice = 0;
foreach (var item in eod_positionList_others)
{
j++;
sheet.Cells[startRowIndex + 1 + j, 1].Value = item.TradeNumber;
sheet.Cells[startRowIndex + 1 + j, 2].Value = item.BuySell;
sheet.Cells[startRowIndex + 1 + j, 3].Value = item.TradeDate;
sheet.Cells[startRowIndex + 1 + j, 4].Value = item.ExerciseDate;
sheet.Cells[startRowIndex + 1 + j, 5].Value = item.TradePrice;
sheet.Cells[startRowIndex + 1 + j, 6].Value = item.TdDetail.OriginalStockEqvNotional;
sheet.Cells[startRowIndex + 1 + j, 7].Value = item.TdDetail.UnderlyingAssetName;
sheet.Cells[startRowIndex + 1 + j, 8].Value = item.TdDetail.UnderlyingCode;
sheet.Cells[startRowIndex + 1 + j, 9].Value = item.TdDetail.InitialSpotPrice;
totalTradePrice += item.TradePrice;
if (item.TdDetail.Propertys != null)
{
foreach (var property in item.TdDetail.Propertys)
{
if (titleColumnDic.ContainsKey(property.name))
{
sheet.Cells[startRowIndex + j + 1, titleColumnDic[property.name]].Value = property.value;
sheet.Cells[startRowIndex + j + 1, titleColumnDic[property.name]].Style.Font.Size = 10;
sheet.Cells[startRowIndex + j + 1, titleColumnDic[property.name]].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex + j + 1, titleColumnDic[property.name]].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
}
else
{
sheet.Cells[startRowIndex + 1, titleColumnDic.Count() + 10].Value = property.name;
sheet.Cells[startRowIndex + 1, titleColumnDic.Count() + 10].Style.Font.Bold = true;
sheet.Cells[startRowIndex + 1, titleColumnDic.Count() + 10].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex + 1, titleColumnDic.Count() + 10].Style.Font.Size = 10;
sheet.Cells[startRowIndex + 1, titleColumnDic.Count() + 10].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
sheet.Cells[startRowIndex + j + 1, titleColumnDic.Count() + 10].Value = property.value;
sheet.Cells[startRowIndex + j + 1, titleColumnDic.Count() + 10].Style.Font.Size = 10;
sheet.Cells[startRowIndex + j + 1, titleColumnDic.Count() + 10].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex + j + 1, titleColumnDic.Count() + 10].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
titleColumnDic.Add(property.name, titleColumnDic.Count() + 10);
}
}
}
for (var col = 1; col <= 9; col++)
{
sheet.Cells[startRowIndex + 1 + j, col].Style.Font.Size = 10;
sheet.Cells[startRowIndex + 1 + j, col].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex + 1 + j, col].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
}
}
sheet.Cells[startRowIndex + 1 + j + 2, 5].Value = totalTradePrice;
sheet.Cells[startRowIndex + 1 + j + 2, 5].Style.Font.Size = 10;
sheet.Cells[startRowIndex + 1 + j + 2, 5].Style.Font.Name = "微软雅黑";
sheet.Cells[startRowIndex + 1 + j + 2, 5].Style.Font.Bold = true;
sheet.Cells[startRowIndex + 1 + j + 2, 5].Style.HorizontalAlignment = ExcelHorizontalAlignment.CenterContinuous;
}
private string GeneratePDFReport(string excelPath)
{
var tempFolder = OtcAppContext.MapPath("~/App_Docs/Temp");
if (!Directory.Exists(tempFolder))
{
Directory.CreateDirectory(tempFolder);
}
var tempExcelFilePath = FileHelper.GetTargetFilePath(excelPath, tempFolder, true);
File.Copy(excelPath, tempExcelFilePath);
var pdfFilePath = FileHelper.ReplaceExtension(excelPath, ".pdf");
var excelfilepath2 = FileHelper.ReplaceExtension(excelPath, ".xlsx");
var wordfilepath = FileHelper.ReplaceExtension(excelPath, ".docx");
if (File.Exists(pdfFilePath))
{
File.Delete(pdfFilePath);
}
if (File.Exists(excelfilepath2))
{
OfficeFileConverter.ConvertFileFormat(excelfilepath2, pdfFilePath);
}
else
{
OfficeFileConverter.ConvertDocxToPDF(wordfilepath, pdfFilePath);
}
return pdfFilePath;
}
public SendTradeDetailReportResult SendTradeDetailReport(TradeDetailsReq req, TradeDetailsReport report, string luoKuan,
List<string> reportFilePath, string template, List<string> receiver = null, List<string> attachFiles = null, bool skip = false)
{
var AppendixType = DBCacheManager.Single.GetStr(CacheTable.TradeDerailsNeedAppendix, template);
var filePathes = new List<string>();
foreach (var item in reportFilePath)
{
var path = string.Empty;
if (AppendixType == "PDF")
{
path = FileHelper.ReplaceExtension(item, ".pdf");
try
{
path = GeneratePDFReport(item);
}
catch (Exception ex)
{
throw new ServiceFaultException($"error:{ex.Message},file:{item}", ex);
}
}
else
{
path = item;
}
filePathes.Add(path);
}
if (attachFiles != null && attachFiles.Count > 0)
{
//var allTradeNumbers = report.CreatedModel.TradeList.Select(o => o.TradeNumber)
// .Concat(report.FinishedModel.TradeList.Select(o => o.TradeNumber))
// .Concat(report.MatureModel.TradeList.Select(o => o.TradeNumber));
//var allContractRCodes = DbContext.trade_contract_r.Where(o => o.IsValid && allTradeNumbers.Contains(o.TradeNumber)).Select(o => o.ContractCode);
var documents = new List<trade_contract_document>();
//var documentCodes = documents.Select(o => o.Code);
//var contractr = DbContext.trade_contract_r.Where(o => o.IsValid && documentCodes.Contains(o.ContractCode));
var message = string.Empty;
var clientIdsInt = new List<int>();
if (!string.IsNullOrWhiteSpace(req.ClientIds))
{
clientIdsInt.AddRange(req.ClientIdsInt);
}
else if (req.ClientId > 0)
{
clientIdsInt.Add(req.ClientId);
}
if (req.ParentFlag)
{
var clientIdList = DataCacheProvider.GetClientDataSource().AsQueryable(O => clientIdsInt.Contains(O.ParentId)).Select(O => O.id).ToList().ToHashSet();
clientIdsInt.AddRange(clientIdList);
}
if (attachFiles.Contains("交易确认书"))
{
var tradeNumbers = report.CreatedModel.TradeList.Select(o => o.TradeNumber);
var ContractRs = DbContext.trade_contract_r.Where(o => o.IsValid && tradeNumbers.Contains(o.TradeNumber)).Select(o => o.ContractCode);
var TempDocuments = DbContext.trade_contract_document.Where(o => attachFiles.Contains(o.Type) && ContractRs.Contains(o.Code) && clientIdsInt.Contains(o.ClientId ?? 0)).ToList(); ;
documents.AddRange(TempDocuments);
var documentCodes = documents.Select(o => o.Code);
var contractr = DbContext.trade_contract_r.Where(o => o.IsValid && documentCodes.Contains(o.ContractCode));
var noDocsTrade = tradeNumbers.Concat(contractr.Select(o => o.TradeNumber)).Except(contractr.Select(o => o.TradeNumber));
if (noDocsTrade != null && noDocsTrade.Count() > 0)
{
message += string.Join(", ", noDocsTrade) + "未生成交易确认书!";
}
}
if (attachFiles.Contains("提前终止确认书"))
{
var tradeNumbers = report.FinishedModel.TradeList.Select(o => o.TradeNumber);
var ContractRs = DbContext.trade_contract_r.Where(o => o.IsValid && tradeNumbers.Contains(o.TradeNumber)).Select(o => o.ContractCode);
var TempDocuments = DbContext.trade_contract_document.Where(o => attachFiles.Contains(o.Type) && ContractRs.Contains(o.Code) && clientIdsInt.Contains(o.ClientId ?? 0)).ToList(); ;
documents.AddRange(TempDocuments);
var documentCodes = documents.Select(o => o.Code);
var contractr = DbContext.trade_contract_r.Where(o => o.IsValid && documentCodes.Contains(o.ContractCode));
var noDocsTrade = tradeNumbers.Concat(contractr.Select(o => o.TradeNumber)).Except(contractr.Select(o => o.TradeNumber));
if (noDocsTrade != null && noDocsTrade.Count() > 0)
{
message += string.Join(", ", noDocsTrade) + "未生成提前终止确认书!";
}
}
if (attachFiles.Contains("结算确认书"))
{
var tradeNumbers = report.MatureModel.TradeList.Select(o => o.TradeNumber);
var ContractRs = DbContext.trade_contract_r.Where(o => o.IsValid && tradeNumbers.Contains(o.TradeNumber)).Select(o => o.ContractCode);
var TempDocuments = DbContext.trade_contract_document.Where(o => attachFiles.Contains(o.Type) && ContractRs.Contains(o.Code) && clientIdsInt.Contains(o.ClientId ?? 0)).ToList(); ;
documents.AddRange(TempDocuments);
var documentCodes = documents.Select(o => o.Code);
var contractr = DbContext.trade_contract_r.Where(o => o.IsValid && documentCodes.Contains(o.ContractCode));
var noDocsTrade = tradeNumbers.Concat(contractr.Select(o => o.TradeNumber)).Except(contractr.Select(o => o.TradeNumber));
if (noDocsTrade != null && noDocsTrade.Count() > 0)
{
message += string.Join(", ", noDocsTrade) + "未生成结算确认书!";
}
}
if (!string.IsNullOrWhiteSpace(message) && !skip)
{
throw new Exception(message + "如需生成确认书请先取消(选择确认将发送含已生成文件的邮件,取消将结束发送邮件)!");
}
var attchFilePathes = documents.Select(o => o.Paths)
.ToHashSet(StringComparer.OrdinalIgnoreCase)
.Select(mapPath =>
{
if (!mapPath.StartsWith("/") && !mapPath.StartsWith("~/"))
{
mapPath = "/" + mapPath;
}
return OtcAppContext.MapPath(mapPath);
});
filePathes.AddRange(attchFilePathes);
}
var clientContacts = new ClientDBContext().clientduty.Where(x => x.ApprovalOrder < 1 && x.ClientId == req.ClientId
&& (x.DeadLine == null || x.DeadLine > DateTime.Now)
&& x.IsReceiveEmail.HasValue
&& x.IsReceiveEmail == 1).ToList();
var clientContactMails = new List<string>();
if (receiver != null && receiver.Count > 0)
{
foreach (var item in clientContacts)
{
var ids = item.ContactTypeId.Split(',');
if (ids.Intersect(receiver).Count() != 0)
{
clientContactMails.Add(item.Email);
}
}
}
else
{
clientContactMails = clientContacts.Select(o => o.Email).ToList();
}
var emails = DataConvert.EmailsSplitByComma(clientContactMails);
// var attachFiles = new List<string> { reportFilePath };
var startstr = req.StartDate.HasValue ? req.StartDate.Value.ToString("yyyy-MM-dd") : "";
var gh = req.StartDate.HasValue && req.EndDate.HasValue ? "-" : "";
var endstr = req.EndDate.HasValue ? req.EndDate.Value.ToString("yyyy-MM-dd") : "";
var endPart = (startstr == endstr) ? startstr : (startstr + gh + endstr);
var title = $"【{PS.Config.Company}】{report.ClientName}-场外交易确认-{endPart}";
//邮件标题格式 "【当前公司】"+ 客户名称 + "-场外交易确认-" + 确认日期或区间
var status = EmailTradeConfirmResultType.Succeed;
string sendMailMsg = null;
var ccemail = DBCacheManager.Single.GetStr(CacheTable.CCEmail, template);
var sendUser = DBCacheManager.Single.GetStr(CacheTable.TradeDetailsSendUser, template);
if (emails.All(o => string.IsNullOrWhiteSpace(o)))
{
status = EmailTradeConfirmResultType.NoEmailSetting;
}
else
{
emails = emails.Where(o => !string.IsNullOrWhiteSpace(o));
if (!string.IsNullOrWhiteSpace(AppendixType))
{
sendMailMsg = EmailHelper.SendMail(string.Join(";", emails), $"{report.ClientAbbreviation ?? ""}{title}", $"{luoKuan}", true, filePathes, ccemail, mailFrom: sendUser);
}
else
{
sendMailMsg = EmailHelper.SendMail(string.Join(";", emails), $"{report.ClientAbbreviation ?? ""}{title}", $"{luoKuan}", true, null, ccemail, mailFrom: sendUser);
}
if (!string.IsNullOrEmpty(sendMailMsg))
{
status = EmailTradeConfirmResultType.EmailSentFailed;
}
}
return new SendTradeDetailReportResult
{
ResultType = status,
ErrorMsg = sendMailMsg
};
}
/// <summary>
/// 根据交易编号获取otctradefull(组合标的名义本金在方法内做了转换)
/// </summary>
public OtcOptionTradeFull GetOtcTradeFull(string tradeNumber)
{
if (string.IsNullOrWhiteSpace(tradeNumber))
{
return null;
}
var dbTrade = DbContext.trade.FirstOrDefault(n => n.TradeNumber == tradeNumber);
return FromDbTrade(dbTrade);
}
/// <summary>
/// 根据交易编号获取otctradefull(组合标的名义本金在方法内做了转换)
/// </summary>
public OtcOptionTradeFull GetOtcTradeFull(int id)
{
if (id < 1)
{
return null;
}
var dbTrade = DbContext.trade.FirstOrDefault(n => n.id == id);
return FromDbTrade(dbTrade);
}
public OtcOptionTradeFull FromDbTrade(OtcTradeBase dbTrade, bool IsExtendFromDb = true)
{
if (dbTrade == null)
{
return null;
}
var otcTrade = new OtcOptionTradeFull();
YLAutoMapper.Map<OtcTradeBase, OtcTradeBase>(dbTrade, otcTrade);
if (IsExtendFromDb)
{
new TradeExtendService(this).SetTradeExtend(new[] { otcTrade });
}
otcTrade.ClientNumber = ClientModule.ClientDataQueryService.GetClient(otcTrade.ClientId)?.Number;
otcTrade.MetaDic = new TradeMetaService(this).GetTradeMeta(otcTrade.id);
if (otcTrade.MetaDic.ContainsKey("MidVol") && double.TryParse(otcTrade.MetaDic["MidVol"], out var midvol))
{
otcTrade.MidVol = midvol;
}
if (otcTrade.MetaDic.ContainsKey("Day1Pnl") && double.TryParse(otcTrade.MetaDic["Day1Pnl"], out var day1pnl))
{
otcTrade.Day1Pnl = day1pnl;
}
if (otcTrade.MetaDic.ContainsKey("ExchangeRate") && double.TryParse(otcTrade.MetaDic["ExchangeRate"], out var exchangeRate))
{
otcTrade.ExchangeRate = exchangeRate;
}
if (otcTrade.CountRatio == null || otcTrade.CountRatio.Value < 1)
{
otcTrade.CountRatio = DataCacheProvider.GetUnderlyingDataSource().GetData(otcTrade.UnderlyingCode)?.CountRatio ?? 1;
}
if (PS.Config.ErpElement.AccumulatorShowMultiplier1)
{
otcTrade.StrikeGearingFactor = otcTrade.OptionType == "看涨" ? otcTrade?.PutMultiplier : otcTrade?.CallMultiplier;
}
return otcTrade;
}
}
/// <summary>
/// 交易详情查询(根据客户)
/// </summary>
public class TradeDetailsReq : BaseSearchReq
{
/// <summary>
/// 客户ID
/// </summary>
public int ClientId { get; set; }
/// <summary>
/// 客户ID列表
/// </summary>
public string ClientIds { get; set; }
public List<int> ClientIdsInt
{
get
{
if (string.IsNullOrEmpty(ClientIds))
{
return new List<int>();
}
return (ClientIds + "").Split(',').Select(c => Convert.ToInt32(c)).ToList();
}
}
/// <summary>
/// 开始日期
/// </summary>
public DateTime? StartDate { get; set; }
/// <summary>
/// 结束日期
/// </summary>
public DateTime? EndDate { get; set; }
/// <summary>
/// 交易状态
/// </summary>
public string DetailStatuses { get; set; }
/// <summary>
/// 交易类型
/// </summary>
public List<string> TradeTypes { get; set; }
public string StructureType { get; set; }
/// <summary>
/// 批量下载结算报告/交易明细时,所在的文件夹路径
/// </summary>
public string OutputFolder { get; set; }
/// <summary>
/// 用户关联的簿记账户(适用于有用户组的场景)
/// </summary>
public IEnumerable<int> UserAssetUnits { get; set; }
/// <summary>
/// 分组TradeId
/// </summary>
public int GroupTradeId { get; set; }
/// <summary>
/// 文件类型
/// <para>仅支持pdf和xlsx</para>
/// </summary>
public string fileType { get; set; }
/// <summary>
/// 是否包含子级账户
/// </summary>
public bool ParentFlag { get; set; }
public TradeDetailsReq Clone()
{
return (TradeDetailsReq)MemberwiseClone();
}
}
public class SendTradeDetailReportResult
{
public string ErrorMsg { get; set; }
public EmailTradeConfirmResultType ResultType { get; set; }
}
}