812 lines
39 KiB
C#
812 lines
39 KiB
C#
using BaseOUDAL;
|
|
using DocumentFormat.OpenXml.Office.Word;
|
|
using System.Collections.Concurrent;
|
|
using System.Drawing.Printing;
|
|
using YLErp.Configuration;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.Model;
|
|
using YLErp.Model.Enum;
|
|
using YLErp.Models;
|
|
using YLErp.Modules.TradeDalModule;
|
|
using YLErp.Modules.TradeModule.DocGenerateModule;
|
|
|
|
namespace YLErp.Modules.TradeModule.DealModule
|
|
{
|
|
/// <summary>
|
|
/// 交易确认书生成
|
|
/// </summary>
|
|
public class TradeContractGenerateService : YLBaseService
|
|
{
|
|
public TradeContractGenerateService(YLBaseService baseService) : base(baseService)
|
|
{
|
|
}
|
|
|
|
public TradeContractGenerateService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// 确认书生成队列
|
|
/// </summary>
|
|
private static readonly ConcurrentQueue<_ContractInfoModel> _ContractQueue = new ConcurrentQueue<_ContractInfoModel>();
|
|
|
|
/// <summary>
|
|
/// 确认书缓存队列结构
|
|
/// </summary>
|
|
private class _ContractInfoModel
|
|
{
|
|
public string ContractType;
|
|
|
|
public List<int> TradeIds;
|
|
|
|
public _ContractInfoModel(string contractType, List<int> tradeIds)
|
|
{
|
|
this.ContractType = contractType;
|
|
this.TradeIds = tradeIds;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 异步生成交易确认书
|
|
/// </summary>
|
|
public void GenerateContractsAsync(List<int> tradeIds, string contractType = "其它")
|
|
{
|
|
var status = false;
|
|
lock (_ContractQueue)
|
|
{
|
|
status = _ContractQueue.IsEmpty;
|
|
_ContractQueue.Enqueue(new _ContractInfoModel(contractType, tradeIds));
|
|
}
|
|
if (status)
|
|
{
|
|
Task.Run(() =>
|
|
{
|
|
while (!_ContractQueue.IsEmpty)
|
|
{
|
|
if (!_ContractQueue.TryPeek(out var obj))
|
|
{
|
|
continue;
|
|
}
|
|
new TradeContractGenerateService(this).GenerateContracts(obj.TradeIds, obj.ContractType);
|
|
lock (_ContractQueue)
|
|
{
|
|
_ContractQueue.TryDequeue(out _);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 同步生成交易确认书
|
|
/// </summary>
|
|
/// <param name="tradeIds"></param>
|
|
/// <param name="contractType">contractType为确认书的话,表示生成交易确认书;否则则生成提前终止确认书或者到期结算单</param>
|
|
private TradeContractGenerateResultModel GenerateContracts(List<int> tradeIds, string contractType = "其它")
|
|
{
|
|
ResetDbContext();
|
|
|
|
var result = new TradeContractGenerateResultModel();
|
|
|
|
try
|
|
{
|
|
if (contractType == "确认书")
|
|
{
|
|
result.ContractType = "确认书";
|
|
result.Success = GJGenerateConfirmBook(tradeIds, "PDF", out var errors, out _);
|
|
result.Message = result.Success ? "生成确认书成功" : string.Join("\r\n", errors.AsEnumerable());
|
|
return result;
|
|
}
|
|
|
|
var clearingTradeIds = new List<int>();
|
|
var unwindReportInputModels = new List<UnwindReportInputModel>();
|
|
|
|
var tcQuery = from tc in DbContext.trade_cash
|
|
join t in DbContext.trade on tc.TradeId equals t.id
|
|
where tradeIds.Contains(tc.TradeId) && !tc.IsDeleted
|
|
select new
|
|
{
|
|
tc.id,
|
|
tc.TradeId,
|
|
tc.Action,
|
|
tc.ExerciseWay,
|
|
tc.IsLastAction,
|
|
ValueDate = tc.HappenedDate ?? tc.ValueDate,
|
|
t.ExerciseDate
|
|
};
|
|
|
|
var lookUp = tcQuery.ToLookup(tc => tc.TradeId);
|
|
var tradeCashes = lookUp.Select(l => l.OrderByDescending(m => m.id).First()).ToList();
|
|
|
|
foreach (var tc in tradeCashes)
|
|
{
|
|
if (tc.Action == ClientCashInCashOut.系统操作_平仓费 ||
|
|
(tc.Action == ClientCashInCashOut.系统操作_行权费 && tc.ExerciseWay == TradeCashExerciseWayEnum.提前终止行权))
|
|
{
|
|
unwindReportInputModels.Add(new UnwindReportInputModel { TradeId = tc.TradeId, TradeCashId = tc.id });
|
|
}
|
|
else if (tc.Action == ClientCashInCashOut.系统操作_行权费)
|
|
{
|
|
clearingTradeIds.Add(tc.TradeId);
|
|
}
|
|
else if (tc.Action == ClientCashInCashOut.系统操作_票息)
|
|
{
|
|
if (tc.ValueDate >= tc.ExerciseDate)
|
|
{
|
|
clearingTradeIds.Add(tc.TradeId);
|
|
}
|
|
else
|
|
{
|
|
unwindReportInputModels.Add(new UnwindReportInputModel { TradeId = tc.TradeId, TradeCashId = tc.id });
|
|
}
|
|
}
|
|
}
|
|
|
|
var hasUnwindReport = unwindReportInputModels.Count > 0;
|
|
|
|
if (hasUnwindReport)
|
|
{
|
|
result.ContractType = "提前终止确认书";
|
|
result.Success = GJGenerateUnwindReport(unwindReportInputModels, "PDF", out var errors, out _);
|
|
result.Message = result.Success ? "生成提前终止确认书成功" : string.Join("\r\n", errors.AsEnumerable());
|
|
}
|
|
|
|
if (clearingTradeIds.Count > 0)
|
|
{
|
|
result.ContractType = "到期结算单";
|
|
|
|
if (GJGenerateSettleBill(clearingTradeIds, "PDF", out var errors, out _))
|
|
{
|
|
if (!hasUnwindReport)
|
|
{
|
|
result.Success = true;
|
|
result.Message = "生成到期结算单成功";
|
|
}
|
|
else if (result.Success)
|
|
{
|
|
result.Message = "生成到期结算单或提前终止确认书成功";
|
|
}
|
|
}
|
|
else if (result.Success)
|
|
{
|
|
result.Success = false;
|
|
result.Message = string.Join("\r\n", errors.AsEnumerable());
|
|
}
|
|
else
|
|
{
|
|
result.Message += (string.IsNullOrEmpty(result.Message) ? string.Empty : "\r\n") + string.Join("\r\n", errors.AsEnumerable());
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
result.Exception = ex;
|
|
LogFactory.GetLogger("生成确认书").Error("确认书类型:" + result.ContractType, ex);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成交易确认书
|
|
/// </summary>
|
|
public bool GJGenerateConfirmBook(List<int> tradeIds, string docType,
|
|
out IEnumerable<string> errors, out IEnumerable<string> files, DateTime? startDate = null, DateTime? endDate = null)
|
|
{
|
|
var logger = LogFactory.GetLogger("生成确认书");
|
|
logger.Info($"[GJGenerateConfirmBook] 开始生成确认书 - tradeIds.Count: {tradeIds?.Count ?? 0}, docType: {docType}, startDate: {startDate}, endDate: {endDate}");
|
|
|
|
Func<int, string> getUnderlyingInstrumentType = new Func<int, string>((underlyingId) =>
|
|
{
|
|
return DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingId)?.UnderlyingInstrumentType;
|
|
});
|
|
List<TradeDocGenerateResult> results = new List<TradeDocGenerateResult>();
|
|
List<string> error = new List<string>();
|
|
List<string> file = new List<string>();
|
|
logger.Info("[GJGenerateConfirmBook] 生成确认书流程");
|
|
|
|
if (tradeIds == null || !tradeIds.Any())
|
|
{
|
|
logger.Info("[GJGenerateConfirmBook] tradeIds 为空,直接返回");
|
|
errors = new List<string>();
|
|
files = new List<string>();
|
|
return true;
|
|
}
|
|
|
|
var trades = DbContext.trade.Where(x => tradeIds.Contains(x.id)).AsNoTracking().ToList();
|
|
logger.Info($"[GJGenerateConfirmBook] 查询到交易记录数: {trades.Count}");
|
|
|
|
if (!trades.Any())
|
|
{
|
|
logger.Info("[GJGenerateConfirmBook] 未找到交易记录,直接返回");
|
|
errors = new List<string>();
|
|
files = new List<string>();
|
|
return true;
|
|
}
|
|
|
|
var clientIds = trades.Select(x => x.ClientId).Distinct().ToList();
|
|
logger.Info($"[GJGenerateConfirmBook] 客户ID数: {clientIds.Count}");
|
|
|
|
if (trades.Any(o => o.TradeType.Equals("收益互换")))
|
|
{
|
|
var allTrades = DbContext.trade.Where(x => clientIds.Contains(x.ClientId) && x.TradeType.Equals("收益互换") && x.ValidState != ConsGlobal.InValid);
|
|
if (startDate.HasValue)
|
|
{
|
|
allTrades = allTrades.Where(x => x.TradeDate >= startDate);
|
|
}
|
|
if (endDate.HasValue)
|
|
{
|
|
allTrades = allTrades.Where(x => x.TradeDate <= endDate);
|
|
}
|
|
var Ids = allTrades.Select(o => o.id).Distinct().ToArray();
|
|
var swapPositions = DbContext.swap_position.Where(s => Ids.Contains(s.SwapTradeId) && s.IsInitial && s.PositionType > 0 && !s.Invalid)
|
|
.Distinct().ToList();
|
|
logger.Info($"[GJGenerateConfirmBook] 查询到持仓记录数: {swapPositions.Count}");
|
|
|
|
var allTradeList = allTrades.AsNoTracking().ToList();
|
|
foreach (var item in allTradeList)
|
|
{
|
|
item.swap_positions.Add(swapPositions.FirstOrDefault(o => o.SwapTradeId == item.id));
|
|
}
|
|
allTradeList = allTradeList.Where(x => x.swap_positions.Any()).ToList();
|
|
logger.Info($"[GJGenerateConfirmBook] 过滤后有持仓的交易数: {allTradeList.Count}");
|
|
|
|
// 按照客户ID、交易日期、多空头进行分组
|
|
var group = allTradeList.GroupBy(O => new { O.ClientId, O.StartDate, O.swap_positions.FirstOrDefault()?.PositionType })
|
|
.ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
|
|
logger.Info($"[GJGenerateConfirmBook] 分组数: {group.Count}");
|
|
|
|
foreach (var item in group)
|
|
{
|
|
var tradeCount = item.Value.Distinct().Count();
|
|
logger.Info($"[GJGenerateConfirmBook] 处理分组 - ClientId: {item.Key.ClientId}, StartDate: {item.Key.StartDate}, PositionType: {item.Key.PositionType}, 交易数: {tradeCount}");
|
|
groupGenerateHandle(item.Value.Distinct().ToList(), docType, startDate, endDate, results, error, file);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (var item in trades)
|
|
{
|
|
groupGenerateHandle_Date(new List<int> { item.id }, docType, startDate, endDate, results, error, file);
|
|
}
|
|
}
|
|
|
|
errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToList();
|
|
files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList();
|
|
logger.Info($"[GJGenerateConfirmBook] 完成生成确认书 - 错误数: {errors.Count()}, 文件数: {files.Count()}");
|
|
return !errors.Any();
|
|
}
|
|
|
|
private void groupGenerateHandle_Date(List<int> ids, string docType, DateTime? startDate, DateTime? endDate, List<TradeDocGenerateResult> results, List<string> error, List<string> file)
|
|
{
|
|
var logger = LogFactory.GetLogger("生成确认书");
|
|
logger.Info($"[groupGenerateHandle_Date] 开始处理 - ids.Count: {ids?.Count ?? 0}");
|
|
|
|
if (ids == null || !ids.Any())
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] ids 为空,直接返回");
|
|
return;
|
|
}
|
|
|
|
var trades = DbContext.trade.Where(c => ids.Contains(c.id)).ToList();
|
|
logger.Info($"[groupGenerateHandle_Date] 查询到交易数: {trades.Count}");
|
|
|
|
if (!trades.Any())
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] 未找到交易记录,直接返回");
|
|
return;
|
|
}
|
|
|
|
var firstTrade = trades.FirstOrDefault();
|
|
if (firstTrade == null)
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] 第一条交易记录为 null,直接返回");
|
|
return;
|
|
}
|
|
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(firstTrade.ClientId);
|
|
if (client == null)
|
|
{
|
|
logger.Info($"[groupGenerateHandle_Date] 未找到客户信息 - ClientId: {firstTrade.ClientId}");
|
|
return;
|
|
}
|
|
|
|
var supProtocolDate = client.SupProtocolDate;
|
|
logger.Info($"[groupGenerateHandle_Date] 客户补充协议日期: {supProtocolDate}");
|
|
|
|
var groupDateDouble = trades.Where(x => supProtocolDate == null || x.TradeDate < supProtocolDate).Select(x => x.id).ToList();
|
|
var groupDateSingle = trades.Where(x => supProtocolDate != null && x.TradeDate >= supProtocolDate).Select(x => x.id).ToList();
|
|
|
|
logger.Info($"[groupGenerateHandle_Date] 双章确认书交易数: {groupDateDouble.Count}, 单章确认书交易数: {groupDateSingle.Count}");
|
|
|
|
// 单章确认书和双章确认书同时生成要生成两个文件
|
|
if (groupDateDouble.Any() && groupDateSingle.Any())
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] 同时生成单章和双章确认书");
|
|
groupGenerateHandle(groupDateDouble, docType, startDate, supProtocolDate.Value.AddDays(-1), results, error, file);
|
|
groupGenerateHandle(groupDateSingle, docType, supProtocolDate, endDate, results, error, file);
|
|
}
|
|
else if (groupDateDouble.Any())
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] 仅生成双章确认书");
|
|
groupGenerateHandle(groupDateDouble, docType, startDate, endDate, results, error, file);
|
|
}
|
|
else if (groupDateSingle.Any())
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] 仅生成单章确认书");
|
|
groupGenerateHandle(groupDateSingle, docType, startDate, endDate, results, error, file);
|
|
}
|
|
else
|
|
{
|
|
logger.Info("[groupGenerateHandle_Date] 没有需要生成的确认书");
|
|
}
|
|
}
|
|
|
|
private void groupGenerateHandle(List<int> ids, string docType, DateTime? startDate, DateTime? endDate, List<TradeDocGenerateResult> results, List<string> error, List<string> file)
|
|
{
|
|
var logger = LogFactory.GetLogger("生成确认书");
|
|
logger.Info($"[groupGenerateHandle] 开始处理 - ids.Count: {ids?.Count ?? 0}, docType: {docType}");
|
|
|
|
if (ids == null || !ids.Any())
|
|
{
|
|
logger.Info("[groupGenerateHandle] ids 为空,直接返回");
|
|
return;
|
|
}
|
|
|
|
var trade_contract_r = DbContext.trade_contract_r.Where(c => ids.Contains(c.TradeId) && c.Type == "交易确认书" && c.IsValid).ToList();
|
|
logger.Info($"[groupGenerateHandle] 找到已存在的确认书记录数: {trade_contract_r.Count}");
|
|
|
|
//DbContext.trade_contract_r.RemoveRange(trade_contract_r);
|
|
trade_contract_r.ForEach(O => O.IsValid = false);
|
|
DbContext.SaveChanges();
|
|
|
|
logger.Info("[groupGenerateHandle] 调用 BatchConfirmationGenerateService.Generate");
|
|
var result = new BatchConfirmationGenerateService(this).Generate(ids, docType, startDate, endDate);
|
|
logger.Info($"[groupGenerateHandle] 生成结果 - 成功数: {result.Count(r => string.IsNullOrWhiteSpace(r.ErrorMessage))}, 失败数: {result.Count(r => !string.IsNullOrWhiteSpace(r.ErrorMessage))}");
|
|
|
|
results.AddRange(result);
|
|
error.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray());
|
|
file.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList());
|
|
|
|
logger.Info($"[groupGenerateHandle] 完成处理 - 当前总错误数: {error.Count}, 当前总文件数: {file.Count}");
|
|
}
|
|
|
|
public bool GXJY_CorrespondingConfirmationTemplate(List<int> tradeIds, out string ErrMsg)
|
|
{
|
|
bool IsExist = true;
|
|
ErrMsg = "";
|
|
var listTrade = DbContext.trade.Where(l => tradeIds.Contains(l.id));
|
|
foreach (var t in listTrade)
|
|
{
|
|
bool IsExistChild = false;
|
|
var exerciseMode = t.ExerciseMode ?? "";
|
|
switch (t.TradeType)
|
|
{
|
|
case "亚式期权":
|
|
IsExistChild = true;
|
|
break;
|
|
case "结构化交易":
|
|
switch (t.StructureType)
|
|
{
|
|
case "普通亚式带保底":
|
|
case "增强亚式":
|
|
case "增强亚式价差":
|
|
case "增强亚式价差组合标的":
|
|
IsExistChild = true;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
IsExistChild = true;
|
|
break;
|
|
}
|
|
if (IsExistChild == false)
|
|
{
|
|
IsExist = false;
|
|
ErrMsg += t.TradeNumber.ToString() + ",";
|
|
}
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(ErrMsg))
|
|
{
|
|
ErrMsg = ErrMsg.Substring(0, ErrMsg.Length - 1);
|
|
ErrMsg += "该交易没有相应确认书模板";
|
|
}
|
|
return IsExist;
|
|
}
|
|
/// <summary>
|
|
/// 生成提前中止确认书
|
|
/// </summary>
|
|
public bool GJGenerateUnwindReport(List<UnwindReportInputModel> trades, string docType,
|
|
out List<string> errors, out List<string> files)
|
|
{
|
|
var tdIds = trades.Select(t => t.TradeId).ToList();
|
|
if (PS.Config.Company == CompanyEnum.国信金阳)
|
|
{
|
|
var IsTradeContract = DbContext.trade_contract_r.Where(l => l.IsValid && tdIds.Contains(l.TradeId) && l.Type == "交易确认书").Select(l => l.TradeId).ToList();
|
|
var IsTradeIds = tdIds.Where(l => !IsTradeContract.Contains(l)).ToList();
|
|
if (IsTradeIds.Count > 0)
|
|
{
|
|
throw new ServiceException(String.Join(",", DbContext.trade.Where(l => IsTradeIds.Contains(l.id)).Select(l => l.TradeNumber).ToArray()) + "请生成该交易编号相应交易确认书");
|
|
}
|
|
if (!GXJY_CorrespondingConfirmationTemplate(tdIds, out string Msg))
|
|
{
|
|
throw new ServiceException(Msg);
|
|
}
|
|
}
|
|
|
|
files = new List<string>();
|
|
errors = new List<string>();
|
|
if (PS.Config.Company == CompanyEnum.兴证)
|
|
{
|
|
IEnumerable<TradeDocGenerateResult> results = null;
|
|
results = new BatchUnwindReportGenerateService(this).Generate(trades, docType, UserId, UserName);
|
|
errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToList();
|
|
files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList();
|
|
}
|
|
else if (PS.Config.Company == CompanyEnum.海通)
|
|
{
|
|
var tradeCashIds = trades.Select(O => O.TradeCashId);
|
|
var tradeCashStatus = new string[] { ClientCashInCashOut.系统操作_行权费, ClientCashInCashOut.系统操作_平仓费 };
|
|
var query = from t in DbContext.trade
|
|
join tc in DbContext.trade_cash
|
|
on t.id equals tc.TradeId
|
|
where
|
|
tradeCashIds.Contains(tc.id) &&
|
|
tc.ValidState != ConsGlobal.InValid && !tc.IsDeleted &&
|
|
tradeCashStatus.Contains(tc.Action) &&
|
|
tc.ExerciseWay == TradeCashExerciseWayEnum.提前终止行权
|
|
select new { t.id, tradeCashId = tc.id, t.ClientId };
|
|
var clientTradeDict = query.AsEnumerable().GroupBy(O => O.ClientId)
|
|
.ToDictionary(K => K.Key, V => V.Select(O => new UnwindReportInputModel() { TradeId = O.id, TradeCashId = O.tradeCashId }).ToList());
|
|
foreach (var ctrades in clientTradeDict)
|
|
{
|
|
var results = new BatchUnwindReportGenerateService(this).Generate(ctrades.Value, "PDF", UserId, UserName);
|
|
errors.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray());
|
|
files.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList());
|
|
if (errors.Any()) break;
|
|
}
|
|
}
|
|
else if (PS.Config.Is方顿) //同一笔交易结构化交易在一个确认书里
|
|
{
|
|
List<TradeDocGenerateResult> results = new List<TradeDocGenerateResult>();
|
|
List<string> error = new List<string>();
|
|
List<string> file = new List<string>();
|
|
|
|
var tradeIds = trades.Select(O => O.TradeId).ToArray();
|
|
var query = DbContext.trade.Where(O => tradeIds.Contains(O.id)).Select(O => new { O.id, O.ParentTradeId }).ToList();
|
|
var group = query.GroupBy(O => O.ParentTradeId).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
|
|
foreach (var item in group)
|
|
{
|
|
if (item.Key == 0)
|
|
{
|
|
foreach (var item2 in item.Value)
|
|
{
|
|
var tradeCashIds = trades.Where(x => x.TradeId == item2).ToList();
|
|
var CashIds = trades.Where(x => x.TradeId == item2).Select(x => x.TradeId).ToList();
|
|
var trade_contract_r = DbContext.trade_contract_r.Where(c => CashIds.Contains(c.TradeCashId.Value) && c.IsValid).ToList();
|
|
trade_contract_r.ForEach(o => o.IsValid = false);
|
|
DbContext.SaveChanges();
|
|
var result = new BatchUnwindReportGenerateService(this).Generate(tradeCashIds, docType, UserId, UserName);
|
|
results.AddRange(result);
|
|
error.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray());
|
|
file.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList());
|
|
if (error.Any()) break; ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var tradeCashIds = (from t1 in item.Value join tc in trades on t1 equals tc.TradeId select tc).ToList();
|
|
var CashIds = (from t1 in item.Value join tc in trades on t1 equals tc.TradeId select tc.TradeId).ToList();
|
|
var trade_contract_r = DbContext.trade_contract_r.Where(c => CashIds.Contains(c.TradeCashId.Value) && c.IsValid).ToList();
|
|
trade_contract_r.ForEach(o => o.IsValid = false);
|
|
DbContext.SaveChanges();
|
|
var result = new BatchUnwindReportGenerateService(this).Generate(tradeCashIds, docType, UserId, UserName);
|
|
results.AddRange(result);
|
|
error.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray());
|
|
file.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList());
|
|
if (error.Any()) break; ;
|
|
}
|
|
}
|
|
errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToList();
|
|
files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList();
|
|
}
|
|
else
|
|
{
|
|
List<TradeDocGenerateResult> results = new List<TradeDocGenerateResult>();
|
|
if (PS.Config.Is国泰君安)
|
|
{
|
|
|
|
List<string> error = new List<string>();
|
|
List<string> file = new List<string>();
|
|
var tradeIds = trades.Select(O => O.TradeId);
|
|
var tradecashId = trades.Select(o => o.TradeCashId).ToList();
|
|
Func<int, string> getUnderlyingInstrumentType = new Func<int, string>((underlyingId) =>
|
|
{
|
|
return DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingId).UnderlyingInstrumentType;
|
|
});
|
|
|
|
List<string> instrumentTypeArr = new List<string>() { ConsGlobal.InstrumentType.Stock, ConsGlobal.InstrumentType.StockIF };
|
|
var query = DbContext.trade.Where(O => tradeIds.Contains(O.id)).Select(O => new { O.id, O.UnderlyingId, O.ClientId, O.TradeType }).ToList();
|
|
if (query.Any(O => instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)) || O.TradeType == "雪球期权"))
|
|
{
|
|
|
|
//暂时将所有子交易都作为判断依据,等拿到模板后再根据模板做调整更改;
|
|
//目前是否为权益类的判断条件只是是否是股票,没有考虑IC IF等品种;
|
|
int count = query.GroupBy(O => new { UnderlyingInstrumentType = (instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)) || O.TradeType == "雪球期权") ? 1 : 0 }).Count();
|
|
if (count > 1)
|
|
{
|
|
throw new ServiceException("不应勾选多个非股票(含股指期货)标的的交易");
|
|
}
|
|
var group = query.GroupBy(O => new { O.ClientId }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
|
|
foreach (var item in group)
|
|
{
|
|
var tradeCashIds = (from t1 in item.Value join tc in trades on t1 equals tc.TradeId select tc).ToList();
|
|
var CashIds = (from t1 in item.Value join tc in trades on t1 equals tc.TradeId select tc.TradeId).ToList();
|
|
var trade_contract_r = DbContext.trade_contract_r.Where(c => CashIds.Contains(c.TradeCashId.Value) && c.IsValid).ToList();
|
|
//DbContext.trade_contract_r.RemoveRange(trade_contract_r);
|
|
trade_contract_r.ForEach(o => o.IsValid = false);
|
|
DbContext.SaveChanges();
|
|
var result = new BatchUnwindReportGenerateService(this).Generate(tradeCashIds, docType, UserId, UserName);
|
|
results.AddRange(result);
|
|
error.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray());
|
|
file.AddRange(results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList());
|
|
if (error.Any()) break; ;
|
|
}
|
|
|
|
}
|
|
}
|
|
if (results.Count == 0)
|
|
{
|
|
results = (List<TradeDocGenerateResult>)new UnwindReportGenerateService(this).Generate(trades, docType);
|
|
}
|
|
errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToList();
|
|
files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToList();
|
|
}
|
|
|
|
return !errors.Any();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成结算确认书
|
|
/// </summary>
|
|
public bool GJGenerateSettleBill(List<int> tradeIds, string docType,
|
|
out IEnumerable<string> errors, out IEnumerable<string> files)
|
|
{
|
|
IEnumerable<TradeDocGenerateResult> results;
|
|
|
|
var settleSv = new SettlementBillGenerateService(this);
|
|
|
|
results = settleSv.Generate(null, tradeIds, docType, UserId, UserName);
|
|
|
|
errors = results.Where(n => !string.IsNullOrWhiteSpace(n.ErrorMessage)).Select(n => n.ErrorMessage).ToArray();
|
|
files = results.Where(n => !string.IsNullOrWhiteSpace(n.OutputFilePath)).Select(n => n.OutputFilePath).ToArray();
|
|
return !errors.Any();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 根据传进来的合约代码过滤出已存在的合约代码
|
|
/// </summary>
|
|
public IEnumerable<string> GetExistsContractCode(IEnumerable<string> contractCodes)
|
|
{
|
|
if (contractCodes == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(contractCodes));
|
|
}
|
|
|
|
if (!contractCodes.Any())
|
|
{
|
|
return Enumerable.Empty<string>();
|
|
}
|
|
|
|
var query = (from a in DbContext.trade_contract_r.AsNoTracking()
|
|
join b in DbContext.trade.AsNoTracking() on a.TradeId equals b.id
|
|
where contractCodes.Contains(a.ContractCode) && b.ValidState != "InValid" && a.IsValid
|
|
select a.ContractCode).Union
|
|
(from tm in DbContext.TradeMeta.AsNoTracking()
|
|
join t in DbContext.trade.AsNoTracking() on tm.TradeId equals t.id
|
|
where (tm.MetaKey == ConsTradeMetaKey.ContractCode || tm.MetaKey.Contains("确认书")) && //伴星确认书编号的Key是合约编号,长江确认书编号的Key是日期+(交易确认书、结算确认书和提前终止确认书)+序号
|
|
t.ValidState != "InValid"
|
|
&& contractCodes.Contains(tm.MetaValue)
|
|
select tm.MetaValue);
|
|
//.Union
|
|
//(from t in DbContext.trade.AsNoTracking()
|
|
// where t.ValidState != "InValid" && contractCodes.Contains(t.TradeNumber)
|
|
// select t.TradeNumber);
|
|
|
|
return query.ToArray();
|
|
}
|
|
|
|
public SearchListResult<clientContractR> GetConfirmBookListByClient(ClientConfirmBookListReq req)
|
|
{
|
|
var result = new SearchListResult<clientContractR>();
|
|
var contractList = new List<clientContractR>();
|
|
|
|
var query = from t in DbContext.trade.AsNoTracking().Where(x => x.TradeType == "收益互换" && x.ValidState != "InValid")
|
|
join tcrs in DbContext.trade_contract_r
|
|
on t.id equals tcrs.TradeId into tcrsGroup
|
|
from tcr in tcrsGroup.Where(r => r.IsValid && r.Type == ContractTypeEnum.Trade).DefaultIfEmpty()
|
|
join tcds in DbContext.trade_contract_document
|
|
on tcr.ContractCode equals tcds.Code into tcdsGroup
|
|
from tcd in tcdsGroup.DefaultIfEmpty()
|
|
join sp in DbContext.swap_position.AsNoTracking().Where(s => s.IsInitial && s.PositionType > 0 && !s.Invalid)
|
|
on t.id equals sp.SwapTradeId
|
|
join oa in DbContext.tradeContractOaResult on t.id equals oa.trade_id into oaTemp
|
|
from oa in oaTemp.DefaultIfEmpty()
|
|
where oa == null || oa.is_valid == true
|
|
select new
|
|
{
|
|
t.id,
|
|
t.TradeDate,
|
|
t.StartDate,
|
|
tcr.ContractCode,
|
|
t.ClientId,
|
|
t.ClientNumber,
|
|
t.ClientName,
|
|
tcr.send_email_result,
|
|
tcd.Status,
|
|
tcd.RelativePath,
|
|
tcd.SealResult,
|
|
ContractId = tcr != null ? tcr.id : 0,
|
|
sp.PositionType,
|
|
t.SentMailCount,
|
|
tcd.StampDocumentFileName,
|
|
tcr.OptDate,
|
|
tcr.OptName,
|
|
ContractDocId = tcd != null ? tcd.id : 0,
|
|
OAStatus = oa != null ? oa.status : "",
|
|
OAURL = oa != null ? oa.oa_url : "",
|
|
OAMessage = oa != null ? oa.oa_msg : ""
|
|
};
|
|
|
|
if (req.StartDate != null && req.StartDate != DateTime.MinValue)
|
|
{
|
|
query = query.Where(o => o.TradeDate >= req.StartDate);
|
|
}
|
|
|
|
if (req.EndDate != null && req.EndDate != DateTime.MaxValue)
|
|
{
|
|
query = query.Where(o => o.TradeDate <= req.EndDate);
|
|
}
|
|
|
|
if (req.ClientIds != null && req.ClientIds.Count > 0)
|
|
{
|
|
query = query.Where(o => req.ClientIds.Contains(o.ClientId));
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(req.ContractCode))
|
|
{
|
|
query = query.Where(o => o.ContractCode.Contains(req.ContractCode));
|
|
}
|
|
|
|
if (req.PositionTypes != null && req.PositionTypes.Count() > 0)
|
|
{
|
|
query = query.Where(o => req.PositionTypes.Contains(o.PositionType));
|
|
}
|
|
//客户希望用StartDate分组, 默认业务中StartDate会是TradeDate+1个交易日
|
|
var contractGroups = query.AsEnumerable()
|
|
.GroupBy(x => new { x.StartDate, x.ClientId, x.PositionType })
|
|
.Select(group => group.ToList())
|
|
.ToList();
|
|
|
|
// 构建返回结果
|
|
foreach (var group in contractGroups)
|
|
{
|
|
var sealResult = group.FirstOrDefault().SealResult;
|
|
contractList.Add(new clientContractR
|
|
{
|
|
id = group.FirstOrDefault().id,
|
|
ContractCode = group.FirstOrDefault().ContractCode,
|
|
TradeDate = group.FirstOrDefault().TradeDate.Value,
|
|
ClientNumber = group.FirstOrDefault().ClientNumber,
|
|
ClientName = group.FirstOrDefault().ClientName,
|
|
StampStatus = group.FirstOrDefault().Status,
|
|
EmailResult = group.FirstOrDefault().send_email_result,
|
|
ContractDocUrl = group.FirstOrDefault().RelativePath,
|
|
tradeIds = group.Select(x => x.id).Distinct().ToList(),
|
|
SealResult = sealResult != null ? Enum.GetName(typeof(SealResultEnum), sealResult) : "",
|
|
HasGeneratedConfirmBook = group.FirstOrDefault().ContractId != 0,
|
|
ContractId = group.FirstOrDefault().ContractId,
|
|
tradeCount = group.Select(x => x.id).Distinct().Count(),
|
|
PositionType = group.FirstOrDefault().PositionType,
|
|
SentMailCount = group.FirstOrDefault().SentMailCount ?? 0,
|
|
StampDocumentFileName = group.FirstOrDefault().StampDocumentFileName,
|
|
OptDate = group.FirstOrDefault().OptDate,
|
|
OptName = group.FirstOrDefault().OptName,
|
|
ContractDocId = group.FirstOrDefault().ContractDocId,
|
|
OAStatus = group.FirstOrDefault().OAStatus,
|
|
OAURL = group.FirstOrDefault().OAURL,
|
|
OAMessage = group.FirstOrDefault().OAMessage
|
|
});
|
|
}
|
|
result = contractList.OrderByDescending(r => r.TradeDate).AsQueryable().ToSearchList(req);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 交易确认书生成结果
|
|
/// </summary>
|
|
public class TradeContractGenerateResultModel
|
|
{
|
|
public bool Success;
|
|
|
|
public string Message;
|
|
|
|
public string ContractType;
|
|
|
|
public Exception Exception;
|
|
}
|
|
|
|
public class ClientConfirmBookListReq : BaseSearchReq
|
|
{
|
|
//合约编号
|
|
public string ContractCode { get; set; }
|
|
|
|
//开仓起始时间
|
|
public DateTime? StartDate { get; set; }
|
|
|
|
//开仓结束时间
|
|
public DateTime? EndDate { get; set; }
|
|
|
|
//客户
|
|
public List<int>? ClientIds { get; set; }
|
|
|
|
public List<int>? PositionTypes { get; set; }
|
|
|
|
|
|
}
|
|
|
|
public class clientContractR
|
|
{
|
|
public int id { get; set; }
|
|
public string ContractCode { get; set; }
|
|
|
|
public DateTime TradeDate { get; set; }
|
|
|
|
public string ClientNumber { get; set; }
|
|
|
|
public string ClientName { get; set; }
|
|
|
|
public string StampStatus { get; set; }
|
|
|
|
public string EmailResult { get; set; }
|
|
|
|
public List<int> tradeIds { get; set; }
|
|
|
|
public string ContractDocUrl { get; set; }
|
|
|
|
public string SealResult { get; set; }
|
|
|
|
|
|
public string ContractEncryptId { get; set; }
|
|
|
|
public bool HasGeneratedConfirmBook { get; set; }
|
|
|
|
public int ContractId { get; set; }
|
|
|
|
public int PositionType { get; set; }
|
|
|
|
public int tradeCount { get; set; }
|
|
|
|
public int SentMailCount { get; set; }
|
|
|
|
public string StampDocumentFileName { get; set; }
|
|
|
|
public DateTime? OptDate { get; set; }
|
|
|
|
public string OptName { get; set; }
|
|
|
|
public int ContractDocId { get; set; }
|
|
|
|
public string OAStatus { get; set; }
|
|
public string OAURL { get; set; }
|
|
public string OAMessage { get; set; }
|
|
|
|
}
|
|
}
|