Replaced manual SQL and file read with async repository update for saving final document bytes. Removed obsolete helper methods and cleaned up unused imports for improved maintainability and testability.
173 lines
6.9 KiB
C#
173 lines
6.9 KiB
C#
using DigitalData.Core.Abstraction.Application.Repository;
|
|
using DigitalData.Modules.Database;
|
|
using EnvelopeGenerator.Application.Common.Dto;
|
|
using EnvelopeGenerator.Application.Configuration.Queries;
|
|
using EnvelopeGenerator.Application.Envelopes.Queries;
|
|
using EnvelopeGenerator.Domain.Constants;
|
|
using EnvelopeGenerator.Domain.Entities;
|
|
using EnvelopeGenerator.ServiceHost.Exceptions;
|
|
using EnvelopeGenerator.ServiceHost.Extensions;
|
|
using EnvelopeGenerator.ServiceHost.Jobs.FinalizeDocument;
|
|
using GdPicture.Internal.MSOfficeBinary.translator.Spreadsheet.XlsFileFormat.Records;
|
|
using GdPicture14;
|
|
using MediatR;
|
|
using Microsoft.Data.SqlClient;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Options;
|
|
using System.Data;
|
|
|
|
namespace EnvelopeGenerator.ServiceHost.Jobs;
|
|
|
|
[Obsolete("ActionService is a placeholder service added by copilot. Migrate the actual logic from CommonServices.Jobs")]
|
|
public class FinalizeDocumentJob(IOptions<WorkerOptions> options, IConfiguration config, ILogger<FinalizeDocumentJob> logger, TempFiles tempFiles, ActionService actionService, PDFBurner pdfBurner, PDFMerger pdfMerger, ReportCreator reportCreator, ReportModel _reportModel, MSSQLServer _database, GdViewer? _gdViewer, LicenseManager licenseManager, IMediator mediator, IRepository<Envelope> envRepo, IRepository<Domain.Entities.DocumentStatus> docStatusRepo)
|
|
{
|
|
private readonly WorkerOptions _options = options.Value;
|
|
|
|
private ConfigDto? _config;
|
|
|
|
private const int CompleteWaitTime = 1;
|
|
private string _parentFolderUid = string.Empty;
|
|
|
|
private sealed class EnvelopeData
|
|
{
|
|
public int EnvelopeId { get; set; }
|
|
public string EnvelopeUuid { get; set; } = string.Empty;
|
|
public string DocumentPath { get; set; } = string.Empty;
|
|
public List<string> AnnotationData { get; set; } = new();
|
|
public byte[]? DocAsByte { get; set; }
|
|
}
|
|
|
|
public bool RethrowOnError { get; set; } = true;
|
|
|
|
public async Task ExecuteAsync(CancellationToken cancel = default)
|
|
{
|
|
var gdPictureKey = _options.GdPictureLicenseKey;
|
|
tempFiles.Create();
|
|
var jobId = typeof(FinalizeDocumentJob).FullName;
|
|
|
|
_config = await mediator.Send(new ReadDefaultConfigQuery(), cancel);
|
|
|
|
var envelopes = await envRepo
|
|
.Where(e => e.Status == EnvelopeStatus.EnvelopeCompletelySigned
|
|
&& e.ChangedWhen.HasValue
|
|
&& EF.Functions.DateDiffMinute(e.ChangedWhen.Value, DateTime.Now) >= CompleteWaitTime)
|
|
.OrderBy(e => e.Id)
|
|
.ToListAsync(cancel);
|
|
|
|
if (envelopes.Count > 0)
|
|
logger.LogInformation("Found [{count}] completed envelopes.", envelopes.Count);
|
|
|
|
foreach (var envelope in envelopes)
|
|
{
|
|
try
|
|
{
|
|
await Finalize(envelope, cancel);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogError(ex, "Unhandled exception while working envelope [{id}]", envelope.Id);
|
|
|
|
if(RethrowOnError)
|
|
throw;
|
|
}
|
|
|
|
logger.LogInformation("Envelope [{id}] finalized!", envelope.Id);
|
|
}
|
|
}
|
|
|
|
private async Task Finalize(Envelope envelope, CancellationToken cancel)
|
|
{
|
|
var annotations = await docStatusRepo.Where(s => s.EnvelopeId == envelope.Id).Select(s => s.Value).ToListAsync(cancel);
|
|
var burnedDocument = pdfBurner!.BurnAnnotsToPDF(envelope.DefaultDocument.ByteData!, annotations, envelope.Id)
|
|
?? throw new ApplicationException("Document could not be finalized");
|
|
|
|
if (!actionService.CreateReport(envelope, cancel))
|
|
{
|
|
logger.LogWarning("Document Report could not be created!");
|
|
throw new ApplicationException("Document Report could not be created");
|
|
}
|
|
|
|
var report = reportCreator!.CreateReport(envelope);
|
|
|
|
var mergedDocument = pdfMerger!.MergeDocuments(burnedDocument, report);
|
|
|
|
var outputDirectoryPath = Path.Combine(_config.ExportPath, _parentFolderUid);
|
|
|
|
if (!Directory.Exists(outputDirectoryPath))
|
|
Directory.CreateDirectory(outputDirectoryPath);
|
|
|
|
var outputFilePath = Path.Combine(outputDirectoryPath, $"{envelope.Uuid}.pdf");
|
|
logger.LogInformation("Output path is [{outputFilePath}]", outputFilePath);
|
|
|
|
try
|
|
{
|
|
File.WriteAllBytes(outputFilePath, mergedDocument);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogWarning("Could not export final document to disk!");
|
|
throw new ExportDocumentException("Could not export final document to disk!", ex);
|
|
}
|
|
|
|
var outputFile = await File.ReadAllBytesAsync(outputFilePath, cancel);
|
|
await envRepo.UpdateAsync(e => e.DocResult = outputFile, e => e.Id == envelope.Id, cancel);
|
|
|
|
if (!SendFinalEmails(envelope))
|
|
throw new ApplicationException("Final emails could not be sent!");
|
|
|
|
logger.LogInformation("Report-mails successfully sent!");
|
|
|
|
if (actionService?.FinalizeEnvelope(envelope) == false)
|
|
{
|
|
logger.LogWarning("Envelope could not be finalized!");
|
|
throw new ApplicationException("Envelope could not be finalized");
|
|
}
|
|
}
|
|
|
|
private bool SendFinalEmails(Envelope envelope)
|
|
{
|
|
var mailToCreator = (FinalEmailType)(envelope.FinalEmailToCreator ?? 0);
|
|
var mailToReceivers = (FinalEmailType)(envelope.FinalEmailToReceivers ?? 0);
|
|
|
|
if (mailToCreator != FinalEmailType.No)
|
|
SendFinalEmailToCreator(envelope, mailToCreator);
|
|
else
|
|
logger?.LogWarning("No SendFinalEmailToCreator - oMailToCreator [{mailToCreator}] <> [{noFinalEmailType}] ", mailToCreator, FinalEmailType.No);
|
|
|
|
if (mailToReceivers != FinalEmailType.No)
|
|
{
|
|
SendFinalEmailToReceivers(envelope, mailToReceivers);
|
|
}
|
|
else
|
|
{
|
|
logger?.LogWarning("No SendFinalEmailToReceivers - oMailToCreator [{mailToReceivers}] <> [{noFinalEmailType}] ", mailToReceivers, FinalEmailType.No);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool SendFinalEmailToCreator(Envelope envelope, FinalEmailType mailToCreator)
|
|
{
|
|
if (actionService?.CompleteEnvelope(envelope) == false)
|
|
{
|
|
logger?.LogError(new Exception("CompleteEnvelope failed"), "Envelope could not be completed for receiver [{email}]", envelope.User?.Email);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
private bool SendFinalEmailToReceivers(Envelope envelope, FinalEmailType mailToReceivers)
|
|
{
|
|
foreach (var receiver in envelope.EnvelopeReceivers ?? Enumerable.Empty<EnvelopeReceiver>())
|
|
{
|
|
if (actionService?.CompleteEnvelope(envelope, receiver.Receiver) == false)
|
|
{
|
|
logger?.LogError(new Exception("CompleteEnvelope failed"), "Envelope could not be completed for receiver [{email}]", receiver.Receiver?.EmailAddress);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
} |