using MediatR; using TakeoutSaaS.Application.App.Tenants.Commands; using TakeoutSaaS.Application.App.Tenants.Dto; using TakeoutSaaS.Application.Messaging.Abstractions; using TakeoutSaaS.Domain.Tenants.Enums; using TakeoutSaaS.Domain.Tenants.Events; using TakeoutSaaS.Domain.Tenants.Repositories; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Tenancy; namespace TakeoutSaaS.Application.App.Tenants.Handlers; /// /// 撤销公告处理器。 /// public sealed class RevokeAnnouncementCommandHandler( ITenantAnnouncementRepository announcementRepository, ITenantProvider tenantProvider, IEventPublisher eventPublisher) : IRequestHandler { /// public async Task Handle(RevokeAnnouncementCommand request, CancellationToken cancellationToken) { if (request.RowVersion == null || request.RowVersion.Length == 0) { throw new BusinessException(ErrorCodes.ValidationFailed, "RowVersion 不能为空"); } // 1. 查询公告 var tenantId = tenantProvider.GetCurrentTenantId(); var announcement = await announcementRepository.FindByIdAsync(tenantId, request.AnnouncementId, cancellationToken); if (announcement == null) { return null; } // 2. 校验状态 if (announcement.Status != AnnouncementStatus.Published) { if (announcement.Status == AnnouncementStatus.Revoked) { throw new BusinessException(ErrorCodes.Conflict, "公告已撤销"); } throw new BusinessException(ErrorCodes.Conflict, "仅已发布公告允许撤销"); } // 3. 撤销公告 announcement.Status = AnnouncementStatus.Revoked; announcement.RevokedAt = DateTime.UtcNow; announcement.RowVersion = request.RowVersion; try { await announcementRepository.UpdateAsync(announcement, cancellationToken); await announcementRepository.SaveChangesAsync(cancellationToken); } catch (Exception exception) when (exception.GetType().Name == "DbUpdateConcurrencyException") { throw new BusinessException(ErrorCodes.Conflict, "公告已被修改,请刷新后重试"); } // 4. 发布领域事件 await eventPublisher.PublishAsync( "tenant-announcement.revoked", new AnnouncementRevoked { AnnouncementId = announcement.Id, RevokedAt = announcement.RevokedAt ?? DateTime.UtcNow }, cancellationToken); return announcement.ToDto(false, null); } }