Improve Error handling across the board
This commit is contained in:
@@ -65,22 +65,13 @@ Namespace Documents
|
||||
Logger.Debug("Found [{0}] files in directory [{1}]", oFiles.Count, oDirectory)
|
||||
|
||||
For Each oFile In oFiles
|
||||
Try
|
||||
Dim oDocument = Await LoadFile(oFile, pTemplate, pMandator)
|
||||
Files.Add(oDocument)
|
||||
FilesLoaded = Files.Count
|
||||
Logger.Info("Loading file [{0}]", oFile.Name)
|
||||
Dim oDocument = Await LoadFile(oFile, pTemplate, pMandator)
|
||||
Files.Add(oDocument)
|
||||
FilesLoaded = Files.Count
|
||||
|
||||
Dim oInfo As New FileLoadInfo(FilesTotal, FilesLoaded)
|
||||
RaiseEvent FileLoadComplete(Me, oInfo)
|
||||
|
||||
Catch ex As MissingAttributeException
|
||||
Logger.Error(ex)
|
||||
Throw New DocumentLoaderException($"Missing Attribute '{ex.Message}' in File '{oFile.Name}'")
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
Dim oInfo As New FileLoadInfo(FilesTotal, FilesLoaded)
|
||||
RaiseEvent FileLoadComplete(Me, oInfo)
|
||||
Next
|
||||
|
||||
Return True
|
||||
@@ -93,20 +84,52 @@ Namespace Documents
|
||||
End Function
|
||||
|
||||
Public Async Function LoadFile(pFileInfo As FileInfo, pTemplate As Template, pMandator As Mandator) As Task(Of Document)
|
||||
Dim oFileList As New List(Of FileInfo) From {pFileInfo}
|
||||
Logger.Info("Loading file [{0}]", pFileInfo.Name)
|
||||
Logger.Debug("Creating new Document object for file [{0}]", pFileInfo.Name)
|
||||
Dim oDocument As Document = New Document With {
|
||||
.File = pFileInfo,
|
||||
.Schema = pTemplate
|
||||
}
|
||||
|
||||
Try
|
||||
Return Await oFileList.
|
||||
Select(AddressOf WrapFileInfo).
|
||||
Select(Function(d) IncludeSchema(d, pTemplate)).
|
||||
Select(Function(d) LoadDocumentData(d, pTemplate, TemplateConfig)).
|
||||
Select(Async Function(d) Await MatchDataFromWinLine(d, Winline.Mandators, pMandator, pTemplate)).
|
||||
SingleOrDefault()
|
||||
oDocument = LoadDocumentData(oDocument, pTemplate, TemplateConfig)
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Throw ex
|
||||
Logger.Error(ex)
|
||||
|
||||
End Try
|
||||
|
||||
Try
|
||||
oDocument = Await MatchDataFromWinLine(oDocument, Winline.Mandators, pMandator, pTemplate)
|
||||
|
||||
Catch ex As Exception
|
||||
Throw ex
|
||||
Logger.Error(ex)
|
||||
|
||||
End Try
|
||||
|
||||
Try
|
||||
oDocument = MarkRequiredFields(oDocument)
|
||||
|
||||
Catch ex As Exception
|
||||
Throw ex
|
||||
Logger.Error(ex)
|
||||
|
||||
End Try
|
||||
|
||||
Return oDocument
|
||||
End Function
|
||||
|
||||
Public Function MarkRequiredFields(pDocument As Document) As Document
|
||||
For Each oRow In pDocument.Rows
|
||||
For Each oField In oRow.Fields
|
||||
If oField.Value.Final = String.Empty And oField.Value.IsRequired Then
|
||||
oField.Value.AddFieldError(FieldErrorType.MissingValue, $"Attribut '{oField.Key}' ist ein Pflichtfeld, wurde aber nicht gefüllt.")
|
||||
End If
|
||||
Next
|
||||
Next
|
||||
|
||||
Return pDocument
|
||||
End Function
|
||||
|
||||
Public Sub ReplaceDocument(pDocument As Document)
|
||||
@@ -154,27 +177,27 @@ Namespace Documents
|
||||
|
||||
Dim oRootElement As XElement = XmlData.GetElement(oDoc, "MESOWebService")
|
||||
If oRootElement Is Nothing Then
|
||||
Throw New MalformedXmlException("Datei enthält kein MESOWebService-Element")
|
||||
pDocument.AddDocumentError(DocumentErrorType.MissingXmlAttribute, "Datei enthält kein MESOWebService-Attribut")
|
||||
End If
|
||||
|
||||
Dim oTemplateName = XmlData.GetElementAttribute(oRootElement, "Template")
|
||||
If oTemplateName Is Nothing Then
|
||||
Throw New MalformedXmlException("Datei enthält kein Template-Attribut")
|
||||
pDocument.AddDocumentError(DocumentErrorType.MissingXmlAttribute, "Datei enthält kein Template-Attribut")
|
||||
End If
|
||||
|
||||
Dim oTemplateType = XmlData.GetElementAttribute(oRootElement, "TemplateType")
|
||||
If oTemplateType Is Nothing Then
|
||||
Throw New MalformedXmlException("Datei enthält kein TemplateType-Attribut")
|
||||
pDocument.AddDocumentError(DocumentErrorType.MissingXmlAttribute, "Datei enthält kein TemplateType-Attribut")
|
||||
End If
|
||||
|
||||
Dim oOption = XmlData.GetElementAttribute(oRootElement, "option")
|
||||
If oOption Is Nothing Then
|
||||
Throw New MalformedXmlException("Datei enthält kein option-Attribut")
|
||||
pDocument.AddDocumentError(DocumentErrorType.MissingXmlAttribute, "Datei enthält kein option-Attribut")
|
||||
End If
|
||||
|
||||
Dim oPrintVoucher = XmlData.GetElementAttribute(oRootElement, "printVoucher")
|
||||
If oPrintVoucher Is Nothing Then
|
||||
Throw New MalformedXmlException("Datei enthält kein printVoucher-Attribut")
|
||||
pDocument.AddDocumentError(DocumentErrorType.MissingXmlAttribute, "Datei enthält kein printVoucher-Attribut")
|
||||
End If
|
||||
|
||||
' The first level of Elements are the document Rows
|
||||
@@ -227,16 +250,18 @@ Namespace Documents
|
||||
Else
|
||||
Logger.Debug("Creating new field from Configuration: [{0}]", oColumn.Name)
|
||||
|
||||
Dim oColumnError = FieldError.None
|
||||
If oColumn.Config?.IsRequired Then
|
||||
oColumnError = FieldError.MissingValue
|
||||
End If
|
||||
|
||||
oFields.Add(oColumn.Name, New DocumentRow.FieldValue With {
|
||||
.[Error] = oColumnError,
|
||||
Dim oValue = New DocumentRow.FieldValue With {
|
||||
.SortKey = oColumnSortKey,
|
||||
.IsVirtual = oColumn.Config.IsVirtual
|
||||
})
|
||||
}
|
||||
|
||||
'oValue.Error = FieldErrorType.None
|
||||
If oColumn.Config?.IsRequired Then
|
||||
'oValue.Error = FieldErrorType.MissingValue
|
||||
oValue.AddFieldError(FieldErrorType.MissingValue, $"Attribut {oSubElement.Name} wird benötigt, ist aber nicht gefüllt.")
|
||||
End If
|
||||
|
||||
oFields.Add(oColumn.Name, oValue)
|
||||
End If
|
||||
|
||||
oColumnSortKey += 1
|
||||
@@ -282,6 +307,9 @@ Namespace Documents
|
||||
|
||||
If oMandator Is Nothing Then
|
||||
Logger.Warn("Mandator not found for File [{0}]", pDocument.File.Name)
|
||||
|
||||
' Without mandator, we just exit, life is meaningless.
|
||||
pDocument.AddDocumentError(DocumentErrorType.MandatorNotFound, "Mandant nicht gefunden. Verarbeitung wurde abgebrochen.")
|
||||
Else
|
||||
' Set mandator befor applying any functions that depend on a valid mandator
|
||||
pDocument.Mandator = oMandator
|
||||
@@ -290,7 +318,7 @@ Namespace Documents
|
||||
.RunningFunction = "Winline-Funktionen"
|
||||
})
|
||||
|
||||
pDocument = ApplyDefinedItemFunctionsForImport(pDocument, oMandator, pTemplate)
|
||||
pDocument = Await ApplyDefinedItemFunctionsForImportAsync(pDocument, oMandator, pTemplate)
|
||||
pDocument = ApplyDynamicItemFunctionsForImport(pDocument, oMandator)
|
||||
|
||||
RaiseEvent FileLoadProgress(Me, New FileLoadProgressInfo(FilesTotal, FilesLoaded) With {
|
||||
@@ -355,7 +383,7 @@ Namespace Documents
|
||||
Return pDocument
|
||||
End Function
|
||||
|
||||
Private Function ApplyDefinedItemFunctionsForImport(pDocument As Document, pMandator As Mandator, pTemplate As Template) As Document
|
||||
Private Async Function ApplyDefinedItemFunctionsForImportAsync(pDocument As Document, pMandator As Mandator, pTemplate As Template) As Task(Of Document)
|
||||
For Each oRow As DocumentRow In pDocument.Rows
|
||||
Dim oTable = pTemplate.Tables.Where(Function(table) table.Name = oRow.TableName).SingleOrDefault()
|
||||
|
||||
@@ -373,14 +401,17 @@ Namespace Documents
|
||||
Dim oFunctionParams = oColumn.Config.FunctionParams
|
||||
Dim oParamsDict = ParseFunctionParamsAsDict(oFunctionParams)
|
||||
|
||||
If oFunctionName = Constants.FUNCTION_GLN Then
|
||||
If oFunctionName = FUNCTION_GLN Then
|
||||
SetAccountByGLN(oRow, pMandator, oField.Key, Nothing, oParamsDict)
|
||||
End If
|
||||
|
||||
If oFunctionName = Constants.FUNCTION_EAN Then
|
||||
If oFunctionName = FUNCTION_EAN Then
|
||||
SetArticleByEAN(oRow, pMandator, oField.Key)
|
||||
End If
|
||||
|
||||
If oFunctionName = FUNCTION_RUNNINGNUMBER Then
|
||||
Await SetVersionedRunningNumber(pDocument, oRow, pMandator, oField.Key, oParamsDict)
|
||||
End If
|
||||
|
||||
Next
|
||||
Next
|
||||
@@ -481,9 +512,7 @@ Namespace Documents
|
||||
pDocument.Rows.
|
||||
SelectMany(Function(row) row.Fields).
|
||||
Where(Function(field) field.Key = oMapping.DestinationItem).
|
||||
SetValue(Sub(field)
|
||||
field.Value.Final = oMapping.DestinationValue
|
||||
End Sub)
|
||||
SetValue(Sub(field) field.Value.Final = oMapping.DestinationValue)
|
||||
|
||||
Else
|
||||
' don't do anything
|
||||
@@ -494,12 +523,12 @@ Namespace Documents
|
||||
Return pDocument
|
||||
End Function
|
||||
|
||||
Private Async Function SetPrice(pRow As DocumentRow, pPriceField As String, oFieldMap As Dictionary(Of String, String), pDocument As Document, pMandator As Mandator, pTemplate As Template) As Task
|
||||
Private Async Function SetPrice(pRow As DocumentRow, pPriceField As String, pParamMap As Dictionary(Of String, String), pDocument As Document, pMandator As Mandator, pTemplate As Template) As Task
|
||||
Dim oPriceItem As DocumentRow.FieldValue = pRow.Fields.GetOrDefault(pPriceField)
|
||||
|
||||
' These fields are fetched from the current row
|
||||
Const PARAMETER_ARTICLE = "Article"
|
||||
Dim oArticleNumberField As String = oFieldMap.GetOrDefault(PARAMETER_ARTICLE, Nothing)
|
||||
Dim oArticleNumberField As String = pParamMap.GetOrDefault(PARAMETER_ARTICLE, Nothing)
|
||||
If oArticleNumberField Is Nothing Then
|
||||
Logger.Warn("Parameter '{0}' not found for Function PRICE", PARAMETER_ARTICLE)
|
||||
End If
|
||||
@@ -510,7 +539,7 @@ Namespace Documents
|
||||
Dim oArticleNumber As String = pRow.Fields.Item(oArticleNumberField).Final
|
||||
|
||||
Const PARAMETER_QUANTITY = "Quantity"
|
||||
Dim oQuantityField As String = oFieldMap.GetOrDefault(PARAMETER_QUANTITY, Nothing)
|
||||
Dim oQuantityField As String = pParamMap.GetOrDefault(PARAMETER_QUANTITY, Nothing)
|
||||
If oQuantityField Is Nothing Then
|
||||
Logger.Warn("Parameter '{0}' not found for Function PRICE", PARAMETER_QUANTITY)
|
||||
End If
|
||||
@@ -521,13 +550,13 @@ Namespace Documents
|
||||
End If
|
||||
|
||||
' These fields a fetched from the head row, ie. the first row
|
||||
Dim oAccountNumberField As String = oFieldMap.GetOrDefault("Account", Nothing)
|
||||
Dim oAccountNumberField As String = pParamMap.GetOrDefault("Account", Nothing)
|
||||
Dim oAccountNumber = pDocument.GetFieldValue(oAccountNumberField)
|
||||
|
||||
Dim oDocumentDateField As String = oFieldMap.GetOrDefault("DocumentDate", Nothing)
|
||||
Dim oDocumentDateField As String = pParamMap.GetOrDefault("DocumentDate", Nothing)
|
||||
Dim oDocumentDate = pDocument.GetFieldValue(oDocumentDateField)
|
||||
|
||||
Dim oDocumentKindField As String = oFieldMap.GetOrDefault("DocumentKind", Nothing)
|
||||
Dim oDocumentKindField As String = pParamMap.GetOrDefault("DocumentKind", Nothing)
|
||||
Dim oDocumentKind As Integer = 0
|
||||
If Integer.TryParse(pDocument.GetFieldValue(oDocumentKindField), oDocumentKind) = False Then
|
||||
Logger.Warn("Value for parameter DocumentKind could not be parsed. Setting to 0.")
|
||||
@@ -538,10 +567,10 @@ Namespace Documents
|
||||
|
||||
' TODO: This function should not be hardcoded, but be replaced with virtual field or something..
|
||||
' It is related to customer SCHAUM and nothing general
|
||||
Dim oWaitingDays As Integer = Await Winline.TryGetWaitingDays(oDocumentKind, pMandator)
|
||||
Dim oWaitingDays As Integer = Await Winline.TryGetWaitingDaysAsync(oDocumentKind, pMandator)
|
||||
' END TODO
|
||||
|
||||
Dim oArticlePrice As Double = Await Winline.TryGetArticlePrice(oArticleNumber, oAccountNumber, oQuantity, oDocumentDate, pMandator, pTemplate, oWaitingDays)
|
||||
Dim oArticlePrice As Double = Await Winline.TryGetArticlePriceAsync(oArticleNumber, oAccountNumber, oQuantity, oDocumentDate, pMandator, pTemplate, oWaitingDays)
|
||||
|
||||
If oArticlePrice > 0 Then
|
||||
oPriceItem.External = oArticlePrice
|
||||
@@ -559,7 +588,8 @@ Namespace Documents
|
||||
oNumberItem.External = oArticleNumber
|
||||
oNumberItem.Final = oArticleNumber
|
||||
Else
|
||||
oNumberItem.Error = FieldError.ArticleNotFound
|
||||
'oNumberItem.Error = FieldErrorType.ArticleNotFound
|
||||
oNumberItem.AddFieldError(FieldErrorType.ArticleNotFound, $"EAN in Attribut '{pArticleField}' konnte nicht aufgelöst werden.")
|
||||
End If
|
||||
End Sub
|
||||
|
||||
@@ -597,7 +627,8 @@ Namespace Documents
|
||||
' If no account was found and the field is required,
|
||||
' mark it as error. Otherwise, do nothing.
|
||||
If oNumberItem.IsRequired Then
|
||||
oNumberItem.Error = FieldError.AccountNotFound
|
||||
'oNumberItem.Error = FieldErrorType.AccountNotFound
|
||||
oNumberItem.AddFieldError(FieldErrorType.AccountNotFound, $"GLN in Attribut '{pNumberField}' konnte nicht aufgelöst werden.")
|
||||
End If
|
||||
End If
|
||||
Catch ex As Exception
|
||||
@@ -606,9 +637,31 @@ Namespace Documents
|
||||
End Try
|
||||
End Sub
|
||||
|
||||
Private Function WrapFileInfo(pFileInfo As FileInfo) As Document
|
||||
Logger.Debug("Creating new Document object for file [{0}]", pFileInfo.Name)
|
||||
Return New Document With {.File = pFileInfo}
|
||||
Public Async Function SetVersionedRunningNumber(pDocument As Document, pRow As DocumentRow, pMandator As Mandator, pRunningNumberField As String, pParams As Dictionary(Of String, String)) As Task
|
||||
Try
|
||||
Const PARAMETER_ACCOUNT = "Account"
|
||||
Dim oAccountField As String = pParams.GetOrDefault(PARAMETER_ACCOUNT, Nothing)
|
||||
If oAccountField Is Nothing Then
|
||||
Logger.Warn("Parameter '{0}' not found for Function RUNNINGNUMBER", PARAMETER_ACCOUNT)
|
||||
End If
|
||||
|
||||
Dim oRunningNumberItem As DocumentRow.FieldValue = pRow.Fields.GetOrDefault(pRunningNumberField)
|
||||
Dim oRunningNumber = oRunningNumberItem.Final
|
||||
|
||||
Dim oAccountNumberItem As DocumentRow.FieldValue = pRow.Fields.GetOrDefault(oAccountField)
|
||||
Dim oAccountNumber = oAccountNumberItem.Final
|
||||
|
||||
Dim oVersionedNumber = Await Winline.GetVersionedRunningNumberAsync(pDocument, pMandator, oAccountNumber, oRunningNumber)
|
||||
|
||||
If oVersionedNumber <> oRunningNumber Then
|
||||
oRunningNumberItem.External = oVersionedNumber
|
||||
oRunningNumberItem.Final = oVersionedNumber
|
||||
End If
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Error(ex)
|
||||
Throw ex
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private Function ParseFunctionParamsAsDict(pParams As String) As Dictionary(Of String, String)
|
||||
|
||||
Reference in New Issue
Block a user