using NPOI.HPSF;
using OfficeOpenXml;
using Qdp.Pricing.Core.Modules;
using Qdp.Pricing.Library.Base.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YLErp.BLL;
using YLErp.Core.Helpers;
using YLErp.DBModels;
using YLErp.DBModels.Consts;
using YLErp.Model;
using YLErp.Models;
using YLErp.Modules.TradeDalModule;
using YLErp.Office;
using YLErp.Plugins.TradeDocGenerator.Abstracts;
using static YLErp.ConsGlobal;
namespace YLErp.Modules.TradeModule.DocGenerateModule
{
public class SwapSettlementBillGenerateService : YLBaseService
{
public SwapSettlementBillGenerateService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 生成结算确认书
///
public IEnumerable Generate(IEnumerable flowEventIds, string docType, int userId, string userName)
{
if (docType == null)
{
throw new ArgumentNullException(nameof(docType));
}
var flowEvents = DbContext.swap_flow_event.Where(l => flowEventIds.Contains(l.id)).ToList();
var clientIds= flowEvents.Select(l => l.ClientId).ToList();
var eventDates= flowEvents.Select(l => l.UnwindDate).ToList();
var flowEventQuery = DbContext.swap_flow_event.Where(l => clientIds.Contains(l.ClientId) && eventDates.Contains(l.UnwindDate) && l.EventType == (int)SwapEventTypeEnum.平仓&&l.PositionType>0);
var newFlowEvents =from se in flowEventQuery
join s in DbContext.swap_event on se.EventId equals s.id
where s.Invalid==false
select se;
var eventIds = newFlowEvents.Select(l => l.EventId).ToList();
var tradeIds = newFlowEvents.Select(l => l.SwapTradeId).ToList();
if (tradeIds.Count() == 0)
{
throw new ArgumentNullException(nameof(tradeIds));
}
var trades = DbContext.trade.Where(x => tradeIds.Contains(x.id)).ToList();
var swapPositions = DbContext.swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && !x.Invalid).ToList();
var allFlowEvents = DbContext.swap_flow_event.Where(x => eventIds.Contains(x.EventId)).ToList();
var tradeContracts = DbContext.trade_contract_r.Where(x=> tradeIds.Contains(x.TradeId)&&x.Type== ContractTypeEnum.Clearing&&x.IsValid).ToList();
flowEvents = newFlowEvents.ToList();
// 定位要点:生成范围按【客户+平仓日】扩张——传入的是用户勾选的 flowEventIds,
// 实际生成会包含同客户同日全部平仓流水(PositionType>0)。若某笔交易未生成过交易确认书,
// TradeSettleBillGenerator 会整批抛"XX未生成交易确认书",此日志用于对齐"勾选了什么 vs 实际生成什么"。
LogFactory.GetLogger("GenerateSingleV2").Info(
$"生成结算确认书-生成范围: 传入flowEventIds[{string.Join(",", flowEventIds)}] " +
$"扩张后待生成[{string.Join(",", flowEvents.Select(f => $"{f.id}:{f.SwapTradeNo}"))}]");
//----------------------------------
// 交易确认书数据
//----------------------------------
var tcrQuery = from aa in DbContext.trade_contract_r
where tradeIds.Contains(aa.TradeId)
&& aa.Type == ContractTypeEnum.Trade && aa.IsValid
select aa;
var tcrDatas = tcrQuery.ToDictionary(K => K.TradeId, V => V);
//----------------------------------
// 生成交易结算书
//----------------------------------
var resultList = new List();
AppManager.TryResolve(out ITradeSettleBillGenerator generatorV2);
Dictionary> noDMAFlows = new Dictionary>();
List extendList = null;
if (flowEvents != null && flowEvents.Any())
{
var flowTradeIds = flowEvents.Where(p => p.PayDate == null || p.EventType != (int)SwapEventTypeEnum.平仓).Select(p => p.SwapTradeId).Distinct().ToList();
if (flowTradeIds != null && flowTradeIds.Count > 0)
{
extendList = DbContext.trade_extend.AsNoTracking().Where(p => flowTradeIds.Contains(p.TradeId)).ToList();
}
}
if (extendList == null)
{
extendList = new List();
}
foreach (var flowEvent in flowEvents)
{
var contract = tradeContracts.FirstOrDefault(x=>x.SwapFlowEventId==flowEvent.id);
if (contract!=null)
{
continue;
}
//重置payDate 解决系统除平仓外其余场景 payDate可能为空的情况
if (flowEvent.PayDate == null || flowEvent.EventType != (int)SwapEventTypeEnum.平仓)
{
var extend = extendList.FirstOrDefault(p => p.TradeId == flowEvent.SwapTradeId);
if (extend != null)
{
flowEvent.PayDate = flowEvent.UnwindDate.Value.AddDays(extend.ExtendObj.SettlementRules);
}
}
var trade = trades.FirstOrDefault(x => x.id == flowEvent.SwapTradeId);
if (trade == null)
{
throw new ServiceException("找不到交易");
}
if (trade.ValidState!=ConsGlobal.InValid)
{
if (noDMAFlows.ContainsKey(trade.ClientId))
{
noDMAFlows[trade.ClientId].Add(flowEvent);
}
else
{
noDMAFlows[trade.ClientId] = new List { flowEvent };
}
}
}
if (noDMAFlows.Count()==0)
{
throw new ServiceException("没有需要生成的确认书");
}
foreach (var item in noDMAFlows)
{
var noDMAResults = GenerateShanxiSwap(item.Key, item.Value, trades, swapPositions, allFlowEvents, generatorV2, docType);
resultList.AddRange(noDMAResults);
}
return resultList;
}
public void DelDoc(List flowEventIds)
{
if (flowEventIds.Count==0)
{
return;
}
var tradeContracts = DbContext.trade_contract_r.Where(x => flowEventIds.Contains(x.SwapFlowEventId??0) && x.Type == ContractTypeEnum.Clearing && x.IsValid).ToList();
var contractCodes = tradeContracts.Select(s=>s.ContractCode).Distinct().ToList();
tradeContracts= DbContext.trade_contract_r.Where(x => contractCodes.Contains(x.ContractCode)).ToList();
var contractDocs = DbContext.trade_contract_document.Where(x => contractCodes.Contains(x.Code)).ToList();
DbContext.trade_contract_document.RemoveRange(contractDocs);
DbContext.trade_contract_r.RemoveRange(tradeContracts);
DbContext.SaveChanges();
}
private List GenerateShanxiSwap(int clientId, List flowEvents, List trades, List swapPositions, List allFlowEvents, ITradeSettleBillGenerator generator,string docType)
{
var client = DataCacheProvider.GetClientDataSource().GetData(clientId);
if (client == null)
{
throw new ServiceException("未找到客户信息");
}
List docGenerateResults = new List();
foreach (var flowEvent in flowEvents.GroupBy(x => x.UnwindDate))//每个客户没日只有一份结算确认书
{
var flowEventGroups = flowEvent.ToList();
var tradeIds = flowEventGroups.Select(l => l.SwapTradeId).ToList();
var _trades = trades.Where(x=> tradeIds.Contains(x.id)).ToList();
try
{
var context = new SettlementBillGenerateContext(client, flowEventGroups, allFlowEvents, _trades, swapPositions, ContractTypeEnum.Clearing, OptUser);
generator.Initialize(docType, context);
var results= generator.GenerateDocuments();
docGenerateResults.AddRange(results);
}
catch (Exception ex)
{
LogFactory.GetLogger("GenerateSingleV2").Error(ex);
return new List() {new TradeDocGenerateResult(_trades)
{
Exception = ex,
ErrorMessage = "出错:" + ex.Message
} };
}
}
return docGenerateResults;
}
}
}