diff --git a/Interfaces/ZUGFeRDInterface.vb b/Interfaces/ZUGFeRDInterface.vb
index 0c04fed8..4c10aa50 100644
--- a/Interfaces/ZUGFeRDInterface.vb
+++ b/Interfaces/ZUGFeRDInterface.vb
@@ -12,6 +12,13 @@ Public Class ZUGFeRDInterface
Private ReadOnly _logger As Logger
Private ReadOnly _Options As ZugferdOptions
+ ' These constants define the specification markers for the different
+ ' zugferd document schema versions. These markers need to be used to
+ ' define the property map in the database (column SPECIFICATION).
+ Public Const ZUGFERD_SPEC_DEFAULT = "DEFAULT"
+ Public Const ZUGFERD_SPEC_10 = "ZUGFERD_10"
+ Public Const ZUGFERD_SPEC_2x = "ZUGFERD_2x"
+
Private ReadOnly ValidFilenames As New List(Of String) From {
PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper,
PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper,
@@ -39,6 +46,13 @@ Public Class ZUGFeRDInterface
Public Property AllowZugferd_2_x_Schema As Boolean = True
End Class
+ Public Class ZugferdResult
+ Public Property DataFileName As String
+ Public Property XPathObject As XPathDocument
+ Public Property SchemaObject As Object
+ Public Property Specification As String
+ End Class
+
'''
''' Create a new instance of ZUGFeRDInterface
'''
@@ -91,14 +105,14 @@ Public Class ZUGFeRDInterface
'''
'''
'''
- Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As Tuple(Of String, Object)
- Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path)
+ Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As ZugferdResult
+ Dim oResult = ValidateZUGFeRDFileWithGDPicture(Path)
- If IsNothing(oXmlDocument.Item2) Then
+ If IsNothing(oResult.SchemaObject) Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
End If
- Return SerializeZUGFeRDDocument(oXmlDocument)
+ Return SerializeZUGFeRDDocument(oResult)
End Function
'''
@@ -106,14 +120,14 @@ Public Class ZUGFeRDInterface
'''
'''
'''
- Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As Tuple(Of String, Object)
- Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Stream)
+ Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As ZugferdResult
+ Dim oResult = ValidateZUGFeRDFileWithGDPicture(Stream)
- If IsNothing(oXmlDocument.Item2) Then
+ If IsNothing(oResult.SchemaObject) Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
End If
- Return SerializeZUGFeRDDocument(oXmlDocument)
+ Return SerializeZUGFeRDDocument(oResult)
End Function
'''
@@ -122,7 +136,7 @@ Public Class ZUGFeRDInterface
'''
'''
''' The embedded xml data as an XPath document
- Public Function ValidateZUGFeRDFileWithGDPicture(pStream As Stream) As Tuple(Of String, XPathDocument)
+ Public Function ValidateZUGFeRDFileWithGDPicture(pStream As Stream) As ZugferdResult
Dim oEmbedExtractor = New PDFEmbeds(_logConfig)
Try
@@ -150,7 +164,7 @@ Public Class ZUGFeRDInterface
'''
'''
''' The embedded xml data as an XPath document
- Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As Tuple(Of String, XPathDocument)
+ Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As ZugferdResult
Dim oEmbedExtractor = New PDFEmbeds(_logConfig)
Try
@@ -172,7 +186,7 @@ Public Class ZUGFeRDInterface
End Try
End Function
- Private Function HandleEmbeddedFiles(pResults As List(Of PDFEmbeds.EmbeddedFile)) As Tuple(Of String, XPathDocument)
+ Private Function HandleEmbeddedFiles(pResults As List(Of PDFEmbeds.EmbeddedFile)) As ZugferdResult
If pResults Is Nothing Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die Attachments nicht gelesen werden konnten.")
End If
@@ -202,7 +216,10 @@ Public Class ZUGFeRDInterface
Try
Using oStream As New MemoryStream(oAllowedResult.FileContents)
- Return New Tuple(Of String, XPathDocument)(oAllowedResult.FileName, New XPathDocument(oStream))
+ Return New ZugferdResult With {
+ .DataFileName = oAllowedResult.FileName,
+ .XPathObject = New XPathDocument(oStream)
+ }
End Using
Catch ex As ZUGFeRDExecption
@@ -216,37 +233,41 @@ Public Class ZUGFeRDInterface
End Try
End Function
- Public Function SerializeZUGFeRDDocument(pDocument As Tuple(Of String, XPathDocument)) As Tuple(Of String, Object)
+ Public Function SerializeZUGFeRDDocument(pResult As ZugferdResult) As ZugferdResult
Try
- Dim oNavigator As XPathNavigator = pDocument.Item2.CreateNavigator()
+ Dim oNavigator As XPathNavigator = pResult.XPathObject.CreateNavigator()
Dim oReader As XmlReader
- Dim oObject As Object = Nothing
- Dim oAllowedTypes As New List(Of Type)
+ Dim oObject As Object = Nothing
+ Dim oSpecification As String = Nothing
+
+ Dim oAllowedTypes As New Dictionary(Of String, Type)
If _Options.AllowZugferd_1_0_Schema Then
- oAllowedTypes.Add(GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType))
+ oAllowedTypes.Add(ZUGFERD_SPEC_10, GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType))
End If
If _Options.AllowZugferd_2_x_Schema Then
- oAllowedTypes.AddRange(New List(Of Type) From {
- GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType),
- GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType),
- GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType)
- })
+ oAllowedTypes.Add(ZUGFERD_SPEC_2x, GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType))
+ oAllowedTypes.Add(ZUGFERD_SPEC_2x, GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType))
+ oAllowedTypes.Add(ZUGFERD_SPEC_2x, GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType))
End If
For Each oType In oAllowedTypes
- _logger.Debug("Trying Type [{0}]", oType.FullName)
- Dim oSerializer As New XmlSerializer(oType)
+ Dim oTypeName As String = oType.Value.FullName
+ Dim oSerializer As New XmlSerializer(oType.Value)
+ _logger.Debug("Trying Type [{0}]", oTypeName)
Try
oReader = oNavigator.ReadSubtree()
+
oObject = oSerializer.Deserialize(oReader)
- _logger.Debug("Serializing with type [{0}] succeeded", oType.FullName)
+ oSpecification = oType.Key
+
+ _logger.Debug("Serializing with type [{0}] succeeded", oTypeName)
Exit For
Catch ex As Exception
- _logger.Debug("Serializing with type [{0}] failed", oType.FullName)
+ _logger.Debug("Serializing with type [{0}] failed", oTypeName)
_logger.Debug(ex.Message)
_logger.Error(ex.InnerException?.Message)
End Try
@@ -256,7 +277,10 @@ Public Class ZUGFeRDInterface
Throw New ApplicationException("No Types matched the given document. Document could not be serialized.")
End If
- Return New Tuple(Of String, Object)(pDocument.Item1, oObject)
+ pResult.Specification = oSpecification
+ pResult.SchemaObject = oObject
+
+ Return pResult
Catch ex As Exception
_logger.Error(ex)
diff --git a/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb b/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb
index a14c456e..672dcce0 100644
--- a/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb
+++ b/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb
@@ -1,8 +1,14 @@
Public Class XmlItemProperty
+ Public IsRequired As Boolean
+ Public IsGrouped As Boolean
+
Public TableName As String
Public TableColumn As String
Public Description As String
- Public IsRequired As Boolean
- Public IsGrouped As Boolean
Public GroupScope As String
+
+ '''
+ ''' Document version, eg. ZUGFeRD Schema version
+ '''
+ Public Specification As String
End Class
\ No newline at end of file
diff --git a/Jobs/Jobs.vbproj b/Jobs/Jobs.vbproj
index eb622bad..aa97236c 100644
--- a/Jobs/Jobs.vbproj
+++ b/Jobs/Jobs.vbproj
@@ -116,9 +116,9 @@
-
+
False
- ..\Interfaces\bin\Debug\DigitalData.Modules.Language.dll
+ ..\Language\bin\Debug\DigitalData.Modules.Language.dll
..\packages\FirebirdSql.Data.FirebirdClient.7.5.0\lib\net452\FirebirdSql.Data.FirebirdClient.dll
diff --git a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb
index 5c61659e..f8a0171b 100644
--- a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb
+++ b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb
@@ -206,7 +206,9 @@ Public Class ImportZUGFeRDFiles
' 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.
- Dim oDocument As Tuple(Of String, Object)
+ ' 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
' Start a global group counter for each file
Dim oGlobalGroupCounter = 0
@@ -283,7 +285,8 @@ Public Class ImportZUGFeRDFiles
' Check the document against the configured property map and return:
' - a List of valid properties
' - a List of missing properties
- Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument, oArgs.PropertyMap, oMessageId)
+ Dim oPropertyMap = GetPropertyMapFor(oArgs, oDocument)
+ 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)
@@ -398,7 +401,6 @@ Public Class ImportZUGFeRDFiles
' That 's why we set it to String.Empty here.
Create_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but unsupported format", oFBTransaction)
- Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, ex.XmlFile)
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, oEmailData.Subject, ex.XmlFile)
@@ -412,7 +414,6 @@ Public Class ImportZUGFeRDFiles
' That 's why we set it to String.Empty here.
Create_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but incorrect format", oFBTransaction)
- Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
Dim oBody = String.Format(EmailStrings.EMAIL_INVALID_DOCUMENT, oEmailData.Subject)
@@ -424,7 +425,6 @@ Public Class ImportZUGFeRDFiles
Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - More than one ZUGFeRD-document in email", oFBTransaction)
- Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
Dim oBody = String.Format(EmailStrings.EMAIL_TOO_MUCH_FERDS, oEmailData.Subject)
@@ -436,7 +436,6 @@ Public Class ImportZUGFeRDFiles
Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - no ZUGFeRD-Document in email", oFBTransaction)
- Dim oBody = EmailStrings.EMAIL_NO_FERDS
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
Dim oBody = String.Format(EmailStrings.EMAIL_NO_FERDS, oEmailData.Subject)
@@ -584,6 +583,26 @@ Public Class ImportZUGFeRDFiles
End Try
End Sub
+ Private Function GetPropertyMapFor(pWorkerArgs As WorkerArgs, pSpecification As String) As Dictionary(Of String, XmlItemProperty)
+ Dim oPropertyMap = DoGetPropertyMapFor(pWorkerArgs, pSpecification)
+
+ _logger.Debug("Found [{0}] Properties for Specification [{1}].", oPropertyMap.Count, pSpecification)
+
+ ' If no properties were found, fall back to the default specification before giving up
+ If oPropertyMap.Count = 0 Then
+ _logger.Warn("No Properties found for Specification [{0}]. Loading default property map!", pSpecification)
+ Return DoGetPropertyMapFor(pWorkerArgs, ZUGFeRDInterface.ZUGFERD_SPEC_DEFAULT)
+ End If
+
+ Return oPropertyMap
+ End Function
+
+ Private Function DoGetPropertyMapFor(pWorkerArgs As WorkerArgs, pSpecification As String) As Dictionary(Of String, XmlItemProperty)
+ Return pWorkerArgs.PropertyMap.
+ Where(Function(kv) kv.Value.Specification = pSpecification).
+ ToDictionary(Function(kv) kv.Key, Function(kv) kv.Value)
+ End Function
+
Private Sub MoveFiles(
Args As WorkerArgs,
MessageId As String,