using MediatR;
using TakeoutSaaS.Application.App.Merchants.Commands;
using TakeoutSaaS.Application.App.Merchants.Dto;
using TakeoutSaaS.Domain.Merchants.Entities;
using TakeoutSaaS.Domain.Merchants.Enums;
using TakeoutSaaS.Domain.Merchants.Repositories;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Exceptions;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.App.Merchants.Handlers;
///
/// 商户审核处理器。
///
public sealed class ReviewMerchantCommandHandler(
IMerchantRepository merchantRepository,
ITenantProvider tenantProvider,
ICurrentUserAccessor currentUserAccessor)
: IRequestHandler
{
public async Task Handle(ReviewMerchantCommand request, CancellationToken cancellationToken)
{
// 1. 读取商户
var tenantId = tenantProvider.GetCurrentTenantId();
var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken)
?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在");
// 2. 已审核通过则直接返回
if (request.Approve && merchant.Status == MerchantStatus.Approved)
{
return MerchantMapping.ToDto(merchant);
}
// 3. 更新审核状态
var previousStatus = merchant.Status;
merchant.Status = request.Approve ? MerchantStatus.Approved : MerchantStatus.Rejected;
merchant.ReviewRemarks = request.Remarks;
merchant.LastReviewedAt = DateTime.UtcNow;
if (request.Approve && merchant.JoinedAt == null)
{
merchant.JoinedAt = DateTime.UtcNow;
}
// 4. 持久化与审计
await merchantRepository.UpdateMerchantAsync(merchant, cancellationToken);
await merchantRepository.AddAuditLogAsync(new MerchantAuditLog
{
TenantId = tenantId,
MerchantId = merchant.Id,
Action = MerchantAuditAction.MerchantReviewed,
Title = request.Approve ? "商户审核通过" : "商户审核驳回",
Description = request.Remarks,
OperatorId = ResolveOperatorId(),
OperatorName = ResolveOperatorName()
}, cancellationToken);
await merchantRepository.SaveChangesAsync(cancellationToken);
// 5. 返回 DTO
return MerchantMapping.ToDto(merchant);
}
private long? ResolveOperatorId()
{
var id = currentUserAccessor.UserId;
return id == 0 ? null : id;
}
private string ResolveOperatorName()
{
var id = currentUserAccessor.UserId;
return id == 0 ? "system" : $"user:{id}";
}
}