136 lines
5.1 KiB
C#
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
|
|
};
|
|
}
|
|
}
|