diff --git a/Interfaces/ZUGFeRDInterface.vb b/Interfaces/ZUGFeRDInterface.vb index 5031a5d9..f991b87d 100644 --- a/Interfaces/ZUGFeRDInterface.vb +++ b/Interfaces/ZUGFeRDInterface.vb @@ -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 + + ''' + ''' Create a new instance of ZUGFeRDInterface + ''' + ''' A LogConfig object + ''' A valid GDPicture License + ''' Optional parameters to control various settings + 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 + + ''' ''' Validates a ZUGFeRD File and extracts the XML Document from it ''' ''' ''' - ''' Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As Object Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path) @@ -59,7 +104,6 @@ Public Class ZUGFeRDInterface ''' ''' ''' - ''' Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As Object Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Stream) @@ -73,15 +117,15 @@ Public Class ZUGFeRDInterface ''' ''' Validates a ZUGFeRD File and extracts the XML Document from it ''' - ''' + ''' ''' - ''' - Public Function ValidateZUGFeRDFileWithGDPicture(Stream As Stream) As XPathDocument + ''' The embedded xml data as an XPath document + 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 + ''' + ''' Validates a ZUGFeRD File and extracts the XML Document from it + ''' + ''' + ''' + ''' The embedded xml data as an XPath document + 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 diff --git a/Interfaces/ZUGFeRDInterface/PDFEmbeds.vb b/Interfaces/ZUGFeRDInterface/PDFEmbeds.vb index b9143772..2385a93b 100644 --- a/Interfaces/ZUGFeRDInterface/PDFEmbeds.vb +++ b/Interfaces/ZUGFeRDInterface/PDFEmbeds.vb @@ -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 ''' List of allowed extensions to be extracted 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") diff --git a/Jobs/EDMI/ADSync/ADSyncArgs.vb b/Jobs/ADSync/ADSyncArgs.vb similarity index 100% rename from Jobs/EDMI/ADSync/ADSyncArgs.vb rename to Jobs/ADSync/ADSyncArgs.vb diff --git a/Jobs/EDMI/ADSync/ADSyncJob.vb b/Jobs/ADSync/ADSyncJob.vb similarity index 100% rename from Jobs/EDMI/ADSync/ADSyncJob.vb rename to Jobs/ADSync/ADSyncJob.vb diff --git a/Jobs/Exceptions.vb b/Jobs/Exceptions.vb index 17d69987..bdd4c341 100644 --- a/Jobs/Exceptions.vb +++ b/Jobs/Exceptions.vb @@ -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 diff --git a/Jobs/EDMI/GraphQL/GraphQLArgs.vb b/Jobs/GraphQL/GraphQLArgs.vb similarity index 100% rename from Jobs/EDMI/GraphQL/GraphQLArgs.vb rename to Jobs/GraphQL/GraphQLArgs.vb diff --git a/Jobs/EDMI/GraphQL/GraphQLConfig.vb b/Jobs/GraphQL/GraphQLConfig.vb similarity index 100% rename from Jobs/EDMI/GraphQL/GraphQLConfig.vb rename to Jobs/GraphQL/GraphQLConfig.vb diff --git a/Jobs/EDMI/GraphQL/GraphQLJob.vb b/Jobs/GraphQL/GraphQLJob.vb similarity index 100% rename from Jobs/EDMI/GraphQL/GraphQLJob.vb rename to Jobs/GraphQL/GraphQLJob.vb diff --git a/Jobs/EDMI/GraphQL/GraphQLQuery.vb b/Jobs/GraphQL/GraphQLQuery.vb similarity index 100% rename from Jobs/EDMI/GraphQL/GraphQLQuery.vb rename to Jobs/GraphQL/GraphQLQuery.vb diff --git a/Jobs/Jobs.vbproj b/Jobs/Jobs.vbproj index 90a55cd3..496f0acf 100644 --- a/Jobs/Jobs.vbproj +++ b/Jobs/Jobs.vbproj @@ -91,17 +91,17 @@ - - - - - - - - - - - + + + + + + + + + + + diff --git a/Jobs/EDMI/ZUGFeRD/EmailData.vb b/Jobs/ZUGFeRD/EmailData.vb similarity index 100% rename from Jobs/EDMI/ZUGFeRD/EmailData.vb rename to Jobs/ZUGFeRD/EmailData.vb diff --git a/Jobs/EDMI/ZUGFeRD/EmailFunctions.vb b/Jobs/ZUGFeRD/EmailFunctions.vb similarity index 100% rename from Jobs/EDMI/ZUGFeRD/EmailFunctions.vb rename to Jobs/ZUGFeRD/EmailFunctions.vb diff --git a/Jobs/EDMI/ZUGFeRD/EmailStrings.vb b/Jobs/ZUGFeRD/EmailStrings.vb similarity index 93% rename from Jobs/EDMI/ZUGFeRD/EmailStrings.vb rename to Jobs/ZUGFeRD/EmailStrings.vb index 3def7e00..b29e11ea 100644 --- a/Jobs/EDMI/ZUGFeRD/EmailStrings.vb +++ b/Jobs/ZUGFeRD/EmailStrings.vb @@ -37,4 +37,8 @@
  • Betrags-Werte weisen ungültiges Format auf (25,01 anstatt 25.01)
  • " + + Public Const EMAIL_UNSUPPORTED_DOCUMENT = " +

    Ihre Email enthielt ein ZUGFeRD Dokument, welches aber zur Zeit noch nicht unsterstützt wird.

    + " End Class diff --git a/Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb similarity index 95% rename from Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb rename to Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb index 11914534..cb09f2aa 100644 --- a/Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb +++ b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb @@ -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) diff --git a/Jobs/EDMI/ZUGFeRD/WorkerArgs.vb b/Jobs/ZUGFeRD/WorkerArgs.vb similarity index 84% rename from Jobs/EDMI/ZUGFeRD/WorkerArgs.vb rename to Jobs/ZUGFeRD/WorkerArgs.vb index 662f107f..a34a90b0 100644 --- a/Jobs/EDMI/ZUGFeRD/WorkerArgs.vb +++ b/Jobs/ZUGFeRD/WorkerArgs.vb @@ -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 \ No newline at end of file