TekH 2b4573ea73 feat(ReadEnvelopeQuery): implement ReadEnvelopeQueryHandler with filtering support
- Added `ReadEnvelopeQueryHandler` to handle `ReadEnvelopeQuery`.
- Supports filtering envelopes by:
  - Included and ignored `EnvelopeStatus` values.
  - Minimum and maximum status.
  - Presence or absence of `DocResult`.
- Uses repository query extension methods and AutoMapper to map to `EnvelopeDto`.
2025-11-05 13:32:30 +01:00

140 lines
5.0 KiB
C#

using MediatR;
using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Application.Common.Query;
using EnvelopeGenerator.Application.Common.Dto;
using AutoMapper;
using DigitalData.Core.Abstraction.Application.Repository;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Domain.Entities;
using Microsoft.EntityFrameworkCore;
namespace EnvelopeGenerator.Application.Envelopes.Queries;
/// <summary>
/// Repräsentiert eine Abfrage für Umschläge.
/// </summary>
public record ReadEnvelopeQuery : EnvelopeQueryBase, IRequest<IEnumerable<EnvelopeDto>>
{
/// <summary>
/// Abfrage des Include des Umschlags
/// </summary>
public EnvelopeStatusQuery? Status { get; init; }
/// <summary>
///
/// </summary>
public bool? HasDocResult { get; init; }
}
/// <summary>
/// Repräsentiert den Include eines Umschlags und dessen Beziehung zum Empfänger. (vgl. auch <see cref="EnvelopeStatusQuery"/>
/// Invalid (0): Ungültiger Include.
/// EnvelopeCreated (1001): Der Umschlag wurde erstellt.
/// EnvelopeSaved (1002): Der Umschlag wurde gespeichert.
/// EnvelopeQueued (1003): Der Umschlag wurde zur Verarbeitung eingeplant.
/// EnvelopeSent (1004): Der Umschlag wurde versendet. (Nicht verwendet)
/// EnvelopePartlySigned (1005): Der Umschlag wurde teilweise unterschrieben.
/// EnvelopeCompletelySigned (1006): Der Umschlag wurde vollständig unterschrieben.
/// EnvelopeReportCreated (1007): Ein Abschlussbericht wurde für den Umschlag erstellt.
/// EnvelopeArchived (1008): Der Umschlag wurde archiviert.
/// EnvelopeDeleted (1009): Der Umschlag wurde gelöscht.
/// AccessCodeRequested (2001): Der Zugriffscode wurde angefordert.
/// AccessCodeCorrect (2002): Der Zugriffscode war korrekt.
/// AccessCodeIncorrect (2003): Der Zugriffscode war falsch.
/// DocumentOpened (2004): Das Dokument wurde geöffnet.
/// DocumentSigned (2005): Ein Dokument wurde unterschrieben.
/// SignatureConfirmed (2006): Die Signatur wurde bestätigt.
/// DocumentRejected (2007): Ein Dokument wurde abgelehnt.
/// EnvelopeShared (2008): Der Umschlag wurde geteilt.
/// EnvelopeViewed (2009): Der Umschlag wurde angesehen.
/// DocumentForwarded (4001): Das Dokument wurde weitergeleitet.
/// MessageInvitationSent (3001): Einladung wurde gesendet (vom Trigger verwendet).
/// MessageAccessCodeSent (3002): Zugriffscode wurde gesendet.
/// MessageConfirmationSent (3003): Bestätigungsnachricht wurde gesendet.
/// MessageDeletionSent (3004): Löschbenachrichtigung wurde gesendet.
/// MessageCompletionSent (3005): Abschlussbenachrichtigung wurde gesendet.
/// </summary>
public record EnvelopeStatusQuery
{
/// <summary>
/// Der minimale Statuswert, der berücksichtigt werden.
/// </summary>
public EnvelopeStatus? Min { get; init; }
/// <summary>
/// Der maximale Statuswert, der berücksichtigt werden.
/// </summary>
public EnvelopeStatus? Max { get; init; }
/// <summary>
/// Eine Liste von Statuswerten, die einbezogen werden.
/// </summary>
public EnvelopeStatus[]? Include { get; init; }
/// <summary>
/// Eine Liste von Statuswerten, die ignoriert werden werden.
/// </summary>
public EnvelopeStatus[]? Ignore { get; init; }
}
/// <summary>
///
/// </summary>
public class ReadEnvelopeQueryHandler : IRequestHandler<ReadEnvelopeQuery, IEnumerable<EnvelopeDto>>
{
private readonly IMapper _mapper;
private readonly IRepository<Envelope> _repo;
/// <summary>
///
/// </summary>
/// <param name="mapper"></param>
/// <param name="repo"></param>
public ReadEnvelopeQueryHandler(IMapper mapper, IRepository<Envelope> repo)
{
_mapper = mapper;
_repo = repo;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="cancel"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
public async Task<IEnumerable<EnvelopeDto>> Handle(ReadEnvelopeQuery request, CancellationToken cancel)
{
var q = _repo.Query.Where(request, notnull: false);
if (request.Status is EnvelopeStatusQuery statusQ)
{
// including status
if (statusQ.Include is EnvelopeStatus[] incStatus)
q = q.Where(e => incStatus.Contains(e.Status));
// ignoring status
if (statusQ.Ignore is EnvelopeStatus[] ignoreStatus)
q = q.Where(e => !ignoreStatus.Contains(e.Status));
// max status
if (statusQ.Max is EnvelopeStatus maxStatus)
q = q.Where(e => e.Status < maxStatus);
// min status
if (statusQ.Min is EnvelopeStatus minStatus)
q = q.Where(e => e.Status > minStatus);
}
if (request.HasDocResult is bool hasDocResult)
q = hasDocResult
? q.Where(e => e.DocResult != null)
: q.Where(e => e.DocResult == null);
var envelopes = await q.ToListAsync(cancel);
return _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
}
}