Interfaces: Rewrite ValidateZugferdDocument, add validation for invalid decimals

This commit is contained in:
Jonathan Jenne 2023-06-21 13:09:11 +02:00
parent a19123dd03
commit a05156a1a6

View File

@ -39,6 +39,7 @@ Public Class ZUGFeRDInterface
UnsupportedFormat
FileTooBig
UnknownError
ValidationFailed
End Enum
Public ReadOnly Property FileGroup As FileGroups
@ -54,6 +55,7 @@ Public Class ZUGFeRDInterface
Public Class ZugferdResult
Public Property DataFileName As String
Public Property XPathObject As XPathDocument
Public Property XElementObject As XElement
Public Property SchemaObject As Object
Public Property Specification As String
Public Property ValidationErrors As New List(Of ZugferdValidationError)
@ -246,13 +248,22 @@ Public Class ZUGFeRDInterface
End If
Try
Dim oXPathObject As XPathDocument = Nothing
Using oStream As New MemoryStream(oAllowedResult.FileContents)
Return New ZugferdResult With {
.DataFileName = oAllowedResult.FileName,
.XPathObject = New XPathDocument(oStream)
}
oXPathObject = New XPathDocument(oStream)
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
' 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.
@ -276,48 +287,67 @@ Public Class ZUGFeRDInterface
oNamespaceManager.AddNamespace("ram", "urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:12")
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
Try
Dim oCurrencyCodeIterator As XPathNodeIterator = oNavigator.
Select("//ram:InvoiceCurrencyCode | //ram:TaxCurrencyCode | //ram:TaxCurrencyCode | //ram:SourceCurrencyCode", oNamespaceManager)
Dim oCurrencyCodeNodes = pResult.XElementObject.Descendants().
Where(Function(n) n.Name.ToString.EndsWith("CurrencyCode"))
While oCurrencyCodeIterator.MoveNext()
Dim oNode As XPathNavigator = oCurrencyCodeIterator.Current
For Each oNode As XElement In oCurrencyCodeNodes
Dim oValid = ValidateCurrencyCode(oNode.Value)
If oValid = False Then
pResult.ValidationErrors.Add(New ZugferdValidationError() With {
.ElementName = oNode.Name,
.ElementName = oNode.Name.LocalName,
.ElementValue = oNode.Value,
.ErrorMessage = "Invalid CurrencyCode. Only 3-Character codes are allowed."
})
End If
End While
Next
Catch ex As Exception
_logger.Error(ex)
End Try
' currencyID
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()
Dim oNode As XPathNavigator = oCurrencyIDIterator.Current
Dim oCurrencyID As String = oNode.GetAttribute("currencyID", "")
For Each oNode As XElement In oCurrencyIDNodes
Dim oCurrencyID As String = oNode.Attribute("currencyID")?.Value
' CurrencyID is optional per spec
If String.IsNullOrWhiteSpace(oCurrencyID) Then
Continue While
Continue For
End If
Dim oValid = ValidateCurrencyCode(oCurrencyID)
If oValid = False Then
pResult.ValidationErrors.Add(New ZugferdValidationError() With {
.ElementName = oNode.Name,
.ElementName = oNode.Name.LocalName,
.ElementValue = oCurrencyID,
.ErrorMessage = "Invalid currencyID. Only 3-Character codes or empty values are allowed."
})
End If
End While
Next
Catch ex As Exception
_logger.Error(ex)
End Try