Ein weiterer informativer Text wurde für den Umschlag hinzugefügt, der von anderen Interessengruppen gestrichen wurde.

This commit is contained in:
Developer 02
2024-06-06 16:55:42 +02:00
parent 290a1dd522
commit f509cc8b3b
11 changed files with 74 additions and 27 deletions

View File

@@ -1,5 +1,6 @@
using DigitalData.Core.Contracts.Application; using DigitalData.Core.Contracts.Application;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory; using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
@@ -17,10 +18,12 @@ namespace EnvelopeGenerator.Application.Contracts
Task<bool> IsRejected(int envelopeId, string? userReference = null); Task<bool> IsRejected(int envelopeId, string? userReference = null);
Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null); Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false);
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null); Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null); Task<IEnumerable<ReceiverDto>> ReadRejectingReceivers(int envelopeId);
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null);
} }
} }

View File

@@ -1,4 +1,5 @@
using DigitalData.UserManager.Application.DTOs.User; using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.DTOs.User;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
@@ -13,5 +14,5 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
UserCreateDto? Sender, UserCreateDto? Sender,
ReceiverDto? Receiver, ReceiverDto? Receiver,
ReferenceType ReferenceType, ReferenceType ReferenceType,
string? Comment = null); string? Comment = null) : BaseDTO<long>(Id);
} }

View File

@@ -1,9 +1,11 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.DTO;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record ReceiverDto( public record ReceiverDto(
int Id, int Id,
string EmailAddress, string EmailAddress,
string Signature, string Signature,
DateTime AddedWhen DateTime AddedWhen
); ) : BaseDTO<int>(Id);
} }

View File

@@ -102,9 +102,9 @@ namespace EnvelopeGenerator.Application
/// <returns>The receiver signature.</returns> /// <returns>The receiver signature.</returns>
public static string? GetReceiverSignature(this string envelopeReceiverId) => envelopeReceiverId.DecodeEnvelopeReceiverId().ReceiverSignature; public static string? GetReceiverSignature(this string envelopeReceiverId) => envelopeReceiverId.DecodeEnvelopeReceiverId().ReceiverSignature;
public static void LogEnvelopeError(this ILogger logger, string envelopeEeceiverId, Exception? exception = null, string? message = null, params object?[] args) public static void LogEnvelopeError(this ILogger logger, string envelopeReceiverId, Exception? exception = null, string? message = null, params object?[] args)
{ {
var sb = new StringBuilder().AppendLine(envelopeEeceiverId.DecodeEnvelopeReceiverId().ToTitle()); var sb = new StringBuilder().AppendLine(envelopeReceiverId.DecodeEnvelopeReceiverId().ToTitle());
if (message is not null) if (message is not null)
sb.AppendLine(message); sb.AppendLine(message);

View File

@@ -183,8 +183,14 @@
<data name="RejectionInfo1" xml:space="preserve"> <data name="RejectionInfo1" xml:space="preserve">
<value>Ihre Ablehnung wurde weitergeleitet!</value> <value>Ihre Ablehnung wurde weitergeleitet!</value>
</data> </data>
<data name="RejectionInfo1_ext" xml:space="preserve">
<value>Vorgang abgebrochen!</value>
</data>
<data name="RejectionInfo2" xml:space="preserve"> <data name="RejectionInfo2" xml:space="preserve">
<value>Sie können bei Bedarf mit {0}, &lt;a href="mailto:{1}?subject={2}&amp;body=Dear%20{0},%0A%0A%0A"&gt;{1}&lt;/a&gt; Kontakt aufnehmen.</value> <value>Sie können bei Bedarf mit {0}, &lt;a href="mailto:{1}?subject={2}&amp;body=Sehr geehrte(r)%20{0},%0A%0A%0A"&gt;{1}&lt;/a&gt; Kontakt aufnehmen.</value>
</data>
<data name="RejectionInfo2_ext" xml:space="preserve">
<value>Das Vorgang wurde von einer der beteiligten Parteien abgelehnt. Sie können bei Bedarf mit {0}, &lt;a href="mailto:{1}?subject={2}&amp;body=Sehr geehrte(r)%20{0},%0A%0A%0A"&gt;{1}&lt;/a&gt; Kontakt aufnehmen.</value>
</data> </data>
<data name="RejectionReasonQ" xml:space="preserve"> <data name="RejectionReasonQ" xml:space="preserve">
<value>Bitte geben Sie einen Grund an:</value> <value>Bitte geben Sie einen Grund an:</value>

View File

@@ -183,9 +183,15 @@
<data name="RejectionInfo1" xml:space="preserve"> <data name="RejectionInfo1" xml:space="preserve">
<value>Your rejection has been forwarded!</value> <value>Your rejection has been forwarded!</value>
</data> </data>
<data name="RejectionInfo1_ext" xml:space="preserve">
<value>Process canceled!</value>
</data>
<data name="RejectionInfo2" xml:space="preserve"> <data name="RejectionInfo2" xml:space="preserve">
<value>You can contact {0}, &lt;a href="mailto:{1}?subject={2}&amp;body=Dear%20{0},%0A%0A%0A"&gt;{1}&lt;/a&gt; if required.</value> <value>You can contact {0}, &lt;a href="mailto:{1}?subject={2}&amp;body=Dear%20{0},%0A%0A%0A"&gt;{1}&lt;/a&gt; if required.</value>
</data> </data>
<data name="RejectionInfo2_ext" xml:space="preserve">
<value>The process has been rejected by one of the parties involved. You can contact {0}, &lt;a href="mailto:{1}?subject={2}&amp;body=Dear%20{0},%0A%0A%0A"&gt;{1}&lt;/a&gt; if required.</value>
</data>
<data name="RejectionReasonQ" xml:space="preserve"> <data name="RejectionReasonQ" xml:space="preserve">
<value>Please give a reason:</value> <value>Please give a reason:</value>
</data> </data>

View File

@@ -8,6 +8,7 @@ using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Application.Resources; using EnvelopeGenerator.Application.Resources;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory; using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
@@ -50,20 +51,33 @@ namespace EnvelopeGenerator.Application.Services
status: (int)EnvelopeStatus.DocumentRejected) > 0; status: (int)EnvelopeStatus.DocumentRejected) > 0;
} }
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null) public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false)
{ {
var histDTOs = _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>( var histDTOs = _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>(
await _repository.ReadAsync( await _repository.ReadAsync(
envelopeId: envelopeId, envelopeId: envelopeId,
userReference: userReference, userReference: userReference,
status: status)); status: status,
withSender: withSender,
withReceiver: withReceiver));
return referenceType is null ? histDTOs : histDTOs.Where(h => h.ReferenceType == referenceType); return referenceType is null ? histDTOs : histDTOs.Where(h => h.ReferenceType == referenceType);
} }
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null) => public async Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null) =>
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected); await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected, withReceiver:true);
public async Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null) => //TODO: use IQueryable in repository to incerease the performance
public async Task<IEnumerable<ReceiverDto>> ReadRejectingReceivers(int envelopeId)
{
var envelopes = await ReadRejectedAsync(envelopeId);
return envelopes is null
? Enumerable.Empty<ReceiverDto>()
: envelopes
.Where(eh => eh?.Receiver != null)
.Select(eh => eh.Receiver!);
}
public async Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null) =>
await CreateAsync(new (EnvelopeId: envelopeId, UserReference: userReference, Status: (int)status, ActionDate: DateTime.Now, Comment: comment)) await CreateAsync(new (EnvelopeId: envelopeId, UserReference: userReference, Status: (int)status, ActionDate: DateTime.Now, Comment: comment))
.ThenAsync( .ThenAsync(
Success: id => Result.Success(id), Success: id => Result.Success(id),

View File

@@ -11,6 +11,9 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="DigitalData.Core.Domain">
<HintPath>..\..\WebCoreModules\DigitalData.Core.Domain\bin\Debug\net7.0\DigitalData.Core.Domain.dll</HintPath>
</Reference>
<Reference Include="DigitalData.UserManager.Domain"> <Reference Include="DigitalData.UserManager.Domain">
<HintPath>..\..\WebUserManager\DigitalData.UserManager.Domain\bin\Debug\net7.0\DigitalData.UserManager.Domain.dll</HintPath> <HintPath>..\..\WebUserManager\DigitalData.UserManager.Domain\bin\Debug\net7.0\DigitalData.UserManager.Domain.dll</HintPath>
</Reference> </Reference>

View File

@@ -70,7 +70,7 @@ namespace EnvelopeGenerator.Web.Controllers
} }
catch(Exception ex) catch(Exception ex)
{ {
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception:ex, message: _localizer[WebKey.UnexpectedError]); _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, exception:ex, message: _localizer[WebKey.UnexpectedError]);
return this.ViewInnerServiceError(); return this.ViewInnerServiceError();
} }
} }
@@ -104,7 +104,7 @@ namespace EnvelopeGenerator.Web.Controllers
} }
catch(Exception ex) catch(Exception ex)
{ {
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex); _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError(); return this.ViewInnerServiceError();
} }
} }
@@ -154,9 +154,15 @@ namespace EnvelopeGenerator.Web.Controllers
return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync<EnvelopeReceiverDto, IActionResult>( return await _envRcvService.ReadByUuidSignatureAsync(uuid: uuid, signature: signature).ThenAsync<EnvelopeReceiverDto, IActionResult>(
SuccessAsync: async er => SuccessAsync: async er =>
{ {
if (await _historyService.IsRejected(envelopeId: er.Envelope!.Id)) //check rejection
var rejRcvrs = await _historyService.ReadRejectingReceivers(er.Envelope!.Id);
if(rejRcvrs.Any())
{
ViewBag.IsExt = !rejRcvrs.Contains(er.Receiver); //external if the current user is not rejected
return View("EnvelopeRejected", er); return View("EnvelopeRejected", er);
}
//check if it has already signed
if (await _historyService.IsSigned(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress)) if (await _historyService.IsSigned(envelopeId: er.Envelope!.Id, userReference: er.Receiver!.EmailAddress))
return View("EnvelopeSigned"); return View("EnvelopeSigned");
@@ -167,7 +173,10 @@ namespace EnvelopeGenerator.Web.Controllers
ViewData["DocumentBytes"] = bytes; ViewData["DocumentBytes"] = bytes;
} }
else else
return this.ViewDocumentNotFound(); {
_logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, message: "No document was found.");
return this.ViewDocumentNotFound();
}
var claims = new List<Claim> { var claims = new List<Claim> {
new(ClaimTypes.NameIdentifier, uuid), new(ClaimTypes.NameIdentifier, uuid),
@@ -204,7 +213,7 @@ namespace EnvelopeGenerator.Web.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex); _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError(); return this.ViewInnerServiceError();
} }
} }
@@ -238,7 +247,7 @@ namespace EnvelopeGenerator.Web.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex); _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError(); return this.ViewInnerServiceError();
} }
} }
@@ -269,7 +278,7 @@ namespace EnvelopeGenerator.Web.Controllers
} }
catch (Exception ex) catch (Exception ex)
{ {
_logger.LogEnvelopeError(envelopeEeceiverId: envelopeReceiverId, exception: ex); _logger.LogEnvelopeError(envelopeReceiverId: envelopeReceiverId, exception: ex);
return this.ViewInnerServiceError(); return this.ViewInnerServiceError();
} }
} }

View File

@@ -11,10 +11,11 @@
@model EnvelopeReceiverDto; @model EnvelopeReceiverDto;
<partial name="_CookieConsentPartial" /> <partial name="_CookieConsentPartial" />
@{ @{
var userCulture = ViewData["UserCulture"] as Culture; var userCulture = ViewData["UserCulture"] as Culture;
var envelope = Model.Envelope; var envelope = Model.Envelope;
var document = Model.Envelope?.Documents?.FirstOrDefault(); var document = Model.Envelope?.Documents?.FirstOrDefault();
var sender = Model.Envelope?.User; var sender = Model.Envelope?.User;
var isExt = ViewBag.IsExt ?? false;
} }
<div class="page container p-5"> <div class="page container p-5">
<header class="text-center"> <header class="text-center">
@@ -54,13 +55,13 @@
c-5.791,5.79-15.176,5.79-20.969,0l-30.32-30.322l-11.676,11.676l30.32,30.32c5.79,5.79,5.79,15.178,0,20.969L299.11,404.045z"/> c-5.791,5.79-15.176,5.79-20.969,0l-30.32-30.322l-11.676,11.676l30.32,30.32c5.79,5.79,5.79,15.178,0,20.969L299.11,404.045z"/>
</svg> </svg>
</div> </div>
<h1>@_localizer[WebKey.RejectionInfo1].TrySanitize(_sanitizer)</h1> <h1>@_localizer[isExt ? WebKey.RejectionInfo1_ext : WebKey.RejectionInfo1].TrySanitize(_sanitizer)</h1>
</header> </header>
<section class="text-center"> <section class="text-center">
<div class="card-body p-0 m-0 ms-4"> <div class="card-body p-0 m-0 ms-4">
<p class="card-text p-0 m-0"> <p class="card-text p-0 m-0">
<small class="text-body-secondary"> <small class="text-body-secondary">
@Html.Raw(string.Format(_localizer[WebKey.RejectionInfo2], @Html.Raw(string.Format(_localizer[isExt ? WebKey.RejectionInfo2_ext : WebKey.RejectionInfo2],
$"{sender?.Prename} {sender?.Name}".TrySanitize(_sanitizer), $"{sender?.Prename} {sender?.Name}".TrySanitize(_sanitizer),
sender?.Email.TrySanitize(_sanitizer), sender?.Email.TrySanitize(_sanitizer),
envelope?.Title.TrySanitize(_sanitizer))) envelope?.Title.TrySanitize(_sanitizer)))

View File

@@ -30,5 +30,7 @@
public static readonly string Hello = nameof(Hello); public static readonly string Hello = nameof(Hello);
public static readonly string RejectionInfo1 = nameof(RejectionInfo1); public static readonly string RejectionInfo1 = nameof(RejectionInfo1);
public static readonly string RejectionInfo2 = nameof(RejectionInfo2); public static readonly string RejectionInfo2 = nameof(RejectionInfo2);
} public static readonly string RejectionInfo1_ext = nameof(RejectionInfo1_ext);
public static readonly string RejectionInfo2_ext = nameof(RejectionInfo2_ext);
}
} }