Files
Yi.Admin/Yi.Abp.Net8/module/ai-hub/Yi.Framework.AiHub.Domain/Managers/PremiumPackageManager.cs

134 lines
4.8 KiB
C#
Raw Normal View History

2025-10-12 16:42:26 +08:00
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Services;
using Yi.Framework.AiHub.Domain.Entities;
using Yi.Framework.AiHub.Domain.Shared.Enums;
using Yi.Framework.SqlSugarCore.Abstractions;
namespace Yi.Framework.AiHub.Domain.Managers;
/// <summary>
/// 尊享包管理器
/// </summary>
public class PremiumPackageManager : DomainService
{
private readonly ISqlSugarRepository<PremiumPackageAggregateRoot, Guid> _premiumPackageRepository;
private readonly ILogger<PremiumPackageManager> _logger;
private readonly ISqlSugarRepository<AiRechargeAggregateRoot> _rechargeRepository;
2025-10-12 16:42:26 +08:00
public PremiumPackageManager(
ISqlSugarRepository<PremiumPackageAggregateRoot, Guid> premiumPackageRepository,
ILogger<PremiumPackageManager> logger, ISqlSugarRepository<AiRechargeAggregateRoot> rechargeRepository)
2025-10-12 16:42:26 +08:00
{
_premiumPackageRepository = premiumPackageRepository;
_logger = logger;
_rechargeRepository = rechargeRepository;
2025-10-12 16:42:26 +08:00
}
/// <summary>
/// 为用户创建尊享包
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="goodsType">商品类型</param>
/// <param name="totalAmount">支付金额</param>
/// <param name="expireMonths">过期月数0或null表示永久</param>
/// <returns></returns>
public async Task<PremiumPackageAggregateRoot> CreatePremiumPackageAsync(
Guid userId,
GoodsTypeEnum goodsType,
decimal totalAmount,
int? expireMonths = null)
{
if (!goodsType.IsPremiumPackage())
{
throw new UserFriendlyException($"商品类型 {goodsType} 不是尊享包商品");
}
var tokenAmount = goodsType.GetTokenAmount();
var packageName = goodsType.GetDisplayName();
var premiumPackage = new PremiumPackageAggregateRoot(userId, tokenAmount, packageName)
{
PurchaseAmount = totalAmount
};
// 设置到期时间
if (expireMonths.HasValue && expireMonths.Value > 0)
{
premiumPackage.SetExpireDateTime(DateTime.Now.AddMonths(expireMonths.Value));
}
await _premiumPackageRepository.InsertAsync(premiumPackage);
// 创建充值记录
var rechargeRecord = new AiRechargeAggregateRoot
{
UserId = userId,
RechargeAmount = totalAmount,
Content = packageName,
ExpireDateTime = premiumPackage.ExpireDateTime,
Remark = "自助充值",
ContactInfo = null,
RechargeType = RechargeTypeEnum.PremiumPackage
};
// 保存充值记录到数据库
await _rechargeRepository.InsertAsync(rechargeRecord);
2025-10-12 16:42:26 +08:00
_logger.LogInformation(
$"用户 {userId} 购买尊享包成功: {packageName}, Token数量: {tokenAmount}, 金额: {totalAmount}");
return premiumPackage;
}
/// <summary>
/// 消耗用户尊享包的Token
/// </summary>
/// <param name="userId">用户ID</param>
/// <param name="tokenCount">需要消耗的Token数量</param>
/// <returns>是否消耗成功</returns>
public async Task<bool> TryConsumeTokensAsync(Guid userId, long tokenCount)
2025-10-12 16:42:26 +08:00
{
// 获取用户所有可用的尊享包按剩余token升序排列优先消耗快用完的
var availablePackages = await _premiumPackageRepository._DbQueryable
.Where(x => x.UserId == userId && x.IsActive)
.OrderBy(x => x.CreationTime)
2025-10-12 16:42:26 +08:00
.ToListAsync();
if (!availablePackages.Any())
{
_logger.LogWarning($"用户 {userId} 没有可用的尊享包");
return false;
}
// 过滤掉已过期的包
var validPackages = availablePackages
.Where(p => p.IsAvailable())
.ToList();
if (!validPackages.Any())
{
_logger.LogWarning($"用户 {userId} 的尊享包已全部过期");
return false;
}
var firstPackage = validPackages.First();
// 直接扣除最早的token包需要消耗的token允许扣减到负数
firstPackage.ConsumeTokens(tokenCount);
await _premiumPackageRepository.UpdateAsync(firstPackage);
2025-10-12 16:42:26 +08:00
return true;
2025-10-12 16:42:26 +08:00
}
/// <summary>
/// 获取用户可用的尊享包总Token数
/// </summary>
/// <param name="userId">用户ID</param>
/// <returns>可用Token总数</returns>
public async Task<long> GetAvailableTokensAsync(Guid userId)
{
return await _premiumPackageRepository._DbQueryable
2025-10-12 16:42:26 +08:00
.Where(x => x.UserId == userId && x.IsActive && x.RemainingTokens > 0)
.Where(p => p.IsActive)
.Where(p => !p.ExpireDateTime.HasValue || p.ExpireDateTime.Value >= DateTime.Now)
.SumAsync(p => p.RemainingTokens);
2025-10-12 16:42:26 +08:00
}
}