ZUGFeRD: WIP Allow blocking factur-x and xrechnung invoice files with config flags
This commit is contained in:
parent
f4adba98eb
commit
0410e11b59
@ -8,42 +8,87 @@ Imports DigitalData.Modules.Logging
|
||||
Imports GdPicture14
|
||||
|
||||
Public Class ZUGFeRDInterface
|
||||
Private _logConfig As LogConfig
|
||||
Private _logger As Logger
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _Options As ZugferdOptions
|
||||
|
||||
Private ReadOnly ValidFilenames As New List(Of String) From {
|
||||
PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_FR.ToUpper
|
||||
}
|
||||
|
||||
Private AllowedFilenames As New List(Of String)
|
||||
|
||||
Public Enum ErrorType
|
||||
NoValidFile
|
||||
NoZugferd
|
||||
NoValidZugferd
|
||||
MissingProperties
|
||||
UnsupportedFormat
|
||||
UnknownError
|
||||
End Enum
|
||||
|
||||
Public ReadOnly Property FileGroup As FileGroups
|
||||
Public ReadOnly Property PropertyValues As PropertyValues
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, GDPictureKey As String)
|
||||
_logConfig = LogConfig
|
||||
Public Class ZugferdOptions
|
||||
Public Property AllowFacturX_Filename As Boolean = True
|
||||
Public Property AllowXRechnung_Filename As Boolean = True
|
||||
End Class
|
||||
|
||||
''' <summary>
|
||||
''' Create a new instance of ZUGFeRDInterface
|
||||
''' </summary>
|
||||
''' <param name="pLogConfig">A LogConfig object</param>
|
||||
''' <param name="pGDPictureKey">A valid GDPicture License</param>
|
||||
''' <param name="pOptions">Optional parameters to control various settings</param>
|
||||
Public Sub New(pLogConfig As LogConfig, pGDPictureKey As String, Optional pOptions As ZugferdOptions = Nothing)
|
||||
_logConfig = pLogConfig
|
||||
_logger = _logConfig.GetLogger()
|
||||
|
||||
If pOptions Is Nothing Then
|
||||
_Options = New ZugferdOptions()
|
||||
Else
|
||||
_Options = pOptions
|
||||
End If
|
||||
|
||||
ApplyFilenameOptions(_Options)
|
||||
|
||||
FileGroup = New FileGroups(_logConfig)
|
||||
PropertyValues = New PropertyValues(_logConfig)
|
||||
|
||||
Try
|
||||
Dim oLicenseManager As New LicenseManager
|
||||
oLicenseManager.RegisterKEY(GDPictureKey)
|
||||
oLicenseManager.RegisterKEY(pGDPictureKey)
|
||||
Catch ex As Exception
|
||||
_logger.Warn("GDPicture License could not be registered!")
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Sub ApplyFilenameOptions(pOptions As ZugferdOptions)
|
||||
Dim oAllowedFilenames As List(Of String) = ValidFilenames
|
||||
|
||||
If pOptions.AllowFacturX_Filename = False Then
|
||||
oAllowedFilenames = oAllowedFilenames.
|
||||
Except(New List(Of String) From {PDFEmbeds.FACTUR_X_XML_FILENAME_FR}).ToList()
|
||||
End If
|
||||
|
||||
If pOptions.AllowXRechnung_Filename = False Then
|
||||
oAllowedFilenames = oAllowedFilenames.
|
||||
Except(New List(Of String) From {PDFEmbeds.FACTUR_X_XML_FILENAME_DE}).ToList()
|
||||
End If
|
||||
|
||||
AllowedFilenames = oAllowedFilenames
|
||||
End Sub
|
||||
|
||||
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
''' <param name="Path"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As Object
|
||||
Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path)
|
||||
|
||||
@ -59,7 +104,6 @@ Public Class ZUGFeRDInterface
|
||||
''' </summary>
|
||||
''' <param name="Stream"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As Object
|
||||
Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Stream)
|
||||
|
||||
@ -73,15 +117,15 @@ Public Class ZUGFeRDInterface
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
''' <param name="Stream"></param>
|
||||
''' <param name="pStream"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(Stream As Stream) As XPathDocument
|
||||
''' <returns>The embedded xml data as an XPath document</returns>
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(pStream As Stream) As XPathDocument
|
||||
Dim oEmbedExtractor = New PDFEmbeds(_logConfig)
|
||||
Dim oAllowedExtensions = New List(Of String) From {"xml"}
|
||||
|
||||
Try
|
||||
Dim oFiles = oEmbedExtractor.Extract(Stream, oAllowedExtensions)
|
||||
' Extract XML attachments only!
|
||||
Dim oFiles = oEmbedExtractor.Extract(pStream, New List(Of String) From {"xml"})
|
||||
|
||||
' Attachments are in this case the files that are embedded into a pdf file,
|
||||
' like for example the zugferd-invoice.xml file
|
||||
@ -98,12 +142,18 @@ Public Class ZUGFeRDInterface
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(Path As String) As XPathDocument
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
''' <param name="pPath"></param>
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns>The embedded xml data as an XPath document</returns>
|
||||
Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As XPathDocument
|
||||
Dim oEmbedExtractor = New PDFEmbeds(_logConfig)
|
||||
Dim oAllowedExtensions = New List(Of String) From {"xml"}
|
||||
|
||||
Try
|
||||
Dim oFiles = oEmbedExtractor.Extract(Path, oAllowedExtensions)
|
||||
' Extract XML attachments only!
|
||||
Dim oFiles = oEmbedExtractor.Extract(pPath, New List(Of String) From {"xml"})
|
||||
|
||||
' Attachments are in this case the files that are embedded into a pdf file,
|
||||
' like for example the zugferd-invoice.xml file
|
||||
@ -120,34 +170,38 @@ Public Class ZUGFeRDInterface
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function HandleEmbeddedFiles(Results As List(Of PDFEmbeds.EmbeddedFile)) As XPathDocument
|
||||
Private Function HandleEmbeddedFiles(pResults As List(Of PDFEmbeds.EmbeddedFile)) As XPathDocument
|
||||
Dim oXmlDocument As XPathDocument
|
||||
|
||||
If Results Is Nothing Then
|
||||
If pResults Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die Attachments nicht gelesen werden konnten.")
|
||||
End If
|
||||
|
||||
If Results.Count = 0 Then
|
||||
If pResults.Count = 0 Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil sie keine Attachments enthält.")
|
||||
End If
|
||||
|
||||
Dim oValidFilenames As New List(Of String) From {
|
||||
PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper,
|
||||
PDFEmbeds.FACTUR_X_XML_FILENAME_FR.ToUpper
|
||||
}
|
||||
|
||||
' Find the first file which filename matches the valid filenames for embedded invoice files
|
||||
Dim oFoundResult As PDFEmbeds.EmbeddedFile = Results.
|
||||
Where(Function(result) oValidFilenames.Contains(result.FileName.ToUpper)).
|
||||
Dim oValidResult As PDFEmbeds.EmbeddedFile = pResults.
|
||||
Where(Function(result) ValidFilenames.Contains(result.FileName.ToUpper)).
|
||||
FirstOrDefault()
|
||||
|
||||
If oFoundResult Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die zugferd-invoice.xml nicht gefunden wurde.")
|
||||
If oValidResult Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil keine entsprechende XML-Datei gefunden wurde.")
|
||||
End If
|
||||
|
||||
' Search the embedded files for the ones which are allowed as per the configuration.
|
||||
' The config might say, allow ZUGFeRD but not Factur-X.
|
||||
Dim oAllowedResult As PDFEmbeds.EmbeddedFile = pResults.
|
||||
Where(Function(result) AllowedFilenames.Contains(result.FileName.ToUpper)).
|
||||
FirstOrDefault()
|
||||
|
||||
If oAllowedResult Is Nothing Then
|
||||
Throw New ZUGFeRDExecption(ErrorType.UnsupportedFormat, "Datei ist eine ZUGFeRD Datei, aber das Format wird nicht unterstützt.")
|
||||
End If
|
||||
|
||||
Try
|
||||
Using oStream As New MemoryStream(oFoundResult.FileContents)
|
||||
Using oStream As New MemoryStream(oAllowedResult.FileContents)
|
||||
oXmlDocument = New XPathDocument(oStream)
|
||||
End Using
|
||||
|
||||
@ -163,9 +217,9 @@ Public Class ZUGFeRDInterface
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function SerializeZUGFeRDDocument(Document As XPathDocument) As Object
|
||||
Public Function SerializeZUGFeRDDocument(pDocument As XPathDocument) As Object
|
||||
Try
|
||||
Dim oNavigator As XPathNavigator = Document.CreateNavigator()
|
||||
Dim oNavigator As XPathNavigator = pDocument.CreateNavigator()
|
||||
Dim oReader As XmlReader
|
||||
Dim oResult = Nothing
|
||||
|
||||
|
||||
@ -28,7 +28,7 @@ Public Class PDFEmbeds
|
||||
Public Function Extract(FilePath As String, AllowedExtensions As List(Of String)) As List(Of EmbeddedFile)
|
||||
Dim oFile As New List(Of EmbeddedFile)
|
||||
Dim oFileInfo As FileInfo
|
||||
Dim oExtensions = AllowedExtensions.ConvertAll(New Converter(Of String, String)(Function(ext) ext.ToUpper))
|
||||
Dim oExtensions = AllowedExtensions.Select(Function(ext) ext.ToUpper).ToList()
|
||||
|
||||
Logger.Debug("Extracting embedded files from [{0}]", FilePath)
|
||||
|
||||
@ -69,7 +69,7 @@ Public Class PDFEmbeds
|
||||
''' <param name="AllowedExtensions">List of allowed extensions to be extracted</param>
|
||||
Public Function Extract(Stream As Stream, AllowedExtensions As List(Of String)) As List(Of EmbeddedFile)
|
||||
Dim oResults As New List(Of EmbeddedFile)
|
||||
Dim oExtensions = AllowedExtensions.ConvertAll(New Converter(Of String, String)(Function(ext) ext.ToUpper))
|
||||
Dim oExtensions = AllowedExtensions.Select(Function(ext) ext.ToUpper).ToList()
|
||||
|
||||
Logger.Debug("Extracting embedded files from stream")
|
||||
|
||||
|
||||
@ -40,6 +40,14 @@ Public Class Exceptions
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
Public Class UnsupportedFerdException
|
||||
Inherits ApplicationException
|
||||
|
||||
Public Sub New()
|
||||
MyBase.New("ZUGFeRD document found but is not supported!")
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
Public Class NoFerdsException
|
||||
Inherits ApplicationException
|
||||
|
||||
|
||||
@ -91,17 +91,17 @@
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="EDMI\ADSync\ADSyncArgs.vb" />
|
||||
<Compile Include="EDMI\ADSync\ADSyncJob.vb" />
|
||||
<Compile Include="EDMI\GraphQL\GraphQLArgs.vb" />
|
||||
<Compile Include="EDMI\GraphQL\GraphQLConfig.vb" />
|
||||
<Compile Include="EDMI\GraphQL\GraphQLJob.vb" />
|
||||
<Compile Include="EDMI\GraphQL\GraphQLQuery.vb" />
|
||||
<Compile Include="EDMI\ZUGFeRD\EmailData.vb" />
|
||||
<Compile Include="EDMI\ZUGFeRD\EmailFunctions.vb" />
|
||||
<Compile Include="EDMI\ZUGFeRD\EmailStrings.vb" />
|
||||
<Compile Include="EDMI\ZUGFeRD\ImportZUGFeRDFiles.vb" />
|
||||
<Compile Include="EDMI\ZUGFeRD\WorkerArgs.vb" />
|
||||
<Compile Include="ADSync\ADSyncArgs.vb" />
|
||||
<Compile Include="ADSync\ADSyncJob.vb" />
|
||||
<Compile Include="GraphQL\GraphQLArgs.vb" />
|
||||
<Compile Include="GraphQL\GraphQLConfig.vb" />
|
||||
<Compile Include="GraphQL\GraphQLJob.vb" />
|
||||
<Compile Include="GraphQL\GraphQLQuery.vb" />
|
||||
<Compile Include="ZUGFeRD\EmailData.vb" />
|
||||
<Compile Include="ZUGFeRD\EmailFunctions.vb" />
|
||||
<Compile Include="ZUGFeRD\EmailStrings.vb" />
|
||||
<Compile Include="ZUGFeRD\ImportZUGFeRDFiles.vb" />
|
||||
<Compile Include="ZUGFeRD\WorkerArgs.vb" />
|
||||
<Compile Include="Exceptions.vb" />
|
||||
<Compile Include="JobInterface.vb" />
|
||||
<Compile Include="JobBase.vb" />
|
||||
|
||||
@ -37,4 +37,8 @@
|
||||
<li>Betrags-Werte weisen ungültiges Format auf (25,01 anstatt 25.01)</li>
|
||||
</ul></p>
|
||||
"
|
||||
|
||||
Public Const EMAIL_UNSUPPORTED_DOCUMENT = "
|
||||
<p>Ihre Email enthielt ein ZUGFeRD Dokument, welches aber zur Zeit noch nicht unsterstützt wird.</p>
|
||||
"
|
||||
End Class
|
||||
@ -26,35 +26,33 @@ Public Class ImportZUGFeRDFiles
|
||||
|
||||
Private Const DIRECTORY_DONT_MOVE = "DIRECTORY_DONT_MOVE"
|
||||
|
||||
|
||||
' List of allowed extensions for PDF/A Attachments
|
||||
' This list should not contain xml so the zugferd xml file will be filtered out
|
||||
Private ReadOnly AllowedExtensions As List(Of String) = New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"}
|
||||
Private ReadOnly AllowedExtensions As New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"}
|
||||
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _zugferd As ZUGFeRDInterface
|
||||
Private ReadOnly _firebird As Firebird
|
||||
Private ReadOnly _filesystem As Filesystem.File
|
||||
Private ReadOnly _EmailOutAccountId As Integer
|
||||
Private ReadOnly _mssql As MSSQLServer
|
||||
Private ReadOnly _email As EmailFunctions
|
||||
Private ReadOnly _gdpictureLicenseKey As String
|
||||
|
||||
Private _zugferd As ZUGFeRDInterface
|
||||
Private _EmailOutAccountId As Integer
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Firebird As Firebird, pEmailOutAccount As Integer, pPortalName As String, Optional MSSQL As MSSQLServer = Nothing)
|
||||
Public Sub New(LogConfig As LogConfig, Firebird As Firebird, Optional MSSQL As MSSQLServer = Nothing)
|
||||
_logConfig = LogConfig
|
||||
_logger = LogConfig.GetLogger()
|
||||
_firebird = Firebird
|
||||
_filesystem = New Filesystem.File(_logConfig)
|
||||
_mssql = MSSQL
|
||||
_EmailOutAccountId = pEmailOutAccount
|
||||
_email = New EmailFunctions(LogConfig, _mssql, _firebird)
|
||||
|
||||
_logger.Debug("Registering GDPicture License")
|
||||
If _mssql IsNot Nothing Then
|
||||
Dim oSQL = "SELECT LICENSE FROM TBDD_3RD_PARTY_MODULES WHERE NAME = 'GDPICTURE'"
|
||||
Dim oLicenseKey As String = _mssql.GetScalarValue(oSQL)
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig, oLicenseKey)
|
||||
_gdpictureLicenseKey = _mssql.GetScalarValue(oSQL)
|
||||
Else
|
||||
_logger.Warn("GDPicture License could not be registered! MSSQL is not enabled!")
|
||||
Throw New ArgumentNullException("MSSQL")
|
||||
@ -125,6 +123,14 @@ Public Class ImportZUGFeRDFiles
|
||||
Dim oPropertyExtractor = New PropertyValues(_logConfig)
|
||||
Dim oAttachmentExtractor = New PDFEmbeds(_logConfig)
|
||||
|
||||
_EmailOutAccountId = oArgs.EmailOutProfileId
|
||||
|
||||
Dim oOptions As New ZUGFeRDInterface.ZugferdOptions() With {
|
||||
.AllowFacturX_Filename = oArgs.AllowFacturX,
|
||||
.AllowXRechnung_Filename = oArgs.AllowXRechnung
|
||||
}
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig, _gdpictureLicenseKey, oOptions)
|
||||
|
||||
_logger.Debug("Starting Job {0}", [GetType].Name)
|
||||
|
||||
Try
|
||||
@ -238,6 +244,10 @@ Public Class ImportZUGFeRDFiles
|
||||
oEmailAttachmentFiles.Add(oFile)
|
||||
Continue For
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.UnsupportedFormat
|
||||
_logger.Info("File [{0}] is an unsupported ZUFeRD document format!")
|
||||
Throw New UnsupportedFerdException()
|
||||
|
||||
Case ZUGFeRDInterface.ErrorType.NoValidZugferd
|
||||
_logger.Warn("File [{0}] is an Incorrectly formatted ZUGFeRD document!", oFile.Name)
|
||||
Throw New InvalidFerdException()
|
||||
@ -380,6 +390,18 @@ Public Class ImportZUGFeRDFiles
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "", oSQLTransaction)
|
||||
|
||||
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.
|
||||
Create_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but unsupported format", oFBTransaction)
|
||||
|
||||
Dim oBody = EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "UnsupportedFerdException", _EmailOutAccountId, oArgs.NamePortal)
|
||||
AddRejectedState(oMessageId, "UnsupportedFerdException", "Nicht unterstütztes Datenformat", "", oSQLTransaction)
|
||||
|
||||
Catch ex As InvalidFerdException
|
||||
_logger.Error(ex)
|
||||
|
||||
@ -14,10 +14,16 @@ Public Class WorkerArgs
|
||||
' Property Parameter
|
||||
Public PropertyMap As New Dictionary(Of String, XmlItemProperty)
|
||||
|
||||
' Email Parameter
|
||||
Public EmailOutProfileId As Integer = 0
|
||||
|
||||
' Misc Flag Parameters
|
||||
Public InsertIntoSQLServer As Boolean = False
|
||||
Public ExceptionEmailAddress As String = Nothing
|
||||
Public IgnoreRejectionStatus As Boolean = False
|
||||
Public MaxAttachmentSizeInMegaBytes As Integer = -1
|
||||
Public NamePortal As String = "NO PORTAL_NAME IN CONFIG"
|
||||
|
||||
Public AllowFacturX As Boolean = True
|
||||
Public AllowXRechnung As Boolean = True
|
||||
End Class
|
||||
Loading…
x
Reference in New Issue
Block a user