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.Reflection
Imports System.Xml
Imports System.Xml.Serialization
Imports DigitalData.Modules.Interfaces.Exceptions
Imports DigitalData.Modules.Interfaces.PDFEmbeds
Imports DigitalData.Modules.Interfaces.Peppol
Imports DigitalData.Modules.Interfaces.ZUGFeRD
Imports DigitalData.Modules.Logging
@ -138,6 +140,44 @@ Public Class ZUGFeRDInterface
End If
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>
''' Validates a ZUGFeRD File and extracts the XML Document from it
''' </summary>

View File

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

View File

@ -16,4 +16,13 @@
''' XML Pfad, für Anzeige in Ablehnungsmail
''' </summary>
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

View File

@ -116,6 +116,7 @@
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Include="ZUGFeRD\XRechnungViewDocument.vb" />
</ItemGroup>
<ItemGroup>
<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
Dim oEmailDataBase = _email.GetEmailDataForMessageId(oMessageId)
Dim oFileCounter As Integer = 0
Try
Dim oInNdex = 0
For Each oFile In oFileGroupFiles
'----------------------------
'----------------------------
'Hier Logik für xml/xRechnungs-Handling - paralleler Zweig zu ProcessFile
Dim oResult As ProcessFileResult = ProcessFile(oMessageId, oEmailDataBase, oZUGFeRDCount, oFile, oConnections, oArgs)
oFileCounter += 1
Dim oResult As ProcessFileResult
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
_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 oMoveDirectory = DIRECTORY_DONT_MOVE Then
_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
' Move all files of the current group
_file.MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
@ -459,34 +466,25 @@ Public Class ImportZUGFeRDFiles
Return oRejectionCodeString
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 oResult As New ProcessFileResult()
' 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)
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
If pFile.Extension.Equals(".xml", StringComparison.OrdinalIgnoreCase) = False Then
' Diese Methode ist nur für den xml-Beleg gedacht
Return oResult
End If
_logger.Info("Start processing file {0}", oFile.Name)
_logger.Info("Start xml processing file {0}", pFile.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)
' Checking filesize
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(oFile.FullName)
oDocument = _zugferd.GetSerializedXMLContentFromFile(pFile)
Catch ex As ValidationException
Throw ex
@ -494,70 +492,156 @@ Public Class ImportZUGFeRDFiles
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)
_logger.Info("File [{0}] is not a valid ZUGFeRD document. Skipping.", pFile.Name)
oResult.EmailAttachmentFiles.Add(oFile)
oResult.EmailAttachmentFiles.Add(pFile)
Return oResult
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)
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()
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
End Select
End Try
' Check if there are more than one ZUGFeRD files
If pZugferdFiles = 1 Then
If pZugferdFileCounter = 1 Then
Throw New TooMuchFerdsException()
End If
' Since extraction went well, increase the amount of ZUGFeRD files
pZugferdFiles += 1
pZugferdFileCounter += 1
_logger.Info("Zugferd file found. Increasing counter.")
' 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)
Dim oAttachments = _embeds.Extract(pFile.FullName, AllowedExtensions)
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
oResult.EmbeddedAttachmentFiles.AddRange(oAttachments)
End If
' Check the Checksum and rejection status
Dim oMD5Checksum = _hash.GenerateAndCheck_MD5Sum(oFile, pMessageId, pArgs.IgnoreRejectionStatus)
Try
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:
' - 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, pMessageId)
Dim oPropertyMap = _zugferd.FilterPropertyMap(pArgs.PropertyMap, pDocument.Specification)
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)
If oCheckResult.MissingProperties.Count > 0 Then
_logger.Warn("[{0}] missing properties found. Exiting.", oCheckResult.MissingProperties.Count)
Throw New MissingValueException(oFile, oCheckResult.MissingProperties)
Throw New MissingValueException(pFile, oCheckResult.MissingProperties)
Else
_logger.Debug("No missing properties found. Continuing.")
End If
If DeleteExistingPropertyValues(pMessageId, oConnections) = False Then
If DeleteExistingPropertyValues(pMessageId, pConnections) = False Then
Throw New Exception("Could not cleanup data. Exiting.")
End If
' 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
Dim oColumnNames As List(Of String) = New List(Of String) From {
@ -569,7 +653,7 @@ Public Class ImportZUGFeRDFiles
"IS_REQUIRED"
}
Dim oBulkResult = BulkInsert(oConnections, oDataTable, "TBEDMI_ITEM_VALUE", oColumnNames)
Dim oBulkResult = BulkInsert(pConnections, oDataTable, "TBEDMI_ITEM_VALUE", oColumnNames)
If oBulkResult = False Then
_logger.Error("Bulk Insert for MessageId [{0}] failed!", pMessageId)
@ -577,15 +661,7 @@ Public Class ImportZUGFeRDFiles
End If
_logger.Info("Bulk Insert finished. [{0}] rows inserted for MessageId [{1}].", oDataTable.Rows.Count, pMessageId)
_logger.Debug("File processed.")
oResult.ZugferdFileFound = True
oResult.MD5Checksum = oMD5Checksum
oResult.ZugferdFileCount = pZugferdFiles
Return oResult
Return True
End Function
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
_logger.Warn("Step [{0}] with SQL [{1}] was not successful.", oStep, oDelSQL)
End Try
Return False
End Function
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