Files
zszq-trs/YLErpWeb/Controllers/trade_spanController.cs
T
hjhan d3e576b0e5 feat(kafka): 添加实时资金计算topic配置
- 在多个环境配置文件中新增RealtimeCalcAccountBalance配置项
- 移除ClientBalanceForTrsResponse中的冗余字段
- 更新Kafka任务和控制器中相关字段引用
- 修改Producer发送的目标topic为新的实时计算topic
2025-12-17 10:05:57 +08:00

905 lines
40 KiB
C#

using iTextSharp.text;
using iTextSharp.text.pdf;
using Microsoft.AspNetCore.Authorization;
using System.Text;
using YLErp.BLL.Eod;
using YLErp.Cache;
using YLErp.DBModels;
using YLErp.DBModels.Consts;
using YLErp.Enums;
using YLErp.Modules.ClientCashModule;
using YLErp.Modules.ClientModule;
using YLErp.Modules.EodModule;
using YLErp.Modules.TradeModule.DocGenerateModule;
using YLErp.Modules.TradeModule.QueryModule;
using YLErp.Modules.TradeModule.SwapModule;
using static YLErp.BLL.Eod.RealTimeClientBanlanceService;
namespace YLErp.Web.Controllers
{
public class trade_spanController : BaseController
{
IYLCache _yLCache;
public trade_spanController(IYLCache yLCache)
{
_yLCache = yLCache;
}
public JsonResult GeneratePaymentDoc(List<int> tradeIds, DateTime? valueDate)
{
if (tradeIds == null || tradeIds.Count == 0)
{
return JsonError("请勾选交易");
}
if (valueDate == null)
{
valueDate = valuedateBLL.ValueDate;
}
var results = new MarginReportGenerateService(CurUser).Generate(tradeIds, valueDate, "PDF");
var errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray();
var files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToArray();
if (errors.Any())
{
return JsonError(string.Join("\r\n", errors.AsEnumerable()), files);
}
return JsonSuccess("生成成功", files);
}
public JsonResult SendMailPaymentDoc(List<int> tradeIds, DateTime? valueDate)
{
if (tradeIds == null || tradeIds.Count == 0)
{
return JsonError("请勾选交易");
}
if (valueDate == null)
{
valueDate = valuedateBLL.ValueDate;
}
var clientTradesDic = yldb.trade.Where(t => tradeIds.Contains(t.id)).AsEnumerable().GroupBy(t => t.ClientId).ToDictionary(g => g.Key, g => g.ToList());
var contractDocList = (from tcr in yldb.trade_contract_r
join tcd in yldb.trade_contract_document
on tcr.ContractCode equals tcd.Code
where tcd.Type == ContractTypeEnum.Margin && tcd.ValueDate == valueDate && tradeIds.Contains(tcr.TradeId) && tcr.Type == tcd.Type && tcr.IsValid
select new
{
tcr.TradeId,
tcr.TradeNumber,
contractDoc = tcd
}).ToList();
if (clientTradesDic.Count > 0)
{
var errorMsg = new List<string>();
foreach (var clientTrades in clientTradesDic)
{
var clientContractList = contractDocList.Where(c => clientTrades.Value.Select(t => t.id).Contains(c.TradeId)).ToList();
var fileList = clientContractList.Select(c => c.contractDoc.AbsolutePath).ToList();
// 要向该客户的所有订阅了邮件通知的人员发送邮件
//var clientContactMails = db.clientduty.Where(x => x.ClientId == clientTrades.Key && x.IsReceiveEmail.HasValue && x.IsReceiveEmail == 1).Select(x => x.Email).ToList();
var emails = ClientDataQueryService.GetClientEmails(clientTrades.Key, false);
var sendMail = EmailHelper.SendMail(string.Join(";", emails), $"追加合格履约保障品通知", "", true, fileList.ToArray());
if (!string.IsNullOrEmpty(sendMail))
{
if (!errorMsg.Contains(sendMail))
{
errorMsg.Add(sendMail);
}
}
}
if (errorMsg.Count > 0)
{
return JsonError(string.Join("<br/>", errorMsg));
}
}
return JsonSuccess("发送追保通知书成功!");
}
/// <summary>
/// 根据日期查询客户的资金结算信息(客户历史资金状况?)
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
[HttpPost]
public JsonResult clientBalanceQuery(TradeSpanReq req)
{
return Json(clientBalanceQueryJson(req));
}
/// <summary>
/// 查询客户最新的资金结算信息(资金状况)
/// </summary>
[HttpPost]
public JsonResult GetClientLatestBalance(DateTime? ValueDateFrom, DateTime? ValueDateTo, int clientId, bool IsClientBalanceGap = false, bool IsGetOuterMarginGap = false, bool ParentFlag = false)
{
CurUser.CheckClientPowerByClientId(clientId);
var cb = ClientAssetDataService.GetClientLatestBalance(ValueDateFrom, ValueDateTo, clientId, IsClientBalanceGap, IsGetOuterMarginGap, ParentFlag);
return Json(cb);
}
/// <summary>
/// 查询客户最新可用资金
/// </summary>
/// <param name="clientId"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpGet]
public JsonResult GetClientBalance(int clientId)
{
if (clientId<=0)
{
return JsonError("找不到该客户");
}
var cb = ClientAssetDataService.GetClientLatestBalance(null, DateTime.Now.Date, clientId, false, false, false);
var obj = new ClientBalanceForTrsResponse
{
AvailableAmount = Math.Round(cb.AvailableAmount,2),
PositionPv = cb.RoundedPositionPv,
PositionPnl = cb.RoundedPositionPnl,
Credit =cb.TotalCredit
};
return JsonSuccess("", obj);
}
/// <summary>
/// trs计算客户下单后可用资金
/// </summary>
/// <param name="calcReqs"></param>
/// <returns></returns>
[AllowAnonymous]
[HttpPost]
public JsonResult CalcClientTradeAvailableAmount([FromBody] List<TradeClientCashCalcReq> calcReqs)
{
if (calcReqs.Count() == 0)
{
return JsonError("缺少参数");
}
var clientIds = calcReqs.Select(s => s.clientId).ToList();
Dictionary<int, ClientBalanceEx> clientBalanceDic = new Dictionary<int, ClientBalanceEx>();
foreach (var clientId in clientIds)
{
var client = DataCacheProvider.GetClientDataSource().GetData(clientId);
if (client == null)
{
continue;
}
clientBalanceDic[clientId] = new ClientBalanceEx
{
ClientId = clientId,
IsTradeCredit = client?.IsTradeCredit == 1,
MarginOptionType = client?.MarginOptionType,
CreditCanApplySwap = client.creditCanApplySwap,
TotalCreditStockEqvNotional = double.NaN,
SettlementCurrency = client?.SettlementCurrency,
ClientType = client.SwapTradeType ?? 0,
ClientName = client.Name
};
}
List<swap_flow> bondFlows = new List<swap_flow>();
foreach (var item in calcReqs)
{
swap_flow flow = new swap_flow()
{
BsType = item.side + 1,
UnderlyingCode = item.underlyingCode,
ClientId = item.clientId,
TradingQty = item.tradingQty,
TradingAmountAvg = item.price,
TradingAmountFeeAvg = item.price
};
bondFlows.Add(flow);
}
new RealTimeClientBanlanceService(new OptUserInfo(0, "计算客户资金变化服务", OptUserFrom.Service)).ProcessClientFrozen(valuedateBLL.ValueDate, bondFlows, clientBalanceDic);
List<TradeClientCashCalcResp> list = new List<TradeClientCashCalcResp>();
foreach (var item in clientBalanceDic)
{
TradeClientCashCalcResp tradeClientCashCalc = new TradeClientCashCalcResp()
{
clientId = item.Key
};
var clientBalanceCache = _yLCache.StringGet<ClientBalanceForTrsResponse>("ClientBalance:" + item.Key);
var availableMoney = clientBalanceCache?.AvailableMoney ?? 0;
tradeClientCashCalc.availableAmount = availableMoney - item.Value.FrozenMarginMoney;
tradeClientCashCalc.availableAmount = Math.Round(tradeClientCashCalc.availableAmount, 2, MidpointRounding.AwayFromZero);
list.Add(tradeClientCashCalc);
}
return JsonSuccess("", list);
}
public Dictionary<string, object> clientBalanceQueryJson(TradeSpanReq req)
{
//按客户日期查询trade_span信息
var clientReq = new ClientSpanReq
{
ClientId = req.ClientId,
ValueDate = req.ValueDate
};
var clientSpanBll = new ClientSpanQueryService(CurUser);
var clientSpans = clientSpanBll.GetClientSpanList(clientReq);
//获取今日客户结算的balance记录
var clientBalanceReq = new ClientBalanceReq
{
ClientId = req.ClientId,
BalanceDate = req.ValueDate
};
var clientbalanceBLL = new ClientBalanceService(CurUser);
var clientBalances = clientbalanceBLL.GetClientBalanceList(clientBalanceReq);
var data = new Dictionary<string, object>();
ClientSpan clientSpan = null;
if (clientSpans != null && clientSpans.Count > 0)
{
clientSpan = clientSpans.First();
data.Add("ClientSpan", clientSpan);
}
if (clientBalances != null && clientBalances.Count > 0)
{
var clientBalance = clientBalances.First();
var bll = new EodPnlBLL();
var eodPositions = bll.GetPositionList(req);
clientBalance.Amount = (clientBalance.ToDayRemainFund ?? 0) + (clientBalance.FrozenBalance ?? 0);
if (eodPositions != null && eodPositions.Count > 0)
{
clientBalance.Amount += double.Parse(((eodPositions.Sum(t => t.Pv) ?? 0) * -1).ToString());
}
var resultClientBalance = clientbalanceStatistics.TransferFromClientbalancedaily(clientBalance);
//由于计算的 WorstCastClientPayable 是带方向的所以 为加
resultClientBalance.AvailableFund = resultClientBalance.ToDayRemainFund + (clientSpan == null ? 0 : clientSpan.WorstCastClientPayable) - resultClientBalance.FrozenMarginMoney;
if ((resultClientBalance.AvailableFund ?? 0) < 0)
{
resultClientBalance.CreditRatio = resultClientBalance.Credit.Value == 0.0
? 0
: Math.Abs((resultClientBalance.AvailableFund ?? 0) * 100 / resultClientBalance.Credit.Value);
}
data.Add("ClientBalance", resultClientBalance);
}
return data;
}
[HttpPost]
public JsonResult GetPositionAndHistoryTotalNumber(DateTime? ValueDateFrom, DateTime? ValueDateTo, int clientId)
{
var eod_pnlbll = new EodPnlBLL();
var positionListNumber = eod_pnlbll.SearchPositionCount(clientId, ValueDateTo ?? DateTime.MaxValue);
var positionSwapListNumber = eod_pnlbll.SearchSwapPositionCount(clientId, ValueDateTo ?? DateTime.MaxValue);
var treq = new TradeReq() { ClientId = clientId, ValueDateStart = ValueDateFrom ?? DateTime.MinValue, ValueDateEnd = ValueDateTo ?? DateTime.Now };
treq.NotInTradeTypes = new List<string>() { "收益互换" };
var historyListNumber = new TradeHistoryQueryService(CurUser).SearchHistoryCount(treq);
treq.NotInTradeTypes = null;
treq.TradeTypes = "收益互换";
var historySwapListNumber = new TradeHistoryQueryService(CurUser).SearchHistoryCount(treq);
if (PS.Config.IsGuoJun)
{
positionSwapListNumber = new EodSwapPositionMannualService(CurUser).SearchPositionCount(clientId, ValueDateTo ?? DateTime.MaxValue);
historySwapListNumber = new TradeSwapService(CurUser).SearchFlowMoreCount(clientId, ValueDateFrom ?? DateTime.MinValue, ValueDateTo ?? DateTime.MaxValue);
}
return Json(new { PostionListNumber = positionListNumber, PositionSwapListNumber = positionSwapListNumber, HistoryListNumber = historyListNumber, HistorySwapListNumber = historySwapListNumber });
}
/// <summary>
/// 客户持仓查询
/// </summary>
[HttpPost]
public JsonResult clientTradePositionQuery(TradeSpanReq req)
{
try
{
CurUser.CheckClientPowerByClientId(req.ClientId ?? 0);
IEnumerable<int> userAssetUnits = null;
if (ConsUserGroup.HasGroup && !ShowAllTrades)
{
userAssetUnits = GetUserAssetunitIds();
}
if (req.TradeTypes == null || !req.TradeTypes.Any())
{
req.NotInTradeTypes = new List<string> { "收益互换" };
}
req.BookIds = AssetUnitModel.IntersectAssetUnits(req.AssetIdGroupList, req.BookIds).ToList();
var result = new ClientPositionQueryService(CurUser) { NeedTradeContractCode = false }.SearchPositionList(req, userAssetUnits);
return Json(result);
}
catch (Exception ex)
{
LogFactory.GetLogger("clientTradePositionQuery").Error(ex);
throw;
}
}
/// <summary>
/// 客户持仓查询
/// </summary>
[HttpPost]
public JsonResult clientTradePositionChildrenQuery(TradeSpanReq req)
{
try
{
CurUser.CheckClientPowerByClientId(req.ClientId ?? 0);
IEnumerable<int> userAssetUnits = null;
if (ConsUserGroup.HasGroup && !ShowAllTrades)
{
userAssetUnits = GetUserAssetunitIds();
}
if (req.TradeTypes == null || !req.TradeTypes.Any())
{
req.NotInTradeTypes = new List<string> { "收益互换" };
}
req.BookIds = AssetUnitModel.IntersectAssetUnits(req.AssetIdGroupList, req.BookIds).ToList();
var result = new ClientPositionQueryService(CurUser) { NeedTradeContractCode = false }.SearchPositionChildrenList(req, userAssetUnits);
return Json(result);
}
catch (Exception ex)
{
LogFactory.GetLogger("clientTradePositionQuery").Error(ex);
throw;
}
}
public List<eod_position> clientTradePositionList(TradeSpanReq req, IEnumerable<int> userAssetUnits)
{
if (req.ClientId == null || req.ValueDate == null)
{
return new List<eod_position>(0);
}
var presidx = req.sidx;
var preorder = req.sord;
var resultList = new ClientPositionQueryService(CurUser).SearchPositionListAll(req, userAssetUnits);
//假排序
if ("ExerciseDate" == presidx)
{
resultList = preorder == "asc"
? resultList.OrderBy(r => r.ExerciseDate).ToList()
: resultList.OrderByDescending(r => r.ExerciseDate).ToList();
}
if ("TradeDate" == presidx)
{
resultList = preorder == "asc" ? resultList.OrderBy(r => r.TradeDate).ToList() : resultList.OrderByDescending(r => r.TradeDate).ToList();
}
return resultList;
}
[HttpPost]
public JsonResult SendReport(TradeSpanReq req)
{
IEnumerable<int> userAssetUnits = null;
if (ConsUserGroup.HasGroup && !ShowAllTrades)
{
userAssetUnits = GetUserAssetunitIds();
}
switch (DoSendReport(req, userAssetUnits))
{
case EmailTradeConfirmResultType.Succeed:
return JsonSuccess("发送成功");
case EmailTradeConfirmResultType.TradeQueryFailed:
return JsonError("查询该交易失败");
case EmailTradeConfirmResultType.NoEmailSetting:
return JsonError("未设置邮箱,无法发送");
case EmailTradeConfirmResultType.EmailSentFailed:
return JsonError("发送失败");
case EmailTradeConfirmResultType.Other:
default:
return JsonError("发送邮件未知错误");
}
}
public EmailTradeConfirmResultType DoSendReport(TradeSpanReq req, IEnumerable<int> userAssetUnits)
{
var document = new Document(PageSize.A4);
try
{
//预付金计算 和 资金状况
var data1 = clientBalanceQueryJson(req);
double? spv1 = null;
double? spv2 = null;
double? spv3 = null;
double? spv4 = null;
double? worstCastClientPayable = null;
if (data1.ContainsKey("ClientSpan"))
{
var clientSpan = (ClientSpan)data1["ClientSpan"];
spv1 = clientSpan.Spv1;
spv2 = clientSpan.Spv2;
spv3 = clientSpan.Spv3;
spv4 = clientSpan.Spv4;
worstCastClientPayable = clientSpan.WorstCastClientPayable;
}
double? inFund = null;
double? optionPremium = null;
double? settlementBalance = null;
double? outFund = null;
double? todayRemainFund = null;
double? worstCastClientPayable2 = null;
double? worstCastClientPayable3 = null;
double? credit = null;
double? creditRatio = null; //%
double? margin = null;
double? amount = null;
if (data1.ContainsKey("ClientBalance"))
{
var clientBalance = (clientbalanceStatistics)data1["ClientBalance"];
inFund = clientBalance.InFund;
optionPremium = clientBalance.OptionPremium;
settlementBalance = clientBalance.SettlementBalance;
outFund = clientBalance.OutFund;
todayRemainFund = Math.Floor((clientBalance.ToDayRemainFund ?? 0) * 100) / 100.0;
worstCastClientPayable2 = Math.Floor((worstCastClientPayable ?? 0.0) * 100) / 100.0;
worstCastClientPayable3 = todayRemainFund + worstCastClientPayable2;
credit = clientBalance.Credit;
creditRatio = clientBalance.CreditRatio; //%
margin = clientBalance.Margin;
amount = Math.Floor((clientBalance.Amount ?? 0) * 100) / 100.0;
}
//持仓交易
var data2 = clientTradePositionList(req, userAssetUnits);
//设置文件名称
var saveFileDir = Server.MapPath("~/App_Docs/tradeSpan");
if (!Directory.Exists(saveFileDir))
{
Directory.CreateDirectory(saveFileDir);
}
var clientName = "客户名称";
var client = ClientDataQueryService.GetClient(req.ClientId ?? 0);
if (client != null)
{
clientName = client.Name;
}
var fileName = $"客户持仓报告-{clientName}-{req.ValueDate.Value:yyyy-MM-dd}.pdf";
var filePath = Path.Combine(saveFileDir, fileName);
PdfWriter.GetInstance(document, new FileStream(filePath, FileMode.Create));
document.Open();
var bftitle = BaseFont.CreateFont("C:\\Windows\\Fonts\\SIMHEI.TTF", BaseFont.IDENTITY_H,
BaseFont.NOT_EMBEDDED); //用系统中的字体文件SimHei.ttf创建文件字体
var fonttitle = new iTextSharp.text.Font(bftitle, 6);
//添加标题
//Paragraph Title = new Paragraph("示例文件", fonttitle); //添加段落,第二个参数指定使用fonttitle格式的字体,写入中文必须指定字体否则无法显示中文
var paragraph1 = new Paragraph($"{PS.Config.CompanyName} 客户结算单", fonttitle)
{
Alignment = Element.ALIGN_LEFT,
SpacingAfter = 1.5f
};
document.Add(paragraph1);
paragraph1 = new Paragraph($"客户名称:{clientName}", fonttitle)
{
Alignment = Element.ALIGN_LEFT,
SpacingAfter = 1.5f
};
document.Add(paragraph1);
paragraph1 = new Paragraph($"结算日期:{req.ValueDate.Value:yyyy-MM-dd}", fonttitle)
{
Alignment = Element.ALIGN_LEFT,
SpacingAfter = 1.5f
};
document.Add(paragraph1);
var paragraph = new Paragraph("资金状况", fonttitle)
{
Alignment = Element.ALIGN_CENTER,
SpacingAfter = 10
};
//paragraph.SpacingBefore = 30;
document.Add(paragraph);
var table2 = new PdfPTable(11);
table2.AddCell(new Phrase("今日入金", fonttitle));
table2.AddCell(new Phrase("期权费支出", fonttitle));
table2.AddCell(new Phrase("结算收支", fonttitle));
table2.AddCell(new Phrase("今日出金", fonttitle));
table2.AddCell(new Phrase("账户现金", fonttitle));
table2.AddCell(new Phrase("维持预付金", fonttitle));
table2.AddCell(new Phrase("可用资金", fonttitle));
table2.AddCell(new Phrase("授信额度", fonttitle));
table2.AddCell(new Phrase("授信占用", fonttitle));
table2.AddCell(new Phrase("追保金额", fonttitle));
table2.AddCell(new Phrase("客户权益", fonttitle));
table2.AddCell(new Phrase($"{inFund ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{optionPremium ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{settlementBalance ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{outFund ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{todayRemainFund ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{worstCastClientPayable2 ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{worstCastClientPayable3 ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{credit ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{creditRatio ?? 0.0:F}%", fonttitle));
table2.AddCell(new Phrase($"{margin ?? 0.0:F}", fonttitle));
table2.AddCell(new Phrase($"{amount ?? 0.0:F}", fonttitle));
document.Add(table2);
//string comments = @"1.期权收支:负数表示客户支付期权费,正数表示客户收到期权费\r\n 2.结算收支:负数表示客户期权结算指出,正数表示客户期权结算收入\r\n 3.持仓量:负数表示客户卖出期权,正数表示客户买入期权";
//paragraph = new iTextSharp.text.Paragraph(comments, fonttitle);
var one = "1.期权收支:负数表示客户支付期权费,正数表示客户收到期权费";
var two = "2.结算收支:负数表示客户期权结算支出,正数表示客户期权结算收入";
var three = "3.持仓量:负数表示客户卖出期权,正数表示客户买入期权";
var four = "4.可用资金 = 账户现金 + 维持预付金,正数表示客户可以出金的金额";
var five = "5.追保金额 = -min(可用资金 + 授信额度, 0)";
var six = "6.客户权益 = 账户现金 + 持仓市值";
var seven = "7.账户现金 = 昨日账户现金 + 今日入金 + 期权费收支 + 结算费收支 - 今日出金";
float indentationLeft = 50;
paragraph = new iTextSharp.text.Paragraph(one, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new Paragraph(two, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new iTextSharp.text.Paragraph(three, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new iTextSharp.text.Paragraph(four, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new Paragraph(five, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new Paragraph(six, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new Paragraph(seven, fonttitle)
{
IndentationLeft = indentationLeft
};
document.Add(paragraph);
paragraph = new Paragraph("持仓交易", fonttitle)
{
Alignment = Element.ALIGN_CENTER,
SpacingAfter = 10,
SpacingBefore = 30
};
document.Add(paragraph);
var table3 = new PdfPTable(12);
table3.AddCell(new Phrase("交易编号", fonttitle));
table3.AddCell(new Phrase("交易日", fonttitle));
table3.AddCell(new Phrase("期权类型", fonttitle));
table3.AddCell(new Phrase("标的合约", fonttitle));
table3.AddCell(new Phrase("标的当前价格", fonttitle));
table3.AddCell(new Phrase("到期日", fonttitle));
table3.AddCell(new Phrase("持仓量", fonttitle));
table3.AddCell(new Phrase("期权成交价", fonttitle));
table3.AddCell(new Phrase("期权现价", fonttitle));
table3.AddCell(new Phrase("持仓市值", fonttitle));
table3.AddCell(new Phrase("浮动盈亏", fonttitle));
table3.AddCell(new Phrase("名义本金", fonttitle));
foreach (var position in data2)
{
table3.AddCell(new Phrase($"{position.TradeNumber}", fonttitle));
if (position.TradeDate != null)
{
table3.AddCell(new Phrase($"{position.TradeDate.Value:yyyy-MM-dd}", fonttitle));
}
else
{
table3.AddCell(new Phrase($"", fonttitle));
}
if (!string.IsNullOrEmpty(position.ExerciseMode))
{
if (position.ExerciseMode == "European")
{
table3.AddCell(new Phrase($"欧式", fonttitle));
}
else if (position.ExerciseMode == "American")
{
table3.AddCell(new Phrase($"美式", fonttitle));
}
else
{
table3.AddCell(new Phrase($"", fonttitle));
}
}
else
{
table3.AddCell(new Phrase($"", fonttitle));
}
table3.AddCell(new Phrase($"{position.UnderlyingCode}", fonttitle));
table3.AddCell(new Phrase($"{position.UnderlyingPrice ?? 0.0:F}", fonttitle));
if (position.ExerciseDate != null)
{
table3.AddCell(new Phrase($"{position.ExerciseDate.Value:yyyy-MM-dd}", fonttitle));
}
else
{
table3.AddCell(new Phrase($"", fonttitle));
}
table3.AddCell(new Phrase($"{position.Notional:F}", fonttitle));
table3.AddCell(new Phrase($"{position.TradePrice ?? 0.0:F}", fonttitle));
table3.AddCell(new Phrase($"{position.CurrentPrice ?? 0.0:F}", fonttitle));
table3.AddCell(new Phrase($"{position.Pv ?? 0:F}", fonttitle));
table3.AddCell(new Phrase($"{position.Pnl ?? 0:F}", fonttitle));
table3.AddCell(new Phrase($"{position.StockEqvNotional ?? 0.0:F}", fonttitle));
}
table3.AddCell(new Phrase(" 合计: ", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase("", fonttitle));
table3.AddCell(new Phrase($"{data2.Sum(x => x.Pv) ?? 0:F}", fonttitle));
table3.AddCell(new Phrase($"{data2.Sum(x => x.Pnl) ?? 0:F}", fonttitle));
table3.AddCell(new Phrase($"{data2.Sum(x => x.StockEqvNotional) ?? 0.0:F}", fonttitle));
document.Add(table3);
document.Close();
var bodyhtmlSb = new StringBuilder();
bodyhtmlSb.Append("<meta http-equiv='Content-Type' content='text/html;charset=utf-8'/>")
.Append($"<p><h2>{PS.Config.CompanyName} 客户结算单</h2></p>")
.Append($"<p><h2>客户名称:{clientName}</h2></p>")
.Append($"<p><h2>结算日期:{req.ValueDate.Value:yyyy-MM-dd}</h2></p>");
#region 预付金计算mail pass
//bodyhtml.Append("<h3>预付金计算</h3>");
//bodyhtml.Append("<table border='1'>");
//bodyhtml.Append("<tr>");
//bodyhtml.Append(" <th> 标的价格*(1+a)&波动率 </th>");
//bodyhtml.Append(" <th> 标的价格*(1+a)&波动率*(1+b) </th>");
//bodyhtml.Append(" <th> 标的价格*(1-a)&波动率 </th>");
//bodyhtml.Append(" <th> 标的价格*(1-a)&波动率*(1+b) </th>");
//bodyhtml.Append(" <th> 维持预付金 </th>");
//bodyhtml.Append(" </tr>");
//bodyhtml.Append(" <tr>");
//bodyhtml.Append($" <td>{spv1:F}</td>");
//bodyhtml.Append($" <td>{spv2:F}</td>");
//bodyhtml.Append($" <td>{spv3:F}</td>");
//bodyhtml.Append($" <td>{spv4:F}</td>");
//bodyhtml.Append($" <td>{worstCastClientPayable:F}</td>");
//bodyhtml.Append(" </tr>");
//bodyhtml.Append("</table>");
#endregion
bodyhtmlSb.Append("<h3>资金状况</h3>");
bodyhtmlSb.Append("<table border='1'>");
bodyhtmlSb.Append("<tr>");
bodyhtmlSb.Append(" <th> 今日入金 </th>");
bodyhtmlSb.Append(" <th> 期权费收支</th>");
bodyhtmlSb.Append(" <th> 结算收支 </th>");
bodyhtmlSb.Append(" <th> 今日出金 </th>");
bodyhtmlSb.Append(" <th> 账户现金</th>");
bodyhtmlSb.Append(" <th> 维持预付金</th>");
bodyhtmlSb.Append(" <th> 可用资金</th>");
bodyhtmlSb.Append(" <th> 授信额度</th>");
bodyhtmlSb.Append(" <th> 授信占用</th>");
bodyhtmlSb.Append(" <th> 追保金额</th>");
bodyhtmlSb.Append(" <th> 客户权益</th>");
bodyhtmlSb.Append(" </tr>");
bodyhtmlSb.Append(" <tr>");
bodyhtmlSb.Append($" <td>{inFund ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{optionPremium ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{settlementBalance ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{outFund ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{todayRemainFund ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{worstCastClientPayable2 ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{worstCastClientPayable3 ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{credit ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{creditRatio ?? 0.0:F}" + (creditRatio.HasValue ? "%</td>" : "</td>"));
bodyhtmlSb.Append($" <td>{margin ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{amount ?? 0.0:F}</td>");
bodyhtmlSb.Append(" </tr>");
bodyhtmlSb.Append("</table>");
bodyhtmlSb.Append($"<p></p>");
bodyhtmlSb.Append($"<p>{one}</p>");
bodyhtmlSb.Append($"<p>{two}</p>");
bodyhtmlSb.Append($"<p>{three}</p>");
bodyhtmlSb.Append($"<p>{four}</p>");
bodyhtmlSb.Append($"<p>{five}</p>");
bodyhtmlSb.Append($"<p>{six}</p>");
bodyhtmlSb.Append($"<p>{seven}</p>");
bodyhtmlSb.Append($"<p></p>");
bodyhtmlSb.Append("<h3>持仓交易</h3>");
bodyhtmlSb.Append("<table border='1'>");
bodyhtmlSb.Append("<tr>");
bodyhtmlSb.Append(" <th> 交易编号 </th>");
bodyhtmlSb.Append(" <th> 交易日</th>");
bodyhtmlSb.Append(" <th> 期权类型</th>");
bodyhtmlSb.Append(" <th> 标的合约</th>");
bodyhtmlSb.Append(" <th> 标的当前价格</th>");
bodyhtmlSb.Append(" <th> 到期日</th>");
bodyhtmlSb.Append(" <th> 持仓量</th>");
bodyhtmlSb.Append(" <th> 期权成交价</th>");
bodyhtmlSb.Append(" <th> 期权现价</th>");
bodyhtmlSb.Append(" <th> 持仓市值</th>");
bodyhtmlSb.Append(" <th> 浮动盈亏</th>");
bodyhtmlSb.Append(" <th> 名义本金</th>");
bodyhtmlSb.Append(" </tr>");
foreach (var position in data2)
{
bodyhtmlSb.Append(" <tr>");
bodyhtmlSb.Append($" <td>{position.TradeNumber}</td>");
if (position.TradeDate != null)
{
bodyhtmlSb.Append($" <td>{position.TradeDate.Value:yyyy-MM-dd}</td>");
}
else
{
bodyhtmlSb.Append(" <td></td>");
}
if (!string.IsNullOrEmpty(position.ExerciseMode))
{
if (position.ExerciseMode == "European")
{
bodyhtmlSb.Append(" <td>欧式</td>");
}
else if (position.ExerciseMode == "American")
{
bodyhtmlSb.Append(" <td>美式</td>");
}
else
{
bodyhtmlSb.Append(" <td></td>");
}
}
else
{
bodyhtmlSb.Append(" <td></td>");
}
bodyhtmlSb.Append($" <td>{position.UnderlyingCode}</td>");
bodyhtmlSb.Append($" <td>{position.UnderlyingPrice ?? 0.0:F}</td>");
if (position.ExerciseDate != null)
{
bodyhtmlSb.Append($" <td>{position.ExerciseDate.Value:yyyy-MM-dd}</td>");
}
else
{
bodyhtmlSb.Append($" <td></td>");
}
bodyhtmlSb.Append($" <td>{position.Notional ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{position.TradePrice ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{position.CurrentPrice ?? 0.0:F}</td>");
bodyhtmlSb.Append($" <td>{position.Pv ?? 0:F}</td>");
bodyhtmlSb.Append($" <td>{position.Pnl ?? 0:F}</td>");
bodyhtmlSb.Append($" <td>{position.StockEqvNotional ?? 0.0:F}</td>");
bodyhtmlSb.Append(" </tr>");
}
bodyhtmlSb.Append("<tr>");
bodyhtmlSb.Append(" <td style='text-align:center'>合计:</td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append(" <td></td>");
bodyhtmlSb.Append($" <td> {data2.Sum(x => x.Pv) ?? 0:F}</td>");
bodyhtmlSb.Append($" <td> {data2.Sum(x => x.Pnl) ?? 0:F}</td>");
bodyhtmlSb.Append($" <td> {data2.Sum(x => x.StockEqvNotional) ?? 0.0:F}</td>");
bodyhtmlSb.Append(" </tr>");
bodyhtmlSb.Append("</table>");
// 要向该客户的所有订阅了邮件通知的人员发送邮件
var emails = ClientDataQueryService.GetClientEmails(req.ClientId ?? 0, false);
var status = EmailTradeConfirmResultType.Succeed;
if (!emails.Any())
{
return EmailTradeConfirmResultType.NoEmailSetting;
}
var bodyhtml = bodyhtmlSb.ToString();
foreach (var email in emails)
{
if (string.IsNullOrEmpty(email))
{
return EmailTradeConfirmResultType.NoEmailSetting;
}
}
if (status == EmailTradeConfirmResultType.Succeed)
{
var sendMail = EmailHelper.SendMail(string.Join(";", emails), "客户持仓报告", bodyhtml, true, new[] { filePath });
if (!string.IsNullOrEmpty(sendMail))
{
status = EmailTradeConfirmResultType.EmailSentFailed;
}
}
return status;
}
catch (Exception ex)
{
LogFactory.GetLogger("DoSendReport").Error(ex);
return EmailTradeConfirmResultType.Other;
}
finally
{
document?.Close();
}
}
#region 结算报告 国君互换
[HttpPost]
public JsonResult clientTradePositionSwapFlowQuery(TradeSpanReq req)
{
try
{
var result = new EodSwapPositionMannualService(CurUser).SearchPositionList(req);
return Json(result);
}
catch (Exception ex)
{
LogFactory.GetLogger("clientTradePositionQuery").Error(ex);
throw;
}
}
#endregion
}
}