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, Attachments = [ ($"unterzeichnetes-dokument.pdf", doc) ] }, cancel); } if (request.SaveDocResult) await Repo.UpdateAsync(e => e.DocResult = doc, e => e.Id == envelope.Id, cancel); } }