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; } } }