Compare commits

..

15 Commits

Author SHA1 Message Date
Developer 02
456c591fae Bump version to 1.2.3 for EnvelopeGenerator.GeneratorAPI
Updated the version information in the project file,
incrementing `<Version>`, `<FileVersion>`, and `<AssemblyVersion>`
from 1.2.2 to 1.2.3.
2025-05-12 11:14:56 +02:00
Developer 02
41b2841c25 Add validation to ReadHistoryQuery and remove StatusName
Updated ReadHistoryQuery to include a [Required] attribute for the EnvelopeId property, enforcing mandatory validation. Removed the StatusName property from ReadHistoryResponse, which may impact how status is accessed in the application.
2025-05-12 11:07:53 +02:00
Developer 02
6a6da4a876 Update mapping in ReadHistoryMappingProfile constructor
Changed mapping from EnvelopeHistory to ReadHistoryResponse.
2025-05-12 10:58:21 +02:00
Developer 02
af280ee64e Add MediatR support for envelope history queries
Updated project references and introduced MediatR for handling
envelope history queries. Added new mapping profile and response
class, and refactored the HistoryController to utilize the
mediator pattern for improved query handling.
2025-05-12 10:55:19 +02:00
Developer 02
9b945ce232 Add error handling and update history query logic
- Introduced a using directive for exceptions in DocumentCreateReadSQL.cs.
- Enhanced CreateParmas method with try-catch for base64 conversion errors, throwing BadRequestException on failure.
- Added switch statement in HistoryController.cs to manage Related property in ReadHistoryQuery, setting flags for receiver and sender.
2025-05-12 10:04:33 +02:00
Developer 02
8b1199bc71 Add Related property to ReadHistoryQuery and update controller
The `ReadHistoryQuery` record now includes a computed `Related` property that determines the context of the record based on the `Status` value. The constructor has been updated to remove the `Related` parameter.

Additionally, the `GetAllAsync` method in `HistoryController` has been modified to handle the `Related` property, setting the `withReceiver` boolean when the value is `ReferenceType.Receiver`.
2025-05-12 09:57:14 +02:00
Developer 02
1d74b7ca06 Remove null check for EmailAddress in GetReceiverName
This commit removes the conditional check for the `EmailAddress` property in the `GetReceiverName` method. As a result, the method will no longer return a `BadRequest` if `EmailAddress` is null, which may lead to unvalidated null values being passed to the `_erService.ReadLastUsedReceiverNameByMailAsync` method.
2025-05-12 09:46:59 +02:00
Developer 02
c1bce7c639 Refactor receiver methods for async support
Updated repository and service interfaces to use async methods for retrieving receiver information. Changed method signatures to include optional parameters for `id` and `signature`, and made existing parameters nullable. Adjusted related service and controller implementations to ensure consistent usage of the new async methods. Improved error handling in the repository to enforce parameter requirements. Updated using directives in the repository for necessary dependencies.
2025-05-12 09:38:29 +02:00
Developer 02
4401a70217 Refactor EnvelopeDto and improve response handling
Updated the `EnvelopeDto` class by removing several properties to simplify the data structure and added `AddedWhen`, `ChangedWhen`, and a nullable `EnvelopeType`.

Modified the return statement in `EnvelopeController.cs` to return `NotFound()` when no envelopes are present, enhancing the accuracy of HTTP responses.
2025-05-12 09:19:12 +02:00
Developer 02
fd53f5bfd6 Enhance DTOs and controller with documentation and checks
- Added XML documentation comments to properties in `EnvelopeHistoryDto.cs`.
- Changed `EnvelopeId` to non-nullable in `ReadHistoryQuery.cs` and added `Status` parameter for filtering.
- Removed unused `using` directives in `HistoryController.cs` and updated `GetAllAsync` to filter histories by `Status`, returning `NotFound` if no results are found.
2025-05-11 20:54:04 +02:00
Developer 02
6126fce24d Refactor MemoryCacheExtensions and HistoryController
Updated MemoryCacheExtensions to accept more flexible parameters in GetEnumAsDictionary and improved the merging logic for ignored values. Simplified HistoryController by removing the logger dependency and adjusted GetReferenceTypes to include a key parameter for cache retrieval.
2025-05-11 15:19:37 +02:00
Developer 02
ce41090979 Enhance MemoryCacheExtensions and update HistoryController
- Modified `GetEnumAsDictionary` to accept a key and ignores for better caching and filtering of enum values.
- Updated XML documentation in `HistoryController.cs` to correct status code descriptions.
- Adjusted `GetEnvelopeStatus` to use the new parameters for improved control over cached enum values.
2025-05-11 15:01:12 +02:00
Developer 02
3fa113003c Update ReferenceType enum and clean up status handling
Modified the `ReferenceType` enum in `Constants.vb` to change the values for `Sender` and `Receiver`. Removed the `ReferenceType` and `StatusName` properties from `EnvelopeHistory.cs`. Updated status code comments in `HistoryController.cs`, adding new codes for `EnvelopeRejected` and `EnvelopeWithdrawn`, and adjusted parameter descriptions to align with the new enum values.
2025-05-11 14:27:28 +02:00
Developer 02
5504093591 Update access code for DocumentForwarded constant
Changed the value of the constant `DocumentForwarded` from `4001` to `2006` to align it with the other access codes, which are now consistently in the range of `2001` to `2009`.
2025-05-11 13:15:25 +02:00
Developer 02
040cf8641d Configure logging for non-development environments
Conditionally clear logging providers and set up NLog only when the application is not in the development environment. This change improves logging management based on the environment, enhancing production logging behavior.
2025-05-11 11:13:30 +02:00
21 changed files with 264 additions and 138 deletions

View File

@@ -21,5 +21,5 @@ public interface IEnvelopeReceiverRepository : ICRUDRepository<EnvelopeReceiver,
Task<IEnumerable<EnvelopeReceiver>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
Task<EnvelopeReceiver?> ReadLastByReceiver(string email);
Task<EnvelopeReceiver?> ReadLastByReceiverAsync(string? email = null, int? id = null, string? signature = null);
}

View File

@@ -35,7 +35,7 @@ public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDt
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, EnvelopeQuery? envelopeQuery = null, ReadReceiverQuery? receiverQuery = null, params int[] ignore_statuses);
Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail);
Task<DataResult<string?>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null);
Task<DataResult<SmsResponse>> SendSmsAsync(string envelopeReceiverId, string message);
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadWithSecretByUuidAsync(string uuid);

View File

@@ -21,9 +21,9 @@ namespace EnvelopeGenerator.Application.DTOs
[TemplatePlaceholder("[MESSAGE]")]
public string Message { get; set; }
public DateTime? ExpiresWhen { get; set; }
public DateTime? ExpiresWarningWhen { get; set; }
public DateTime AddedWhen { get; set; }
public DateTime? ChangedWhen { get; set; }
[TemplatePlaceholder("[DOCUMENT_TITLE]")]
@@ -33,40 +33,22 @@ namespace EnvelopeGenerator.Application.DTOs
public string Language { get; set; }
public bool? SendReminderEmails { get; set; }
public int? FirstReminderDays { get; set; }
public int? ReminderIntervalDays { get; set; }
public int? EnvelopeTypeId { get; set; }
public int? CertificationType { get; set; }
public bool? UseAccessCode { get; set; }
public int? FinalEmailToCreator { get; set; }
public int? FinalEmailToReceivers { get; set; }
public int? ExpiresWhenDays { get; set; }
public int? ExpiresWarningWhenDays { get; set; }
public bool TFAEnabled { get; init; }
public bool DmzMoved { get; set; }
public UserReadDto? User { get; set; }
public EnvelopeType? EnvelopeType { get; set; }
public string? EnvelopeTypeTitle { get; set; }
public bool IsAlreadySent { get; set; }
public string? StatusTranslated { get; set; }
public string? ContractTypeTranslated { get; set; }
public byte[]? DocResult { get; init; }
public IEnumerable<EnvelopeDocumentDto>? Documents { get; set; }

View File

@@ -5,19 +5,32 @@ using EnvelopeGenerator.Application.DTOs.Receiver;
using Microsoft.AspNetCore.Mvc;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
{
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeHistoryDto(
long Id,
int EnvelopeId,
string UserReference,
int Status,
string? StatusName,
DateTime AddedWhen,
DateTime? ActionDate,
UserCreateDto? Sender,
ReceiverReadDto? Receiver,
ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
}
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
/// <summary>
///
/// </summary>
/// <param name="Id"></param>
/// <param name="EnvelopeId"></param>
/// <param name="UserReference"></param>
/// <param name="Status"></param>
/// <param name="StatusName"></param>
/// <param name="AddedWhen"></param>
/// <param name="ActionDate"></param>
/// <param name="Sender"></param>
/// <param name="Receiver"></param>
/// <param name="ReferenceType"></param>
/// <param name="Comment"></param>
[ApiExplorerSettings(IgnoreApi = true)]
public record EnvelopeHistoryDto(
long Id,
int EnvelopeId,
string UserReference,
int Status,
string? StatusName,
DateTime AddedWhen,
DateTime? ActionDate,
UserCreateDto? Sender,
ReceiverReadDto? Receiver,
ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;

View File

@@ -31,6 +31,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
</ItemGroup>

View File

@@ -0,0 +1,18 @@
using AutoMapper;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
/// <summary>
///
/// </summary>
public class ReadHistoryMappingProfile: Profile
{
/// <summary>
///
/// </summary>
public ReadHistoryMappingProfile()
{
CreateMap<EnvelopeHistory, ReadHistoryResponse>();
}
}

View File

@@ -1,6 +1,6 @@
using EnvelopeGenerator.Application.Envelopes.Queries.Read;
using EnvelopeGenerator.Application.Receivers.Queries.Read;
using EnvelopeGenerator.Common;
using EnvelopeGenerator.Common;
using MediatR;
using System.ComponentModel.DataAnnotations;
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
@@ -9,9 +9,12 @@ namespace EnvelopeGenerator.Application.Histories.Queries.Read;
/// Repräsentiert eine Abfrage für die Verlaufshistorie eines Umschlags.
/// </summary>
/// <param name="EnvelopeId">Die eindeutige Kennung des Umschlags.</param>
/// <param name="Related">Abfrage, die angibt, worauf sich der Datensatz bezieht. Ob er sich auf den Empfänger, den Sender oder das System bezieht, wird durch 0, 1 bzw. 2 dargestellt.</param>
/// <param name="Status">Der Status des Umschlags, der abgefragt werden soll. Kann optional angegeben werden, um die Ergebnisse zu filtern.</param>
/// <param name="OnlyLast">Abfrage zur Steuerung, ob nur der aktuelle Status oder der gesamte Datensatz zurückgegeben wird.</param>
public record ReadHistoryQuery(
int? EnvelopeId = null,
Constants.ReferenceType? Related = null,
bool? OnlyLast = true);
[Required]
int EnvelopeId,
Constants.EnvelopeStatus? Status = null,
bool? OnlyLast = true) : IRequest<IEnumerable<ReadHistoryResponse>>
{
};

View File

@@ -0,0 +1,44 @@
using AutoMapper;
using EnvelopeGenerator.Application.Contracts.Repositories;
using EnvelopeGenerator.Application.Exceptions;
using MediatR;
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
/// <summary>
///
/// </summary>
public class ReadHistoryQueryHandler : IRequestHandler<ReadHistoryQuery, IEnumerable<ReadHistoryResponse>>
{
private readonly IEnvelopeHistoryRepository _repository;
private readonly IMapper _mapper;
/// <summary>
///
/// </summary>
/// <param name="repository"></param>
/// <param name="mapper"></param>
public ReadHistoryQueryHandler(IEnvelopeHistoryRepository repository, IMapper mapper)
{
_repository = repository;
_mapper = mapper;
}
/// <summary>
///
/// </summary>
/// <param name="request"></param>
/// <param name="cancellationToken"></param>
/// <returns></returns>
/// <exception cref="NotFoundException"></exception>
public async Task<IEnumerable<ReadHistoryResponse>> Handle(ReadHistoryQuery request, CancellationToken cancellationToken)
{
var hists = await _repository.ReadAsync(request.EnvelopeId, status: request.Status is null ? null : (int) request.Status);
if (!hists.Any())
throw new NotFoundException();
return _mapper.Map<IEnumerable<ReadHistoryResponse>>(hists);
}
}

View File

@@ -0,0 +1,60 @@
using EnvelopeGenerator.Common;
namespace EnvelopeGenerator.Application.Histories.Queries.Read;
/// <summary>
/// Represents the history of an envelope, including its status, user actions, and references.
/// </summary>
public class ReadHistoryResponse
{
/// <summary>
/// Gets or sets the unique identifier of the envelope history record.
/// </summary>
public long Id { get; set; }
/// <summary>
/// Gets or sets the identifier of the associated envelope.
/// </summary>
public int EnvelopeId { get; set; }
/// <summary>
/// Gets or sets the reference identifier of the user who performed the action.
/// </summary>
public string UserReference { get; set; }
/// <summary>
/// Gets or sets the status code of the envelope.
/// </summary>
public int Status { get; set; }
/// <summary>
///
/// </summary>
public Common.Constants.ReferenceType ReferenceType => Status.ToString().FirstOrDefault() switch
{
'1' => Constants.ReferenceType.Sender,
'2' => Constants.ReferenceType.Receiver,
_ => Constants.ReferenceType.System,
};
/// <summary>
/// Gets or sets the date and time when the record was added.
/// </summary>
public DateTime AddedWhen { get; set; }
/// <summary>
/// Gets or sets the date and time when the action occurred.
/// </summary>
public DateTime? ActionDate { get; set; }
/// <summary>
/// Gets or sets the optional comment about the envelope history record.
/// </summary>
public string? Comment { get; set; }
/// <inheritdoc/>
public override int GetHashCode()
{
return Id.GetHashCode();
}
}

View File

@@ -1,5 +1,6 @@
using Dapper;
using EnvelopeGenerator.Application.Contracts.SQLExecutor;
using EnvelopeGenerator.Application.Exceptions;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.SQL;
@@ -34,9 +35,16 @@ public class DocumentCreateReadSQL : ISQL<EnvelopeDocument>
/// <returns></returns>
public static DynamicParameters CreateParmas(string base64)
{
var parameters = new DynamicParameters();
byte[] byteData = Convert.FromBase64String(base64);
parameters.Add("ByteData", byteData, System.Data.DbType.Binary);
return parameters;
try
{
var parameters = new DynamicParameters();
byte[] byteData = Convert.FromBase64String(base64);
parameters.Add("ByteData", byteData, System.Data.DbType.Binary);
return parameters;
}
catch(FormatException ex)
{
throw new BadRequestException(ex.Message.Replace("input", "dataAsBase64"));
}
}
}

View File

@@ -57,7 +57,7 @@ namespace EnvelopeGenerator.Application.Services
{
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
{
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMail(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMailAsync(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";

View File

@@ -162,9 +162,9 @@ public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverReposit
return Result.Success(dto_list);
}
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail)
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMailAsync(string? mail = null, int? id = null, string? signature = null)
{
var er = await _repository.ReadLastByReceiver(mail);
var er = await _repository.ReadLastByReceiverAsync(mail, id, signature);
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
}

View File

@@ -20,7 +20,7 @@
AccessCodeIncorrect = 2003
DocumentOpened = 2004
DocumentSigned = 2005
DocumentForwarded = 4001
DocumentForwarded = 2006
DocumentRejected = 2007
EnvelopeShared = 2008
EnvelopeViewed = 2009
@@ -48,8 +48,8 @@
'TODO: standardize in xwiki
Public Enum ReferenceType
Receiver = 0
Sender
Sender = 1
Receiver
System
Unknown
End Enum

View File

@@ -2,7 +2,6 @@
using DigitalData.UserManager.Domain.Entities;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Domain.Entities
{
@@ -42,19 +41,5 @@ namespace EnvelopeGenerator.Domain.Entities
[ForeignKey("UserReference")]
public virtual Receiver? Receiver { get; set; }
[NotMapped]
public ReferenceType ReferenceType => (Status / 1000) switch
{
1 => ReferenceType.Sender,
2 or 3 => ReferenceType.Receiver,
_ => ReferenceType.Unknown,
};
[NotMapped]
public string? StatusName
=> (Enum.IsDefined(typeof(EnvelopeStatus), Status))
? Enum.GetName(typeof(EnvelopeStatus), Status)
: null;
}
}

View File

@@ -6,11 +6,24 @@ public static class MemoryCacheExtensions
{
private static readonly Guid BaseId = Guid.NewGuid();
public static IDictionary<string, int> GetEnumAsDictionary<TEnum>(this IMemoryCache memoryCache)
public static IDictionary<string, int> GetEnumAsDictionary<TEnum>(this IMemoryCache memoryCache, string key = "", params object[] ignores)
where TEnum : Enum
=> memoryCache.GetOrCreate(BaseId + typeof(TEnum).FullName, _ =>
Enum.GetValues(typeof(TEnum))
=> memoryCache.GetOrCreate(BaseId + typeof(TEnum).FullName + key, _ =>
{
var mergedIgnores = new List<TEnum>();
foreach (var ignore in ignores)
{
if (ignore is IEnumerable<TEnum> ignoreList)
mergedIgnores.AddRange(ignoreList);
else if (ignore is TEnum ignoreVal)
mergedIgnores.Add(ignoreVal);
}
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.ToDictionary(e => e.ToString(), e => Convert.ToInt32(e)))
.Where(e => !mergedIgnores.Contains(e))
.ToDictionary(e => e.ToString(), e => Convert.ToInt32(e));
})
?? throw new InvalidOperationException($"Failed to cache or retrieve enum dictionary for type '{typeof(TEnum).FullName}'.");
}

View File

@@ -74,7 +74,7 @@ public class EnvelopeController : ControllerBase
if (envelope.Uuid is string uuid)
envelopes = envelopes.Where(e => e.Uuid == uuid);
return Ok(envelopes);
return envelopes.Any() ? Ok(envelopes) : NotFound();
},
Fail: IActionResult (msg, ntc) =>
{

View File

@@ -112,7 +112,7 @@ public class EnvelopeReceiverController : ControllerBase
/// <summary>
/// Ruft den Namen des zuletzt verwendeten Empfängers basierend auf der angegebenen E-Mail-Adresse ab.
/// </summary>
/// <param name="receiverName">Die Abfrage, die die E-Mail-Adresse des Empfängers enthält.</param>
/// <param name="receiver">Abfrage, bei der nur eine der Angaben ID, Signatur oder E-Mail-Adresse des Empfängers eingegeben werden muss.</param>
/// <returns>Eine HTTP-Antwort mit dem Namen des Empfängers oder einem Fehlerstatus.</returns>
/// <remarks>
/// Dieser Endpunkt ermöglicht es, den Namen des zuletzt verwendeten Empfängers basierend auf der E-Mail-Adresse abzurufen.
@@ -123,13 +123,10 @@ public class EnvelopeReceiverController : ControllerBase
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
[Authorize]
[HttpGet("salute")]
public async Task<IActionResult> GetReceiverName([FromQuery] ReadReceiverNameQuery receiverName)
public async Task<IActionResult> GetReceiverName([FromQuery] ReadReceiverNameQuery receiver)
{
if (receiverName.EmailAddress is null)
return BadRequest();
return await _erService.ReadLastUsedReceiverNameByMail(receiverName.EmailAddress).ThenAsync(
Success: res => res is null ? Ok(string.Empty) : Ok(res),
return await _erService.ReadLastUsedReceiverNameByMailAsync(receiver.EmailAddress, receiver.Id, receiver.Signature).ThenAsync(
Success: res => res is null ? NotFound() : Ok(res),
Fail: IActionResult (msg, ntc) =>
{
if (ntc.HasFlag(Flag.NotFound))

View File

@@ -1,13 +1,12 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
using EnvelopeGenerator.Application.Contracts.Services;
using EnvelopeGenerator.Application.Contracts.Services;
using EnvelopeGenerator.Application.Histories.Queries.Read;
using EnvelopeGenerator.Extensions;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.GeneratorAPI.Controllers;
/// <summary>
@@ -18,34 +17,35 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers;
[Authorize]
public class HistoryController : ControllerBase
{
private readonly ILogger<HistoryController> _logger;
private readonly IEnvelopeHistoryService _service;
private readonly IMemoryCache _memoryCache;
private readonly IMediator _mediator;
/// <summary>
/// Konstruktor für den HistoryController.
/// </summary>
/// <param name="logger">Der Logger, der für das Protokollieren von Informationen verwendet wird.</param>
/// <param name="service">Der Dienst, der für die Verarbeitung der Umschlaghistorie verantwortlich ist.</param>
public HistoryController(ILogger<HistoryController> logger, IEnvelopeHistoryService service, IMemoryCache memoryCache)
/// <param name="memoryCache"></param>
/// param name="mediator"
public HistoryController(IEnvelopeHistoryService service, IMemoryCache memoryCache, IMediator mediator)
{
_logger = logger;
_service = service;
_memoryCache = memoryCache;
_mediator = mediator;
}
/// <summary>
/// Gibt alle möglichen Verweise auf alle möglichen Status in einem Verlaufsdatensatz zurück. (z. B. DocumentSigned bezieht sich auf Receiver.)
/// Dies wird hinzugefügt, damit Client-Anwendungen sich selbst auf dem neuesten Stand halten können.
/// 0 - Receiver:
/// Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 1* beginnen.
/// 1 - Sender:
/// Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 2* beginnen.
/// 2 - System:
/// Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 1* beginnen.
/// 2 - Receiver:
/// Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 2* beginnen.
/// 3 - System:
/// Historische Datensätze, die sich auf den allgemeinen Zustand des Umschlags beziehen. Diese haben Statuscodes, die mit 3* beginnen.
/// 3 - Unknown:
/// 4 - Unknown:
/// Ein unbekannter Datensatz weist auf einen möglichen Mangel oder eine Unstimmigkeit im Aktualisierungsprozess der Anwendung hin.
/// </summary>
/// <returns></returns>
@@ -54,29 +54,25 @@ public class HistoryController : ControllerBase
[Authorize]
public IActionResult GetReferenceTypes(ReferenceType? referenceType = null)
{
return referenceType is null ? Ok(_memoryCache.GetEnumAsDictionary<ReferenceType>()) : Ok(referenceType.ToString());
return referenceType is null ? Ok(_memoryCache.GetEnumAsDictionary<ReferenceType>("gen.api", ReferenceType.Unknown)) : Ok(referenceType.ToString());
}
/// <summary>
/// Gibt alle möglichen Status in einem Verlaufsdatensatz zurück.
/// Dies wird hinzugefügt, damit Client-Anwendungen sich selbst auf dem neuesten Stand halten können.
/// 0: Invalid
/// 1001: EnvelopeCreated
/// 1002: EnvelopeSaved
/// 1003: EnvelopeQueued
/// 1004: EnvelopeSent (Nicht verwendet)
/// 1005: EnvelopePartlySigned
/// 1006: EnvelopeCompletelySigned
/// 1007: EnvelopeReportCreated
/// 1008: EnvelopeArchived
/// 1009: EnvelopeDeleted
/// 10007: EnvelopeRejected
/// 10009: EnvelopeWithdrawn
/// 2001: AccessCodeRequested
/// 2002: AccessCodeCorrect
/// 2003: AccessCodeIncorrect
/// 2004: DocumentOpened
/// 2005: DocumentSigned
/// 4001: DocumentForwarded
/// 2006: SignatureConfirmed
/// 2006: DocumentForwarded
/// 2007: DocumentRejected
/// 2008: EnvelopeShared
/// 2009: EnvelopeViewed
@@ -88,9 +84,9 @@ public class HistoryController : ControllerBase
/// </summary>
/// <param name="status">
/// Abfrageparameter, der angibt, auf welche Referenz sich der Status bezieht.
/// 0 - Sender: Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 1* beginnen.
/// 1 - Receiver: Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 2* beginnen.
/// 2 - System: Diese werden durch Datenbank-Trigger aktualisiert und sind in den Tabellen EnvelopeHistory und EmailOut zu finden.Sie arbeiten
/// 1 - Sender: Historische Datensätze, die sich auf den Status des Absenders beziehen. Sie haben Statuscodes, die mit 1* beginnen.
/// 2 - Receiver: Historische Datensätze über den Status der Empfänger. Diese haben Statuscodes, die mit 2* beginnen.
/// 3 - System: Diese werden durch Datenbank-Trigger aktualisiert und sind in den Tabellen EnvelopeHistory und EmailOut zu finden.Sie arbeiten
/// integriert mit der Anwendung EmailProfiler, um E-Mails zu versenden und haben die Codes, die mit 3* beginnen.
/// </param>
/// <returns>Gibt die HTTP-Antwort zurück.</returns>
@@ -99,13 +95,13 @@ public class HistoryController : ControllerBase
[Authorize]
public IActionResult GetEnvelopeStatus([FromQuery] EnvelopeStatus? status = null)
{
return status is null ? Ok(_memoryCache.GetEnumAsDictionary<EnvelopeStatus>()) : Ok(status.ToString());
return status is null ? Ok(_memoryCache.GetEnumAsDictionary<EnvelopeStatus>("gen.api", Status.NonHist, Status.RelatedToFormApp)) : Ok(status.ToString());
}
/// <summary>
/// Ruft die gesamte Umschlaghistorie basierend auf den angegebenen Abfrageparametern ab.
/// </summary>
/// <param name="history">Die Abfrageparameter, die die Filterkriterien für die Umschlaghistorie definieren.</param>
/// <param name="historyQuery">Die Abfrageparameter, die die Filterkriterien für die Umschlaghistorie definieren.</param>
/// <returns>Eine Liste von Historieneinträgen, die den angegebenen Kriterien entsprechen, oder nur der letzte Eintrag.</returns>
/// <response code="200">Die Anfrage war erfolgreich, und die Umschlaghistorie wird zurückgegeben.</response>
/// <response code="400">Die Anfrage war ungültig oder unvollständig.</response>
@@ -114,29 +110,10 @@ public class HistoryController : ControllerBase
/// <response code="500">Ein unerwarteter Fehler ist aufgetreten.</response>
[HttpGet]
[Authorize]
public async Task<IActionResult> GetAllAsync([FromQuery] ReadHistoryQuery history)
public async Task<IActionResult> GetAllAsync([FromQuery] ReadHistoryQuery historyQuery)
{
var history = await _mediator.Send(historyQuery);
bool withReceiver = false;
bool withSender = false;
switch (history.Related)
{
case ReferenceType.Receiver:
withReceiver = true;
break;
case ReferenceType.Sender:
withSender = true;
break;
}
var histories = await _service.ReadAsync(
envelopeId: history.EnvelopeId,
referenceType: history.Related,
withSender: withSender,
withReceiver: withReceiver);
return Ok(histories);
return Ok((historyQuery.OnlyLast ?? false) ? history.MaxBy(h => h.AddedWhen) : history);
}
}

View File

@@ -10,9 +10,9 @@
<Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company>
<Product>EnvelopeGenerator.GeneratorAPI</Product>
<Version>1.2.2</Version>
<FileVersion>1.2.2</FileVersion>
<AssemblyVersion>1.2.2</AssemblyVersion>
<Version>1.2.3</Version>
<FileVersion>1.2.3</FileVersion>
<AssemblyVersion>1.2.3</AssemblyVersion>
<PackageOutputPath>Copyright © 2025 Digital Data GmbH. All rights reserved.</PackageOutputPath>
<DocumentationFile>bin\$(Configuration)\$(TargetFramework)\$(AssemblyName).xml</DocumentationFile>
</PropertyGroup>

View File

@@ -26,9 +26,13 @@ try
{
var builder = WebApplication.CreateBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.SetMinimumLevel(Microsoft.Extensions.Logging.LogLevel.Trace);
builder.Host.UseNLog();
if (!builder.Environment.IsDevelopment())
{
builder.Logging.ClearProviders();
builder.Host.UseNLog();
}
var config = builder.Configuration;

View File

@@ -2,6 +2,9 @@
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Application.Contracts.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Http.HttpResults;
using EnvelopeGenerator.Application.Exceptions;
using EnvelopeGenerator.Common.My.Resources;
namespace EnvelopeGenerator.Infrastructure.Repositories;
@@ -93,8 +96,26 @@ public class EnvelopeReceiverRepository : CRUDRepository<EnvelopeReceiver, (int
return await query.Include(er => er.Envelope).Include(er => er.Receiver).ToListAsync();
}
public async Task<EnvelopeReceiver?> ReadLastByReceiver(string email)
public async Task<EnvelopeReceiver?> ReadLastByReceiverAsync(string? email = null, int? id = null, string? signature = null)
{
return await _dbSet.Where(er => er.Receiver!.EmailAddress == email).OrderBy(er => er.EnvelopeId).LastOrDefaultAsync();
var parameters = new[] { email, id?.ToString(), signature }.Count(p => p != null);
if (parameters == 0)
throw new BadRequestException("You must provide either 'email', 'id', or 'signature' for the query.");
if (parameters > 1)
throw new BadRequestException("Please provide only one parameter: either 'email', 'id', or 'signature'.");
var query = _dbSet.AsNoTracking();
if(email is not null)
query = query.Where(er => er.Receiver!.EmailAddress == email);
if (id is not null)
query = query.Where(er => er.Receiver!.Id == id);
if (signature is not null)
query = query.Where(er => er.Receiver!.Signature == signature);
return await query.OrderBy(er => er.EnvelopeId).LastOrDefaultAsync();
}
}