700 lines
37 KiB
C#
700 lines
37 KiB
C#
using BaseOUDAL;
|
|
using System.Collections.Concurrent;
|
|
using YLErp.Configuration;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.Model;
|
|
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)
|
|
{
|
|
if (PS.Config.Company == CompanyEnum.国信金阳)
|
|
{
|
|
if (!GXJY_CorrespondingConfirmationTemplate(tradeIds, out string Msg))
|
|
{
|
|
|
|
throw new ServiceException(Msg);
|
|
}
|
|
}
|
|
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>();
|
|
if (PS.Config.Is国泰君安 || PS.Config.Is厦门象屿)
|
|
{
|
|
var Tradelist = new TradeDalService(this).GetTradeOrEodTradeOfTidAPid(tradeIds, SystemValueDate, false, false);
|
|
using (var basedb = new ErpBaseContext())
|
|
{
|
|
if (Tradelist.Any(O => O.IsGroup > 0))
|
|
{
|
|
int count = Tradelist.Where(O => O.IsGroup != 2).GroupBy(O => O.IsGroup).Count();
|
|
if (count > 1)
|
|
{
|
|
throw new ServiceException("不应勾选多个非黑盒标的的交易");
|
|
}
|
|
var list = Tradelist.Where(x => x.TradeType == "结构化交易");
|
|
var group = list.GroupBy(O => new { O.ClientId, O.StructureType }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item in group)
|
|
{
|
|
if (item.Key.StructureType == "折价")
|
|
{
|
|
var list2 = list.Where(x => item.Value.Contains(x.id) && x.TradeType == "结构化交易").ToList();
|
|
list2.ForEach(x =>
|
|
{
|
|
var options = x.Propertys?.Where(o => o.name == "看涨看跌").ToList();
|
|
if (options != null && options.Any())
|
|
{
|
|
x.ExtendOptionTypeInfo = JsonHelper.Serialize(options);
|
|
}
|
|
else
|
|
{
|
|
throw new ServiceException("看涨看跌不能为空:" + x.TradeNumber);
|
|
}
|
|
});
|
|
var group2 = list2.GroupBy(O => O.ExtendOptionTypeInfo).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item2 in group2)
|
|
{
|
|
groupGenerateHandle_Date(item2.Value, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
groupGenerateHandle_Date(item.Value, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
}
|
|
|
|
var swapList = Tradelist.Where(x => x.TradeType == "收益互换" && x.ParentTradeId == 0);
|
|
foreach (var item in swapList)
|
|
{
|
|
groupGenerateHandle_Date(new List<int> { item.id }, docType, startDate, endDate, results, error, file);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (results.Count == 0)
|
|
{
|
|
var structTradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => c.TradeType != "结构化交易");
|
|
List<string> instrumentTypeArr = new List<string>() { ConsGlobal.InstrumentType.Stock, ConsGlobal.InstrumentType.StockIndex, ConsGlobal.InstrumentType.StockIF };
|
|
DataCacheProvider.GetUnderlyingDataSource().AsQueryable();
|
|
if (structTradeQuery.Any(O => instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)) || O.TradeType == "雪球期权"))
|
|
{
|
|
//暂时将所有子交易都作为判断依据,等拿到模板后再根据模板做调整更改;
|
|
//目前是否为权益类的判断条件只是是否是股票,没有考虑IC IF等品种;
|
|
int count = structTradeQuery.GroupBy(O => new { UnderlyingInstrumentType = (instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId)) || O.TradeType == "雪球期权") ? 1 : 0 }).Count();
|
|
if (count > 1)
|
|
{
|
|
throw new ServiceException("不应勾选多个非股票(含股指期货)标的的交易");
|
|
}
|
|
var group = structTradeQuery.GroupBy(O => new { O.ClientId, O.TradeType }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
|
|
foreach (var item in group)
|
|
{
|
|
if (item.Key.TradeType == "雪球期权")
|
|
{
|
|
if (structTradeQuery.Any(O => !instrumentTypeArr.Contains(getUnderlyingInstrumentType(O.UnderlyingId))))
|
|
{
|
|
var group2 = DbContext.trade.Where(c => item.Value.Contains(c.id)).AsEnumerable().GroupBy(m => m.OptionType).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item2 in group2)
|
|
{
|
|
groupGenerateHandle_Date(item2.Value, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var group2 = DbContext.trade_snowball.Where(c => item.Value.Contains(c.TradeId)).AsEnumerable().GroupBy(m => m.IsFixedCoupon).ToDictionary(K => K.Key, V => V.Select(O => O.TradeId).ToList());
|
|
foreach (var item2 in group2)
|
|
{
|
|
if (item2.Key)
|
|
{
|
|
groupGenerateHandle_Date(item2.Value, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
else
|
|
{
|
|
var group3 = DbContext.trade.Where(c => item2.Value.Contains(c.id)).AsEnumerable().GroupBy(m => m.OptionType).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item3 in group3)
|
|
{
|
|
groupGenerateHandle_Date(item3.Value, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
groupGenerateHandle_Date(item.Value, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (PS.Config.Is润和)
|
|
{
|
|
var TradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => (c.TradeType != "结构化交易" || c.IsGroup == 1) && tradeIds.Contains(c.id));
|
|
if (TradeQuery.Any())
|
|
{
|
|
var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item in group)
|
|
{
|
|
var group2 = DbContext.trade.Where(c => item.Value.Contains(c.id) && c.TradeType == "远期").Select(O => O.id).ToList();
|
|
if (group2.Any())
|
|
{
|
|
groupGenerateHandle(group2, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
var group4 = DbContext.trade.Where(c => item.Value.Contains(c.id) && c.TradeType == "亚式期权").Select(O => O.id).ToList();
|
|
if (group4.Any())
|
|
{
|
|
groupGenerateHandle(group4, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
var group3 = DbContext.trade.Where(c => item.Value.Contains(c.id) && c.TradeType != "远期" && c.TradeType != "亚式期权").Select(O => O.id).ToList();
|
|
if (group3.Any())
|
|
{
|
|
groupGenerateHandle(group3, docType, startDate, endDate, results, error, file);
|
|
if (error.Any()) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (PS.Config.Is东吴)
|
|
{
|
|
var TradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => (c.TradeType != "结构化交易" || c.IsGroup == 1) && tradeIds.Contains(c.id));
|
|
if (TradeQuery.Any())
|
|
{
|
|
var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item in group)
|
|
{
|
|
var query = from t in DbContext.trade
|
|
join tc in DbContext.trade_cash on t.id equals tc.TradeId
|
|
where t.ClientId == item.Key.ClientId &&
|
|
tc.ValueDate == item.Key.TradeDate && !tc.IsDeleted && tc.Action == ClientCashInCashOut.系统操作_期权费
|
|
select new { t.id };
|
|
if (query.Any())
|
|
{
|
|
groupGenerateHandle(query.Select(l => l.id).ToList(), docType, startDate, endDate, results, error, file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if(PS.Config.Is物产中大)
|
|
{
|
|
var TradeQuery = new TradeDalService(this).GetTradeOrEodTradeOfTidASid(tradeIds, SystemValueDate).Where(c => (c.TradeType != "结构化交易" || c.IsGroup == 1) && tradeIds.Contains(c.id));
|
|
if (TradeQuery.Any())
|
|
{
|
|
var group = TradeQuery.GroupBy(O => new { O.ClientId, O.TradeDate,O.TradeType }).ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList());
|
|
foreach (var item in group)
|
|
{
|
|
if (item.Value.Count > 10)
|
|
{
|
|
throw new ServiceException("同客户同日期同类型交易生成超过限制!");
|
|
}
|
|
var query = from t in DbContext.trade
|
|
join tc in DbContext.trade_cash on t.id equals tc.TradeId
|
|
where item.Value.Contains(tc.TradeId) && !tc.IsDeleted
|
|
select new { t.id };
|
|
if (query.Any())
|
|
{
|
|
groupGenerateHandle(query.Select(l => l.id).ToList(), docType, startDate, endDate, results, error, file);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (results.Count == 0)
|
|
{
|
|
results = new ConfirmationGenerateService(this).Generate(tradeIds, 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();
|
|
}
|
|
|
|
private void groupGenerateHandle_Date(List<int> ids, string docType, DateTime? startDate, DateTime? endDate, List<TradeDocGenerateResult> results, List<string> error, List<string> file)
|
|
{
|
|
var trades = DbContext.trade.Where(c => ids.Contains(c.id)).ToList();
|
|
var supProtocolDate = DataCacheProvider.GetClientDataSource().GetData(trades.FirstOrDefault().ClientId).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();
|
|
// 单章确认书和双章确认书同时生成要生成两个文件
|
|
if (groupDateDouble.Any() && groupDateSingle.Any())
|
|
{
|
|
groupGenerateHandle(groupDateDouble, docType, startDate, supProtocolDate.Value.AddDays(-1), results, error, file);
|
|
groupGenerateHandle(groupDateSingle, docType, supProtocolDate, endDate, results, error, file);
|
|
}
|
|
else if (groupDateDouble.Any())
|
|
{
|
|
groupGenerateHandle(groupDateDouble, docType, startDate, endDate, results, error, file);
|
|
}
|
|
else if (groupDateSingle.Any())
|
|
{
|
|
groupGenerateHandle(groupDateSingle, docType, startDate, endDate, results, error, file);
|
|
}
|
|
}
|
|
|
|
private void groupGenerateHandle(List<int> ids, string docType, DateTime? startDate, DateTime? endDate, List<TradeDocGenerateResult> results, List<string> error, List<string> file)
|
|
{
|
|
var trade_contract_r = DbContext.trade_contract_r.Where(c => ids.Contains(c.TradeId) && c.Type == "交易确认书" && c.IsValid).ToList();
|
|
//DbContext.trade_contract_r.RemoveRange(trade_contract_r);
|
|
trade_contract_r.ForEach(O => O.IsValid = false);
|
|
DbContext.SaveChanges();
|
|
var result = new BatchConfirmationGenerateService(this).Generate(ids, docType, startDate, endDate);
|
|
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());
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 交易确认书生成结果
|
|
/// </summary>
|
|
public class TradeContractGenerateResultModel
|
|
{
|
|
public bool Success;
|
|
|
|
public string Message;
|
|
|
|
public string ContractType;
|
|
|
|
public Exception Exception;
|
|
}
|
|
}
|