feat(application): add MediatR commands and handlers with exception improvements
MediatR Commands (CQRS Pattern): - CreateEmailProfileCommand + Handler - UpdateEmailProfileCommand + Handler - DeleteEmailProfileCommand + Handler - CreateEmailAccountCommand + Handler - ProcessEmailCommand + Handler (core email processing logic) Command Handlers: - Create/Update/Delete operations for EmailProfile - Create operation for EmailAccount - ProcessEmail: Complete email processing workflow including: * Duplicate detection using MessageId hash * Email history creation * PDF attachment validation * windream DMS archiving support (placeholder) * Domain event publishing (EmailProcessedEvent) * Error handling and status tracking Exception Improvements: - Added ErrorCode property to DomainException - Added ErrorCode overload to ValidationException - Simplified AttachmentProcessingException to use base ErrorCode Field Mappings Fixed: - EmailProfile: ProcessId (not EmailProcessId), ValidationSql (not SenderFilter/SubjectFilter) - EmailAccount: Username, EncryptedPassword, UseOAuth2, EncryptedClientSecret - EmailHistory: SenderAddress, EmailDate, OriginalMessageId, EmailBodyText/Html - EmailAttachment: OriginalFileName, SavedFileName, FilePath, FileSize - Audit fields: AddedWhen/AddedWho, ChangedWhen/ChangedWho (not CreatedDate/By, ModifiedDate/By) All commands follow Clean Architecture and use UnitOfWork pattern. Build successful with 1 minor warning (dmsService marked for future implementation).
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Application.Features.EmailProfiles.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Command to create a new email profile.
|
||||
/// </summary>
|
||||
public record CreateEmailProfileCommand : IRequest<int>
|
||||
{
|
||||
public string ProfileName { get; init; } = string.Empty;
|
||||
public int EmailAccountId { get; init; }
|
||||
public int? ProcessId { get; init; }
|
||||
public string? ValidationSql { get; init; }
|
||||
public int PollIntervalMinutes { get; init; } = 15;
|
||||
public bool IsActive { get; init; } = true;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
using DigitalData.EmailProfiler.Application.Interfaces.Repositories;
|
||||
using DigitalData.EmailProfiler.Domain.Entities;
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Application.Features.EmailProfiles.Commands;
|
||||
|
||||
public class CreateEmailProfileCommandHandler(IUnitOfWork unitOfWork)
|
||||
: IRequestHandler<CreateEmailProfileCommand, int>
|
||||
{
|
||||
public async Task<int> Handle(CreateEmailProfileCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var profile = new EmailProfile
|
||||
{
|
||||
ProfileName = request.ProfileName,
|
||||
EmailAccountId = request.EmailAccountId,
|
||||
ProcessId = request.ProcessId,
|
||||
ValidationSql = request.ValidationSql,
|
||||
PollIntervalMinutes = request.PollIntervalMinutes,
|
||||
IsActive = request.IsActive,
|
||||
AddedWhen = DateTime.Now,
|
||||
AddedWho = "System" // TODO: Get from current user context
|
||||
};
|
||||
|
||||
var createdProfile = await unitOfWork.EmailProfiles.AddAsync(profile, cancellationToken);
|
||||
await unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return createdProfile.Id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Application.Features.EmailProfiles.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Command to delete an email profile.
|
||||
/// </summary>
|
||||
public record DeleteEmailProfileCommand(int Id) : IRequest<Unit>;
|
||||
@@ -0,0 +1,20 @@
|
||||
using DigitalData.EmailProfiler.Application.Interfaces.Repositories;
|
||||
using DigitalData.EmailProfiler.Domain.Exceptions;
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Application.Features.EmailProfiles.Commands;
|
||||
|
||||
public class DeleteEmailProfileCommandHandler(IUnitOfWork unitOfWork)
|
||||
: IRequestHandler<DeleteEmailProfileCommand, Unit>
|
||||
{
|
||||
public async Task<Unit> Handle(DeleteEmailProfileCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var profile = await unitOfWork.EmailProfiles.GetByIdAsync(request.Id, cancellationToken)
|
||||
?? throw new DomainException($"Email profile with ID {request.Id} not found");
|
||||
|
||||
await unitOfWork.EmailProfiles.DeleteAsync(profile, cancellationToken);
|
||||
await unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return Unit.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Application.Features.EmailProfiles.Commands;
|
||||
|
||||
/// <summary>
|
||||
/// Command to update an existing email profile.
|
||||
/// </summary>
|
||||
public record UpdateEmailProfileCommand : IRequest<Unit>
|
||||
{
|
||||
public int Id { get; init; }
|
||||
public string ProfileName { get; init; } = string.Empty;
|
||||
public string? ValidationSql { get; init; }
|
||||
public int PollIntervalMinutes { get; init; }
|
||||
public bool IsActive { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
using DigitalData.EmailProfiler.Application.Interfaces.Repositories;
|
||||
using DigitalData.EmailProfiler.Domain.Exceptions;
|
||||
using MediatR;
|
||||
|
||||
namespace DigitalData.EmailProfiler.Application.Features.EmailProfiles.Commands;
|
||||
|
||||
public class UpdateEmailProfileCommandHandler(IUnitOfWork unitOfWork)
|
||||
: IRequestHandler<UpdateEmailProfileCommand, Unit>
|
||||
{
|
||||
public async Task<Unit> Handle(UpdateEmailProfileCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var profile = await unitOfWork.EmailProfiles.GetByIdAsync(request.Id, cancellationToken)
|
||||
?? throw new DomainException($"Email profile with ID {request.Id} not found");
|
||||
|
||||
profile.ProfileName = request.ProfileName;
|
||||
profile.ValidationSql = request.ValidationSql;
|
||||
profile.PollIntervalMinutes = request.PollIntervalMinutes;
|
||||
profile.IsActive = request.IsActive;
|
||||
profile.ChangedWhen = DateTime.Now;
|
||||
profile.ChangedWho = "System"; // TODO: Get from current user context
|
||||
|
||||
await unitOfWork.EmailProfiles.UpdateAsync(profile, cancellationToken);
|
||||
await unitOfWork.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return Unit.Value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user