refactor: 订阅任务按租户上下文执行
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class BatchExtendSubscriptionsCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<BatchExtendSubscriptionsCommandHandler> logger)
|
||||
: IRequestHandler<BatchExtendSubscriptionsCommand, BatchExtendResult>
|
||||
@@ -23,8 +21,6 @@ public sealed class BatchExtendSubscriptionsCommandHandler(
|
||||
/// <inheritdoc />
|
||||
public async Task<BatchExtendResult> Handle(BatchExtendSubscriptionsCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
var successCount = 0;
|
||||
var failures = new List<BatchFailureItem>();
|
||||
|
||||
@@ -41,8 +37,7 @@ public sealed class BatchExtendSubscriptionsCommandHandler(
|
||||
// 查询所有订阅
|
||||
var subscriptions = await subscriptionRepository.FindByIdsAsync(
|
||||
request.SubscriptionIds,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
foreach (var subscriptionId in request.SubscriptionIds)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class BatchSendReminderCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<BatchSendReminderCommandHandler> logger)
|
||||
: IRequestHandler<BatchSendReminderCommand, BatchSendReminderResult>
|
||||
@@ -23,16 +21,13 @@ public sealed class BatchSendReminderCommandHandler(
|
||||
/// <inheritdoc />
|
||||
public async Task<BatchSendReminderResult> Handle(BatchSendReminderCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
var successCount = 0;
|
||||
var failures = new List<BatchFailureItem>();
|
||||
|
||||
// 查询所有订阅及租户信息
|
||||
var subscriptions = await subscriptionRepository.FindByIdsWithTenantAsync(
|
||||
request.SubscriptionIds,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
foreach (var subscriptionId in request.SubscriptionIds)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Dto;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Queries;
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ChangeSubscriptionPlanCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IIdGenerator idGenerator,
|
||||
IMediator mediator)
|
||||
: IRequestHandler<ChangeSubscriptionPlanCommand, SubscriptionDetailDto?>
|
||||
@@ -23,13 +21,10 @@ public sealed class ChangeSubscriptionPlanCommandHandler(
|
||||
/// <inheritdoc />
|
||||
public async Task<SubscriptionDetailDto?> Handle(ChangeSubscriptionPlanCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 查询订阅
|
||||
var subscription = await subscriptionRepository.FindByIdAsync(
|
||||
request.SubscriptionId,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
if (subscription == null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Dto;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Queries;
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ExtendSubscriptionCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IIdGenerator idGenerator,
|
||||
IMediator mediator)
|
||||
: IRequestHandler<ExtendSubscriptionCommand, SubscriptionDetailDto?>
|
||||
@@ -23,13 +21,10 @@ public sealed class ExtendSubscriptionCommandHandler(
|
||||
/// <inheritdoc />
|
||||
public async Task<SubscriptionDetailDto?> Handle(ExtendSubscriptionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 查询订阅
|
||||
var subscription = await subscriptionRepository.FindByIdAsync(
|
||||
request.SubscriptionId,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
if (subscription == null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Dto;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Queries;
|
||||
using TakeoutSaaS.Application.App.Tenants;
|
||||
@@ -12,20 +11,16 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// 订阅详情查询处理器。
|
||||
/// </summary>
|
||||
public sealed class GetSubscriptionDetailQueryHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
ISubscriptionRepository subscriptionRepository)
|
||||
: IRequestHandler<GetSubscriptionDetailQuery, SubscriptionDetailDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<SubscriptionDetailDto?> Handle(GetSubscriptionDetailQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 查询订阅基础信息
|
||||
var detail = await subscriptionRepository.GetDetailAsync(
|
||||
request.SubscriptionId,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
if (detail == null)
|
||||
{
|
||||
@@ -35,8 +30,7 @@ public sealed class GetSubscriptionDetailQueryHandler(
|
||||
// 2. 查询配额使用情况
|
||||
var quotaUsages = await subscriptionRepository.GetQuotaUsagesAsync(
|
||||
detail.Subscription.TenantId,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
var quotaUsageDtos = BuildQuotaUsageDtos(detail.Package, quotaUsages);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Dto;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Queries;
|
||||
using TakeoutSaaS.Domain.Tenants.Repositories;
|
||||
@@ -11,15 +10,12 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// 订阅分页查询处理器。
|
||||
/// </summary>
|
||||
public sealed class GetSubscriptionListQueryHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor)
|
||||
ISubscriptionRepository subscriptionRepository)
|
||||
: IRequestHandler<GetSubscriptionListQuery, PagedResult<SubscriptionListDto>>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<PagedResult<SubscriptionListDto>> Handle(GetSubscriptionListQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 构建查询过滤条件
|
||||
var filter = new SubscriptionSearchFilter
|
||||
{
|
||||
@@ -36,8 +32,7 @@ public sealed class GetSubscriptionListQueryHandler(
|
||||
// 2. 执行分页查询
|
||||
var (items, total) = await subscriptionRepository.SearchPagedAsync(
|
||||
filter,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
// 3. 映射为 DTO
|
||||
var dtos = items.Select(x => new SubscriptionListDto
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
@@ -14,7 +13,6 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ProcessAutoRenewalCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ITenantBillingRepository billingRepository,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<ProcessAutoRenewalCommandHandler> logger)
|
||||
@@ -23,8 +21,6 @@ public sealed class ProcessAutoRenewalCommandHandler(
|
||||
/// <inheritdoc />
|
||||
public async Task<ProcessAutoRenewalResult> Handle(ProcessAutoRenewalCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 计算续费阈值时间
|
||||
var now = DateTime.UtcNow;
|
||||
var renewalThreshold = now.AddDays(request.RenewalDaysBeforeExpiry);
|
||||
@@ -33,8 +29,7 @@ public sealed class ProcessAutoRenewalCommandHandler(
|
||||
var candidates = await subscriptionRepository.FindAutoRenewalCandidatesAsync(
|
||||
now,
|
||||
renewalThreshold,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
var createdBillCount = 0;
|
||||
|
||||
// 3. 遍历候选订阅,生成账单
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using System.Text.Json;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
@@ -15,7 +14,6 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ProcessRenewalRemindersCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ITenantNotificationRepository notificationRepository,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<ProcessRenewalRemindersCommandHandler> logger)
|
||||
@@ -26,8 +24,6 @@ public sealed class ProcessRenewalRemindersCommandHandler(
|
||||
/// <inheritdoc />
|
||||
public async Task<ProcessRenewalRemindersResult> Handle(ProcessRenewalRemindersCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 读取提醒配置
|
||||
var now = DateTime.UtcNow;
|
||||
var candidateCount = 0;
|
||||
@@ -46,8 +42,7 @@ public sealed class ProcessRenewalRemindersCommandHandler(
|
||||
var candidates = await subscriptionRepository.FindRenewalReminderCandidatesAsync(
|
||||
startOfDay,
|
||||
endOfDay,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
candidateCount += candidates.Count;
|
||||
|
||||
foreach (var item in candidates)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
@@ -12,26 +11,21 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class ProcessSubscriptionExpiryCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILogger<ProcessSubscriptionExpiryCommandHandler> logger)
|
||||
: IRequestHandler<ProcessSubscriptionExpiryCommand, ProcessSubscriptionExpiryResult>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<ProcessSubscriptionExpiryResult> Handle(ProcessSubscriptionExpiryCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 查询到期订阅
|
||||
var now = DateTime.UtcNow;
|
||||
var expiredActive = await subscriptionRepository.FindExpiredActiveSubscriptionsAsync(
|
||||
now,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
var gracePeriodExpired = await subscriptionRepository.FindGracePeriodExpiredSubscriptionsAsync(
|
||||
now,
|
||||
request.GracePeriodDays,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
// 2. 更新订阅状态
|
||||
foreach (var subscription in expiredActive)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Dto;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Queries;
|
||||
@@ -12,20 +11,16 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateSubscriptionCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IMediator mediator)
|
||||
: IRequestHandler<UpdateSubscriptionCommand, SubscriptionDetailDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<SubscriptionDetailDto?> Handle(UpdateSubscriptionCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 查询订阅
|
||||
var subscription = await subscriptionRepository.FindByIdAsync(
|
||||
request.SubscriptionId,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
if (subscription == null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using MediatR;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Commands;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Dto;
|
||||
using TakeoutSaaS.Application.App.Subscriptions.Queries;
|
||||
@@ -12,20 +11,16 @@ namespace TakeoutSaaS.Application.App.Subscriptions.Handlers;
|
||||
/// </summary>
|
||||
public sealed class UpdateSubscriptionStatusCommandHandler(
|
||||
ISubscriptionRepository subscriptionRepository,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
IMediator mediator)
|
||||
: IRequestHandler<UpdateSubscriptionStatusCommand, SubscriptionDetailDto?>
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public async Task<SubscriptionDetailDto?> Handle(UpdateSubscriptionStatusCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var ignoreTenantFilter = SubscriptionTenantAccess.ShouldIgnoreTenantFilter(httpContextAccessor);
|
||||
|
||||
// 1. 查询订阅
|
||||
var subscription = await subscriptionRepository.FindByIdAsync(
|
||||
request.SubscriptionId,
|
||||
cancellationToken,
|
||||
ignoreTenantFilter: ignoreTenantFilter);
|
||||
cancellationToken);
|
||||
|
||||
if (subscription == null)
|
||||
{
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Subscriptions;
|
||||
|
||||
internal static class SubscriptionTenantAccess
|
||||
{
|
||||
public static bool ShouldIgnoreTenantFilter(IHttpContextAccessor httpContextAccessor)
|
||||
{
|
||||
var httpContext = httpContextAccessor.HttpContext;
|
||||
if (httpContext == null)
|
||||
{
|
||||
// Background jobs / out-of-request execution should process across tenants.
|
||||
return true;
|
||||
}
|
||||
// (空行后) 请求上下文下强制不允许跨租户
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user