Files
TakeoutSaaS.AdminApi/src/Application/TakeoutSaaS.Application/App/Subscriptions/Handlers/BatchExtendSubscriptionsCommandHandler.cs

136 lines
5.1 KiB
C#

using MediatR;
using Microsoft.Extensions.Logging;
using System.Text.Json;
using TakeoutSaaS.Application.App.Subscriptions.Commands;
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
using TakeoutSaaS.Domain.Tenants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Ids;
namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
/// <summary>
/// 批量延期订阅命令处理器。
/// </summary>
public sealed class BatchExtendSubscriptionsCommandHandler(
ISubscriptionRepository subscriptionRepository,
IIdGenerator idGenerator,
ILogger<BatchExtendSubscriptionsCommandHandler> logger)
: IRequestHandler<BatchExtendSubscriptionsCommand, BatchExtendResult>
{
/// <inheritdoc />
public async Task<BatchExtendResult> Handle(BatchExtendSubscriptionsCommand request, CancellationToken cancellationToken)
{
var successCount = 0;
var failures = new List<BatchFailureItem>();
// 验证参数
if (!request.DurationDays.HasValue && !request.DurationMonths.HasValue)
{
throw new InvalidOperationException("必须指定延期天数或延期月数");
}
// 计算延期时间
var extendDays = request.DurationDays ?? 0;
var extendMonths = request.DurationMonths ?? 0;
// 查询所有订阅
var subscriptions = await subscriptionRepository.FindByIdsAsync(
request.SubscriptionIds,
cancellationToken);
foreach (var subscriptionId in request.SubscriptionIds)
{
try
{
var subscription = subscriptions.FirstOrDefault(s => s.Id == subscriptionId);
if (subscription == null)
{
failures.Add(new BatchFailureItem
{
SubscriptionId = subscriptionId,
Reason = "订阅不存在"
});
continue;
}
// 记录原始到期时间
var originalEffectiveTo = subscription.EffectiveTo;
// 计算新的到期时间
var newEffectiveTo = subscription.EffectiveTo;
if (extendMonths > 0)
{
newEffectiveTo = newEffectiveTo.AddMonths(extendMonths);
}
if (extendDays > 0)
{
newEffectiveTo = newEffectiveTo.AddDays(extendDays);
}
subscription.EffectiveTo = newEffectiveTo;
// 更新备注
if (!string.IsNullOrWhiteSpace(request.Notes))
{
subscription.Notes = request.Notes;
}
// 记录变更历史
var history = new TenantSubscriptionHistory
{
Id = idGenerator.NextId(),
TenantId = subscription.TenantId,
TenantSubscriptionId = subscription.Id,
FromPackageId = subscription.TenantPackageId,
ToPackageId = subscription.TenantPackageId,
ChangeType = SubscriptionChangeType.Renew,
EffectiveFrom = originalEffectiveTo,
EffectiveTo = newEffectiveTo,
Amount = null,
Currency = null,
Notes = request.Notes ?? $"批量延期: {(extendMonths > 0 ? $"{extendMonths}" : "")}{(extendDays > 0 ? $"{extendDays}" : "")}"
};
await subscriptionRepository.AddHistoryAsync(history, cancellationToken);
await subscriptionRepository.UpdateAsync(subscription, cancellationToken);
successCount++;
}
catch (Exception ex)
{
logger.LogError(ex, "批量延期订阅失败: SubscriptionId={SubscriptionId}", subscriptionId);
failures.Add(new BatchFailureItem
{
SubscriptionId = subscriptionId,
Reason = $"处理失败: {ex.Message}"
});
}
}
// 记录操作日志
var operationLog = new OperationLog
{
Id = idGenerator.NextId(),
OperationType = "BatchExtend",
TargetType = "Subscription",
TargetIds = JsonSerializer.Serialize(request.SubscriptionIds),
Parameters = JsonSerializer.Serialize(new { request.DurationDays, request.DurationMonths, request.Notes }),
Result = JsonSerializer.Serialize(new { SuccessCount = successCount, FailureCount = failures.Count }),
Success = failures.Count == 0,
CreatedAt = DateTime.UtcNow
};
await subscriptionRepository.AddOperationLogAsync(operationLog, cancellationToken);
// 保存所有更改
await subscriptionRepository.SaveChangesAsync(cancellationToken);
return new BatchExtendResult
{
SuccessCount = successCount,
FailureCount = failures.Count,
Failures = failures
};
}
}