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
This commit is contained in:
tekh 2025-11-14 13:19:56 +01:00
parent 629b02863b
commit e5a061d5b5
3 changed files with 29 additions and 5 deletions

View File

@ -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
/// <summary>
/// Die eindeutige Kennung des Umschlags.
/// </summary>
[Required]
public int EnvelopeId { get; set; }
[Obsolete("Use Envelope property")]
public int? EnvelopeId { get; set; }
/// <summary>
/// Der Include des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.
/// </summary>
public EnvelopeStatus? Status { get; set; }
/// <summary>
///
/// </summary>
public EnvelopeQueryBase? Envelope { get; set; }
}

View File

@ -17,7 +17,7 @@ public record ReadHistoryQuery : HistoryQueryBase, IRequest<IEnumerable<HistoryD
/// <summary>
/// Abfrage zur Steuerung, ob nur der aktuelle Include oder der gesamte Datensatz zurückgegeben wird.
/// </summary>
public bool? OnlyLast { get; init; } = true;
public bool OnlyLast { get; init; } = true;
}
/// <summary>
@ -49,10 +49,25 @@ public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumer
/// <exception cref="NotFoundException"></exception>
public async Task<IEnumerable<HistoryDto>> 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<List<HistoryDto>>(hists);
}

View File

@ -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)