using BaseOUDAL; using Org.BouncyCastle.Ocsp; using Qdp.Pricing.Library.Base.Utilities; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Linq.Dynamic.Core; using YLErp.Helpers; using YLErp.Model; using YLErp.Office; using Newtonsoft.Json; using OfficeOpenXml; using YieldChain.Commons; using YLErp.Abstract; using Microsoft.Extensions.DependencyInjection; namespace YLErp.Modules.SwapModule { public class SwapRateService : YLBaseService { IKafkaProduce kafkaProduceHelper; public SwapRateService(OptUserInfo userInfo) : base(userInfo) { kafkaProduceHelper = YLServiceLocator.ServiceProvider.GetService(); } /// /// 查询阶梯费率 /// public SearchListResult SearchList(SwapRateSearchRequest req) { var predicate = PredicateBuilder.Create(n => 1 == 1); if (req.OptDateStart.HasValue) { predicate = predicate.And(n => n.opt_time >= req.OptDateStart.Value); } if (req.OptDateEnd.HasValue) { predicate = predicate.And(n => n.opt_time <= req.OptDateEnd.Value); } if (req.ClientIds.Count > 0) { predicate = predicate.And(n => req.ClientIds.Contains(n.ClientId)); } if (!string.IsNullOrEmpty(req.ClientNumber)) { predicate = predicate.And(x => x.ClientNumber.Contains(req.ClientNumber.Trim())); } if (req.TakeEffectDate.HasValue) { predicate = predicate.And(n => n.TakeEffectDate == req.TakeEffectDate); } if (!string.IsNullOrEmpty(req.OptName)) { predicate = predicate.And(n => n.opt_name == req.OptName); } var rateQuery = DbContext.swap_rate.Where(predicate); var clientQuery = DataCacheProvider.GetClientDataSource().AsQueryable(); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "create_time"; req.sord = "desc"; } var retListResult = rateQuery.ToSearchList(req); foreach (var item in retListResult.rows) { var client = clientQuery.FirstOrDefault(x => x.id == item.ClientId); item.ClientName = client?.Name; } return retListResult; } /// /// 保存互换费率 /// /// /// public void SaveSwapRate(SwapRate req) { var changeClient = DataCacheProvider.GetClientDataSource().GetData(req.ClientId); req.ClientNumber = changeClient?.Number; req.ClientName = changeClient?.Name; ValidateSwapRate(req); string changeStr = string.Empty; string changeTitle = "新增"; if (req.id > 0) { var swapRate = DbContext.swap_rate.Find(req.id); if (swapRate == null) { throw new ServiceException("未找到该阶梯费率"); } var client = DataCacheProvider.GetClientDataSource().GetData(swapRate.ClientId); swapRate.ClientNumber = client?.Number; swapRate.ClientName = client?.Name; var changeList = DataChangeHelper.GetDataChanges(swapRate, req); changeStr = changeList.ToJson(); changeTitle = "编辑"; swapRate.ClientId = req.ClientId; swapRate.ClientNumber = req.ClientNumber; swapRate.TakeEffectDate = req.TakeEffectDate; swapRate.TempRateIsPercent = req.TempRateIsPercent; swapRate.TempRate = req.TempRate; swapRate.BaseRate = req.BaseRate; swapRate.BaseRateIsPercent = req.BaseRateIsPercent; swapRate.DiscountAccDown = req.DiscountAccDown; swapRate.DiscountRateIsPercent = req.DiscountRateIsPercent; swapRate.DiscountRate = req.DiscountRate; swapRate.FrontDeskCharge = req.FrontDeskCharge; swapRate.FrontDeskChargeIsPercent = req.FrontDeskChargeIsPercent; swapRate.BackDeskCharge = req.BackDeskCharge; swapRate.BackDeskChargeIsPercent = req.BackDeskChargeIsPercent; swapRate.SetOpt(UserId, UserName); } else { req.SetCreator(UserId, UserName); req.SetOpt(UserId, UserName); DbContext.swap_rate.Add(req); } DbContext.SaveChanges(); new SwapRateLogService(UserInfo).AddSwapRateLog(0, req.id, changeTitle, changeStr, null); } /// /// 校验数据 /// /// /// private void ValidateSwapRate(SwapRate req) { if (req.BaseRate == null && req.TempRate == null) { throw new ServiceException("临时费率或基础费率不能为空"); } if (req.DiscountRate.HasValue && req.DiscountAccDown == null) { throw new ServiceException("优惠累计量下限不能为空"); } if (!req.DiscountRate.HasValue && req.DiscountAccDown.HasValue) { throw new ServiceException("优惠累计量下限有值的情况,优惠汇率不能为空"); } if (DbContext.swap_rate.Any(x => x.ClientId == req.ClientId && x.id != req.id && x.TakeEffectDate == req.TakeEffectDate)) { throw new ServiceException($"该客户在{req.TakeEffectDate:D}已经存在阶梯费率"); } } /// /// 删除阶梯费率 /// /// /// public int DeleteSwapRate(int id) { var swapRate = DbContext.swap_rate.Find(id); if (swapRate == null) { throw new ServiceException("未找到该阶梯费率"); } DbContext.swap_rate.Remove(swapRate); DbContext.SaveChanges(); return swapRate.ClientId; } /// /// 获取详细 /// /// /// /// public SwapRate GetSwapRate(int id) { var swapRate = DbContext.swap_rate.Find(id); if (swapRate == null) { throw new ServiceException("未找到该阶梯费率"); } var client = DataCacheProvider.GetClientDataSource().GetData(swapRate.ClientId); swapRate.ClientName = client?.Name; swapRate.ClientNumber = client?.Number; return swapRate; } /// /// 阶梯费率导入 excel /// /// 上传的文件 /// 总条数 /// 成功条数 public List ImportSwapRateFromExcel(Stream streamIn, out int totalNum, out int successNum) { totalNum = 0; successNum = 0; var rowIndex = 0; List clientIds = new List(); var trans = DbContext.Database.BeginTransaction(); try { var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0); if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2) { throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" }; } var table = ds.Tables[0]; var reader = new DataRowReaderHelper(table); rowIndex = 1; totalNum = table.Rows.Count - rowIndex; var clientList = DataCacheProvider.GetClientDataSource().AsQueryable().ToList(); foreach (var row in table.Rows.Cast().Skip(rowIndex)) { rowIndex++; if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString()))) { totalNum--; continue; } reader.SetDataRow(row, rowIndex); var swapRate = new SwapRate(); swapRate.ClientNumber = reader.GetString("客户编号", true); swapRate.TakeEffectDate = reader.GetDate("生效日期", true).Value; var client = clientList.FirstOrDefault(x => x.Number == swapRate.ClientNumber); if (client == null) { throw new ServiceException($"找不到客户编号为{swapRate.ClientNumber}的客户"); } swapRate.ClientId = client.id; clientIds.Add(client.id); var tempRate = reader.GetString("临时费率"); if (!string.IsNullOrEmpty(tempRate)) { decimal rate = 0; if (tempRate.EndsWith("%")) { swapRate.TempRateIsPercent = true; tempRate = tempRate.Replace("%", ""); decimal.TryParse(tempRate, out rate); rate = rate / 100; } else { swapRate.TempRateIsPercent = false; decimal.TryParse(tempRate, out rate); } swapRate.TempRate = rate; } var baseRate = reader.GetString("基础费率"); if (!string.IsNullOrEmpty(baseRate)) { decimal rate = 0; if (baseRate.EndsWith("%")) { swapRate.BaseRateIsPercent = true; baseRate = baseRate.Replace("%", ""); decimal.TryParse(baseRate, out rate); rate = rate / 100; } else { swapRate.BaseRateIsPercent = false; decimal.TryParse(baseRate, out rate); } swapRate.BaseRate = rate; } var disAccRate = reader.GetString("优惠费率"); if (!string.IsNullOrEmpty(disAccRate)) { decimal rate = 0; if (disAccRate.EndsWith("%")) { swapRate.DiscountRateIsPercent = true; disAccRate = disAccRate.Replace("%", ""); decimal.TryParse(disAccRate, out rate); rate = rate / 100; } else { swapRate.DiscountRateIsPercent = false; decimal.TryParse(disAccRate, out rate); } swapRate.DiscountRate = rate; } var frontRate = reader.GetString("现券对冲交易费用"); if (!string.IsNullOrEmpty(frontRate)) { if (frontRate.EndsWith("‱")) { swapRate.FrontDeskChargeIsPercent = true; frontRate = frontRate.Replace("‱", ""); } decimal.TryParse(frontRate, out var rate); swapRate.FrontDeskCharge = rate * 0.0001m; } var backRate = reader.GetString("现券对冲结算费用"); if (!string.IsNullOrEmpty(backRate)) { if (backRate.EndsWith("‱")) { swapRate.BackDeskChargeIsPercent = true; backRate = backRate.Replace("‱", ""); } decimal.TryParse(backRate, out var rate); swapRate.BackDeskCharge = rate * 0.0001m; } swapRate.DiscountAccDown = reader.GetDecimal("优惠累计量下限"); ValidateSwapRate(swapRate); swapRate.SetCreator(UserId, UserName); swapRate.SetOpt(UserId, UserName); DbContext.swap_rate.Add(swapRate); DbContext.SaveChanges(); new SwapRateLogService(UserInfo).AddSwapRateLog(0, swapRate.id, "新增", null, "导入"); successNum++; } trans.Commit(); trans.Dispose(); return clientIds; } catch (Exception ex) { trans.Rollback(); trans.Dispose(); LogFactory.GetLogger("导入阶梯费率").Error(ex); throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}"); } } /// /// 阶梯费率导出 /// /// /// /// public byte[] exprotSwapRateExcel(SwapRateSearchRequest req) { //获取数据 var ret = SearchList(req); List list = new List(); foreach (var item in ret.rows) { SwapRateExportModel exportModel = new SwapRateExportModel(); exportModel.ClientNumber = item.ClientNumber; exportModel.ClientName = item.ClientName; exportModel.TakeEffectDate = item.TakeEffectDate.OtcFormatDate(); exportModel.BaseRate = item.BaseRateIsPercent ? item.BaseRate.OtcFormatPercent(4) : item.BaseRate.OtcFormatMoney(true); exportModel.TempRate = item.TempRateIsPercent ? item.TempRate.OtcFormatPercent(4) : item.TempRate.OtcFormatMoney(true); exportModel.DiscountRate = item.DiscountRateIsPercent ? item.DiscountRate.OtcFormatPercent(4) : item.DiscountRate.OtcFormatMoney(true); exportModel.DiscountAccDown = item.DiscountAccDown.OtcFormatMoney(true); exportModel.FrontDeskCharge = item.FrontDeskChargeIsPercent == true ? item.FrontDeskCharge.OtcFormatTenThousandsPercent(4) : item.FrontDeskCharge.OtcFormatMoney(true); exportModel.BackDeskCharge = item.BackDeskChargeIsPercent == true ? item.BackDeskCharge.OtcFormatTenThousandsPercent(4) : item.BackDeskCharge.OtcFormatMoney(true); list.Add(exportModel); } var tplFilePath = OtcAppContext.MapPath("/App_Docs"); var sourceFileName = Path.Combine(tplFilePath, "导出模板", "阶梯费率导出模板.xlsx"); var modelDict = new Dictionary(); var model = new { list = list }; modelDict.Add("Sheet1", model); ExcelPackage.LicenseContext = LicenseContext.NonCommercial; return new ExcelTemplateGenerator().SetTemplateFile(sourceFileName).SetTemplateData(modelDict).Output(); } /// /// 将最新的费率发送到kafka /// /// /// public void SendSwapRateToKafka(int clientId) { var swapRate = GetClientSwapRate(clientId); if (swapRate == null) { swapRate = new SwapRate() { ClientId = clientId, }; } var monthStart = GetMonthStart(); var clientPosiNotional = DbContext.trade.Where(x => x.TradeDate >= monthStart && x.ValidState != ConsGlobal.InValid && x.TradeType == "收益互换" && x.ClientId == clientId && ConsTrade.TradeStatusCustomexport.Contains(x.TradeStatus)).ToList().Sum(s => s.OriginalStockEqvNotional ?? 0); SendToKafka(swapRate, clientPosiNotional); } public void SendAllSwapRateToKafka() { var swapRates = DbContext.swap_rate.Where(x => x.TakeEffectDate <= DateTime.Now.Date).GroupBy(g => g.ClientId).Select(g => g.OrderByDescending(o => o.TakeEffectDate).FirstOrDefault()).ToList(); var monthStart = GetMonthStart(); var posiNotionalValueGroup = DbContext.trade.Where(x => x.TradeDate >= monthStart && x.ValidState != ConsGlobal.InValid && x.TradeType == "收益互换" && ConsTrade.TradeStatusCustomexport.Contains(x.TradeStatus)).ToList().GroupBy(x => x.ClientId); foreach (var swapRate in swapRates) { var clientPosiNotional = posiNotionalValueGroup.FirstOrDefault(x => x.Key == swapRate.ClientId).ToList().Sum(s => s.OriginalStockEqvNotional ?? 0); SendToKafka(swapRate, clientPosiNotional); } } /// /// 获取月初 /// /// private DateTime GetMonthStart() { DateTime currentDate = DateTime.Today; // 获取当前日期(包括当前年月日) DateTime monthStart = new DateTime(currentDate.Year, currentDate.Month, 1); return monthStart; } private void SendToKafka(SwapRate swapRate, double clientPosiNotional) { SwapRateKafkaModel swapRateKafkaModel = new SwapRateKafkaModel(); swapRateKafkaModel.clientId = swapRate.ClientId; swapRateKafkaModel.frontDeskCharge = swapRate.FrontDeskCharge ?? 0; swapRateKafkaModel.isFrontDeskChargePercent = swapRate.FrontDeskChargeIsPercent ?? true; swapRateKafkaModel.backDeskCharge = swapRate.BackDeskCharge ?? 0; swapRateKafkaModel.isBackDeskChargePercent = swapRate.BackDeskChargeIsPercent ?? true; if (swapRate.TempRate.HasValue) { swapRateKafkaModel.isRate = swapRate.TempRateIsPercent; swapRateKafkaModel.rate = swapRate.TempRate ?? 0; } else { swapRateKafkaModel.isRate = swapRate.BaseRateIsPercent; swapRateKafkaModel.rate = swapRate.BaseRate ?? 0; swapRateKafkaModel.disRateDown = swapRate.DiscountAccDown ?? 0; if (swapRate.DiscountAccDown.HasValue && Convert.ToDecimal(clientPosiNotional) >= swapRateKafkaModel.disRateDown) { swapRateKafkaModel.isDisRate = swapRate.DiscountRateIsPercent; swapRateKafkaModel.disRate = swapRate.DiscountRate ?? 0; swapRateKafkaModel.rate = swapRateKafkaModel.disRate; } } kafkaProduceHelper.Produce(Environment.GetEnvironmentVariable("KafkaConfig_ClientRateTopic"), JsonConvert.SerializeObject(swapRateKafkaModel)); } private SwapRate GetClientSwapRate(int clientId) { return DbContext.swap_rate.Where(x => x.ClientId == clientId && x.TakeEffectDate <= DateTime.Now.Date).OrderByDescending(o => o.TakeEffectDate).FirstOrDefault(); } } }