refactor(EnvelopeGenerator.Common): umbenennen in EnvelopeGenerator.CommonService

This commit is contained in:
Developer 02
2025-05-26 11:14:12 +02:00
parent a5261baec5
commit c1d46b446a
120 changed files with 93 additions and 93 deletions

View File

@@ -0,0 +1,52 @@
Namespace Jobs.FinalizeDocument
Public Class FinalizeDocumentExceptions
Public Class MergeDocumentException
Inherits ApplicationException
Public Sub New(message As String)
MyBase.New(message)
End Sub
Public Sub New(message As String, innerException As Exception)
MyBase.New(message, innerException)
End Sub
End Class
Public Class BurnAnnotationException
Inherits ApplicationException
Public Sub New(message As String)
MyBase.New(message)
End Sub
Public Sub New(message As String, innerException As Exception)
MyBase.New(message, innerException)
End Sub
End Class
Public Class CreateReportException
Inherits ApplicationException
Public Sub New(message As String)
MyBase.New(message)
End Sub
Public Sub New(message As String, innerException As Exception)
MyBase.New(message, innerException)
End Sub
End Class
Public Class ExportDocumentException
Inherits ApplicationException
Public Sub New(message As String)
MyBase.New(message)
End Sub
Public Sub New(message As String, innerException As Exception)
MyBase.New(message, innerException)
End Sub
End Class
End Class
End Namespace

View File

@@ -0,0 +1,456 @@
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Base
Imports GdPicture14
Imports Quartz
Imports System.Security.Cryptography
Imports System.IO
Imports EnvelopeGenerator.CommonServices.Jobs.FinalizeDocument.FinalizeDocumentExceptions
Imports EnvelopeGenerator.CommonServices.Jobs.FinalizeDocument
Imports EnvelopeGenerator.Domain.Constants
Imports DevExpress.DataProcessing
Imports System.Data.SqlClient
Imports EnvelopeGenerator.Domain.Entities
Namespace Jobs
Public Class FinalizeDocumentJob
Implements IJob
Private ReadOnly LicenseManager As New LicenseManager()
Private GdViewer As GdViewer
Private LogConfig As LogConfig
Private Logger As Logger
Private Database As MSSQLServer
Private Config As DbConfig
Private ConfigModel As ConfigModel
Private EnvelopeModel As EnvelopeModel
Private ReportModel As ReportModel
Private ActionService As ActionService
Private PDFBurner As PDFBurner
Private PDFMerger As PDFMerger
Private ReportCreator As ReportCreator
Private ReadOnly CompleteWaitTime As Integer = 1
Private ParentFolderUID As String = ""
Private myTempFiles As TempFiles
Private Class EnvelopeData
Public EnvelopeId As Integer
Public EnvelopeUUID As String
Public DocumentPath As String
Public AnnotationData As List(Of String)
Public DocAsByte As Byte()
End Class
Public Function Execute(pContext As IJobExecutionContext) As Task Implements IJob.Execute
Dim oGdPictureKey As String = pContext.MergedJobDataMap.Item(Domain.Constants.GDPICTURE)
LogConfig = pContext.MergedJobDataMap.Item(Domain.Constants.LOGCONFIG)
Logger = LogConfig.GetLogger()
myTempFiles = New TempFiles(LogConfig)
myTempFiles.Create()
Dim JobId = pContext.JobDetail.Key
Logger.Debug("Starting job {0}", JobId)
Try
Logger.Debug("Loading GdViewer..")
GdViewer = New GdViewer()
LicenseManager.RegisterKEY(oGdPictureKey)
Logger.Debug("Loading Database..")
Database = GetDatabase(pContext, LogConfig)
Logger.Debug("Loading Models & Services")
Dim oState = GetState()
InitializeModels(oState)
Logger.Debug("Loading Configuration..")
Config = ConfigModel.LoadConfiguration()
oState.DbConfig = Config
InitializeServices(oState)
Logger.Debug("Loading PDFBurner..")
Dim pdfBurnerParams As PDFBurnerParams = pContext.MergedJobDataMap.Item(PDF_BURNER_PARAMS)
PDFBurner = New PDFBurner(LogConfig, oGdPictureKey, pdfBurnerParams)
Logger.Debug("Loading PDFMerger..")
PDFMerger = New PDFMerger(LogConfig, oGdPictureKey)
Logger.Debug("Loading ReportCreator..")
ReportCreator = New ReportCreator(LogConfig, oState)
Config.DocumentPath = Config.DocumentPath
Logger.Debug("DocumentPath: [{0}]", Config.DocumentPath)
Logger.Debug("ExportPath: [{0}]", Config.ExportPath)
Dim oCompleteStatus As Integer = EnvelopeStatus.EnvelopeCompletelySigned
Dim oSql = $"SELECT * FROM TBSIG_ENVELOPE WHERE STATUS = {oCompleteStatus} AND DATEDIFF(minute, CHANGED_WHEN, GETDATE()) >= {CompleteWaitTime} ORDER BY GUID"
Dim oTable = Database.GetDatatable(oSql)
Dim oEnvelopeIds As List(Of Integer) = oTable.Rows.Cast(Of DataRow).
Select(Function(r) r.Item("GUID")).
Cast(Of Integer).
ToList()
If oEnvelopeIds.Count > 0 Then
Logger.Info("Found [{0}] completed envelopes.", oEnvelopeIds.Count)
End If
Dim oTotal As Integer = oEnvelopeIds.Count
Dim oCurrent As Integer = 1
For Each oId In oEnvelopeIds
Logger.Info("Finalizing Envelope [{0}] ({1}/{2})", oId, oCurrent, oTotal)
Try
Dim oEnvelope = EnvelopeModel.GetById(oId)
If oEnvelope Is Nothing Then
Logger.Warn("Envelope could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
Logger.Debug("Loading Envelope Data..")
Dim oEnvelopeData = GetEnvelopeData(oId)
If oEnvelopeData Is Nothing Then
Logger.Warn("EnvelopeData could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
Logger.Debug("Burning Annotations to pdf ...")
Dim oBurnedDocument As Byte() = BurnAnnotationsToPdf(oEnvelopeData)
If oBurnedDocument Is Nothing Then
Logger.Warn("Document could not be finalized!")
Throw New ApplicationException("Document could not be finalized")
End If
If ActionService.CreateReport(oEnvelope) = False Then
Logger.Warn("Document Report could not be created!")
Throw New ApplicationException("Document Report could not be created")
End If
Logger.Debug("Creating report..")
Dim oReport As Byte() = ReportCreator.CreateReport(oEnvelope)
Logger.Debug("Report created!")
Logger.Debug("Merging documents ...")
Dim oMergedDocument As Byte() = PDFMerger.MergeDocuments(oBurnedDocument, oReport)
Logger.Debug("Documents merged!")
Dim oOutputDirectoryPath = Path.Combine(Config.ExportPath, ParentFolderUID)
If Not Directory.Exists(oOutputDirectoryPath) Then
Directory.CreateDirectory(oOutputDirectoryPath)
End If
Dim oOutputFilePath = Path.Combine(oOutputDirectoryPath, $"{oEnvelope.Uuid}.pdf")
Logger.Debug("Writing finalized Pdf to disk..")
Logger.Info("Output path is [{0}]", oOutputFilePath)
Try
File.WriteAllBytes(oOutputFilePath, oMergedDocument)
Catch ex As Exception
Logger.Warn("Could not export final document to disk!")
Throw New ExportDocumentException("Could not export final document to disk!", ex)
End Try
Logger.Debug("Writing EB-bytes to database...")
Update_File_DB(oOutputFilePath, oEnvelope.Id)
If SendFinalEmails(oEnvelope) = False Then ', oOutputFilePath
Throw New ApplicationException("Final emails could not be sent!")
Else
Logger.Info("Report-mails successfully sent!")
End If
Logger.Debug("Setting envelope status..")
If ActionService.FinalizeEnvelope(oEnvelope) = False Then
Logger.Warn("Envelope could not be finalized!")
Throw New ApplicationException("Envelope could not be finalized")
End If
Catch ex As Exception
Logger.Warn(ex, $"Unhandled exception while working envelope [{oId}]")
End Try
oCurrent += 1
Logger.Info($"Envelope [{oId}] finalized!")
Next
Logger.Debug("Completed job {0} successfully!", JobId)
Catch ex As MergeDocumentException
Logger.Warn("Certificate Document job failed at step: Merging documents!")
Logger.Error(ex)
Catch ex As ExportDocumentException
Logger.Warn("Certificate Document job failed at step: Exporting document!")
Logger.Error(ex)
Catch ex As Exception
Logger.Warn("Certificate Document job failed!")
Logger.Error(ex)
Finally
Logger.Debug("Job execution for [{0}] ended", JobId)
End Try
Return Task.FromResult(True)
End Function
Private Sub Update_File_DB(pFilePath As String, pEnvelopeID As Long)
Dim SqlCom As SqlCommand
Dim imageData As Byte()
Dim sFileName As String
Dim qry As String
Try
'Read Image Bytes into a byte array
'Initialize SQL Server Connection
'Convert File to bytes Array
imageData = ReadFile(pFilePath)
If Not IsNothing(imageData) Then
sFileName = System.IO.Path.GetFileName(pFilePath)
'Set insert query
qry = $"UPDATE TBSIG_ENVELOPE SET DOC_RESULT = @ImageData WHERE GUID = {pEnvelopeID}"
'Initialize SqlCommand object for insert.
SqlCom = New SqlCommand(qry, Database.GetConnection)
'We are passing File Name and Image byte data as sql parameters.
SqlCom.Parameters.Add(New SqlParameter("@ImageData", DirectCast(imageData, Object)))
'Execute the Query
SqlCom.ExecuteNonQuery()
End If
Catch ex As Exception
Logger.Error(ex)
End Try
End Sub
'Open file in to a filestream and read data in a byte array.
Private Function ReadFile(ByVal sPath As String) As Byte()
'Initialize byte array with a null value initially.
Dim data As Byte() = Nothing
'Use FileInfo object to get file size.
Dim fInfo As New FileInfo(sPath)
Dim numBytes As Long = fInfo.Length
'Open FileStream to read file
Dim fStream As New FileStream(sPath, FileMode.Open, FileAccess.Read)
'Use BinaryReader to read file stream into byte array.
Dim br As New BinaryReader(fStream)
'When you use BinaryReader, you need to supply number of bytes to read from file.
'In this case we want to read entire file. So supplying total number of bytes.
data = br.ReadBytes(CInt(numBytes))
Return data
End Function
'Private Function NetUse_Command(pDestinationPath As String, pUsername As String, pPassword As String)
' Dim oDectryptedPW = Helpers.Decrypt(My.Settings.NetUse_PW)
' Dim netUseCommand As String = $"net use {pDestinationPath} /user:{pUsername} {oDectryptedPW}"
' Logger.Debug("EXECUTING NetUse_Command for " & pDestinationPath)
' Dim processInfo As New ProcessStartInfo("cmd.exe", $"/C {netUseCommand}")
' processInfo.RedirectStandardOutput = True
' processInfo.UseShellExecute = False
' processInfo.CreateNoWindow = True
' Using process As Process = Process.Start(processInfo)
' process.WaitForExit()
' ' Prüfe den Rückgabewert des net use Befehls
' If process.ExitCode = 0 Then
' Return True
' Else
' Return False
' End If
' End Using
'End Function
'Private Function Clean_DNZ_PAth(pSourcePath As String) As Boolean
' Dim oFilename = System.IO.Path.GetFileName(pSourcePath)
' Logger.Debug("## Starting Clean_DNZ_PAth ...")
' Logger.Debug("## pSourcePath {0}", pSourcePath)
' Dim oDirectorySource = Path.Combine(pSourcePath, ParentFolderUID)
' Try
' Logger.Debug($"Deleting oDirectorySource {oDirectorySource} ...")
' Directory.Delete(oDirectorySource, True)
' Console.WriteLine($"Folder successfully deleted!")
' Logger.Debug($"...Deleted!")
' Return True
' Catch ex As Exception
' Logger.Error(ex)
' Return False
' End Try
'End Function
Private Function SendFinalEmails(pEnvelope As Envelope) As Boolean ', pAttachment As String
Dim oMailToCreator = pEnvelope.FinalEmailToCreator
Dim oMailToReceivers = pEnvelope.FinalEmailToReceivers
If oMailToCreator <> FinalEmailType.No Then
Logger.Debug("Sending email to creator ...")
SendFinalEmailToCreator(pEnvelope) ', pAttachment
Else
Logger.Warn($"No SendFinalEmailToCreator - oMailToCreator [{oMailToCreator}] <> [{FinalEmailType.No}] ")
End If
If oMailToReceivers <> FinalEmailType.No Then
Logger.Debug("Sending emails to receivers..")
SendFinalEmailToReceivers(pEnvelope) ', pAttachment
Else
Logger.Warn($"No SendFinalEmailToReceivers - oMailToCreator [{oMailToReceivers}] <> [{FinalEmailType.No}] ")
End If
Return True
End Function
Private Function SendFinalEmailToCreator(pEnvelope As Envelope) As Boolean ', pAttachment As String
Dim oIncludeAttachment = SendFinalEmailWithAttachment(pEnvelope.FinalEmailToCreator)
' Dim oAttachment = String.Empty
Logger.Debug("Attachment included: [{0}]", oIncludeAttachment)
If oIncludeAttachment Then
'oAttachment = pAttachment
End If
If ActionService.CompleteEnvelope(pEnvelope) = False Then ', oAttachment
Logger.Error("Envelope could not be completed for receiver [{0}]", pEnvelope.User.Email)
Return False
End If
Return True
End Function
Private Function SendFinalEmailToReceivers(pEnvelope As Envelope) As Boolean ', pAttachment As String
Dim oIncludeAttachment = SendFinalEmailWithAttachment(pEnvelope.FinalEmailToReceivers)
'Dim oAttachment = String.Empty
Logger.Debug("Attachment included: [{0}]", oIncludeAttachment)
If oIncludeAttachment Then
' oAttachment = pAttachment
End If
For Each oReceiver In pEnvelope.Receivers
If ActionService.CompleteEnvelope(pEnvelope, oReceiver) = False Then ', oAttachment
Logger.Error("Envelope could not be completed for receiver [{0}]", oReceiver.EmailAddress)
Return False
End If
Next
Return True
End Function
Private Function SendFinalEmailWithAttachment(pType As FinalEmailType)
If pType = FinalEmailType.YesWithAttachment Then
Return True
Else
Return False
End If
End Function
Private Function BurnAnnotationsToPdf(pEnvelopeData As EnvelopeData) As Byte()
Dim pEnvelopeId = pEnvelopeData.EnvelopeId
Logger.Info($"Burning [{pEnvelopeData.AnnotationData.Count}] signatures")
Dim oAnnotations = pEnvelopeData.AnnotationData
Dim oInputPath = ""
If IsNothing(pEnvelopeData.DocAsByte) Then
oInputPath = pEnvelopeData.DocumentPath
Logger.Info($"Input path: [{oInputPath}]")
Else
Logger.Debug($"we got bytes..")
oInputPath = Config.DocumentPathOrigin
Logger.Debug($"oInputPath: {Config.DocumentPathOrigin}")
End If
If IsNothing(pEnvelopeData.DocAsByte) Then
Dim oDirectorySource As String = Path.GetDirectoryName(oInputPath)
Dim split As String() = oDirectorySource.Split("\")
ParentFolderUID = split(split.Length - 1)
Else
ParentFolderUID = pEnvelopeData.EnvelopeUUID
End If
Logger.Info("ParentFolderUID: [{0}]", ParentFolderUID)
Dim oInputDocumentBuffer As Byte()
If Not IsNothing(pEnvelopeData.DocAsByte) Then
oInputDocumentBuffer = pEnvelopeData.DocAsByte
Else
Try
oInputDocumentBuffer = File.ReadAllBytes(oInputPath)
Catch ex As Exception
Throw New BurnAnnotationException("Source document could not be read from disk!", ex)
End Try
End If
Return PDFBurner.BurnInstantJSONAnnotationsToPDF(oInputDocumentBuffer, oAnnotations)
End Function
Private Function GetEnvelopeData(pEnvelopeId As Integer) As EnvelopeData
Dim oSql = $"SELECT T.GUID, T.ENVELOPE_UUID,T2.FILEPATH, T2.BYTE_DATA FROM [dbo].[TBSIG_ENVELOPE] T
JOIN TBSIG_ENVELOPE_DOCUMENT T2 ON T.GUID = T2.ENVELOPE_ID
WHERE T.GUID = {pEnvelopeId}"
Dim oTable As DataTable = Database.GetDatatable(oSql)
Dim oRow As DataRow = oTable.Rows.Cast(Of DataRow).SingleOrDefault()
If oRow Is Nothing Then
Return Nothing
End If
Dim oAnnotationData = GetAnnotationData(pEnvelopeId)
Dim oData As New EnvelopeData With {
.EnvelopeId = pEnvelopeId,
.DocumentPath = oRow.ItemEx("FILEPATH", ""),
.AnnotationData = oAnnotationData,
.DocAsByte = DirectCast(oRow.Item("BYTE_DATA"), Byte()),
.EnvelopeUUID = oRow.ItemEx("ENVELOPE_UUID", "")
}
Logger.Debug("Document path: [{0}]", oData.DocumentPath)
Return oData
End Function
Private Function GetAnnotationData(pEnvelopeId As Integer) As List(Of String)
Dim oSql = $"SELECT VALUE FROM TBSIG_DOCUMENT_STATUS WHERE ENVELOPE_ID = {pEnvelopeId}"
Dim oTable As DataTable = Database.GetDatatable(oSql)
Return oTable.Rows.Cast(Of DataRow).
Select(Function(r) r.ItemEx("VALUE", String.Empty)).
Cast(Of String).
ToList()
End Function
Private Sub InitializeServices(pState As State)
ActionService = New ActionService(pState, Database)
End Sub
Private Sub InitializeModels(pState As State)
ConfigModel = New ConfigModel(pState)
EnvelopeModel = New EnvelopeModel(pState)
ReportModel = New ReportModel(pState)
End Sub
Private Function GetDatabase(pContext As IJobExecutionContext, pLogConfig As LogConfig) As MSSQLServer
Dim oConnectionString As String = pContext.MergedJobDataMap.Item(Domain.Constants.DATABASE)
Dim Database = New MSSQLServer(pLogConfig, MSSQLServer.DecryptConnectionString(oConnectionString))
Return Database
End Function
Private Function GetState() As State
Return New State With {
.LogConfig = LogConfig,
.Database = Database,
.UserId = 0,
.Config = Nothing,
.DbConfig = Nothing
}
End Function
End Class
End Namespace

View File

@@ -0,0 +1,221 @@
Imports System.Drawing
Imports System.IO
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
Imports GdPicture14
Imports Newtonsoft.Json
Imports EnvelopeGenerator.CommonServices.Jobs.FinalizeDocument.FinalizeDocumentExceptions
Namespace Jobs.FinalizeDocument
Public Class PDFBurner
Inherits BaseClass
Private ReadOnly Manager As AnnotationManager
Private ReadOnly LicenseManager As LicenseManager
Private Const ANNOTATION_TYPE_IMAGE = "pspdfkit/image"
Private Const ANNOTATION_TYPE_INK = "pspdfkit/ink"
Private Const ANNOTATION_TYPE_WIDGET = "pspdfkit/widget"
Private Property _pdfBurnerParams As PDFBurnerParams
Public Sub New(pLogConfig As LogConfig, pGDPictureLicenseKey As String, pdfBurnerParams As PDFBurnerParams)
MyBase.New(pLogConfig)
LicenseManager = New LicenseManager()
LicenseManager.RegisterKEY(pGDPictureLicenseKey)
Manager = New AnnotationManager()
_pdfBurnerParams = pdfBurnerParams
End Sub
Public Function BurnInstantJSONAnnotationsToPDF(pSourceBuffer As Byte(), pInstantJSONList As List(Of String)) As Byte()
Dim oResult As GdPictureStatus
Using oSourceStream As New MemoryStream(pSourceBuffer)
' Open PDF
oResult = Manager.InitFromStream(oSourceStream)
If oResult <> GdPictureStatus.OK Then
Throw New BurnAnnotationException($"Could not open document for burning: [{oResult}]")
End If
' Add annotation to PDF
For Each oJSON In pInstantJSONList
If AddInstantJSONAnnotationToPDF(oJSON) = False Then
Logger.Warn($"Error in AddInstantJSONAnnotationToPDF - oJson: ")
Logger.Warn(oJSON)
Throw New BurnAnnotationException($"Adding Annotation failed")
End If
Next
oResult = Manager.BurnAnnotationsToPage(RemoveInitialAnnots:=True, VectorMode:=True)
If oResult <> GdPictureStatus.OK Then
Throw New BurnAnnotationException($"Could not burn annotations to file: [{oResult}]")
End If
'Save PDF
Using oNewStream As New MemoryStream()
oResult = Manager.SaveDocumentToPDF(oNewStream)
If oResult <> GdPictureStatus.OK Then
Throw New BurnAnnotationException($"Could not save document to stream: [{oResult}]")
End If
Manager.Close()
Return oNewStream.ToArray()
End Using
End Using
End Function
Private Function AddInstantJSONAnnotationToPDF(pInstantJSON As String) As Boolean
Try
Dim oAnnotationData = JsonConvert.DeserializeObject(Of AnnotationData)(pInstantJSON)
oAnnotationData.annotations.Reverse()
Dim formFieldIndex = 0
For Each oAnnotation In oAnnotationData.annotations
Logger.Debug("Adding AnnotationID: " + oAnnotation.id)
Select Case oAnnotation.type
Case ANNOTATION_TYPE_IMAGE
AddImageAnnotation(oAnnotation, oAnnotationData.attachments)
Case ANNOTATION_TYPE_INK
AddInkAnnotation(oAnnotation)
Case ANNOTATION_TYPE_WIDGET
'Add form field values
Dim formFieldValue = oAnnotationData.formFieldValues.FirstOrDefault(Function(fv) fv.name = oAnnotation.id)
If formFieldValue IsNot Nothing AndAlso Not _pdfBurnerParams.IgnoredLabels.Contains(formFieldValue.value) Then
AddFormFieldValue(oAnnotation, formFieldValue, formFieldIndex)
formFieldIndex += 1
End If
End Select
Next
Return True
Catch ex As Exception
Logger.Warn("Could not create annotation from InstantJSON")
Logger.Error(ex)
Return False
End Try
End Function
Private Function AddImageAnnotation(pAnnotation As Annotation, pAttachments As Dictionary(Of String, Attachment)) As Boolean
Try
Dim oAttachment = pAttachments.Where(Function(a) a.Key = pAnnotation.imageAttachmentId).
SingleOrDefault()
' Convert pixels to Inches
Dim oBounds = pAnnotation.bbox.Select(AddressOf ToInches).ToList()
Dim oX = oBounds.Item(0)
Dim oY = oBounds.Item(1)
Dim oWidth = oBounds.Item(2)
Dim oHeight = oBounds.Item(3)
Manager.SelectPage(pAnnotation.pageIndex + 1)
Manager.AddEmbeddedImageAnnotFromBase64(oAttachment.Value.binary, oX, oY, oWidth, oHeight)
Return True
Catch ex As Exception
Logger.Warn("Could not add image annotation!")
Logger.Error(ex)
Return False
End Try
End Function
Private Function AddInkAnnotation(pAnnotation As Annotation) As Boolean
Try
Dim oSegments = pAnnotation.lines.points
Dim oColor = ColorTranslator.FromHtml(pAnnotation.strokeColor)
Manager.SelectPage(pAnnotation.pageIndex + 1)
For Each oSegment As List(Of List(Of Single)) In oSegments
Dim oPoints = oSegment.
Select(AddressOf ToPointF).
ToArray()
Manager.AddFreeHandAnnot(oColor, oPoints)
Next
Return True
Catch ex As Exception
Logger.Warn("Could not add image annotation!")
Logger.Error(ex)
Return False
End Try
End Function
Private Function AddFormFieldValue(pAnnotation As Annotation, formFieldValue As FormFieldValue, index As Integer) As Boolean
Try
' Convert pixels to Inches
Dim oBounds = pAnnotation.bbox.Select(AddressOf ToInches).ToList()
Dim oX = oBounds.Item(0)
Dim oY = oBounds.Item(1) + _pdfBurnerParams.YOffset * index + _pdfBurnerParams.TopMargin
Dim oWidth = oBounds.Item(2)
Dim oHeight = oBounds.Item(3)
Manager.SelectPage(pAnnotation.pageIndex + 1)
' Add the text annotation
Dim ant = Manager.AddTextAnnot(oX, oY, oWidth, oHeight, formFieldValue.value)
' Set the font properties
ant.FontName = _pdfBurnerParams.FontName
ant.FontSize = _pdfBurnerParams.FontSize
ant.FontStyle = _pdfBurnerParams.FontStyle
Manager.SaveAnnotationsToPage()
Return True
Catch ex As Exception
Logger.Warn("Could not add image annotation!")
Logger.Error(ex)
Return False
End Try
End Function
Private Function ToPointF(pPoints As List(Of Single)) As PointF
Dim oPoints = pPoints.Select(AddressOf ToInches).ToList()
Return New PointF(oPoints.Item(0), oPoints.Item(1))
End Function
Private Function ToInches(pValue As Double) As Double
Return pValue / 72
End Function
Private Function ToInches(pValue As Single) As Single
Return pValue / 72
End Function
Friend Class AnnotationData
Public Property annotations As List(Of Annotation)
Public Property attachments As Dictionary(Of String, Attachment)
Public Property formFieldValues As List(Of FormFieldValue)
End Class
Friend Class Annotation
Public Property id As String
Public Property bbox As List(Of Double)
Public Property type As String
Public Property isSignature As Boolean
Public Property imageAttachmentId As String
Public Property lines As Lines
Public Property pageIndex As Integer
Public Property strokeColor As String
End Class
Friend Class Lines
Public Property points As List(Of List(Of List(Of Single)))
End Class
Friend Class Attachment
Public Property binary As String
Public Property contentType As String
End Class
Friend Class FormFieldValue
Public Property name As String
Public Property value As String
End Class
End Class
End Namespace

View File

@@ -0,0 +1,16 @@
Imports System.Drawing
Namespace Jobs.FinalizeDocument
Public Class PDFBurnerParams
Public Property IgnoredLabels As New List(Of String) From {"Date", "Datum", "ZIP", "PLZ", "Place", "Ort", "Position", "Stellung"}
Public Property TopMargin As Double = 0.1
Public Property YOffset As Double = -0.3
Public Property FontName As String = "Arial"
Public Property FontSize As Integer = 8
Public Property FontStyle As FontStyle = FontStyle.Italic
End Class
End Namespace

View File

@@ -0,0 +1,71 @@
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
Imports EnvelopeGenerator.CommonServices.Jobs.FinalizeDocument.FinalizeDocumentExceptions
Imports GdPicture14
Imports System.IO
Public Class PDFMerger
Inherits BaseClass
Private ReadOnly Manager As AnnotationManager
Private ReadOnly LicenseManager As LicenseManager
Private Const ALLOW_RASTERIZATION = True
Private Const ALLOW_VECTORIZATION = True
Private ReadOnly PDFAConformanceLevel As PdfConversionConformance = PdfConversionConformance.PDF_A_1b
Public Sub New(pLogConfig As LogConfig, pGDPictureLicenseKey As String)
MyBase.New(pLogConfig)
LicenseManager = New LicenseManager()
LicenseManager.RegisterKEY(pGDPictureLicenseKey)
Manager = New AnnotationManager()
End Sub
Public Function MergeDocuments(pDocument As Byte(), pReport As Byte()) As Byte()
Using oDocumentStream As New MemoryStream(pDocument)
Using oReportStream As New MemoryStream(pReport)
Using oFinalStream As New MemoryStream()
Using oDocumentPDF As New GdPicturePDF()
Using oReportPDF As New GdPicturePDF()
Dim oStatus As GdPictureStatus = GdPictureStatus.OK
' Load the source file into memory
oDocumentPDF.LoadFromStream(oDocumentStream, True)
oStatus = oDocumentPDF.GetStat()
If oStatus <> GdPictureStatus.OK Then
Throw New MergeDocumentException($"Document could not be loaded: {oStatus}")
End If
' Load the report file into memory
oReportPDF.LoadFromStream(oReportStream, True)
oStatus = oReportPDF.GetStat()
If oStatus <> GdPictureStatus.OK Then
Throw New MergeDocumentException($"Report could not be loaded: {oStatus}")
End If
' Merge the documents
Dim oMergedPDF = oDocumentPDF.Merge2Documents(oDocumentPDF, oReportPDF)
oStatus = oMergedPDF.GetStat()
If oStatus <> GdPictureStatus.OK Then
Throw New MergeDocumentException($"Documents could not be merged: {oStatus}")
End If
' Convert to PDF/A
oMergedPDF.ConvertToPDFA(oFinalStream, PDFAConformanceLevel, ALLOW_VECTORIZATION, ALLOW_RASTERIZATION)
oStatus = oDocumentPDF.GetStat()
If oStatus <> GdPictureStatus.OK Then
Throw New MergeDocumentException($"Document could not be converted to PDF/A: {oStatus}")
End If
Return oFinalStream.ToArray()
End Using
End Using
End Using
End Using
End Using
End Function
End Class

View File

@@ -0,0 +1,92 @@
Imports System.IO
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Base
Imports EnvelopeGenerator.CommonServices.Jobs.FinalizeDocument.FinalizeDocumentExceptions
Imports EnvelopeGenerator.Domain.Entities
Public Class ReportCreator
Inherits BaseClass
Private Envelope As Envelope
Private ReadOnly ReportModel As ReportModel
Private ReadOnly EnvelopeModel As EnvelopeModel
Public Sub New(pLogConfig As LogConfig, pState As State)
MyBase.New(pLogConfig)
ReportModel = New ReportModel(pState)
EnvelopeModel = New EnvelopeModel(pState)
End Sub
Public Function CreateReport(pEnvelope As Domain.Entities.Envelope) As Byte()
Try
Logger.Debug("Loading report data..")
Dim oTable = ReportModel.List(pEnvelope.Id)
Dim oItems = GetReportSource(oTable)
Envelope = pEnvelope
If oItems.Count = 0 Then
Throw New CreateReportException("No report data found!")
End If
Logger.Debug("Creating report with [{0}] items..", oItems.Count)
Dim oBuffer = DoCreateReport(oItems)
Logger.Debug("Report created!")
Return oBuffer
Catch ex As Exception
Logger.Error(ex)
Throw New CreateReportException("Could not prepare report data!", ex)
End Try
End Function
Private Function GetReportSource(pDataTable As DataTable) As List(Of ReportItem)
Logger.Debug("Preparing report data")
Return pDataTable.Rows.
Cast(Of DataRow).
Select(AddressOf ToReportItem).
OrderByDescending(Function(r) r.ItemDate).
ToList()
End Function
Private Function DoCreateReport(pReportItems As List(Of ReportItem)) As Byte()
Dim oItems = pReportItems.Select(AddressOf MergeEnvelope).ToList()
Dim oSource As New ReportSource With {.Items = oItems}
Dim oReport As New rptEnvelopeHistory() With {.DataSource = oSource, .DataMember = "Items"}
Logger.Debug("Creating report in memory..")
oReport.CreateDocument()
Logger.Debug("Exporting report to stream..")
Using oStream As New MemoryStream()
oReport.ExportToPdf(oStream)
Logger.Debug("Writing report to buffer..")
Return oStream.ToArray()
End Using
End Function
Private Function MergeEnvelope(pItem As ReportItem) As ReportItem
If pItem.Envelope Is Nothing Then
pItem.Envelope = Envelope
End If
Return pItem
End Function
Private Function ToReportItem(pRow As DataRow) As ReportItem
Try
Return New ReportItem() With {
.EnvelopeId = pRow.Item("ENVELOPE_ID"),
.EnvelopeTitle = pRow.ItemEx("HEAD_TITLE", String.Empty),
.EnvelopeSubject = pRow.ItemEx("HEAD_SUBJECT", String.Empty),
.ItemDate = pRow.ItemEx(Of Date)("POS_WHEN", Nothing),
.ItemStatus = pRow.ItemEx("POS_STATUS", 0),
.ItemUserReference = pRow.ItemEx("POS_WHO", "")
}
Catch ex As Exception
Logger.Error(ex)
Throw New CreateReportException("Could not read data from database!", ex)
End Try
End Function
End Class

View File

@@ -0,0 +1,22 @@
Imports EnvelopeGenerator.Domain
Imports EnvelopeGenerator.Domain.Entities
Public Class ReportItem
Public Property Envelope As Envelope
Public Property EnvelopeId As Integer
Public Property EnvelopeTitle As String
Public Property EnvelopeSubject As String
Public Property ItemStatus As Constants.EnvelopeStatus
Public ReadOnly Property ItemStatusTranslated As String
Get
Dim oStatus = ItemStatus.ToString()
Return My.Resources.Model.ResourceManager.GetString(oStatus)
End Get
End Property
Public Property ItemUserReference As String
Public Property ItemDate As Date
End Class

View File

@@ -0,0 +1,3 @@
Public Class ReportSource
Public Property Items As List(Of ReportItem)
End Class