176 lines
5.7 KiB
C#
176 lines
5.7 KiB
C#
|
|
using YD_Event.Application.Refund.Dtos;
|
||
|
|
using YD_Event.Core.Entities;
|
||
|
|
|
||
|
|
namespace YD_Event.Application.Refund;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 退款配置服务
|
||
|
|
/// </summary>
|
||
|
|
public class RefundConfigService : BaseService<RefundConfig>, ITransient
|
||
|
|
{
|
||
|
|
private readonly ISqlSugarRepository<RefundConfig> _repository;
|
||
|
|
private readonly IIdGenerator _idGenerator;
|
||
|
|
private readonly IEasyCachingProvider _easyCachingProvider;
|
||
|
|
private const string CacheKey = "RefundConfig:List";
|
||
|
|
|
||
|
|
public RefundConfigService(ISqlSugarRepository<RefundConfig> repository,
|
||
|
|
IIdGenerator idGenerator,
|
||
|
|
IEasyCachingProvider easyCachingProvider) : base(repository)
|
||
|
|
{
|
||
|
|
_repository = repository;
|
||
|
|
_idGenerator = idGenerator;
|
||
|
|
_easyCachingProvider = easyCachingProvider;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 获取所有退款配置
|
||
|
|
/// </summary>
|
||
|
|
/// <returns></returns>
|
||
|
|
[DisplayName("获取所有退款配置")]
|
||
|
|
[HttpGet("list")]
|
||
|
|
public async Task<List<RefundConfigDto>> GetList()
|
||
|
|
{
|
||
|
|
// 优先从缓存获取
|
||
|
|
var cacheValue = await _easyCachingProvider.GetAsync<List<RefundConfigDto>>(CacheKey);
|
||
|
|
if (cacheValue.HasValue)
|
||
|
|
{
|
||
|
|
return cacheValue.Value;
|
||
|
|
}
|
||
|
|
|
||
|
|
var list = await _repository.GetListAsync();
|
||
|
|
var dtos = list.OrderBy(x => x.DayStart).Adapt<List<RefundConfigDto>>();
|
||
|
|
|
||
|
|
// 写入缓存,过期时间 1 小时
|
||
|
|
await _easyCachingProvider.SetAsync(CacheKey, dtos, TimeSpan.FromHours(1));
|
||
|
|
|
||
|
|
return dtos;
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 分页查询退款配置
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="input"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[DisplayName("分页查询退款配置")]
|
||
|
|
[HttpGet("page")]
|
||
|
|
public async Task<PageResult<RefundConfigDto>> Page([FromQuery] RefundConfigQueryInput input)
|
||
|
|
{
|
||
|
|
return await _repository.AsQueryable()
|
||
|
|
.WhereIF(input.Status.HasValue, x => x.Status == input.Status)
|
||
|
|
.OrderBy(x => x.DayStart)
|
||
|
|
.Select(x => new RefundConfigDto
|
||
|
|
{
|
||
|
|
Id = x.Id,
|
||
|
|
DayStart = x.DayStart,
|
||
|
|
DayEnd = x.DayEnd,
|
||
|
|
DeductPercentage = x.DeductPercentage,
|
||
|
|
Remark = x.Remark,
|
||
|
|
Status = x.Status
|
||
|
|
})
|
||
|
|
.ToPagedListAsync(input);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 添加退款配置
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="input"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[DisplayName("添加退款配置")]
|
||
|
|
[HttpPost("add")]
|
||
|
|
public async Task Add(RefundConfigInput input)
|
||
|
|
{
|
||
|
|
// 简单重叠校验
|
||
|
|
var isExist = await _repository.IsAnyAsync(x =>
|
||
|
|
(input.DayStart >= x.DayStart && input.DayStart < x.DayEnd) ||
|
||
|
|
(input.DayEnd > x.DayStart && input.DayEnd <= x.DayEnd) ||
|
||
|
|
(input.DayStart <= x.DayStart && input.DayEnd >= x.DayEnd));
|
||
|
|
|
||
|
|
if (isExist) throw Oops.Bah("退款规则时间段存在重叠");
|
||
|
|
|
||
|
|
var entity = input.Adapt<RefundConfig>();
|
||
|
|
entity.Id = _idGenerator.NextId();
|
||
|
|
await _repository.InsertAsync(entity);
|
||
|
|
|
||
|
|
// 清除缓存
|
||
|
|
await _easyCachingProvider.RemoveAsync(CacheKey);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 更新退款配置
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="input"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[DisplayName("更新退款配置")]
|
||
|
|
[HttpPut("update")]
|
||
|
|
public async Task Update(RefundConfigInput input)
|
||
|
|
{
|
||
|
|
if (!input.Id.HasValue) throw Oops.Bah("Id不能为空");
|
||
|
|
|
||
|
|
// 校验重叠 (排除自身)
|
||
|
|
var isExist = await _repository.IsAnyAsync(x =>
|
||
|
|
x.Id != input.Id &&
|
||
|
|
((input.DayStart >= x.DayStart && input.DayStart < x.DayEnd) ||
|
||
|
|
(input.DayEnd > x.DayStart && input.DayEnd <= x.DayEnd) ||
|
||
|
|
(input.DayStart <= x.DayStart && input.DayEnd >= x.DayEnd)));
|
||
|
|
|
||
|
|
if (isExist) throw Oops.Bah("退款规则时间段存在重叠");
|
||
|
|
|
||
|
|
var entity = await _repository.GetByIdAsync(input.Id.Value);
|
||
|
|
if (entity == null) throw Oops.Bah("配置不存在");
|
||
|
|
|
||
|
|
input.Adapt(entity);
|
||
|
|
await _repository.UpdateAsync(entity);
|
||
|
|
|
||
|
|
// 清除缓存
|
||
|
|
await _easyCachingProvider.RemoveAsync(CacheKey);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 删除退款配置
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="ids"></param>
|
||
|
|
/// <returns></returns>
|
||
|
|
[DisplayName("删除退款配置")]
|
||
|
|
[HttpPost("delete")]
|
||
|
|
public async Task Delete([FromBody] List<long> ids)
|
||
|
|
{
|
||
|
|
await _repository.DeleteAsync(x => ids.Contains(x.Id));
|
||
|
|
|
||
|
|
// 清除缓存
|
||
|
|
await _easyCachingProvider.RemoveAsync(CacheKey);
|
||
|
|
}
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// 计算退款金额
|
||
|
|
/// </summary>
|
||
|
|
/// <param name="totalAmount">总金额</param>
|
||
|
|
/// <param name="eventStartTime">赛事开始时间</param>
|
||
|
|
/// <returns>应退金额</returns>
|
||
|
|
[NonAction]
|
||
|
|
public async Task<decimal> CalculateRefundAmount(decimal totalAmount, DateTime eventStartTime)
|
||
|
|
{
|
||
|
|
// 优先使用 GetList (带缓存)
|
||
|
|
var configs = await GetList();
|
||
|
|
configs = configs.Where(x => x.Status == Core.Enum.AvailabilityStatus.Enable).ToList();
|
||
|
|
|
||
|
|
if (!configs.Any()) return totalAmount;
|
||
|
|
|
||
|
|
var daysRemaining = (eventStartTime - DateTime.Now).TotalDays;
|
||
|
|
if (daysRemaining < 0) daysRemaining = 0;
|
||
|
|
|
||
|
|
// 查找匹配的规则
|
||
|
|
var matchConfig = configs.FirstOrDefault(c =>
|
||
|
|
daysRemaining >= c.DayStart &&
|
||
|
|
(c.DayEnd == int.MaxValue ? true : daysRemaining < c.DayEnd)
|
||
|
|
);
|
||
|
|
|
||
|
|
if (matchConfig != null)
|
||
|
|
{
|
||
|
|
var deductAmount = totalAmount * (matchConfig.DeductPercentage / 100m);
|
||
|
|
return totalAmount - deductAmount;
|
||
|
|
}
|
||
|
|
|
||
|
|
return totalAmount;
|
||
|
|
}
|
||
|
|
}
|