400 lines
18 KiB
C#
400 lines
18 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 System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading.Tasks;
|
|
using YLErp.DBModels;
|
|
using YLErp.Helpers;
|
|
using YLErp.Model;
|
|
using static YLErp.Commons.ExcelHelper;
|
|
using YLErp.Modules.SystemModule;
|
|
using System.Drawing;
|
|
using YLErp.Commons;
|
|
using YLErp.Office.ExcelModule;
|
|
using YLErp.Office;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.BLL.Calculation;
|
|
using OfficeOpenXml;
|
|
|
|
namespace YLErp.Modules.SwapModule
|
|
{
|
|
public class SwapFloatRateService : YLBaseService
|
|
{
|
|
public SwapFloatRateService(OptUserInfo userInfo) : base(userInfo)
|
|
{
|
|
}
|
|
/// <summary>
|
|
/// 查询浮动利率
|
|
/// </summary>
|
|
public SearchListResult<SwapFloatRate> SearchList(SwapFloatRateSearchRequest req)
|
|
{
|
|
var predicate = PredicateBuilder.Create<SwapFloatRate>(n => n.RateMode==req.RateMode);
|
|
|
|
if (req.StartDate.HasValue)
|
|
{
|
|
predicate = predicate.And(n => n.StartDate >= req.StartDate.Value);
|
|
}
|
|
if (req.EndDate.HasValue)
|
|
{
|
|
predicate = predicate.And(n => n.EndDate <= req.EndDate.Value);
|
|
}
|
|
if (req.ClientIds!=null&&req.ClientIds.Count > 0)
|
|
{
|
|
predicate = predicate.And(n => req.ClientIds.Contains(n.ClientId??0));
|
|
}
|
|
if (!string.IsNullOrEmpty(req.ClientNumber))
|
|
{
|
|
predicate = predicate.And(x => x.ClientNumber.Contains(req.ClientNumber.Trim()));
|
|
}
|
|
if (!string.IsNullOrEmpty(req.UnderlyingCodes))
|
|
{
|
|
var underlyings = req.UnderlyingCodes.Split(",");
|
|
predicate = predicate.And(x => underlyings.Contains(x.UnderlyingCode));
|
|
}
|
|
var rateQuery = DbContext.swap_float_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 SaveSwapFloatRate(SwapFloatRate req)
|
|
{
|
|
ValidateSwapFloatRate(req);
|
|
string changeStr = string.Empty;
|
|
string changeTitle = "新增";
|
|
if (req.id > 0)
|
|
{
|
|
var swapFloatRate = DbContext.swap_float_rate.Find(req.id);
|
|
if (swapFloatRate == null)
|
|
{
|
|
throw new ServiceException("未找到该浮动利率");
|
|
}
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFloatRate.UnderlyingCode);
|
|
swapFloatRate.UnderlyingName = underlying?.UnderlyingName;
|
|
if (swapFloatRate.ClientId>0)
|
|
{
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(swapFloatRate.ClientId.Value);
|
|
swapFloatRate.ClientName=client?.Name;
|
|
swapFloatRate.ClientNumber=client?.Number;
|
|
}
|
|
var changeList = DataChangeHelper.GetDataChanges(swapFloatRate, req);
|
|
changeStr = changeList.ToJson();
|
|
changeTitle = "编辑";
|
|
swapFloatRate.UnderlyingCode= req.UnderlyingCode;
|
|
swapFloatRate.StartDate = req.StartDate;
|
|
swapFloatRate.EndDate = req.EndDate;
|
|
swapFloatRate.LongPricePoint = req.LongPricePoint;
|
|
swapFloatRate.ShortPricePoint = req.ShortPricePoint;
|
|
swapFloatRate.BaseUnderlyingCode = req.BaseUnderlyingCode;
|
|
swapFloatRate.ClientId = req.ClientId;
|
|
swapFloatRate.ClientNumber = req.ClientNumber;
|
|
swapFloatRate.ClientName = req.ClientName;
|
|
swapFloatRate.interest_type = req.interest_type;
|
|
swapFloatRate.interest_rest_days = req.interest_rest_days;
|
|
swapFloatRate.interest_rule = req.interest_rule;
|
|
swapFloatRate.is_annualized = req.is_annualized;
|
|
swapFloatRate.SetOpt(UserId, UserName);
|
|
}
|
|
else
|
|
{
|
|
req.SetCreator(UserId, UserName);
|
|
req.SetOpt(UserId, UserName);
|
|
DbContext.swap_float_rate.Add(req);
|
|
}
|
|
DbContext.SaveChanges();
|
|
new SwapRateLogService(UserInfo).AddSwapRateLog(1, req.id, changeTitle, changeStr, null);
|
|
}
|
|
/// <summary>
|
|
/// 校验数据
|
|
/// </summary>
|
|
/// <param name="req"></param>
|
|
/// <exception cref="ServiceException"></exception>
|
|
private void ValidateSwapFloatRate(SwapFloatRate req)
|
|
{
|
|
if (!string.IsNullOrEmpty(req.UnderlyingCode))
|
|
{
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.UnderlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"债券代码{req.UnderlyingCode}不存在");
|
|
}
|
|
req.UnderlyingName = underlying.UnderlyingName;
|
|
}
|
|
if (!string.IsNullOrEmpty(req.BaseUnderlyingCode))
|
|
{
|
|
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(req.BaseUnderlyingCode);
|
|
if (underlying == null)
|
|
{
|
|
throw new ServiceException($"基准利率代码{req.BaseUnderlyingCode}不存在");
|
|
}
|
|
req.UnderlyingName = underlying.UnderlyingName;
|
|
}
|
|
if (req.RateMode== (int)ConstSwapFloatRateEnum.Special)
|
|
{
|
|
if (!req.ClientId.HasValue)
|
|
{
|
|
throw new ServiceException("客户名称不能为空");
|
|
}
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(req.ClientId.Value);
|
|
if (client==null)
|
|
{
|
|
throw new ServiceException("客户名称不存在");
|
|
|
|
}
|
|
req.ClientName = client?.Name;
|
|
req.ClientNumber = client?.Number;
|
|
}
|
|
if (req.StartDate==null)
|
|
{
|
|
throw new ServiceException("生效起始日不能为空");
|
|
}
|
|
if (req.EndDate == null)
|
|
{
|
|
throw new ServiceException("生效终止日不能为空");
|
|
}
|
|
if (req.StartDate> req.EndDate)
|
|
{
|
|
throw new ServiceException("生效终止日不能早于生效起始日");
|
|
}
|
|
if (req.LongPricePoint==null&&req.ShortPricePoint==null)
|
|
{
|
|
throw new ServiceException("多头价格加点或空头价格减点不能为空");
|
|
}
|
|
var predicate = PredicateBuilder.Create<SwapFloatRate>(x => x.id != req.id && x.UnderlyingCode == req.UnderlyingCode && x.StartDate <= req.EndDate && x.EndDate >= req.StartDate&&x.RateMode==req.RateMode);
|
|
if (req.ClientId>0)
|
|
{
|
|
predicate = predicate.And(x=>x.ClientId==req.ClientId);
|
|
}
|
|
if (DbContext.swap_float_rate.Any(predicate))
|
|
{
|
|
throw new ServiceException($"该生效区间内已经存在浮动利率");
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// 删除阶梯费率
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <exception cref="Exception"></exception>
|
|
public void DeleteSwapFloatRate(int id)
|
|
{
|
|
var clientRate = DbContext.swap_float_rate.Find(id);
|
|
if (clientRate == null)
|
|
{
|
|
throw new ServiceException("未找到该浮动利率");
|
|
}
|
|
DbContext.swap_float_rate.Remove(clientRate);
|
|
DbContext.SaveChanges();
|
|
}
|
|
/// <summary>
|
|
/// 获取详细
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="ServiceException"></exception>
|
|
public SwapFloatRate GetSwapFloatRate(int id)
|
|
{
|
|
var swapFloatRate = DbContext.swap_float_rate.Find(id);
|
|
if (swapFloatRate == null)
|
|
{
|
|
throw new ServiceException("未找到该浮动利率");
|
|
}
|
|
if (swapFloatRate.ClientId>0)
|
|
{
|
|
var client = DataCacheProvider.GetClientDataSource().GetData(swapFloatRate.ClientId.Value);
|
|
swapFloatRate.ClientName = client?.Name;
|
|
}
|
|
return swapFloatRate;
|
|
}
|
|
/// <summary>
|
|
/// 阶梯费率导入 excel
|
|
/// </summary>
|
|
/// <param name="streamIn">上传的文件</param>
|
|
/// <param name="totalNum">总条数</param>
|
|
/// <param name="successNum">成功条数</param>
|
|
public void ImportSwapFloatRateFromExcel(Stream streamIn, out int totalNum, out int successNum)
|
|
{
|
|
totalNum = 0;
|
|
successNum = 0;
|
|
var rowIndex = 0;
|
|
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 swapFloatRate = new SwapFloatRate();
|
|
swapFloatRate.UnderlyingCode = reader.GetString("债券代码");
|
|
swapFloatRate.BaseUnderlyingCode = reader.GetString("基准利率");
|
|
swapFloatRate.StartDate = reader.GetDate("生效起始日",true).Value;
|
|
swapFloatRate.EndDate = reader.GetDate("生效终止日", true).Value;
|
|
swapFloatRate.interest_rest_days = reader.GetInt32("重置频率", true);
|
|
var interestType = reader.GetString("计息方式", true);
|
|
if (Enum.TryParse<InterestTypeEnum>(interestType, out InterestTypeEnum parsedInterestType))
|
|
{
|
|
swapFloatRate.interest_type = (int)parsedInterestType;
|
|
}
|
|
else
|
|
{
|
|
// 如果转换失败,可以根据需要处理错误
|
|
throw new Exception($"无法将计息方式 '{interestType}' 转换为有效的枚举值");
|
|
}
|
|
var rule = reader.GetString("利率准则", true);
|
|
if (Enum.TryParse<SwapInterestRule>(rule, out SwapInterestRule parsedRule))
|
|
{
|
|
swapFloatRate.interest_rule = (int)parsedRule;
|
|
}
|
|
else
|
|
{
|
|
// 如果转换失败,可以根据需要处理错误
|
|
throw new Exception($"无法将利率准则 '{rule}' 转换为有效的枚举值");
|
|
}
|
|
var is_annualized = reader.GetString("是否年化", true);
|
|
swapFloatRate.is_annualized = is_annualized == "是";
|
|
swapFloatRate.LongPricePoint = reader.GetDecimal("利差(多头加点)");
|
|
swapFloatRate.ShortPricePoint = reader.GetDecimal("利差(空头减点)");
|
|
swapFloatRate.ClientName = reader.GetString("客户名称");
|
|
if (!string.IsNullOrEmpty(swapFloatRate.ClientName))
|
|
{
|
|
var client = clientList.FirstOrDefault(x => x.Name == swapFloatRate.ClientName);
|
|
if (client == null)
|
|
{
|
|
throw new ServiceException($"找不到客户名称为{swapFloatRate.ClientName}的客户");
|
|
}
|
|
swapFloatRate.ClientId = client.id;
|
|
swapFloatRate.ClientNumber = client.Number;
|
|
}
|
|
if (reader.ExistFieldName("客户名称"))
|
|
{
|
|
swapFloatRate.RateMode = 1;
|
|
}
|
|
ValidateSwapFloatRate(swapFloatRate);
|
|
swapFloatRate.SetCreator(UserId,UserName);
|
|
swapFloatRate.SetOpt(UserId, UserName);
|
|
DbContext.swap_float_rate.Add(swapFloatRate);
|
|
DbContext.SaveChanges();
|
|
new SwapRateLogService(UserInfo).AddSwapRateLog(1, swapFloatRate.id, "新增", null, "导入");
|
|
successNum++;
|
|
}
|
|
trans.Commit();
|
|
trans.Dispose();
|
|
}
|
|
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[] exprotSwapFloatRateExcel(SwapFloatRateSearchRequest req)
|
|
{
|
|
//获取数据
|
|
var ret = SearchList(req);
|
|
var tplFilePath = OtcAppContext.MapPath("/App_Docs");
|
|
var tplName = "浮动利率默认设置导出模板.xlsx";
|
|
if (req.RateMode==(int)ConstSwapFloatRateEnum.Special)
|
|
{
|
|
tplName = "浮动利率特殊设置导出模板.xlsx";
|
|
}
|
|
var sourceFileName = Path.Combine(tplFilePath, "导出模板", tplName);
|
|
var modelDict = new Dictionary<string, object>();
|
|
var model = new { list = ret.rows.ToList() };
|
|
modelDict.Add("Sheet1", model);
|
|
ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
|
|
return new ExcelTemplateGenerator().SetTemplateFile(sourceFileName).SetTemplateData(modelDict).Output();
|
|
}
|
|
|
|
/// <summary>
|
|
/// 匹配最适用的浮动利率
|
|
/// </summary>
|
|
/// <param name="clientId"></param>
|
|
/// <param name="underlyingCode"></param>
|
|
/// <param name="startDate"></param>
|
|
/// <param name="endDate"></param>
|
|
/// <returns></returns>
|
|
public SwapFloatRate MatchRate(int clientId,string underlyingCode,DateTime startDate,DateTime? endDate)
|
|
{
|
|
var predicate = PredicateBuilder.Create<SwapFloatRate>(x => x.StartDate <= startDate);
|
|
if (endDate.HasValue)
|
|
{
|
|
predicate = predicate.And(x=>x.EndDate>=endDate);
|
|
}
|
|
var query=DbContext.swap_float_rate.Where(predicate);
|
|
SwapFloatRate swapFloatRate = GetSwapFloatRate(query,clientId, underlyingCode);
|
|
return swapFloatRate;
|
|
}
|
|
public SwapFloatRate GetSwapFloatRate(IQueryable<SwapFloatRate> query, int clientId, string underlyingCode)
|
|
{
|
|
SwapFloatRate swapFloatRate = null;
|
|
if (!string.IsNullOrEmpty(underlyingCode))
|
|
{
|
|
swapFloatRate = query.Where(x => x.UnderlyingCode == underlyingCode && x.ClientId == clientId).OrderByDescending(o => o.StartDate).FirstOrDefault();//取特殊逻辑 客户+标的
|
|
if (swapFloatRate != null)
|
|
{
|
|
return swapFloatRate;
|
|
}
|
|
}
|
|
swapFloatRate = query.Where(x => x.ClientId == clientId&&string.IsNullOrEmpty(x.UnderlyingCode)).OrderByDescending(o => o.StartDate).FirstOrDefault();//取特殊逻辑 客户+空标的
|
|
if (swapFloatRate != null)
|
|
{
|
|
return swapFloatRate;
|
|
}
|
|
if (!string.IsNullOrEmpty(underlyingCode))
|
|
{
|
|
swapFloatRate = query.Where(x => x.UnderlyingCode == underlyingCode&& x.RateMode == 0).OrderByDescending(o => o.StartDate).FirstOrDefault();//取默认逻辑 标的
|
|
if (swapFloatRate != null)
|
|
{
|
|
return swapFloatRate;
|
|
}
|
|
}
|
|
swapFloatRate = query.Where(x=>x.RateMode==0&&string.IsNullOrEmpty(x.UnderlyingCode)).OrderByDescending(o => o.StartDate).FirstOrDefault();//取默认逻辑 空标的
|
|
return swapFloatRate;
|
|
}
|
|
}
|
|
}
|