using AutoMapper; using DigitalData.Core.Abstraction.Application.Repository; using DigitalData.Core.Exceptions; using EnvelopeGenerator.Application.Common.Dto; using EnvelopeGenerator.Application.Common.Enums; using EnvelopeGenerator.Application.Documents.Queries; using EnvelopeGenerator.Application.EnvelopeReceivers.Queries; using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Exceptions; using MediatR; using Microsoft.EntityFrameworkCore; namespace EnvelopeGenerator.Application.PdfSigning; /// /// /// public record SignPdfByEnvelopeReceiverCommand : IRequest { /// /// /// public int EnvelopeId { get; init; } /// /// /// public int ReceiverId { get; init; } } /// /// /// public class SignPdfByEnvelopeReceiverCommandHandler(IRepository Repo, IMapper Mapper, ISender Sender) : IRequestHandler { /// /// /// /// /// /// /// public async Task Handle(SignPdfByEnvelopeReceiverCommand request, CancellationToken cancel) { cancel.ThrowIfCancellationRequested(); // read elements var elements = await Repo.Where(el => el.ReceiverId == request.ReceiverId && el.Document.EnvelopeId == request.EnvelopeId) .Include(e => e.Receiver) .ToListAsync(cancel) ?? throw new NotFoundException($"No elements found for Envelope ID {request.EnvelopeId} and Receiver ID {request.ReceiverId}."); var elementDtos = Mapper.Map>(elements) .OrderBy(e => e.Page) .ThenBy(e => e.Id) .ToList(); // read secrets for phone number var erSecrets = await Sender.Send(new ReadEnvelopeReceiverSecretQuery() { Envelope = new() { Id = request.EnvelopeId }, Receiver = new() { Id = request.ReceiverId } }, cancel) ?? throw new DataIntegrityException($"No secrets found for Envelope ID {request.EnvelopeId} and Receiver ID {request.ReceiverId}."); // read document var unsignedDoc = await Sender.Send(new ReadDocumentQuery(EnvelopeId: request.EnvelopeId), cancel); var unsignedDocBytes = unsignedDoc.ByteData ?? throw new NotFoundException($"Document not found for Envelope ID {request.EnvelopeId} and Receiver ID {request.ReceiverId}."); Stream doc = new MemoryStream(unsignedDocBytes); // sign document for each element foreach (var element in elementDtos) { var lastElement = element == elementDtos.Last(); var signedDoc = await Sender.Send(new SignPdfByElementCommand { Document = doc, Element = element, CertificationLevel = lastElement ? PdfSignatureCertificationLevel.NoChangesAllowed : PdfSignatureCertificationLevel.FillFormsAndAnnotate, Phone = erSecrets.PhoneNumber }, cancel); await doc.DisposeAsync(); doc = signedDoc; } return doc; } }