3 Commits

Author SHA1 Message Date
Jonathan Jenne
0da1eb55a9 Interfaces: Version 1.11.0.0 2023-06-21 13:10:16 +02:00
Jonathan Jenne
18b0d4cdaf Jobs: Fix zugferd email string typo 2023-06-21 13:09:32 +02:00
Jonathan Jenne
a05156a1a6 Interfaces: Rewrite ValidateZugferdDocument, add validation for invalid decimals 2023-06-21 13:09:11 +02:00
3 changed files with 51 additions and 21 deletions

View File

@@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices
<Assembly: AssemblyCompany("Digital Data")> <Assembly: AssemblyCompany("Digital Data")>
<Assembly: AssemblyProduct("Modules.Interfaces")> <Assembly: AssemblyProduct("Modules.Interfaces")>
<Assembly: AssemblyCopyright("Copyright © 2023")> <Assembly: AssemblyCopyright("Copyright © 2023")>
<Assembly: AssemblyTrademark("1.10.5.1")> <Assembly: AssemblyTrademark("1.11.0.0")>
<Assembly: ComVisible(False)> <Assembly: ComVisible(False)>
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
' übernehmen, indem Sie "*" eingeben: ' übernehmen, indem Sie "*" eingeben:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.10.5.1")> <Assembly: AssemblyVersion("1.11.0.0")>
<Assembly: AssemblyFileVersion("1.10.5.1")> <Assembly: AssemblyFileVersion("1.11.0.0")>

View File

@@ -39,6 +39,7 @@ Public Class ZUGFeRDInterface
UnsupportedFormat UnsupportedFormat
FileTooBig FileTooBig
UnknownError UnknownError
ValidationFailed
End Enum End Enum
Public ReadOnly Property FileGroup As FileGroups Public ReadOnly Property FileGroup As FileGroups
@@ -54,6 +55,7 @@ Public Class ZUGFeRDInterface
Public Class ZugferdResult Public Class ZugferdResult
Public Property DataFileName As String Public Property DataFileName As String
Public Property XPathObject As XPathDocument Public Property XPathObject As XPathDocument
Public Property XElementObject As XElement
Public Property SchemaObject As Object Public Property SchemaObject As Object
Public Property Specification As String Public Property Specification As String
Public Property ValidationErrors As New List(Of ZugferdValidationError) Public Property ValidationErrors As New List(Of ZugferdValidationError)
@@ -246,13 +248,22 @@ Public Class ZUGFeRDInterface
End If End If
Try Try
Dim oXPathObject As XPathDocument = Nothing
Using oStream As New MemoryStream(oAllowedResult.FileContents) Using oStream As New MemoryStream(oAllowedResult.FileContents)
Return New ZugferdResult With { oXPathObject = New XPathDocument(oStream)
.DataFileName = oAllowedResult.FileName,
.XPathObject = New XPathDocument(oStream)
}
End Using End Using
Dim oXElementObject As XElement = Nothing
Using oStream As New MemoryStream(oAllowedResult.FileContents)
oXElementObject = XElement.Load(oStream)
End Using
Return New ZugferdResult With {
.DataFileName = oAllowedResult.FileName,
.XElementObject = oXElementObject,
.XPathObject = oXPathObject
}
Catch ex As ZUGFeRDExecption Catch ex As ZUGFeRDExecption
' Don't log ZUGFeRD Exceptions here, they should be handled by the calling code. ' 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. ' It also produces misleading error messages when checking if an attachment is a zugferd file.
@@ -276,48 +287,67 @@ Public Class ZUGFeRDInterface
oNamespaceManager.AddNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12") oNamespaceManager.AddNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12")
oNamespaceManager.AddNamespace("rsm", "urn:ferd:CrossIndustryDocument:invoice:1p0") oNamespaceManager.AddNamespace("rsm", "urn:ferd:CrossIndustryDocument:invoice:1p0")
Try
Dim oDecimalNodes = pResult.XElementObject.Descendants().
Where(Function(n) n.Name.ToString.EndsWith("Amount") Or n.Name.ToString.EndsWith("Percent"))
For Each oNode As XElement In oDecimalNodes
Dim oParsedValue As Decimal = 0.0
If Decimal.TryParse(oNode.Value, oParsedValue) = False Then
pResult.ValidationErrors.Add(New ZugferdValidationError() With {
.ElementName = oNode.Name.LocalName,
.ElementValue = oNode.Value,
.ErrorMessage = "Value could not be parsed as Decimal"
})
End If
Next
Catch ex As Exception
_logger.Error(ex)
End Try
' CurrencyCode Nodes ' CurrencyCode Nodes
Try Try
Dim oCurrencyCodeIterator As XPathNodeIterator = oNavigator. Dim oCurrencyCodeNodes = pResult.XElementObject.Descendants().
Select("//ram:InvoiceCurrencyCode | //ram:TaxCurrencyCode | //ram:TaxCurrencyCode | //ram:SourceCurrencyCode", oNamespaceManager) Where(Function(n) n.Name.ToString.EndsWith("CurrencyCode"))
While oCurrencyCodeIterator.MoveNext() For Each oNode As XElement In oCurrencyCodeNodes
Dim oNode As XPathNavigator = oCurrencyCodeIterator.Current
Dim oValid = ValidateCurrencyCode(oNode.Value) Dim oValid = ValidateCurrencyCode(oNode.Value)
If oValid = False Then If oValid = False Then
pResult.ValidationErrors.Add(New ZugferdValidationError() With { pResult.ValidationErrors.Add(New ZugferdValidationError() With {
.ElementName = oNode.Name, .ElementName = oNode.Name.LocalName,
.ElementValue = oNode.Value, .ElementValue = oNode.Value,
.ErrorMessage = "Invalid CurrencyCode. Only 3-Character codes are allowed." .ErrorMessage = "Invalid CurrencyCode. Only 3-Character codes are allowed."
}) })
End If End If
End While Next
Catch ex As Exception Catch ex As Exception
_logger.Error(ex) _logger.Error(ex)
End Try End Try
' currencyID ' currencyID
Try Try
Dim oCurrencyIDIterator As XPathNodeIterator = oNavigator.Select("//*[@currencyID]") Dim oCurrencyIDNodes = pResult.XElementObject.Descendants().
Where(Function(n) n.Attributes.Any(Function(a) a.Name.LocalName = "currencyID"))
While oCurrencyIDIterator.MoveNext() For Each oNode As XElement In oCurrencyIDNodes
Dim oNode As XPathNavigator = oCurrencyIDIterator.Current Dim oCurrencyID As String = oNode.Attribute("currencyID")?.Value
Dim oCurrencyID As String = oNode.GetAttribute("currencyID", "")
' CurrencyID is optional per spec ' CurrencyID is optional per spec
If String.IsNullOrWhiteSpace(oCurrencyID) Then If String.IsNullOrWhiteSpace(oCurrencyID) Then
Continue While Continue For
End If End If
Dim oValid = ValidateCurrencyCode(oCurrencyID) Dim oValid = ValidateCurrencyCode(oCurrencyID)
If oValid = False Then If oValid = False Then
pResult.ValidationErrors.Add(New ZugferdValidationError() With { pResult.ValidationErrors.Add(New ZugferdValidationError() With {
.ElementName = oNode.Name, .ElementName = oNode.Name.LocalName,
.ElementValue = oCurrencyID, .ElementValue = oCurrencyID,
.ErrorMessage = "Invalid currencyID. Only 3-Character codes or empty values are allowed." .ErrorMessage = "Invalid currencyID. Only 3-Character codes or empty values are allowed."
}) })
End If End If
End While Next
Catch ex As Exception Catch ex As Exception
_logger.Error(ex) _logger.Error(ex)
End Try End Try

View File

@@ -38,7 +38,7 @@
Public Const EMAIL_INVALID_DOCUMENT = " Public Const EMAIL_INVALID_DOCUMENT = "
<p>Ihre Email ({0}) enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.</p> <p>Ihre Email ({0}) enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.</p>
<p>Mögliche Gründe für ein inkorrektes Format:<ul> <p>Mögliche Gründe für ein inkorrektes Format:<ul>
<li>Betrags-Werte weisen ungültiges Format auf (25,01 anstatt 25.01)</li> <li>Betrags-Werte weisen ungültiges Format auf (z.B. 25,01 anstatt 25.01)</li>
</ul></p> </ul></p>
" "