MergeCommit

This commit is contained in:
Developer01 2025-01-29 14:28:30 +01:00
commit 6a051f7a92
6 changed files with 189 additions and 53 deletions

View File

@ -1,7 +1,9 @@
Imports System.IO Imports System.IO
Imports System.Reflection
Imports System.Xml Imports System.Xml
Imports System.Xml.Serialization Imports System.Xml.Serialization
Imports DigitalData.Modules.Interfaces.Exceptions Imports DigitalData.Modules.Interfaces.Exceptions
Imports DigitalData.Modules.Interfaces.PDFEmbeds
Imports DigitalData.Modules.Interfaces.Peppol Imports DigitalData.Modules.Interfaces.Peppol
Imports DigitalData.Modules.Interfaces.ZUGFeRD Imports DigitalData.Modules.Interfaces.ZUGFeRD
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
@ -138,6 +140,44 @@ Public Class ZUGFeRDInterface
End If End If
End Function End Function
Public Function GetSerializedXMLContentFromFile(oFileInfo As FileInfo) As ZugferdResult
Dim oResult = New ZugferdResult()
Try
Dim oFileSize As Integer = oFileInfo.Length
Dim oFileData As Byte() = File.ReadAllBytes(oFileInfo.FullName)
Dim oXmlFile As EmbeddedFile = New EmbeddedFile() With {
.FileName = oFileInfo.Name,
.FileContents = oFileData
}
Using oStream As New MemoryStream(oXmlFile.FileContents)
oResult = New ZugferdResult With {
.DataFileName = oXmlFile.FileName,
.XElementObject = XElement.Load(oStream)
}
End Using
Catch ex As ZUGFeRDExecption
' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code.
' It also produces misleading error messages when checking if an attachment is a zugferd file.
Throw ex
Catch ex As Exception
_logger.Error(ex)
Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, "Datei ist eine ungültige XML Datei.")
End Try
If oResult.ValidationErrors.Any() Then
Throw New ValidationException() With {
.ValidationErrors = oResult.ValidationErrors
}
End If
Return SerializeZUGFeRDDocument(oResult)
End Function
''' <summary> ''' <summary>
''' Validates a ZUGFeRD File and extracts the XML Document from it ''' Validates a ZUGFeRD File and extracts the XML Document from it
''' </summary> ''' </summary>

View File

@ -30,6 +30,8 @@ Public Class PropertyValues
Public Description As String Public Description As String
Public Value As String Public Value As String
Public XMLPath As String Public XMLPath As String
Public ItemType As Integer = 0
End Class End Class
Public Class MissingProperty Public Class MissingProperty
@ -109,6 +111,7 @@ Public Class PropertyValues
Dim oIsRequired As Boolean = oColumn.Key.IsRequired Dim oIsRequired As Boolean = oColumn.Key.IsRequired
Dim oPropertyDescription As String = oColumn.Key.Description Dim oPropertyDescription As String = oColumn.Key.Description
Dim oPropertyPath As String = oColumn.Key.XMLPath Dim oPropertyPath As String = oColumn.Key.XMLPath
Dim oItemType As Integer = oColumn.Key.ItemType
Dim oRowCounter = oRowIndex + oGlobalGroupCounter + 1 Dim oRowCounter = oRowIndex + oGlobalGroupCounter + 1
@ -144,7 +147,8 @@ Public Class PropertyValues
.TableName = oTableName, .TableName = oTableName,
.TableColumn = oTableColumn, .TableColumn = oTableColumn,
.IsRequired = oIsRequired, .IsRequired = oIsRequired,
.XMLPath = oPropertyPath .XMLPath = oPropertyPath,
.ItemType = oItemType
}) })
Next Next
Next Next
@ -162,6 +166,7 @@ Public Class PropertyValues
Dim oTableName = oItem.Value.TableName Dim oTableName = oItem.Value.TableName
Dim oIsRequired = oItem.Value.IsRequired Dim oIsRequired = oItem.Value.IsRequired
Dim oDescription = oItem.Value.Description Dim oDescription = oItem.Value.Description
Dim oItemType = oItem.Value.ItemType
Try Try
oPropertyValueList = GetPropValue(pDocument, oItem.Key) oPropertyValueList = GetPropValue(pDocument, oItem.Key)
@ -225,7 +230,8 @@ Public Class PropertyValues
.TableName = oTableName, .TableName = oTableName,
.TableColumn = oTableColumn, .TableColumn = oTableColumn,
.IsRequired = oIsRequired, .IsRequired = oIsRequired,
.XMLPath = oPropertyPath .XMLPath = oPropertyPath,
.ItemType = oItemType
}) })
Next Next
@ -304,7 +310,6 @@ Public Class PropertyValues
Return oResults Return oResults
End If End If
Next Next
Return New List(Of Object) From {Obj} Return New List(Of Object) From {Obj}

View File

@ -16,4 +16,13 @@
''' XML Pfad, für Anzeige in Ablehnungsmail ''' XML Pfad, für Anzeige in Ablehnungsmail
''' </summary> ''' </summary>
Public XMLPath As String Public XMLPath As String
''' <summary>
''' (Daten-)Typ des Knoten
''' 0 = Default / Text
''' 1 = Datum
''' 2 = Gleitkomma
''' 3 = Memo-Feld
''' </summary>
Public ItemType As Integer
End Class End Class

View File

@ -116,6 +116,7 @@
<DesignTimeSharedInput>True</DesignTimeSharedInput> <DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon> <DependentUpon>Settings.settings</DependentUpon>
</Compile> </Compile>
<Compile Include="ZUGFeRD\XRechnungViewDocument.vb" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="FirebirdSql.Data.FirebirdClient, Version=7.5.0.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c, processorArchitecture=MSIL"> <Reference Include="FirebirdSql.Data.FirebirdClient, Version=7.5.0.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c, processorArchitecture=MSIL">

View File

@ -166,14 +166,18 @@ Public Class ImportZUGFeRDFiles
End If End If
Dim oEmailDataBase = _email.GetEmailDataForMessageId(oMessageId) Dim oEmailDataBase = _email.GetEmailDataForMessageId(oMessageId)
Dim oFileCounter As Integer = 0
Try Try
Dim oInNdex = 0
For Each oFile In oFileGroupFiles For Each oFile In oFileGroupFiles
'---------------------------- oFileCounter += 1
'---------------------------- Dim oResult As ProcessFileResult
'Hier Logik für xml/xRechnungs-Handling - paralleler Zweig zu ProcessFile
Dim oResult As ProcessFileResult = ProcessFile(oMessageId, oEmailDataBase, oZUGFeRDCount, oFile, oConnections, oArgs) If oFileCounter = 1 AndAlso oFile.Name.ToUpper.EndsWith(".XML") Then
oResult = ProcessXMLFile(oMessageId, oZUGFeRDCount, oFile, oConnections, oArgs)
Else
oResult = ProcessFile(oMessageId, oZUGFeRDCount, oFile, oConnections, oArgs)
End If
If oResult.ZugferdFileFound = True Then If oResult.ZugferdFileFound = True Then
_logger.Debug("Zugferd File found") _logger.Debug("Zugferd File found")
@ -394,6 +398,9 @@ Public Class ImportZUGFeRDFiles
' If an application error occurred, dont move files so they will be processed again later ' If an application error occurred, dont move files so they will be processed again later
If oMoveDirectory = DIRECTORY_DONT_MOVE Then If oMoveDirectory = DIRECTORY_DONT_MOVE Then
_logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId) _logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId)
ElseIf (1 = 0) Then
' Hier das neue PDF erzeugen
Else Else
' Move all files of the current group ' Move all files of the current group
_file.MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess) _file.MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
@ -459,34 +466,25 @@ Public Class ImportZUGFeRDFiles
Return oRejectionCodeString Return oRejectionCodeString
End Function End Function
Private Function ProcessFile(pMessageId As String, pEmailData As EmailData, pZugferdFiles As Integer, oFile As FileInfo, oConnections As DatabaseConnections, pArgs As WorkerArgs) As ProcessFileResult Private Function ProcessXMLFile(pMessageId As String, pZugferdFileCounter As Integer, pFile As FileInfo, pConnections As DatabaseConnections, pArgs As WorkerArgs) As ProcessFileResult
Dim oDocument As ZUGFeRDInterface.ZugferdResult Dim oDocument As ZUGFeRDInterface.ZugferdResult
Dim oResult As New ProcessFileResult() Dim oResult As New ProcessFileResult()
' Only pdf files are allowed from here on If pFile.Extension.Equals(".xml", StringComparison.OrdinalIgnoreCase) = False Then
If Not oFile.Name.ToUpper.EndsWith(".PDF") Then ' Diese Methode ist nur für den xml-Beleg gedacht
_logger.Debug("Skipping non-pdf file {0}", oFile.Name)
oResult.EmailAttachmentFiles.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
Return oResult Return oResult
End If End If
_logger.Info("Start processing file {0}", oFile.Name) _logger.Info("Start xml processing file {0}", pFile.Name)
' Checking filesize for pdf files ' Checking filesize
If _filesystem.TestFileSizeIsLessThanMaxFileSize(oFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then If _filesystem.TestFileSizeIsLessThanMaxFileSize(pFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes) _logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", pFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
Throw New FileSizeLimitReachedException(oFile.Name, pArgs.MaxAttachmentSizeInMegaBytes) Throw New FileSizeLimitReachedException(pFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
End If End If
Try Try
oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(oFile.FullName) oDocument = _zugferd.GetSerializedXMLContentFromFile(pFile)
Catch ex As ValidationException Catch ex As ValidationException
Throw ex Throw ex
@ -494,70 +492,156 @@ Public Class ImportZUGFeRDFiles
Catch ex As ZUGFeRDExecption Catch ex As ZUGFeRDExecption
Select Case ex.ErrorType Select Case ex.ErrorType
Case ZUGFeRDInterface.ErrorType.NoZugferd Case ZUGFeRDInterface.ErrorType.NoZugferd
_logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", oFile.Name) _logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", pFile.Name)
oResult.EmailAttachmentFiles.Add(oFile) oResult.EmailAttachmentFiles.Add(pFile)
Return oResult Return oResult
Case ZUGFeRDInterface.ErrorType.UnsupportedFormat Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
_logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", oFile.Name, ex.XmlFile) _logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", pFile.Name, ex.XmlFile)
Throw New UnsupportedFerdException(ex.XmlFile) Throw New UnsupportedFerdException(ex.XmlFile)
Case ZUGFeRDInterface.ErrorType.NoValidZugferd Case ZUGFeRDInterface.ErrorType.NoValidZugferd
_logger.Info("File [{0}] is an Incorrectly formatted ZUGFeRD document!", oFile.Name) _logger.Info("File [{0}] is an Incorrectly formatted ZUGFeRD document!", pFile.Name)
Throw New InvalidFerdException() Throw New InvalidFerdException()
Case Else Case Else
_logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", oFile.Name) _logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", pFile.Name)
Throw ex
End Select
End Try
Try
Dim sqlResult As Boolean = StoreXMLItemsInDatabase(pMessageId, oDocument, pFile, pConnections, pArgs)
Catch ex As Exception
Throw ex
End Try
_logger.Debug("File processed.")
Dim oMD5Checksum = _hash.GenerateAndCheck_MD5Sum(pFile, pMessageId, pArgs.IgnoreRejectionStatus)
oResult.ZugferdFileFound = True
oResult.MD5Checksum = oMD5Checksum
oResult.ZugferdFileCount = 1 ' Es kann hier nur genau einen Treffer geben!
Return oResult
End Function
Private Function ProcessFile(pMessageId As String, pZugferdFileCounter As Integer, pFile As FileInfo, pConnections As DatabaseConnections, pArgs As WorkerArgs) As ProcessFileResult
Dim oDocument As ZUGFeRDInterface.ZugferdResult
Dim oResult As New ProcessFileResult()
' Only pdf files are allowed from here on
If Not pFile.Name.ToUpper.EndsWith(".PDF") Then
_logger.Debug("Skipping non-pdf file {0}", pFile.Name)
oResult.EmailAttachmentFiles.Add(pFile)
' Checking filesize for attachment files
If _filesystem.TestFileSizeIsLessThanMaxFileSize(pFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", pFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
Throw New FileSizeLimitReachedException(pFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
End If
Return oResult
End If
_logger.Info("Start processing file {0}", pFile.Name)
' Checking filesize for pdf files
If _filesystem.TestFileSizeIsLessThanMaxFileSize(pFile.FullName, pArgs.MaxAttachmentSizeInMegaBytes) = False Then
_logger.Warn("Filesize for File [{0}] exceeded limit of {1} MB", pFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
Throw New FileSizeLimitReachedException(pFile.Name, pArgs.MaxAttachmentSizeInMegaBytes)
End If
Try
oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(pFile.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.", pFile.Name)
oResult.EmailAttachmentFiles.Add(pFile)
Return oResult
Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
_logger.Info("File [{0}/{1}] is an unsupported ZUFeRD document format!", pFile.Name, ex.XmlFile)
Throw New UnsupportedFerdException(ex.XmlFile)
Case ZUGFeRDInterface.ErrorType.NoValidZugferd
_logger.Info("File [{0}] is an Incorrectly formatted ZUGFeRD document!", pFile.Name)
Throw New InvalidFerdException()
Case Else
_logger.Warn("Unexpected Error occurred while extracting ZUGFeRD Information from file {0}", pFile.Name)
Throw ex Throw ex
End Select End Select
End Try End Try
' Check if there are more than one ZUGFeRD files ' Check if there are more than one ZUGFeRD files
If pZugferdFiles = 1 Then If pZugferdFileCounter = 1 Then
Throw New TooMuchFerdsException() Throw New TooMuchFerdsException()
End If End If
' Since extraction went well, increase the amount of ZUGFeRD files ' Since extraction went well, increase the amount of ZUGFeRD files
pZugferdFiles += 1 pZugferdFileCounter += 1
_logger.Info("Zugferd file found. Increasing counter.") _logger.Info("Zugferd file found. Increasing counter.")
' Extract all attachments with the extensions specified in `AllowedExtensions`. ' 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. ' 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`. ' Right now the zugferd-invoice.xml is filtered out because `AllowedExtensions` does not contain `xml`.
Dim oAttachments = _embeds.Extract(oFile.FullName, AllowedExtensions) Dim oAttachments = _embeds.Extract(pFile.FullName, AllowedExtensions)
If oAttachments Is Nothing Then If oAttachments Is Nothing Then
_logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName) _logger.Warn("Attachments for file [{0}] could not be extracted", pFile.FullName)
Else Else
oResult.EmbeddedAttachmentFiles.AddRange(oAttachments) oResult.EmbeddedAttachmentFiles.AddRange(oAttachments)
End If End If
' Check the Checksum and rejection status Try
Dim oMD5Checksum = _hash.GenerateAndCheck_MD5Sum(oFile, pMessageId, pArgs.IgnoreRejectionStatus) Dim sqlResult As Boolean = StoreXMLItemsInDatabase(pMessageId, oDocument, pFile, pConnections, pArgs)
Catch ex As Exception
Throw ex
End Try
_logger.Debug("File processed.")
' Check the Checksum and rejection status
Dim oMD5Checksum = _hash.GenerateAndCheck_MD5Sum(pFile, pMessageId, pArgs.IgnoreRejectionStatus)
oResult.ZugferdFileFound = True
oResult.MD5Checksum = oMD5Checksum
oResult.ZugferdFileCount = pZugferdFileCounter
Return oResult
End Function
Private Function StoreXMLItemsInDatabase(pMessageId As String, pDocument As ZUGFeRDInterface.ZugferdResult, pFile As FileInfo, pConnections As DatabaseConnections, pArgs As WorkerArgs) As Boolean
' Check the document against the configured property map and return: ' Check the document against the configured property map and return:
' - a List of valid properties ' - a List of valid properties
' - a List of missing properties ' - a List of missing properties
Dim oPropertyMap = _zugferd.FilterPropertyMap(pArgs.PropertyMap, oDocument.Specification) Dim oPropertyMap = _zugferd.FilterPropertyMap(pArgs.PropertyMap, pDocument.Specification)
Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument.SchemaObject, oPropertyMap, pMessageId) Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(pDocument.SchemaObject, oPropertyMap, pMessageId)
_logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count) _logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count)
If oCheckResult.MissingProperties.Count > 0 Then If oCheckResult.MissingProperties.Count > 0 Then
_logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count) _logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
Throw New MissingValueException(oFile, oCheckResult.MissingProperties) Throw New MissingValueException(pFile, oCheckResult.MissingProperties)
Else Else
_logger.Debug("No missing properties found. Continuing.") _logger.Debug("No missing properties found. Continuing.")
End If End If
If DeleteExistingPropertyValues(pMessageId, oConnections) = False Then If DeleteExistingPropertyValues(pMessageId, pConnections) = False Then
Throw New Exception("Could not cleanup data. Exiting.") Throw New Exception("Could not cleanup data. Exiting.")
End If End If
' DataTable vorbereiten ' DataTable vorbereiten
Dim oDataTable As DataTable = FillDataTable(pMessageId, oCheckResult, oDocument.Specification, oDocument.UsedXMLSchema) Dim oDataTable As DataTable = FillDataTable(pMessageId, oCheckResult, pDocument.Specification, pDocument.UsedXMLSchema)
' ColumnList initialisieren ' ColumnList initialisieren
Dim oColumnNames As List(Of String) = New List(Of String) From { Dim oColumnNames As List(Of String) = New List(Of String) From {
@ -569,7 +653,7 @@ Public Class ImportZUGFeRDFiles
"IS_REQUIRED" "IS_REQUIRED"
} }
Dim oBulkResult = BulkInsert(oConnections, oDataTable, "TBEDMI_ITEM_VALUE", oColumnNames) Dim oBulkResult = BulkInsert(pConnections, oDataTable, "TBEDMI_ITEM_VALUE", oColumnNames)
If oBulkResult = False Then If oBulkResult = False Then
_logger.Error("Bulk Insert for MessageId [{0}] failed!", pMessageId) _logger.Error("Bulk Insert for MessageId [{0}] failed!", pMessageId)
@ -577,15 +661,7 @@ Public Class ImportZUGFeRDFiles
End If End If
_logger.Info("Bulk Insert finished. [{0}] rows inserted for MessageId [{1}].", oDataTable.Rows.Count, pMessageId) _logger.Info("Bulk Insert finished. [{0}] rows inserted for MessageId [{1}].", oDataTable.Rows.Count, pMessageId)
Return True
_logger.Debug("File processed.")
oResult.ZugferdFileFound = True
oResult.MD5Checksum = oMD5Checksum
oResult.ZugferdFileCount = pZugferdFiles
Return oResult
End Function End Function
Private Function FillDataTable(pMessageId As String, pCheckResult As PropertyValues.CheckPropertyValuesResult, pSpecification As String, pUsedXMLSchema As String) As DataTable Private Function FillDataTable(pMessageId As String, pCheckResult As PropertyValues.CheckPropertyValuesResult, pSpecification As String, pUsedXMLSchema As String) As DataTable
@ -660,6 +736,8 @@ Public Class ImportZUGFeRDFiles
Catch ex As Exception Catch ex As Exception
_logger.Warn("Step [{0}] with SQL [{1}] was not successful.", oStep, oDelSQL) _logger.Warn("Step [{0}] with SQL [{1}] was not successful.", oStep, oDelSQL)
End Try End Try
Return False
End Function End Function
Private Function BulkInsert(pConnections As DatabaseConnections, pTable As DataTable, pDestinationTable As String, pColumns As List(Of String)) As Boolean Private Function BulkInsert(pConnections As DatabaseConnections, pTable As DataTable, pDestinationTable As String, pColumns As List(Of String)) As Boolean

View File

@ -0,0 +1,3 @@
Public Class XRechnungViewDocument
End Class