This commit is contained in:
Developer01
2026-09-17 12:35:49 +02:00
7 changed files with 3620 additions and 16 deletions

View File

@@ -265,6 +265,7 @@
<Compile Include="GrapQLInterface\LoginData.vb" /> <Compile Include="GrapQLInterface\LoginData.vb" />
<Compile Include="GrapQLInterface\LogoutData.vb" /> <Compile Include="GrapQLInterface\LogoutData.vb" />
<Compile Include="GrapQLInterface\QueryData.vb" /> <Compile Include="GrapQLInterface\QueryData.vb" />
<Compile Include="ZUGFeRDInterface\ebInterface6.1\InvoiceType.vb" />
<Compile Include="ZUGFeRDInterface\Enums\ErrorCodes.vb" /> <Compile Include="ZUGFeRDInterface\Enums\ErrorCodes.vb" />
<Compile Include="ZUGFeRDInterface\Enums\Item_Types.vb" /> <Compile Include="ZUGFeRDInterface\Enums\Item_Types.vb" />
<Compile Include="ZUGFeRDInterface\Exceptions.vb" /> <Compile Include="ZUGFeRDInterface\Exceptions.vb" />

View File

@@ -3,6 +3,7 @@ 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.PDFEmbeds
Imports DigitalData.Modules.Interfaces.PropertyValues
Imports DigitalData.Modules.Interfaces.ZUGFeRD Imports DigitalData.Modules.Interfaces.ZUGFeRD
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
Imports GdPicture14 Imports GdPicture14
@@ -21,8 +22,6 @@ Public Class ZUGFeRDInterface
Public Const ZUGFERD_SPEC_2x = "ZUGFERD_2x" Public Const ZUGFERD_SPEC_2x = "ZUGFERD_2x"
Public Const ZUGFERD_SPEC_2_3x = "ZUGFERD_2_3x" Public Const ZUGFERD_SPEC_2_3x = "ZUGFERD_2_3x"
Public Const UBL_SPEC_21 = "UBL_21"
Public Const XMLSCHEMA_ZUGFERD_10 = "Version1_0" Public Const XMLSCHEMA_ZUGFERD_10 = "Version1_0"
Public Const XMLSCHEMA_ZUGFERD_20 = "Version2_0" Public Const XMLSCHEMA_ZUGFERD_20 = "Version2_0"
Public Const XMLSCHEMA_ZUGFERD_211 = "Version2_1_1" Public Const XMLSCHEMA_ZUGFERD_211 = "Version2_1_1"
@@ -31,9 +30,14 @@ Public Class ZUGFeRDInterface
Public Const XMLSCHEMA_ZUGFERD_233 = "Version2_3_3_FacturX" Public Const XMLSCHEMA_ZUGFERD_233 = "Version2_3_3_FacturX"
Public Const XMLSCHEMA_ZUGFERD_24 = "Version2_4_FacturX" Public Const XMLSCHEMA_ZUGFERD_24 = "Version2_4_FacturX"
Public Const XMLSCHEMA_ZUGFERD_25 = "Version2_5_FacturX" Public Const XMLSCHEMA_ZUGFERD_25 = "Version2_5_FacturX"
Public Const UBL_SPEC_21 = "UBL_21"
Public Const XMLSCHEMA_UBL_21_INVOICE = "UBL2_1_INVOICE" Public Const XMLSCHEMA_UBL_21_INVOICE = "UBL2_1_INVOICE"
Public Const XMLSCHEMA_UBL_21_CREDITNOTE = "UBL2_1_CREDITNOTE" Public Const XMLSCHEMA_UBL_21_CREDITNOTE = "UBL2_1_CREDITNOTE"
Public Const EBINTERFACE_SPEC_61 = "EBINTERFACE_61"
Public Const XMLSCHEMA_EBINTERFACE_61 = "Version6_1"
Public Const RECEIPT_TYPE_XML = "XML" Public Const RECEIPT_TYPE_XML = "XML"
Public Const RECEIPT_TYPE_PDF = "PDF" Public Const RECEIPT_TYPE_PDF = "PDF"
@@ -67,6 +71,7 @@ Public Class ZUGFeRDInterface
Public Property AllowZugferd_2_x_Schema As Boolean = True Public Property AllowZugferd_2_x_Schema As Boolean = True
Public Property AllowZugferd_2_3_x_Schema As Boolean = True Public Property AllowZugferd_2_3_x_Schema As Boolean = True
Public Property AllowPeppol_3_x_Schema As Boolean = False Public Property AllowPeppol_3_x_Schema As Boolean = False
Public Property AllowEBInterface_Schema As Boolean = False
End Class End Class
Public Class ZugferdResult Public Class ZugferdResult
@@ -152,6 +157,20 @@ Public Class ZUGFeRDInterface
Where(Function(kv) kv.Specification = pSpecification Or kv.Specification = ZUGFERD_SPEC_DEFAULT). Where(Function(kv) kv.Specification = pSpecification Or kv.Specification = ZUGFERD_SPEC_DEFAULT).
ToDictionary(Function(kv) kv.XMLPath, Function(kv) kv) ToDictionary(Function(kv) kv.XMLPath, Function(kv) kv)
Catch ex As Exception
_logger.Error(ex)
End Try
ElseIf pSpecification = EBINTERFACE_SPEC_61 Then
Try
' root-Elemente werden hier herausgefiltert
Dim countElements As Integer = pPropertyMapList.Where(Function(x) x.Specification = pSpecification And Not x.XMLPath.StartsWith("root.")).Count
_logger.Debug("Property map list contains [{0}] elements for specification [{1}]", countElements, pSpecification)
Return pPropertyMapList.
Where(Function(kv) kv.Specification = pSpecification And Not kv.XMLPath.StartsWith("root.")).
ToDictionary(Function(kv) kv.XMLPath, Function(kv) kv)
Catch ex As Exception Catch ex As Exception
_logger.Error(ex) _logger.Error(ex)
End Try End Try
@@ -174,6 +193,28 @@ Public Class ZUGFeRDInterface
Return Nothing Return Nothing
End Function End Function
Public Function FilterRootPropertyMap(pPropertyMapList As List(Of XmlItemProperty), pSpecification As String) As Dictionary(Of String, XmlItemProperty)
' Aktuell verwendet nur ebeInterafce attribute im root-Knoten
If pSpecification = EBINTERFACE_SPEC_61 Then
Try
' root-Elemente werden hier herausgefiltert
Dim countElements As Integer = pPropertyMapList.Where(Function(x) x.Specification = pSpecification And x.XMLPath.StartsWith("root.")).Count
_logger.Debug("Property map list contains [{0}] root attribute elements for specification [{1}]", countElements, pSpecification)
Return pPropertyMapList.
Where(Function(kv) kv.Specification = pSpecification And kv.XMLPath.StartsWith("root.")).
ToDictionary(Function(kv) kv.XMLPath, Function(kv) kv)
Catch ex As Exception
_logger.Error(ex)
End Try
Else
Return Nothing
End If
End Function
Public Function GetSerializedXMLContentFromFile(oFileInfo As FileInfo) As ZugferdResult Public Function GetSerializedXMLContentFromFile(oFileInfo As FileInfo) As ZugferdResult
Dim oResult = New ZugferdResult() Dim oResult = New ZugferdResult()
Dim oMessage As String = String.Empty Dim oMessage As String = String.Empty
@@ -455,6 +496,16 @@ Public Class ZUGFeRDInterface
}) })
End If End If
If _Options.AllowEBInterface_Schema Then
oAllowedTypes.AddRange(New List(Of AllowedType) From {
New AllowedType With {
.SchemaType = GetType(EBINTERFACE_61.InvoiceType),
.Specification = EBINTERFACE_SPEC_61,
.XMLSchema = XMLSCHEMA_EBINTERFACE_61
}
})
End If
For Each oType In oAllowedTypes For Each oType In oAllowedTypes
Dim oTypeName As String = oType.SchemaType.FullName Dim oTypeName As String = oType.SchemaType.FullName
Dim oSerializer As New XmlSerializer(oType.SchemaType) Dim oSerializer As New XmlSerializer(oType.SchemaType)
@@ -497,4 +548,5 @@ Public Class ZUGFeRDInterface
Throw New ZUGFeRDExecption(ErrorCodes.UnsupportedFerdException, oMessage) Throw New ZUGFeRDExecption(ErrorCodes.UnsupportedFerdException, oMessage)
End Try End Try
End Function End Function
End Class End Class

View File

@@ -1,8 +1,8 @@
Public Enum Item_Types Public Enum Item_Types
StringType '0 StringType = 0 '0
DateType '1 DateType = 1 '1
MoneyType '2 MoneyType = 2 '2
FileType '3 FileType = 3 '3
ListType '4 - vgl. Währung ListType = 4 '4 - vgl. Währung
End Enum End Enum

View File

@@ -1,7 +1,9 @@
Imports System.Globalization Imports System.Globalization
Imports System.Reflection Imports System.Reflection
Imports System.Text.RegularExpressions Imports System.Text.RegularExpressions
Imports System.Xml
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
Imports GdPicture.Internal.MSOfficeBinary.translator.Tools
Public Class PropertyValues Public Class PropertyValues
Private _logger As Logger Private _logger As Logger
@@ -122,12 +124,13 @@ Public Class PropertyValues
' Returns nothing if oColumn.Value contains an empty list ' Returns nothing if oColumn.Value contains an empty list
Dim oPropertyValue = oColumn.Value.ElementAtOrDefault(oRowIndex) Dim oPropertyValue = oColumn.Value.ElementAtOrDefault(oRowIndex)
_logger.Debug("Processing itemColumn *TableColumn* [{0}].", oTableColumn) '_logger.Debug("Processing itemColumn *TableColumn* [{0}].", oTableColumn)
If oTableColumn = "INVOICE_SELLER_EMAIL" Then 'If oTableColumn = "INVOICE_SELLER_EMAIL" Then
Console.WriteLine("INVOICE_SELLER_EMAIL") ' Console.WriteLine("INVOICE_SELLER_EMAIL")
ElseIf oTableColumn = "INVOICE_POSITION_ARTICLE" Then 'ElseIf oTableColumn = "INVOICE_POSITION_ARTICLE" Then
Console.WriteLine("INVOICE_POSITION_ARTICLE") ' Console.WriteLine("INVOICE_POSITION_ARTICLE")
End If 'End If
If IsNothing(oPropertyValue) OrElse String.IsNullOrEmpty(oPropertyValue) Then If IsNothing(oPropertyValue) OrElse String.IsNullOrEmpty(oPropertyValue) Then
If oColumn.Key.IsRequired Then If oColumn.Key.IsRequired Then
_logger.Warn($"{MessageId} - oPropertyValue for column [{oTableColumn}] is empty or not found but is required. Continuing with Empty String.") _logger.Warn($"{MessageId} - oPropertyValue for column [{oTableColumn}] is empty or not found but is required. Continuing with Empty String.")
@@ -154,7 +157,11 @@ Public Class PropertyValues
End If End If
If oTableColumn = "INVOICE_CURRENCY" Or oItemType = 4 Then If oItemType = Item_Types.MoneyType Then
oPropertyValue = GetFormattedDecimalValue(oPropertyValue)
End If
If oTableColumn = "INVOICE_CURRENCY" Or oItemType = Item_Types.ListType Then
Dim oValuestring = oPropertyValue.ToString() Dim oValuestring = oPropertyValue.ToString()
' Bei Listenelementen entfernen wir den String Item, um den Wert zu erhalten ' Bei Listenelementen entfernen wir den String Item, um den Wert zu erhalten
@@ -247,8 +254,12 @@ Public Class PropertyValues
End If End If
End If End If
If oItemType = Item_Types.MoneyType Then
oPropertyValue = GetFormattedDecimalValue(oPropertyValue)
End If
' Statt dem Zahlenwert des Enums, wollen wir die Währungsbezeichnung ' Statt dem Zahlenwert des Enums, wollen wir die Währungsbezeichnung
If oTableColumn = "INVOICE_CURRENCY" Or oItemType = 4 Then If oTableColumn = "INVOICE_CURRENCY" Or oItemType = Item_Types.ListType Then
Dim oValuestring = oPropertyValue.ToString() Dim oValuestring = oPropertyValue.ToString()
' Bei Listenelementen entfernen wir den String Item, um den Wert zu erhalten ' Bei Listenelementen entfernen wir den String Item, um den Wert zu erhalten
@@ -275,6 +286,167 @@ Public Class PropertyValues
Return oResult Return oResult
End Function End Function
Private Function GetFormattedDecimalValue(pPropertyValue As Object) As Object
' wir versuchen den gefundenen Wert in einen decimal mit 2 Nachommastellen umzuwandeln
' Eingaben können mit . oder mit , als Dezimal-Trenner kommen: 19.00 = 19,00
If IsNothing(pPropertyValue) OrElse String.IsNullOrEmpty(pPropertyValue) Then
Return String.Empty
End If
Try
Dim stringValue = pPropertyValue.ToString()
Dim deCulture As New CultureInfo("de-DE")
Dim usCulture As New CultureInfo("en-US")
Dim decimalValue As Decimal
If stringValue.Contains(".") AndAlso Not stringValue.Contains(",") Then
' Wir wandeln mit en-US um
If Decimal.TryParse(pPropertyValue, NumberStyles.Any, usCulture, decimalValue) Then
decimalValue = Math.Round(decimalValue, 2)
pPropertyValue = decimalValue.ToString("F2", CultureInfo.InvariantCulture)
End If
ElseIf stringValue.Contains(",") AndAlso Not stringValue.Contains(".") Then
' Wir wandeln mit de-DE um, wenn Komma als Trennzeichen enthalten ist
If Decimal.TryParse(pPropertyValue, NumberStyles.Any, deCulture, decimalValue) Then
decimalValue = Math.Round(decimalValue, 2)
pPropertyValue = decimalValue.ToString("F2", CultureInfo.InvariantCulture)
End If
ElseIf Not stringValue.Contains(",") AndAlso Not stringValue.Contains(".") Then
' Wir wandeln mit en-US um, wenn KEIN Trennzeichen enthalten ist
If Decimal.TryParse(pPropertyValue, NumberStyles.Any, usCulture, decimalValue) Then
decimalValue = Math.Round(decimalValue, 2)
pPropertyValue = decimalValue.ToString("F2", CultureInfo.InvariantCulture)
End If
End If
Return pPropertyValue
Catch ex As Exception
_logger.Error(ex)
Return Nothing
End Try
End Function
Public Function CheckRootAttributeValues(pDocument As Object, pPropertyMap As Dictionary(Of String, XmlItemProperty), pMessageId As String, pCheckResult As CheckPropertyValuesResult) As CheckPropertyValuesResult
If pPropertyMap Is Nothing Then
Return pCheckResult
End If
' PropertyMap items with `IsGrouped = False` are handled normally
Dim oRootAttributeProperties As Dictionary(Of String, XmlItemProperty) = pPropertyMap.
ToDictionary(Function(Item) Item.Key,
Function(Item) Item.Value)
For Each oItem As KeyValuePair(Of String, XmlItemProperty) In oRootAttributeProperties
Dim oTableColumn As String = oItem.Value.TableColumn
Dim oPropertyDescription As String = oItem.Value.Description
Dim oPropertyPath As String = oItem.Value.XMLPath
Dim oPropertyValue As Object = Nothing
Dim oTableName = oItem.Value.TableName
Dim oIsRequired = oItem.Value.IsRequired
Dim oDescription = oItem.Value.Description
Dim oItemType = oItem.Value.ItemType
Dim oEN16931_ID = oItem.Value.EN16931_ID
Try
oPropertyValue = GetRootAttributeValue(pDocument, oItem.Key)
Catch ex As Exception
_logger.Error(ex)
oPropertyValue = Nothing
End Try
If IsNothing(oPropertyValue) OrElse String.IsNullOrEmpty(oPropertyValue) Then
If oItem.Value.IsRequired Then
_logger.Warn("Column [{0}] is empty, but marked as required! Adding MissingProperty.", oTableColumn)
Dim oMissingProperty = New MissingProperty With
{
.EN16931_ID = oEN16931_ID,
.Description = oPropertyDescription,
.XMLPath = oPropertyPath
}
pCheckResult.MissingProperties.Add(oMissingProperty)
Continue For
Else
_logger.Debug("oPropertyValue for Column [{0}] is empty or not found. Skipping.", oTableColumn)
Continue For
End If
End If
If pDocument.Specification = "EBINTERFACE_61" Then
' ebInterface DocumentType in UNTDID 1001 — Document type
If oTableColumn = "INVOICE_TYPE" Then
oPropertyValue = GetUNTDID1001_DocumentType(oPropertyValue)
_logger.Debug("oPropertyValue for Column [{0}] in EBINTERFACE_61 with value [{1}] ", oTableColumn, oPropertyValue)
End If
End If
pCheckResult.ValidProperties.Add(New ValidProperty() With {
.MessageId = pMessageId,
.Description = oPropertyDescription,
.Value = oPropertyValue,
.GroupCounter = 0,
.TableName = oTableName,
.TableColumn = oTableColumn,
.IsRequired = oIsRequired,
.XMLPath = oPropertyPath,
.ItemType = oItemType,
.EN16931_ID = oEN16931_ID
})
Next
Return pCheckResult
End Function
Private Function GetUNTDID1001_DocumentType(oPropertyValue As String) As String
Select Case oPropertyValue
Case "CreditMemo"
Return 381 ' Credit note
Case "FinalSettlement"
Return 877 ' Final construction invoice
Case "Invoice"
Return 380 ' Commercial invoice
Case "InvoiceForAdvancePayment"
Return 386 ' Prepayment invoice
Case "InvoiceForPartialDelivery"
Return 381 ' Partial invoice
Case "SelfBilling"
Return 261 ' Self billed credit note
Case "SubsequentCredit"
Return 83 ' Credit note related to financial adjustments
Case "SubsequentDebit"
Return 84 ' Debit note related to financial adjustments
Case Else
Return 0
End Select
End Function
Private Function GetRootAttributeValue(pDocument As Object, pXmlPath As String) As String
If pDocument.XElementObject Is Nothing Then
Return Nothing
End If
Try
Dim attributeName As String = pXmlPath.Replace("root.", "")
Dim attributeValue As String = pDocument.XElementObject.Attribute(attributeName).Value
Return attributeValue
Catch ex As Exception
_logger.Error(ex)
Return Nothing
End Try
End Function
Public Function GetPropValue(Obj As Object, PropertyName As String) As List(Of Object) Public Function GetPropValue(Obj As Object, PropertyName As String) As List(Of Object)
Dim oNameParts As String() = PropertyName.Split("."c) Dim oNameParts As String() = PropertyName.Split("."c)

File diff suppressed because it is too large Load Diff

View File

@@ -120,7 +120,8 @@ Public Class ImportZUGFeRDFiles
_zugferd = New ZUGFeRDInterface(_logConfig, _gdpictureLicenseKey, New ZUGFeRDInterface.ZugferdOptions() With { _zugferd = New ZUGFeRDInterface(_logConfig, _gdpictureLicenseKey, New ZUGFeRDInterface.ZugferdOptions() With {
.AllowFacturX_Filename = oArgs.AllowFacturX, .AllowFacturX_Filename = oArgs.AllowFacturX,
.AllowXRechnung_Filename = oArgs.AllowXRechnung, .AllowXRechnung_Filename = oArgs.AllowXRechnung,
.AllowPeppol_3_x_Schema = oArgs.AllowPeppolBISBill3x .AllowPeppol_3_x_Schema = oArgs.AllowPeppolBISBill3x,
.AllowEBInterface_Schema = oArgs.AllowEBInterface
}) })
_logger.Debug("Starting Job {0}", [GetType].Name) _logger.Debug("Starting Job {0}", [GetType].Name)
@@ -719,6 +720,10 @@ Public Class ImportZUGFeRDFiles
Dim oPropertyMap As Dictionary(Of String, XmlItemProperty) = _zugferd.FilterPropertyMap(pArgs.PropertyMapList, pDocument.Specification) Dim oPropertyMap As Dictionary(Of String, XmlItemProperty) = _zugferd.FilterPropertyMap(pArgs.PropertyMapList, pDocument.Specification)
Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(pDocument.SchemaObject, oPropertyMap, pMessageId) Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(pDocument.SchemaObject, oPropertyMap, pMessageId)
' root-Attribute falls konfiguriert auslesen, Ergebnis im oCheckResult enthalten
Dim oRootAttributePropertyMap As Dictionary(Of String, XmlItemProperty) = _zugferd.FilterRootPropertyMap(pArgs.PropertyMapList, pDocument.Specification)
oCheckResult = _zugferd.PropertyValues.CheckRootAttributeValues(pDocument, oRootAttributePropertyMap, pMessageId, oCheckResult)
_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

View File

@@ -33,5 +33,6 @@ Public Class WorkerArgs
Public AllowZugferd2x As Boolean = True Public AllowZugferd2x As Boolean = True
Public AllowZugferd23x As Boolean = True Public AllowZugferd23x As Boolean = True
Public AllowPeppolBISBill3x As Boolean = False Public AllowPeppolBISBill3x As Boolean = False
Public AllowEBInterface As Boolean = False
End Class End Class