Files
zszq-trs/YLErpDAL/Modules/SwapModule/SwapRateService.cs
T
hjhan ea609525f2 feat(SwapModule): 添加阶梯费率导入功能的详细日志记录
- 在解析线下费率前记录原始值和空值检查结果
- 记录百分比格式识别和转换过程中的详细信息
- 添加解析成功和失败情况的日志输出
- 记录直接解析小数格式的处理过程
- 添加最终设置OfflineRate值的日志记录
- 完善空值情况下的日志输出
2026-01-26 17:35:56 +08:00

414 lines
19 KiB
C#

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;
using YLErp.Cache;
namespace YLErp.Modules.SwapModule
{
public class SwapRateService : YLBaseService
{
IKafkaProduce kafkaProduceHelper;
public SwapRateService(OptUserInfo userInfo) : base(userInfo)
{
kafkaProduceHelper = YLServiceLocator.ServiceProvider.GetService<IKafkaProduce>();
}
/// <summary>
/// 查询阶梯费率
/// </summary>
public SearchListResult<SwapRate> SearchList(SwapRateSearchRequest req)
{
var predicate = PredicateBuilder.Create<SwapRate>(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;
}
/// <summary>
/// 保存互换费率
/// </summary>
/// <param name="req"></param>
/// <exception cref="Exception"></exception>
public void SaveSwapRate(SwapRate req, IYLCache ylCache)
{
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.OfflineRate = req.OfflineRate;
swapRate.SetOpt(UserId, UserName);
// 盘中修改了阶梯费率,存储到redis中
ylCache.StringSetWithNoPrefix<string>("TRS:Update:ClientRate:" + swapRate.ClientId, swapRate.id, TimeSpan.FromHours(8));
}
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);
}
/// <summary>
/// 校验数据
/// </summary>
/// <param name="req"></param>
/// <exception cref="ServiceException"></exception>
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}已经存在阶梯费率");
}
}
/// <summary>
/// 删除阶梯费率
/// </summary>
/// <param name="id"></param>
/// <exception cref="Exception"></exception>
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;
}
/// <summary>
/// 获取详细
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
/// <exception cref="ServiceException"></exception>
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;
}
/// <summary>
/// 阶梯费率导入 excel
/// </summary>
/// <param name="streamIn">上传的文件</param>
/// <param name="totalNum">总条数</param>
/// <param name="successNum">成功条数</param>
public List<int> ImportSwapRateFromExcel(Stream streamIn, out int totalNum, out int successNum)
{
totalNum = 0;
successNum = 0;
var rowIndex = 0;
List<int> clientIds = new List<int>();
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<DataRow>().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 = true;
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 = true;
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 = true;
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("优惠累计量下限");
// 处理线下费率
var offlineRate = reader.GetString("线下费率");
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,原始线下费率值: '{offlineRate}', IsNullOrEmpty: {string.IsNullOrEmpty(offlineRate)}");
if (!string.IsNullOrEmpty(offlineRate))
{
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,线下费率非空,准备解析: '{offlineRate}'");
decimal rate = 0;
if (offlineRate.EndsWith("%"))
{
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,线下费率是百分比格式: '{offlineRate}'");
offlineRate = offlineRate.Replace("%", "");
if (decimal.TryParse(offlineRate, out rate))
{
rate /= 100;
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,百分比解析成功: {offlineRate}% -> {rate}");
}
else
{
LogFactory.GetLogger("导入阶梯费率").Error($"第{rowIndex}行,百分比数值解析失败: '{offlineRate}'");
rate = 0;
}
}
else
{
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,线下费率不是百分比格式: '{offlineRate}', 尝试直接解析");
// 如果不是百分比格式,直接尝试解析为小数
if (!decimal.TryParse(offlineRate, out rate))
{
// 解析失败时的处理
LogFactory.GetLogger("导入阶梯费率").Error($"第{rowIndex}行,线下费率解析失败: '{offlineRate}'");
rate = 0;
}
else
{
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,直接解析成功: {offlineRate} -> {rate}");
}
}
swapRate.OfflineRate = rate;
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,最终设置OfflineRate为: {rate}");
}
else
{
LogFactory.GetLogger("导入阶梯费率").Info($"第{rowIndex}行,线下费率为null或空字符串");
}
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}");
}
}
/// <summary>
/// 阶梯费率导出
/// </summary>
/// <param name="req"></param>
/// <returns></returns>
/// <exception cref="ServiceException"></exception>
public byte[] exprotSwapRateExcel(SwapRateSearchRequest req)
{
//获取数据
var ret = SearchList(req);
List<SwapRateExportModel> list = new List<SwapRateExportModel>();
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);
exportModel.OfflineRate = item.OfflineRate.OtcFormatPercent(4);
list.Add(exportModel);
}
var tplFilePath = OtcAppContext.MapPath("/App_Docs");
var sourceFileName = Path.Combine(tplFilePath, "导出模板", "阶梯费率导出模板.xlsx");
var modelDict = new Dictionary<string, object>();
var model = new { list = list };
modelDict.Add("Sheet1", model);
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
return new ExcelTemplateGenerator().SetTemplateFile(sourceFileName).SetTemplateData(modelDict).Output();
}
}
}