From e5a061d5b5e9d82586eea8d7c5be9f9ee0c66187 Mon Sep 17 00:00:00 2001 From: TekH Date: Fri, 14 Nov 2025 13:19:56 +0100 Subject: [PATCH] feat(ReadHistoryQuery): enhance ReadHistoryQuery to support Envelope object and UUID - Replace nullable `OnlyLast` with non-nullable default `true` - Support filtering by Envelope object (Id or Uuid) in addition to deprecated EnvelopeId - Throw `BadRequestException` if no valid Envelope reference is provided - Preserve status filtering and ordering for latest history entries --- .../Histories/Queries/HistoryQueryBase.cs | 12 +++++++++--- .../Histories/Queries/ReadHistoryQuery.cs | 19 +++++++++++++++++-- .../Controllers/AnnotationController.cs | 3 +++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/EnvelopeGenerator.Application/Histories/Queries/HistoryQueryBase.cs b/EnvelopeGenerator.Application/Histories/Queries/HistoryQueryBase.cs index 1286e465..ad953ee2 100644 --- a/EnvelopeGenerator.Application/Histories/Queries/HistoryQueryBase.cs +++ b/EnvelopeGenerator.Application/Histories/Queries/HistoryQueryBase.cs @@ -1,4 +1,5 @@ -using EnvelopeGenerator.Domain.Constants; +using EnvelopeGenerator.Application.Common.Query; +using EnvelopeGenerator.Domain.Constants; using System.ComponentModel.DataAnnotations; namespace EnvelopeGenerator.Application.Histories.Queries; @@ -12,11 +13,16 @@ public record HistoryQueryBase /// /// Die eindeutige Kennung des Umschlags. /// - [Required] - public int EnvelopeId { get; set; } + [Obsolete("Use Envelope property")] + public int? EnvelopeId { get; set; } /// /// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern. /// public EnvelopeStatus? Status { get; set; } + + /// + /// + /// + public EnvelopeQueryBase? Envelope { get; set; } } \ No newline at end of file diff --git a/EnvelopeGenerator.Application/Histories/Queries/ReadHistoryQuery.cs b/EnvelopeGenerator.Application/Histories/Queries/ReadHistoryQuery.cs index 6d86e8b8..e8852cfd 100644 --- a/EnvelopeGenerator.Application/Histories/Queries/ReadHistoryQuery.cs +++ b/EnvelopeGenerator.Application/Histories/Queries/ReadHistoryQuery.cs @@ -17,7 +17,7 @@ public record ReadHistoryQuery : HistoryQueryBase, IRequest /// Abfrage zur Steuerung, ob nur der aktuelle Include oder der gesamte Datensatz zurückgegeben wird. /// - public bool? OnlyLast { get; init; } = true; + public bool OnlyLast { get; init; } = true; } /// @@ -49,10 +49,25 @@ public class ReadHistoryQueryHandler : IRequestHandler public async Task> Handle(ReadHistoryQuery request, CancellationToken cancel = default) { - var query = _repo.Where(h => h.EnvelopeId == request.EnvelopeId); + var query = _repo.Query; + + if (request.Envelope?.Id is int envId) + query = query.Where(e => e.Id == envId); + else if (request.Envelope?.Uuid is string uuid) + query = query.Where(e => e.Envelope!.Uuid == uuid); +#pragma warning disable CS0618 // Type or member is obsolete + else if (request.EnvelopeId is not null) + query = query.Where(h => h.EnvelopeId == request.EnvelopeId); +#pragma warning restore CS0618 // Type or member is obsolete + else + throw new BadRequestException("Invalid request: An Envelope object or a valid EnvelopeId/UUID must be supplied."); + if (request.Status is not null) query = query.Where(h => h.Status == request.Status); + if (request.OnlyLast) + query = query.OrderByDescending(x => x.AddedWhen); + var hists = await query.ToListAsync(cancel); return _mapper.Map>(hists); } diff --git a/EnvelopeGenerator.Web/Controllers/AnnotationController.cs b/EnvelopeGenerator.Web/Controllers/AnnotationController.cs index c6fce59a..c7db46f0 100644 --- a/EnvelopeGenerator.Web/Controllers/AnnotationController.cs +++ b/EnvelopeGenerator.Web/Controllers/AnnotationController.cs @@ -4,6 +4,7 @@ using EnvelopeGenerator.Application.Common.Extensions; using EnvelopeGenerator.Application.Common.Interfaces.Services; using EnvelopeGenerator.Application.Common.Notifications.DocSigned; using EnvelopeGenerator.Application.EnvelopeReceivers.Queries; +using EnvelopeGenerator.Application.Histories.Queries; using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Web.Extensions; using MediatR; @@ -59,6 +60,8 @@ public class AnnotationController : ControllerBase // Again check if receiver has already signed if (await _mediator.IsSignedAsync(uuid, signature, cancel)) return Problem(statusCode: 403); + else if (await _mediator.AnyHistoryAsync()) + return Problem(statusCode: 200); var docSignedNotification = await _mediator .ReadEnvelopeReceiverAsync(uuid, signature, cancel)