Refactor: Processfiles
This commit is contained in:
parent
3c149a32e9
commit
c187bdbe5e
@ -7,11 +7,13 @@ Public Class Exceptions
|
||||
Inherits ApplicationException
|
||||
|
||||
Public ReadOnly File As FileInfo
|
||||
Public ReadOnly MissingProperties As List(Of String)
|
||||
|
||||
Public Sub New(File As FileInfo)
|
||||
MyBase.New($"Missing values in [{File.Name}]")
|
||||
Public Sub New(pFile As FileInfo, pMissingProperties As List(Of String))
|
||||
MyBase.New($"Missing values in [{pFile.Name}]")
|
||||
|
||||
Me.File = File
|
||||
Me.File = pFile
|
||||
Me.MissingProperties = pMissingProperties
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
|
||||
@ -45,9 +45,13 @@ Public Class ImportZUGFeRDFiles
|
||||
Private _EmailOutAccountId As Integer
|
||||
|
||||
Private Class ProcessFileResult
|
||||
Public ZugferdFileCount As Integer
|
||||
Public MD5Hash As String = Nothing
|
||||
Public ZugferdFileFound As Boolean = False
|
||||
|
||||
Public ZugferdFileCount As Integer = 0
|
||||
Public MD5Checksum As String = Nothing
|
||||
|
||||
Public EmailAttachmentFiles As New List(Of FileInfo)
|
||||
Public EmbeddedAttachmentFiles As New List(Of PDFEmbeds.EmbeddedFile)
|
||||
End Class
|
||||
|
||||
Private Class DatabaseConnections
|
||||
@ -152,147 +156,147 @@ Public Class ImportZUGFeRDFiles
|
||||
Dim oEmbeddedAttachmentFiles As New List(Of PDFEmbeds.EmbeddedFile)
|
||||
|
||||
Dim oMessageId As String = oFileGroup.Key
|
||||
Dim oMissingProperties As New List(Of String)
|
||||
Dim oMD5CheckSum As String = String.Empty
|
||||
|
||||
_logger.Info("Start processing file group {0}", oMessageId)
|
||||
|
||||
' TODO: Use this refactored function
|
||||
' ProcessFileGroup(oMessageId, oFileGroupFiles, oConnections, oArgs)
|
||||
Dim oEmailDataBase = _email.GetEmailDataForMessageId(oMessageId)
|
||||
|
||||
Try
|
||||
For Each oFile In oFileGroupFiles
|
||||
' 09.12.2021: oDocument is now an Object, because have different classes corresponding to the
|
||||
' different versions of ZUGFeRD and the type is unknown at compile-time.
|
||||
' 17.11.2022: oDocument is now a Tuple of (String, Object), to be able to return the filename
|
||||
' of the extracted xml file.
|
||||
' 21.12.2022: oDocument is now an object of type ZugferdResult to be able to save
|
||||
' the new meta data, ie. the type of schema (zugferd version)
|
||||
Dim oDocument As ZUGFeRDInterface.ZugferdResult
|
||||
Dim oResult As ProcessFileResult = ProcessFile(oMessageId, oEmailDataBase, oZUGFeRDCount, oFile, oConnections, oArgs)
|
||||
|
||||
' Start a global group counter for each file
|
||||
Dim oGlobalGroupCounter = 0
|
||||
' Clear missing properties for the new file
|
||||
oMissingProperties = New List(Of String)
|
||||
|
||||
' Only pdf files are allowed from here on
|
||||
If Not oFile.Name.ToUpper.EndsWith(".PDF") Then
|
||||
_logger.Debug("Skipping non-pdf file {0}", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
|
||||
' Checking filesize for attachment files
|
||||
If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, oArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
If oResult.ZugferdFileFound = False Then
|
||||
_logger.Debug("Zugferd File found")
|
||||
oMD5CheckSum = oResult.MD5Checksum
|
||||
oZUGFeRDCount = oResult.ZugferdFileCount
|
||||
oEmailAttachmentFiles.AddRange(oResult.EmailAttachmentFiles)
|
||||
oEmbeddedAttachmentFiles.AddRange(oResult.EmbeddedAttachmentFiles)
|
||||
End If
|
||||
' ------------------------------------------------------------
|
||||
#Region "REFACTOR"
|
||||
|
||||
Continue For
|
||||
End If
|
||||
|
||||
_logger.Info("Start processing file {0}", oFile.Name)
|
||||
'Dim oDocument As ZUGFeRDInterface.ZugferdResult
|
||||
|
||||
' Checking filesize for pdf files
|
||||
If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, oArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
End If
|
||||
'' Only pdf files are allowed from here on
|
||||
'If Not oFile.Name.ToUpper.EndsWith(".PDF") Then
|
||||
' _logger.Debug("Skipping non-pdf file {0}", oFile.Name)
|
||||
' oEmailAttachmentFiles.Add(oFile)
|
||||
|
||||
Try
|
||||
oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(oFile.FullName)
|
||||
' ' Checking filesize for attachment files
|
||||
' If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, oArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
' _logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
' Throw New FileSizeLimitReachedException(oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
' End If
|
||||
|
||||
Catch ex As ValidationException
|
||||
Throw ex
|
||||
' Continue For
|
||||
'End If
|
||||
|
||||
Catch ex As ZUGFeRDExecption
|
||||
Select Case ex.ErrorType
|
||||
Case ZUGFeRDInterface.ErrorType.NoZugferd
|
||||
_logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
Continue For
|
||||
'_logger.Info("Start processing file {0}", oFile.Name)
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
|
||||
_logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", oFile.Name, ex.XmlFile)
|
||||
Throw New UnsupportedFerdException(ex.XmlFile)
|
||||
'' Checking filesize for pdf files
|
||||
'If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, oArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
' _logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
' Throw New FileSizeLimitReachedException(oFile.Name, oArgs.MaxAttachmentSizeInMegaBytes)
|
||||
'End If
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.NoValidZugferd
|
||||
_logger.Info("File [{0}] is an Incorrectly formatted ZUGFeRD document!", oFile.Name)
|
||||
Throw New InvalidFerdException()
|
||||
'Try
|
||||
' oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(oFile.FullName)
|
||||
|
||||
Case Else
|
||||
_logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", oFile.Name)
|
||||
Throw ex
|
||||
End Select
|
||||
End Try
|
||||
'Catch ex As ValidationException
|
||||
' Throw ex
|
||||
|
||||
' Check if there are more than one ZUGFeRD files
|
||||
If oZUGFeRDCount = 1 Then
|
||||
Throw New TooMuchFerdsException()
|
||||
End If
|
||||
'Catch ex As ZUGFeRDExecption
|
||||
' Select Case ex.ErrorType
|
||||
' Case ZUGFeRDInterface.ErrorType.NoZugferd
|
||||
' _logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", oFile.Name)
|
||||
' oEmailAttachmentFiles.Add(oFile)
|
||||
' Continue For
|
||||
|
||||
' Since extraction went well, increase the amount of ZUGFeRD files
|
||||
oZUGFeRDCount += 1
|
||||
' Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
|
||||
' _logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", oFile.Name, ex.XmlFile)
|
||||
' Throw New UnsupportedFerdException(ex.XmlFile)
|
||||
|
||||
' Extract all attachments with the extensions specified in `AllowedExtensions`.
|
||||
' If you need to extract and use embedded xml files, you need to filter out the zugferd-invoice.xml yourself.
|
||||
' Right now the zugferd-invoice.xml is filtered out because `AllowedExtensions` does not contain `xml`.
|
||||
Dim oAttachments = oAttachmentExtractor.Extract(oFile.FullName, AllowedExtensions)
|
||||
If oAttachments Is Nothing Then
|
||||
_logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName)
|
||||
Else
|
||||
oEmbeddedAttachmentFiles.AddRange(oAttachments)
|
||||
End If
|
||||
' Case ZUGFeRDInterface.ErrorType.NoValidZugferd
|
||||
' _logger.Info("File [{0}] is an Incorrectly formatted ZUGFeRD document!", oFile.Name)
|
||||
' Throw New InvalidFerdException()
|
||||
|
||||
' Check the Checksum and rejection status
|
||||
oMD5CheckSum = GenerateAndCheck_MD5Sum(oFile, oMessageId, oArgs.IgnoreRejectionStatus)
|
||||
' Case Else
|
||||
' _logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", oFile.Name)
|
||||
' Throw ex
|
||||
' End Select
|
||||
'End Try
|
||||
|
||||
' Check the document against the configured property map and return:
|
||||
' - a List of valid properties
|
||||
' - a List of missing properties
|
||||
'' Check if there are more than one ZUGFeRD files
|
||||
'If oZUGFeRDCount = 1 Then
|
||||
' Throw New TooMuchFerdsException()
|
||||
'End If
|
||||
|
||||
Dim oPropertyMap = _zugferd.FilterPropertyMap(oArgs.PropertyMap, oDocument.Specification)
|
||||
Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument.SchemaObject, oPropertyMap, oMessageId)
|
||||
'' Since extraction went well, increase the amount of ZUGFeRD files
|
||||
'oZUGFeRDCount += 1
|
||||
|
||||
_logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count)
|
||||
'' Extract all attachments with the extensions specified in `AllowedExtensions`.
|
||||
'' If you need to extract and use embedded xml files, you need to filter out the zugferd-invoice.xml yourself.
|
||||
'' Right now the zugferd-invoice.xml is filtered out because `AllowedExtensions` does not contain `xml`.
|
||||
'Dim oAttachments = oAttachmentExtractor.Extract(oFile.FullName, AllowedExtensions)
|
||||
'If oAttachments Is Nothing Then
|
||||
' _logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName)
|
||||
'Else
|
||||
' oEmbeddedAttachmentFiles.AddRange(oAttachments)
|
||||
'End If
|
||||
|
||||
If oCheckResult.MissingProperties.Count > 0 Then
|
||||
_logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
|
||||
oMissingProperties = oCheckResult.MissingProperties
|
||||
Throw New MissingValueException(oFile)
|
||||
Else
|
||||
_logger.Debug("No missing properties found. Continuing.")
|
||||
'' Check the Checksum and rejection status
|
||||
'oMD5CheckSum = GenerateAndCheck_MD5Sum(oFile, oMessageId, oArgs.IgnoreRejectionStatus)
|
||||
|
||||
End If
|
||||
'' Check the document against the configured property map and return:
|
||||
'' - a List of valid properties
|
||||
'' - a List of missing properties
|
||||
|
||||
DeleteExistingPropertyValues(oMessageId, oConnections)
|
||||
'Dim oPropertyMap = _zugferd.FilterPropertyMap(oArgs.PropertyMap, oDocument.Specification)
|
||||
'Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument.SchemaObject, oPropertyMap, oMessageId)
|
||||
|
||||
Dim oFirstProperty = oCheckResult.ValidProperties.FirstOrDefault()
|
||||
If oFirstProperty IsNot Nothing Then
|
||||
InsertPropertyValue(oMessageId, oConnections, New PropertyValues.ValidProperty() With {
|
||||
.MessageId = oMessageId,
|
||||
.Description = "ZUGFeRDSpezifikation",
|
||||
.GroupCounter = 0,
|
||||
.IsRequired = False,
|
||||
.Value = oDocument.Specification,
|
||||
.TableName = oFirstProperty.TableName,
|
||||
.TableColumn = "ZUGFERD_SPECIFICATION"
|
||||
})
|
||||
End If
|
||||
'_logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count)
|
||||
|
||||
For Each oProperty In oCheckResult.ValidProperties
|
||||
InsertPropertyValue(oMessageId, oConnections, oProperty)
|
||||
Next
|
||||
'If oCheckResult.MissingProperties.Count > 0 Then
|
||||
' _logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
|
||||
' Throw New MissingValueException(oFile, oCheckResult.MissingProperties)
|
||||
'Else
|
||||
' _logger.Debug("No missing properties found. Continuing.")
|
||||
|
||||
'End If
|
||||
|
||||
'DeleteExistingPropertyValues(oMessageId, oConnections)
|
||||
|
||||
'Dim oFirstProperty = oCheckResult.ValidProperties.FirstOrDefault()
|
||||
'If oFirstProperty IsNot Nothing Then
|
||||
' InsertPropertyValue(oMessageId, oConnections, New PropertyValues.ValidProperty() With {
|
||||
' .MessageId = oMessageId,
|
||||
' .Description = "ZUGFeRDSpezifikation",
|
||||
' .GroupCounter = 0,
|
||||
' .IsRequired = False,
|
||||
' .Value = oDocument.Specification,
|
||||
' .TableName = oFirstProperty.TableName,
|
||||
' .TableColumn = "ZUGFERD_SPECIFICATION"
|
||||
' })
|
||||
'End If
|
||||
|
||||
'For Each oProperty In oCheckResult.ValidProperties
|
||||
' InsertPropertyValue(oMessageId, oConnections, oProperty)
|
||||
'Next
|
||||
#End Region
|
||||
Next
|
||||
|
||||
'Check if there are no ZUGFeRD files
|
||||
If oZUGFeRDCount = 0 Then
|
||||
' If NonZugferdDirectory is not set, a NoFerdsException will be thrown and a rejection will be generated
|
||||
' This is the default/initial behaviour.
|
||||
If oArgs.NonZugferdDirectory Is Nothing OrElse oArgs.NonZugferdDirectory = String.Empty Then
|
||||
If String.IsNullOrEmpty(oArgs.NonZugferdDirectory) Then
|
||||
Throw New NoFerdsException()
|
||||
End If
|
||||
|
||||
' Also, if the directory is set but does not exist, still a rejection will be generated.
|
||||
If Not IO.Directory.Exists(oArgs.NonZugferdDirectory) Then
|
||||
If Not Directory.Exists(oArgs.NonZugferdDirectory) Then
|
||||
Throw New NoFerdsException()
|
||||
End If
|
||||
|
||||
@ -302,12 +306,11 @@ Public Class ImportZUGFeRDFiles
|
||||
|
||||
End If
|
||||
|
||||
'If no errors occurred...
|
||||
'Log the History
|
||||
If oMD5CheckSum <> String.Empty Then
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, "SUCCESS")
|
||||
Else
|
||||
'If no errors occurred, update the history table for this MessageId
|
||||
If String.IsNullOrEmpty(oMD5CheckSum) Then
|
||||
_history.Update_HistoryEntry(oMessageId, String.Empty, "SUCCESS (with empty MD5Hash)")
|
||||
Else
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, "SUCCESS")
|
||||
End If
|
||||
|
||||
oIsSuccess = True
|
||||
@ -395,13 +398,13 @@ Public Class ImportZUGFeRDFiles
|
||||
_logger.Error(ex)
|
||||
|
||||
Dim oMessage As String = ""
|
||||
For Each prop In oMissingProperties
|
||||
For Each prop In ex.MissingProperties
|
||||
oMessage &= $"- {prop}"
|
||||
Next
|
||||
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, $"REJECTED - Missing Required Properties: [{oMessage}]")
|
||||
|
||||
Dim oBody = _email.CreateBodyForMissingProperties(ex.File.Name, oMissingProperties)
|
||||
Dim oBody = _email.CreateBodyForMissingProperties(ex.File.Name, ex.MissingProperties)
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage, oSQLTransaction)
|
||||
@ -523,43 +526,15 @@ Public Class ImportZUGFeRDFiles
|
||||
End Sub
|
||||
|
||||
#Region "=== REFACTOR"
|
||||
Private Function ProcessFileGroup(oMessageId As String, pFiles As List(Of FileInfo), oConnections As DatabaseConnections, pArgs As WorkerArgs)
|
||||
Dim oMissingProperties = New List(Of String)
|
||||
Dim oEmailAttachmentFiles = New List(Of FileInfo)
|
||||
Dim oEmbeddedAttachmentFiles = New List(Of PDFEmbeds.EmbeddedFile)
|
||||
Dim oZUGFeRDCount = 0
|
||||
Dim oMD5CheckSum As String = Nothing
|
||||
|
||||
' Set the default Move Directory
|
||||
Dim oMoveDirectory As String = pArgs.ErrorDirectory
|
||||
|
||||
' Flag to save if the whole process was a success.
|
||||
' Will be set only at the end of the function if no error occurred.
|
||||
Dim oIsSuccess As Boolean = False
|
||||
|
||||
' Flag to save if the occurred error (if any) was expected
|
||||
' Used to determine if transactions should be committed or not
|
||||
Dim oExpectedError As Boolean = True
|
||||
|
||||
Try
|
||||
For Each oFile In pFiles
|
||||
' 09.12.2021: oDocument is now an Object, because have different classes corresponding to the
|
||||
' different versions of ZUGFeRD and the type is unknown at compile-time.
|
||||
' 17.11.2022: oDocument is now a Tuple of (String, Object), to be able to return the filename
|
||||
' of the extracted xml file.
|
||||
' 21.12.2022: oDocument is now an object of type ZugferdResult to be able to save
|
||||
' the new meta data, ie. the type of schema (zugferd version)
|
||||
Private Function ProcessFile(pMessageId As String, pEmailData As EmailData, pZugferdFiles As Integer, oFile As FileInfo, oConnections As DatabaseConnections, pArgs As WorkerArgs) As ProcessFileResult
|
||||
Dim oDocument As ZUGFeRDInterface.ZugferdResult
|
||||
|
||||
' Start a global group counter for each file
|
||||
Dim oGlobalGroupCounter = 0
|
||||
' Clear missing properties for the new file
|
||||
oMissingProperties = New List(Of String)
|
||||
Dim oResult As New ProcessFileResult()
|
||||
Dim oMissingProperties As New List(Of String)
|
||||
|
||||
' Only pdf files are allowed from here on
|
||||
If Not oFile.Name.ToUpper.EndsWith(".PDF") Then
|
||||
_logger.Debug("Skipping non-pdf file {0}", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
oResult.EmailAttachmentFiles.Add(oFile)
|
||||
|
||||
' Checking filesize for attachment files
|
||||
If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
@ -567,7 +542,7 @@ Public Class ImportZUGFeRDFiles
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
|
||||
End If
|
||||
|
||||
Continue For
|
||||
Return oResult
|
||||
End If
|
||||
|
||||
_logger.Info("Start processing file {0}", oFile.Name)
|
||||
@ -588,8 +563,9 @@ Public Class ImportZUGFeRDFiles
|
||||
Select Case ex.ErrorType
|
||||
Case ZUGFeRDInterface.ErrorType.NoZugferd
|
||||
_logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
Continue For
|
||||
|
||||
oResult.EmailAttachmentFiles.Add(oFile)
|
||||
Return oResult
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
|
||||
_logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", oFile.Name, ex.XmlFile)
|
||||
@ -606,12 +582,12 @@ Public Class ImportZUGFeRDFiles
|
||||
End Try
|
||||
|
||||
' Check if there are more than one ZUGFeRD files
|
||||
If oZUGFeRDCount = 1 Then
|
||||
If pZugferdFiles = 1 Then
|
||||
Throw New TooMuchFerdsException()
|
||||
End If
|
||||
|
||||
' Since extraction went well, increase the amount of ZUGFeRD files
|
||||
oZUGFeRDCount += 1
|
||||
pZugferdFiles += 1
|
||||
|
||||
' Extract all attachments with the extensions specified in `AllowedExtensions`.
|
||||
' If you need to extract and use embedded xml files, you need to filter out the zugferd-invoice.xml yourself.
|
||||
@ -620,375 +596,11 @@ Public Class ImportZUGFeRDFiles
|
||||
If oAttachments Is Nothing Then
|
||||
_logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName)
|
||||
Else
|
||||
oEmbeddedAttachmentFiles.AddRange(oAttachments)
|
||||
oResult.EmbeddedAttachmentFiles.AddRange(oAttachments)
|
||||
End If
|
||||
|
||||
' Check the Checksum and rejection status
|
||||
oMD5CheckSum = GenerateAndCheck_MD5Sum(oFile, oMessageId, pArgs.IgnoreRejectionStatus)
|
||||
|
||||
' Check the document against the configured property map and return:
|
||||
' - a List of valid properties
|
||||
' - a List of missing properties
|
||||
|
||||
Dim oPropertyMap = _zugferd.FilterPropertyMap(pArgs.PropertyMap, oDocument.Specification)
|
||||
Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument.SchemaObject, oPropertyMap, oMessageId)
|
||||
|
||||
_logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count)
|
||||
|
||||
If oCheckResult.MissingProperties.Count > 0 Then
|
||||
_logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
|
||||
oMissingProperties = oCheckResult.MissingProperties
|
||||
Throw New MissingValueException(oFile)
|
||||
Else
|
||||
_logger.Debug("No missing properties found. Continuing.")
|
||||
|
||||
End If
|
||||
|
||||
DeleteExistingPropertyValues(oMessageId, oConnections)
|
||||
|
||||
Dim oFirstProperty = oCheckResult.ValidProperties.FirstOrDefault()
|
||||
If oFirstProperty IsNot Nothing Then
|
||||
InsertPropertyValue(oMessageId, oConnections, New PropertyValues.ValidProperty() With {
|
||||
.MessageId = oMessageId,
|
||||
.Description = "ZUGFeRDSpezifikation",
|
||||
.GroupCounter = 0,
|
||||
.IsRequired = False,
|
||||
.Value = oDocument.Specification,
|
||||
.TableName = oFirstProperty.TableName,
|
||||
.TableColumn = "ZUGFERD_SPECIFICATION"
|
||||
})
|
||||
End If
|
||||
|
||||
For Each oProperty In oCheckResult.ValidProperties
|
||||
InsertPropertyValue(oMessageId, oConnections, oProperty)
|
||||
Next
|
||||
Next
|
||||
|
||||
'Check if there are no ZUGFeRD files
|
||||
If oZUGFeRDCount = 0 Then
|
||||
|
||||
' If NonZugferdDirectory is not set, a NoFerdsException will be thrown and a rejection will be generated
|
||||
' This is the default/initial behaviour.
|
||||
If pArgs.NonZugferdDirectory Is Nothing OrElse pArgs.NonZugferdDirectory = String.Empty Then
|
||||
Throw New NoFerdsException()
|
||||
End If
|
||||
|
||||
' Also, if the directory is set but does not exist, still a rejection will be generated.
|
||||
If Not IO.Directory.Exists(pArgs.NonZugferdDirectory) Then
|
||||
Throw New NoFerdsException()
|
||||
End If
|
||||
|
||||
' Only if the directory is set and does exist, it will be used and any file groups which
|
||||
' do NOT CONTAIN ANY ZUGFERD DOCUMENTS, are moved to that directory.
|
||||
Throw New NoFerdsAlternateException()
|
||||
|
||||
End If
|
||||
|
||||
'If no errors occurred...
|
||||
'Log the History
|
||||
If oMD5CheckSum <> String.Empty Then
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, "SUCCESS")
|
||||
Else
|
||||
_history.Update_HistoryEntry(oMessageId, String.Empty, "SUCCESS (with empty MD5Hash)")
|
||||
End If
|
||||
|
||||
oIsSuccess = True
|
||||
oMoveDirectory = pArgs.SuccessDirectory
|
||||
|
||||
Catch ex As ValidationException
|
||||
_logger.Error(ex)
|
||||
|
||||
Dim oErrors = ex.ValidationErrors
|
||||
Dim oMessage = "REJECTED - ZUGFeRD yes but formal validation failed!"
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, oMessage)
|
||||
|
||||
Dim oErrorList As String = ""
|
||||
For Each oError In oErrors
|
||||
oErrorList += $"<li>Element '{oError.ElementName}' mit Wert '{oError.ElementValue}': {oError.ErrorMessage}</li>"
|
||||
Next
|
||||
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_VALIDATION_ERROR, oErrorList)
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "ValidationException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "ValidationException", "Die Rechnungsvalidierung ist fehlgeschlagen!", "", oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As MD5HashException
|
||||
_logger.Error(ex)
|
||||
|
||||
' When MD5HashException is thrown, we don't have a MD5Hash yet.
|
||||
' That 's why we set it to String.Empty here.
|
||||
Dim oMessage = "REJECTED - Already processed (MD5Hash)"
|
||||
_history.Update_HistoryEntry(oMessageId, String.Empty, oMessage)
|
||||
|
||||
Dim oBody = EmailStrings.EMAIL_MD5_ERROR
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "", oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As UnsupportedFerdException
|
||||
_logger.Error(ex)
|
||||
|
||||
' When UnsupportedFerdException is thrown, we don't have a MD5Hash yet.
|
||||
' That 's why we set it to String.Empty here.
|
||||
_history.Update_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but unsupported format")
|
||||
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, oEmailData.Subject, ex.XmlFile)
|
||||
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "UnsupportedFerdException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "UnsupportedFerdException", "Nicht unterstütztes Datenformat", "", oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As InvalidFerdException
|
||||
_logger.Error(ex)
|
||||
|
||||
' When InvalidFerdException is thrown, we don't have a MD5Hash yet.
|
||||
' That 's why we set it to String.Empty here.
|
||||
_history.Update_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but incorrect format")
|
||||
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_INVALID_DOCUMENT, oEmailData.Subject)
|
||||
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "", oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As TooMuchFerdsException
|
||||
_logger.Error(ex)
|
||||
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - More than one ZUGFeRD-document in email")
|
||||
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_TOO_MUCH_FERDS, oEmailData.Subject)
|
||||
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "", oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As NoFerdsException
|
||||
_logger.Error(ex)
|
||||
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - no ZUGFeRD-Document in email")
|
||||
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_NO_FERDS, oEmailData.Subject)
|
||||
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "", oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As MissingValueException
|
||||
_logger.Error(ex)
|
||||
|
||||
Dim oMessage As String = ""
|
||||
For Each prop In oMissingProperties
|
||||
oMessage &= $"- {prop}"
|
||||
Next
|
||||
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, $"REJECTED - Missing Required Properties: [{oMessage}]")
|
||||
|
||||
Dim oBody = _email.CreateBodyForMissingProperties(ex.File.Name, oMissingProperties)
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage, oConnections.SQLServerTransaction)
|
||||
|
||||
Catch ex As FileSizeLimitReachedException
|
||||
_logger.Error(ex)
|
||||
|
||||
_history.Update_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - File size limit reached")
|
||||
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(pArgs, oMessageId)
|
||||
|
||||
Dim oKey = FileSizeLimitReachedException.KEY_FILENAME
|
||||
Dim oFileExceedingThreshold As String = IIf(ex.Data.Contains(oKey), ex.Data.Item(oKey), "")
|
||||
Dim oFileWithoutMessageId = oFileExceedingThreshold.
|
||||
Replace(oMessageId, "").
|
||||
Replace("~", "")
|
||||
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_FILE_SIZE_REACHED, pArgs.MaxAttachmentSizeInMegaBytes, oFileWithoutMessageId)
|
||||
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "FileSizeLimitReachedException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "FileSizeLimitReachedException", "Erlaubte Dateigröße überschritten", "", oConnections.SQLServerTransaction)
|
||||
|
||||
|
||||
Catch ex As NoFerdsAlternateException
|
||||
' TODO: Maybe dont even log this 'error', since it's not really an error and it might happen *A LOT*
|
||||
_logger.Error(ex)
|
||||
oMoveDirectory = pArgs.NonZugferdDirectory
|
||||
|
||||
Catch ex As OutOfMemoryException
|
||||
_logger.Warn("OutOfMemory Error occurred: {0}", ex.Message)
|
||||
_logger.Error(ex)
|
||||
|
||||
' Send Email to Digital Data
|
||||
Dim oBody = _email.CreateBodyForUnhandledException(oMessageId, ex)
|
||||
Dim oEmailData As New EmailData With {
|
||||
.From = pArgs.ExceptionEmailAddress,
|
||||
.Subject = $"OutOfMemoryException im ZUGFeRD-Parser @ {oMessageId}"
|
||||
}
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "OutOfMemoryException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
|
||||
' Rollback Transaction
|
||||
oConnections.SQLServerTransaction.Rollback()
|
||||
|
||||
oMoveDirectory = DIRECTORY_DONT_MOVE
|
||||
|
||||
oExpectedError = False
|
||||
|
||||
Catch ex As Exception
|
||||
_logger.Warn("Unknown Error occurred: {0}", ex.Message)
|
||||
_logger.Error(ex)
|
||||
|
||||
' Send Email to Digital Data
|
||||
Dim oBody = _email.CreateBodyForUnhandledException(oMessageId, ex)
|
||||
Dim oEmailData As New EmailData With {
|
||||
.From = pArgs.ExceptionEmailAddress,
|
||||
.Subject = $"UnhandledException im ZUGFeRD-Parser @ {oMessageId}"
|
||||
}
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "UnhandledException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
|
||||
' Rollback Transaction
|
||||
oConnections.SQLServerTransaction.Rollback()
|
||||
|
||||
oMoveDirectory = DIRECTORY_DONT_MOVE
|
||||
|
||||
oExpectedError = False
|
||||
|
||||
Finally
|
||||
Try
|
||||
' If an application error occurred, dont move files so they will be processed again later
|
||||
If oMoveDirectory = DIRECTORY_DONT_MOVE Then
|
||||
_logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId)
|
||||
Else
|
||||
' Move all files of the current group
|
||||
_file.MoveFiles(pArgs, oMessageId, pFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
|
||||
End If
|
||||
_logger.Info("Finished processing file group {0}", oMessageId)
|
||||
Catch ex As Exception
|
||||
' Send Email to Digital Data
|
||||
Dim oBody = _email.CreateBodyForUnhandledException(oMessageId, ex)
|
||||
Dim oEmailData As New EmailData With {
|
||||
.From = pArgs.ExceptionEmailAddress,
|
||||
.Subject = $"FileMoveException im ZUGFeRD-Parser @ {oMessageId}"
|
||||
}
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "FileMoveException", _EmailOutAccountId, pArgs.NamePortal)
|
||||
|
||||
_logger.Warn("Could not move files!")
|
||||
_logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
|
||||
Try
|
||||
' If everything went OK or an expected error occurred,
|
||||
' finally commit all changes To the Database
|
||||
' ==================================================================
|
||||
If oIsSuccess Or oExpectedError Then
|
||||
' Commit Transaction
|
||||
oConnections.SQLServerTransaction.Commit()
|
||||
End If
|
||||
|
||||
_logger.Info("FileGroup for MessageId [{0}] successfully processed!", oMessageId)
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Database Transactions were not committed successfully.")
|
||||
End Try
|
||||
|
||||
Try
|
||||
oConnections.SQLServerConnection.Close()
|
||||
Catch ex As Exception
|
||||
_logger.Error(ex)
|
||||
_logger.Warn("Database Connections were not closed successfully.")
|
||||
End Try
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function ProcessFile(pMessageId As String, oFile As FileInfo, oConnections As DatabaseConnections, pArgs As WorkerArgs) As ProcessFileResult
|
||||
' 09.12.2021: oDocument is now an Object, because have different classes corresponding to the
|
||||
' different versions of ZUGFeRD and the type is unknown at compile-time.
|
||||
' 17.11.2022: oDocument is now a Tuple of (String, Object), to be able to return the filename
|
||||
' of the extracted xml file.
|
||||
' 21.12.2022: oDocument is now an object of type ZugferdResult to be able to save
|
||||
' the new meta data, ie. the type of schema (zugferd version)
|
||||
Dim oDocument As ZUGFeRDInterface.ZugferdResult
|
||||
|
||||
Dim oMissingProperties = New List(Of String)
|
||||
Dim oEmailAttachmentFiles = New List(Of FileInfo)
|
||||
Dim oEmbeddedAttachmentFiles = New List(Of PDFEmbeds.EmbeddedFile)
|
||||
Dim oZugferdFiles As Integer = 0
|
||||
|
||||
' Start a global group counter for each file
|
||||
Dim oGlobalGroupCounter = 0
|
||||
' Clear missing properties for the new file
|
||||
oMissingProperties = New List(Of String)
|
||||
|
||||
' Only pdf files are allowed from here on
|
||||
If Not oFile.Name.ToUpper.EndsWith(".PDF") Then
|
||||
_logger.Debug("Skipping non-pdf file {0}", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
|
||||
' Checking filesize for attachment files
|
||||
If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
|
||||
End If
|
||||
|
||||
'TODO: how to handle?
|
||||
'Continue For
|
||||
End If
|
||||
|
||||
_logger.Info("Start processing file {0}", oFile.Name)
|
||||
|
||||
' Checking filesize for pdf files
|
||||
If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then
|
||||
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
|
||||
Throw New FileSizeLimitReachedException(oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
|
||||
End If
|
||||
|
||||
Try
|
||||
oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(oFile.FullName)
|
||||
|
||||
Catch ex As ValidationException
|
||||
Throw ex
|
||||
|
||||
Catch ex As ZUGFeRDExecption
|
||||
Select Case ex.ErrorType
|
||||
Case ZUGFeRDInterface.ErrorType.NoZugferd
|
||||
_logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", oFile.Name)
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
|
||||
'TODO: How to handle?
|
||||
'Continue For
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
|
||||
_logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", oFile.Name, ex.XmlFile)
|
||||
Throw New UnsupportedFerdException(ex.XmlFile)
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.NoValidZugferd
|
||||
_logger.Info("File [{0}] is an Incorrectly formatted ZUGFeRD document!", oFile.Name)
|
||||
Throw New InvalidFerdException()
|
||||
|
||||
Case Else
|
||||
_logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", oFile.Name)
|
||||
Throw ex
|
||||
End Select
|
||||
End Try
|
||||
|
||||
' Check if there are more than one ZUGFeRD files
|
||||
If oZugferdFiles = 1 Then
|
||||
Throw New TooMuchFerdsException()
|
||||
End If
|
||||
|
||||
' Since extraction went well, increase the amount of ZUGFeRD files
|
||||
oZugferdFiles += 1
|
||||
|
||||
' Extract all attachments with the extensions specified in `AllowedExtensions`.
|
||||
' If you need to extract and use embedded xml files, you need to filter out the zugferd-invoice.xml yourself.
|
||||
' Right now the zugferd-invoice.xml is filtered out because `AllowedExtensions` does not contain `xml`.
|
||||
Dim oAttachments = _embeds.Extract(oFile.FullName, AllowedExtensions)
|
||||
If oAttachments Is Nothing Then
|
||||
_logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName)
|
||||
Else
|
||||
oEmbeddedAttachmentFiles.AddRange(oAttachments)
|
||||
End If
|
||||
|
||||
' Check the Checksum and rejection status
|
||||
Dim oMD5CheckSum = GenerateAndCheck_MD5Sum(oFile, pMessageId, pArgs.IgnoreRejectionStatus)
|
||||
Dim oMD5Checksum = GenerateAndCheck_MD5Sum(oFile, pMessageId, pArgs.IgnoreRejectionStatus)
|
||||
|
||||
' Check the document against the configured property map and return:
|
||||
' - a List of valid properties
|
||||
@ -1002,7 +614,7 @@ Public Class ImportZUGFeRDFiles
|
||||
If oCheckResult.MissingProperties.Count > 0 Then
|
||||
_logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
|
||||
oMissingProperties = oCheckResult.MissingProperties
|
||||
Throw New MissingValueException(oFile)
|
||||
Throw New MissingValueException(oFile, oCheckResult.MissingProperties)
|
||||
Else
|
||||
_logger.Debug("No missing properties found. Continuing.")
|
||||
|
||||
@ -1027,9 +639,14 @@ Public Class ImportZUGFeRDFiles
|
||||
InsertPropertyValue(pMessageId, oConnections, oProperty)
|
||||
Next
|
||||
|
||||
Return New ProcessFileResult With {
|
||||
.ZugferdFileCount = oZugferdFiles
|
||||
}
|
||||
_logger.Debug("File processed.")
|
||||
|
||||
oResult.ZugferdFileFound = True
|
||||
oResult.MD5Checksum = oMD5Checksum
|
||||
oResult.ZugferdFileCount = pZugferdFiles
|
||||
|
||||
Return oResult
|
||||
|
||||
End Function
|
||||
#End Region
|
||||
|
||||
@ -1058,8 +675,8 @@ Public Class ImportZUGFeRDFiles
|
||||
Dim oCommand = $"INSERT INTO {pProperty.TableName} (REFERENCE_GUID, ITEM_DESCRIPTION, ITEM_VALUE, GROUP_COUNTER, SPEC_NAME, IS_REQUIRED) VALUES
|
||||
('{pMessageId}', '{pProperty.Description}', '{pProperty.Value.Replace("'", "''")}', {oGroupCounterValue},'{pProperty.TableColumn}','{pProperty.IsRequired}')"
|
||||
_logger.Debug("Mapping Property [{0}] with value [{1}], Will be inserted into table [{2}]", pProperty.TableColumn, pProperty.Value.Replace("'", "''"), pProperty.TableName)
|
||||
' Insert into SQL Server
|
||||
|
||||
' Insert into SQL Server
|
||||
Dim oResult = _mssql.ExecuteNonQueryWithConnectionObject(oCommand, pConnections.SQLServerConnection, MSSQLServer.TransactionMode.ExternalTransaction, pConnections.SQLServerTransaction)
|
||||
If oResult = False Then
|
||||
_logger.Warn($"SQL Command [{oCommand}] was not successful. Check the log.")
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user