- 在多个环境配置文件中新增RealtimeCalcAccountBalance配置项 - 移除ClientBalanceForTrsResponse中的冗余字段 - 更新Kafka任务和控制器中相关字段引用 - 修改Producer发送的目标topic为新的实时计算topic
905 lines
40 KiB
C#
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
|
|
}
|
|
}
|