Compare commits

...

7 Commits

13 changed files with 2235 additions and 2175 deletions

View File

@@ -0,0 +1,18 @@
using System.Text.Json;
namespace EnvelopeGenerator.Application.Common.Extensions;
/// <summary>
///
/// </summary>
public static class JsonExtensions
{
/// <summary>
///
/// </summary>
/// <param name="obj"></param>
/// <param name="options"></param>
/// <returns></returns>
public static string ToJson(this object obj, JsonSerializerOptions? options = null)
=> JsonSerializer.Serialize(obj, options);
}

View File

@@ -1,4 +1,5 @@
using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver; using EnvelopeGenerator.Application.Common.Dto.EnvelopeReceiver;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Constants;
using MediatR; using MediatR;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -27,7 +28,7 @@ public record DocSignedNotification(EnvelopeReceiverDto Original) : EnvelopeRece
/// </summary> /// </summary>
public string EmailAddress => Receiver?.EmailAddress public string EmailAddress => Receiver?.EmailAddress
?? throw new InvalidOperationException($"Receiver is null." + ?? throw new InvalidOperationException($"Receiver is null." +
$"DocSignedNotification:\n{JsonConvert.SerializeObject(this, Format.Json.ForDiagnostics)}"); $"DocSignedNotification:\n{this.ToJson(Format.Json.ForDiagnostics)}");
} }
/// <summary> /// <summary>

View File

@@ -1,8 +1,7 @@
using EnvelopeGenerator.Application.Common.Notifications.DocSigned; using EnvelopeGenerator.Application.DocStatus.Commands;
using EnvelopeGenerator.Application.DocStatus.Commands;
using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Constants;
using MediatR; using MediatR;
using Newtonsoft.Json; using System.Text.Json;
namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers; namespace EnvelopeGenerator.Application.Common.Notifications.DocSigned.Handlers;
@@ -34,7 +33,7 @@ public class AnnotationHandler : INotificationHandler<DocSignedNotification>
{ {
Envelope = new() { Id = notification.EnvelopeId }, Envelope = new() { Id = notification.EnvelopeId },
Receiver = new() { Id = notification.ReceiverId}, Receiver = new() { Id = notification.ReceiverId},
Value = JsonConvert.SerializeObject(notification.Annotations, Format.Json.ForAnnotations) Value = JsonSerializer.Serialize(notification.Annotations, Format.Json.ForAnnotations)
}, cancel); }, cancel);
} }
} }

View File

@@ -1,4 +1,4 @@
using EnvelopeGenerator.Application.Common.Notifications.DocSigned; using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Histories.Commands; using EnvelopeGenerator.Application.Histories.Commands;
using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Constants;
using MediatR; using MediatR;
@@ -32,14 +32,13 @@ public class HistoryHandler : INotificationHandler<DocSignedNotification>
{ {
if(notification.Receiver is null) if(notification.Receiver is null)
if (notification.Receiver is null) if (notification.Receiver is null)
throw new InvalidOperationException($"Receiver information is missing in the notification. DocSignedNotification:\n {JsonConvert.SerializeObject(notification, Format.Json.ForDiagnostics)}"); throw new InvalidOperationException($"Receiver information is missing in the notification. DocSignedNotification:\n {notification.ToJson(Format.Json.ForDiagnostics)}");
await _sender.Send(new CreateHistoryCommand() await _sender.Send(new CreateHistoryCommand()
{ {
EnvelopeId = notification.EnvelopeId, EnvelopeId = notification.EnvelopeId,
UserReference = notification.Receiver.EmailAddress, UserReference = notification.Receiver.EmailAddress,
Status = EnvelopeStatus.DocumentSigned, Status = EnvelopeStatus.DocumentSigned,
Comment = JsonConvert.SerializeObject(notification.Annotations, Format.Json.ForAnnotations)
}, cancel); }, cancel);
} }
} }

View File

@@ -1,6 +1,7 @@
using DigitalData.Core.Abstraction.Application.Repository; using DigitalData.Core.Abstraction.Application.Repository;
using DigitalData.EmailProfilerDispatcher.Abstraction.Entities; using DigitalData.EmailProfilerDispatcher.Abstraction.Entities;
using EnvelopeGenerator.Application.Common.Configurations; using EnvelopeGenerator.Application.Common.Configurations;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Constants;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using MediatR; using MediatR;
@@ -101,7 +102,7 @@ public abstract class SendMailHandler<TNotification> : INotificationHandler<TNot
.ReadOnly() .ReadOnly()
.SingleOrDefaultAsync(x => x.Name == notification.TemplateType.ToString(), cancel) .SingleOrDefaultAsync(x => x.Name == notification.TemplateType.ToString(), cancel)
?? throw new InvalidOperationException($"Receiver information is missing in the notification." + ?? throw new InvalidOperationException($"Receiver information is missing in the notification." +
$"{typeof(TNotification)}:\n {JsonConvert.SerializeObject(notification, Format.Json.ForDiagnostics)}"); $"{typeof(TNotification)}:\n {notification.ToJson(Format.Json.ForDiagnostics)}");
temp.Subject = ReplacePlaceHolders(temp.Subject, placeHolders, MailParams.Placeholders); temp.Subject = ReplacePlaceHolders(temp.Subject, placeHolders, MailParams.Placeholders);

View File

@@ -20,4 +20,14 @@ public record ReceiverQueryBase
/// Eindeutige Signatur des Empfängers /// Eindeutige Signatur des Empfängers
/// </summary> /// </summary>
public virtual string? Signature { get; set; } public virtual string? Signature { get; set; }
/// <summary>
/// Checks whether any of the specified query criteria have a value.
/// </summary>
/// <remarks>
/// This property returns <c>true</c> if at least one of the fields
/// <see cref="Id"/>, <see cref="EmailAddress"/>, or <see cref="Signature"/> is not null.
/// <para>Usage example: The query can be executed only if at least one criterion is specified.</para>
/// </remarks>
public bool HasAnyCriteria => Id is not null || EmailAddress is not null || Signature is not null;
} }

View File

@@ -91,6 +91,8 @@ public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeRece
{ {
private readonly IRepository<EnvelopeReceiver> _repo; private readonly IRepository<EnvelopeReceiver> _repo;
private readonly IRepository<Receiver> _rcvRepo;
private readonly IMapper _mapper; private readonly IMapper _mapper;
/// <summary> /// <summary>
@@ -98,10 +100,11 @@ public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeRece
/// </summary> /// </summary>
/// <param name="envelopeReceiver"></param> /// <param name="envelopeReceiver"></param>
/// <param name="mapper"></param> /// <param name="mapper"></param>
public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IMapper mapper) public ReadEnvelopeReceiverQueryHandler(IRepository<EnvelopeReceiver> envelopeReceiver, IRepository<Receiver> rcvRepo, IMapper mapper)
{ {
_repo = envelopeReceiver; _repo = envelopeReceiver;
_mapper = mapper; _mapper = mapper;
_rcvRepo = rcvRepo;
} }
/// <summary> /// <summary>
@@ -138,6 +141,14 @@ public class ReadEnvelopeReceiverQueryHandler : IRequestHandler<ReadEnvelopeRece
.Include(er => er.Receiver) .Include(er => er.Receiver)
.ToListAsync(cancel); .ToListAsync(cancel);
if (request.Receiver.HasAnyCriteria && envRcvs.Any())
{
var receiver = await _rcvRepo.ReadOnly().Where(request.Receiver).FirstAsync(cancel);
foreach (var envRcv in envRcvs)
envRcv.Envelope?.Documents?.First().Elements.RemoveAll(s => s.ReceiverId != receiver.Id);
}
return _mapper.Map<List<EnvelopeReceiverDto>>(envRcvs); return _mapper.Map<List<EnvelopeReceiverDto>>(envRcvs);
} }
} }

View File

@@ -104,7 +104,7 @@ Public Class frmFinalizePDF
Catch ex As Exception Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical)
End Try End Try
End Sub End Sub
End Class End Class

View File

@@ -1,5 +1,7 @@
using Newtonsoft.Json; #if NET
using Newtonsoft.Json.Serialization; using System.Text.Json;
using System.Text.Json.Serialization;
#endif
namespace EnvelopeGenerator.Domain.Constants namespace EnvelopeGenerator.Domain.Constants
{ {
@@ -8,18 +10,21 @@ namespace EnvelopeGenerator.Domain.Constants
#region Json Serializer Settings #region Json Serializer Settings
public static class Json public static class Json
{ {
public static readonly JsonSerializerSettings ForDiagnostics = new JsonSerializerSettings() #if NET
public static readonly JsonSerializerOptions ForDiagnostics = new()
{ {
ContractResolver = new CamelCasePropertyNamesContractResolver(), PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Formatting = Formatting.Indented, WriteIndented = true,
NullValueHandling = NullValueHandling.Include DefaultIgnoreCondition = JsonIgnoreCondition.Never
}; };
public static readonly JsonSerializerSettings ForAnnotations = new JsonSerializerSettings()
public static readonly JsonSerializerOptions ForAnnotations = new()
{ {
ContractResolver = new CamelCasePropertyNamesContractResolver(), PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
Formatting = Formatting.None, WriteIndented = false,
NullValueHandling = NullValueHandling.Ignore DefaultIgnoreCondition = JsonIgnoreCondition.Never,
}; };
#endif
} }
#endregion #endregion
} }

View File

@@ -0,0 +1,15 @@
namespace EnvelopeGenerator.Tests.Application;
public class DocSignedNotificationTest
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
Assert.Pass();
}
}

View File

@@ -1,4 +1,5 @@
using DigitalData.Core.Exceptions; using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries; using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Constants;
using MediatR; using MediatR;
@@ -33,7 +34,7 @@ public class DocumentController : ControllerBase
if(byteData is null || byteData.Length == 0) if(byteData is null || byteData.Length == 0)
{ {
_logger.LogError("Document byte data is null or empty for envelope-receiver entity:\n{envelopeKey}.", _logger.LogError("Document byte data is null or empty for envelope-receiver entity:\n{envelopeKey}.",
JsonConvert.SerializeObject(envRcv, Format.Json.ForDiagnostics)); envRcv.ToJson(Format.Json.ForDiagnostics));
throw new NotFoundException("Document is empty."); throw new NotFoundException("Document is empty.");
} }

View File

@@ -1,15 +1,15 @@
using Microsoft.AspNetCore.Authorization; using DigitalData.Core.Abstraction.Application.DTO;
using Microsoft.AspNetCore.Mvc; using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Application.Common.Extensions;
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
using EnvelopeGenerator.Application.Interfaces.Services; using EnvelopeGenerator.Application.Interfaces.Services;
using EnvelopeGenerator.Domain.Constants; using EnvelopeGenerator.Domain.Constants;
using DigitalData.Core.Abstraction.Application.DTO;
using EnvelopeGenerator.Web.Extensions; using EnvelopeGenerator.Web.Extensions;
using MediatR; using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Dynamic; using System.Dynamic;
using EnvelopeGenerator.Application.EnvelopeReceivers.Queries;
using DigitalData.Core.Exceptions;
using EnvelopeGenerator.Application.Common.Notifications.DocSigned;
using EnvelopeGenerator.Application.Common.Extensions;
namespace EnvelopeGenerator.Web.Controllers; namespace EnvelopeGenerator.Web.Controllers;

View File

@@ -5,7 +5,6 @@
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<PackageId>EnvelopeGenerator.Web</PackageId> <PackageId>EnvelopeGenerator.Web</PackageId>
<Version>3.1.4</Version>
<Authors>Digital Data GmbH</Authors> <Authors>Digital Data GmbH</Authors>
<Company>Digital Data GmbH</Company> <Company>Digital Data GmbH</Company>
<Product>EnvelopeGenerator.Web</Product> <Product>EnvelopeGenerator.Web</Product>
@@ -13,8 +12,9 @@
<PackageTags>digital data envelope generator web</PackageTags> <PackageTags>digital data envelope generator web</PackageTags>
<Description>EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description> <Description>EnvelopeGenerator.Web is an ASP.NET MVC application developed to manage signing processes. It uses Entity Framework Core (EF Core) for database operations. The user interface for signing processes is developed with Razor View Engine (.cshtml files) and JavaScript under wwwroot, integrated with PSPDFKit. This integration allows users to view and sign documents seamlessly.</Description>
<ApplicationIcon>Assets\icon.ico</ApplicationIcon> <ApplicationIcon>Assets\icon.ico</ApplicationIcon>
<AssemblyVersion>3.1.4</AssemblyVersion> <Version>3.2.1</Version>
<FileVersion>3.1.4</FileVersion> <AssemblyVersion>3.2.1</AssemblyVersion>
<FileVersion>3.2.1</FileVersion>
<Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright> <Copyright>Copyright © 2025 Digital Data GmbH. All rights reserved.</Copyright>
</PropertyGroup> </PropertyGroup>