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.Ids;
using TakeoutSaaS.Shared.Abstractions.Security;
using TakeoutSaaS.Shared.Abstractions.Tenancy;
namespace TakeoutSaaS.Application.App.Merchants.Handlers;
///
/// 创建商户合同。
///
public sealed class CreateMerchantContractCommandHandler(
IMerchantRepository merchantRepository,
ITenantProvider tenantProvider,
IIdGenerator idGenerator,
ICurrentUserAccessor currentUserAccessor)
: IRequestHandler
{
public async Task Handle(CreateMerchantContractCommand request, CancellationToken cancellationToken)
{
// 1. 校验时间
if (request.EndDate <= request.StartDate)
{
throw new BusinessException(ErrorCodes.BadRequest, "合同结束时间必须晚于开始时间");
}
// 2. 查询商户
var tenantId = tenantProvider.GetCurrentTenantId();
var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken)
?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在");
// 3. 构建合同
var contract = new MerchantContract
{
Id = idGenerator.NextId(),
MerchantId = merchant.Id,
ContractNumber = request.ContractNumber.Trim(),
StartDate = request.StartDate,
EndDate = request.EndDate,
FileUrl = request.FileUrl.Trim()
};
// 4. 持久化与审计
await merchantRepository.AddContractAsync(contract, cancellationToken);
await merchantRepository.AddAuditLogAsync(new MerchantAuditLog
{
TenantId = tenantId,
MerchantId = merchant.Id,
Action = MerchantAuditAction.ContractUpdated,
Title = "新增合同",
Description = $"合同号:{contract.ContractNumber}",
OperatorId = ResolveOperatorId(),
OperatorName = ResolveOperatorName()
}, cancellationToken);
await merchantRepository.SaveChangesAsync(cancellationToken);
// 5. 返回 DTO
return MerchantMapping.ToDto(contract);
}
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}";
}
}