diff --git a/EnvelopeGenerator.Application/Envelopes/Queries/ReadSignedEnvelopeQuery.cs b/EnvelopeGenerator.Application/Envelopes/Queries/ReadSignedEnvelopeQuery.cs
new file mode 100644
index 00000000..80f196ea
--- /dev/null
+++ b/EnvelopeGenerator.Application/Envelopes/Queries/ReadSignedEnvelopeQuery.cs
@@ -0,0 +1,62 @@
+using AutoMapper;
+using DigitalData.Core.Abstraction.Application.Repository;
+using EnvelopeGenerator.Application.Common.Dto;
+using EnvelopeGenerator.Domain.Entities;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace EnvelopeGenerator.Application.Envelopes.Queries;
+
+///
+///
+///
+public record ReadSignedEnvelopeQuery : IRequest>
+{
+ ///
+ ///
+ ///
+ public bool? Burned { get; init; } = null;
+
+ internal int? UserId { get; private set; } = null;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ReadSignedEnvelopeQuery Authorized(int userId)
+ {
+ UserId = userId;
+ return this;
+ }
+}
+
+///
+///
+///
+///
+///
+public class ReadSignedEnvelopeQueryHandler(IRepository Repo, IMapper Mapper) : IRequestHandler>
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task> Handle(ReadSignedEnvelopeQuery request, CancellationToken cancel)
+ {
+ var eQuery = Repo.Query.Where(e => e.Status == Domain.Constants.EnvelopeStatus.EnvelopeCompletelySigned);
+
+ if (request.Burned is bool burned)
+ eQuery = burned ? eQuery.Where(e => e.DocResult != null) : eQuery.Where(e => e.DocResult == null);
+
+ if(request.UserId is int userId)
+ eQuery = eQuery.Where(e => e.UserId == userId);
+
+ var envelopes = await eQuery.ToListAsync(cancel);
+
+ return Mapper.Map>(envelopes);
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Application/PdfSigning/FinalizeEnvelopeCommand.cs b/EnvelopeGenerator.Application/PdfSigning/FinalizeEnvelopeCommand.cs
new file mode 100644
index 00000000..67ac39a5
--- /dev/null
+++ b/EnvelopeGenerator.Application/PdfSigning/FinalizeEnvelopeCommand.cs
@@ -0,0 +1,107 @@
+using DigitalData.Core.Abstraction.Application.Repository;
+using DigitalData.Core.Exceptions;
+using EnvelopeGenerator.Application.Common.Interfaces.Services.Notification;
+using EnvelopeGenerator.Application.Common.Query;
+using EnvelopeGenerator.Domain.Constants;
+using EnvelopeGenerator.Domain.Entities;
+using EnvelopeGenerator.Domain.Interfaces;
+using MediatR;
+using Microsoft.EntityFrameworkCore;
+
+namespace EnvelopeGenerator.Application.PdfSigning;
+
+///
+///
+///
+public record FinalizeEnvelopeCommand : EnvelopeQueryBase, IRequest
+{
+ internal int? UserId { get; private set; } = null;
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public FinalizeEnvelopeCommand Authorized(int userId)
+ {
+ UserId = userId;
+ return this;
+ }
+
+ ///
+ ///
+ ///
+ public bool BurnedAllowed { get; init; } = false;
+
+ ///
+ ///
+ ///
+ public bool SaveDocResult { get; init; } = true;
+}
+
+///
+///
+///
+///
+///
+public class FinalizeEnvelopeCommandHandler(IRepository Repo, ISender Sender, IEnvelopeNotificationService NtfServer) : IRequestHandler
+{
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public async Task Handle(FinalizeEnvelopeCommand request, CancellationToken cancel)
+ {
+ var envelopeQuery = Repo.Query;
+
+ if (request.Id is int id)
+ envelopeQuery = envelopeQuery.Where(e => e.Id == id);
+ else if (request.Uuid is string uuid)
+ envelopeQuery = envelopeQuery.Where(e => e.Uuid == uuid);
+
+ var envelope = await envelopeQuery
+ .Include(e => e.EnvelopeReceivers).ThenInclude(er => er.Receiver)
+ .Include(e => e.Documents)
+ .SingleOrDefaultAsync(cancel)
+ ?? throw new NotFoundException($"Envelope is not found ID: {request.Id} UUID: {request.Uuid}");
+
+ if(request.UserId is int userId && userId != envelope.UserId)
+ throw new InvalidOperationException($"Envelope is not owned by user ID: {request.Id} UUID: {request.Uuid}");
+
+ // already burned
+ if (!request.BurnedAllowed && envelope.IsBurned())
+ throw new InvalidOperationException($"Envelope is already burned ID: {request.Id} UUID: {request.Uuid}");
+
+ // envelope is not completely signed
+ if (envelope.Status!= EnvelopeStatus.EnvelopeCompletelySigned)
+ throw new InvalidOperationException($"Envelope status is not completely signed ID: {request.Id} UUID: {request.Uuid}");
+
+ using var docStream = await Sender.Send(new SignPdfByEnvelopeCommand()
+ {
+ Envelope = envelope
+ }, cancel);
+
+ if (docStream.CanSeek)
+ docStream.Position = 0;
+
+ using var ms = new MemoryStream();
+ docStream.CopyTo(ms);
+ byte[] doc = ms.ToArray();
+
+ foreach (var er in envelope.EnvelopeReceivers)
+ {
+ await NtfServer.Notify(er.Receiver.EmailAddress, new DocumentSignedNotification()
+ {
+ DocumentTitle = envelope.Title,
+ NameReceiver = er.Name,
+ Attachment = doc
+ }, cancel);
+ }
+
+ if (request.SaveDocResult)
+ await Repo.UpdateAsync(e => e.DocResult = doc, e => e.Id == envelope.Id, cancel);
+ }
+}
\ No newline at end of file
diff --git a/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs b/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs
index 3ce35e81..019e977b 100644
--- a/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs
+++ b/EnvelopeGenerator.Application/PdfSigning/SignPdfByEnvelopeCommand.cs
@@ -29,6 +29,8 @@ public record SignPdfByEnvelopeCommand : EnvelopeQueryBase, IRequest
UserId = userId;
return this;
}
+
+ internal Envelope? Envelope { get; set; }
}
///
@@ -45,15 +47,20 @@ public class SignPdfByEnvelopeCommandHandler(IRepository Repo, ISender
///
public async Task Handle(SignPdfByEnvelopeCommand request, CancellationToken cancel)
{
- var envelopeQuery = Repo.Query;
+ if (request.Envelope is null)
+ {
+ var envelopeQuery = Repo.Query;
- if (request.Id is int id)
- envelopeQuery = envelopeQuery.Where(e => e.Id == id);
- else if (request.Uuid is string uuid)
- envelopeQuery = envelopeQuery.Where(e => e.Uuid == uuid);
+ if (request.Id is int id)
+ envelopeQuery = envelopeQuery.Where(e => e.Id == id);
+ else if (request.Uuid is string uuid)
+ envelopeQuery = envelopeQuery.Where(e => e.Uuid == uuid);
- var envelope = await envelopeQuery.Include(e => e.EnvelopeReceivers).Include(e => e.Documents).SingleOrDefaultAsync(cancel)
- ?? throw new NotFoundException($"Envelope is not found ID: {request.Id} UUID: {request.Uuid}");
+ request.Envelope = await envelopeQuery.Include(e => e.EnvelopeReceivers).Include(e => e.Documents).SingleOrDefaultAsync(cancel)
+ ?? throw new NotFoundException($"Envelope is not found ID: {request.Id} UUID: {request.Uuid}");
+ }
+
+ var envelope = request.Envelope;
if (request.UserId is int userId && userId != envelope.UserId)
throw new AuthorizationException($"Envelope is not authorized for user with Id: {request.UserId} Envelope ID: {request.Id} UUID: {request.Uuid}");