Better Logging and Error Handling

This commit is contained in:
Jonathan Jenne 2022-04-21 15:50:30 +02:00
parent 31e0835914
commit 85318a3e81
2 changed files with 101 additions and 44 deletions

View File

@ -116,6 +116,7 @@ Namespace Documents
Private Function IncludeSchema(pDocument As Document, pTemplate As Template) As Document Private Function IncludeSchema(pDocument As Document, pTemplate As Template) As Document
Logger.Debug("Adding schema to Document object.")
pDocument.Schema = pTemplate pDocument.Schema = pTemplate
Return pDocument Return pDocument
End Function End Function
@ -133,8 +134,23 @@ Namespace Documents
''' </MESOWebService> ''' </MESOWebService>
''' </example> ''' </example>
Private Function LoadDocumentData(pDocument As Document, pTemplate As Template, pTemplateConfig As TemplateConfig) As Document Private Function LoadDocumentData(pDocument As Document, pTemplate As Template, pTemplateConfig As TemplateConfig) As Document
Dim oText As String = IO.File.ReadAllText(pDocument.FullName) Logger.Debug("Loading file contents")
Dim oDoc = XDocument.Parse(oText)
Dim oText As String
Dim oDoc As XDocument
Try
Logger.Debug("Loading file from fs..")
oText = IO.File.ReadAllText(pDocument.FullName)
Logger.Debug("Parsing file..")
oDoc = XDocument.Parse(oText)
Catch ex As Exception
Logger.Error(ex)
Throw ex
End Try
Logger.Debug("File Loaded.")
Dim oRootElement As XElement = XmlData.GetElement(oDoc, "MESOWebService") Dim oRootElement As XElement = XmlData.GetElement(oDoc, "MESOWebService")
If oRootElement Is Nothing Then If oRootElement Is Nothing Then
@ -181,6 +197,8 @@ Namespace Documents
Where(Function(t) t.Name = oTopLevelElement.Name). Where(Function(t) t.Name = oTopLevelElement.Name).
FirstOrDefault() FirstOrDefault()
Logger.Debug("Creating fields from [{0}] columns for Table [{1}]", oTable.Columns, oTable.Name)
For Each oColumn In oTable.Columns For Each oColumn In oTable.Columns
Dim oSubElement = oSubElements. Dim oSubElement = oSubElements.
Where(Function(e) e.Name = oColumn.Name). Where(Function(e) e.Name = oColumn.Name).
@ -190,6 +208,8 @@ Namespace Documents
Dim oRequired = oColumn.IsRequired Dim oRequired = oColumn.IsRequired
Dim oValue = oSubElement.Value.Trim() Dim oValue = oSubElement.Value.Trim()
Logger.Debug("Creating existing field from Element: [{0}]", oSubElement.Name.ToString)
' TODO: Needed when we have time for date times ' TODO: Needed when we have time for date times
'If oTemplateField.DataType = Constants.ColumnType.Date Then 'If oTemplateField.DataType = Constants.ColumnType.Date Then
' Dim oDate = Date.ParseExact(oValue, "yyyy-MM-dd", CultureInfo.InvariantCulture) ' Dim oDate = Date.ParseExact(oValue, "yyyy-MM-dd", CultureInfo.InvariantCulture)
@ -205,6 +225,8 @@ Namespace Documents
.SortKey = oColumnSortKey .SortKey = oColumnSortKey
}) })
Else Else
Logger.Debug("Creating new field from Configuration: [{0}]", oColumn.Name)
Dim oColumnError = FieldError.None Dim oColumnError = FieldError.None
If oColumn.Config?.IsRequired Then If oColumn.Config?.IsRequired Then
oColumnError = FieldError.MissingValue oColumnError = FieldError.MissingValue
@ -542,59 +564,72 @@ Namespace Documents
End Sub End Sub
Private Sub SetAccountByGLN(oRow As DocumentRow, pMandator As Mandator, pNumberField As String, pNameField As String, pParams As Dictionary(Of String, String)) Private Sub SetAccountByGLN(oRow As DocumentRow, pMandator As Mandator, pNumberField As String, pNameField As String, pParams As Dictionary(Of String, String))
' Try to read the Account number (which is a GLN really) and account Name Try
Dim oNumberItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNumberField) ' Try to read the Account number (which is a GLN really) and account Name
Dim oNameItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNameField) Dim oNumberItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNumberField)
Dim oContainsAccountName As Boolean = Not IsNothing(oNameItem) Dim oNameItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNameField)
Dim oContainsAccountName As Boolean = Not IsNothing(oNameItem)
If oNumberItem Is Nothing Then If oNumberItem Is Nothing Then
Exit Sub Exit Sub
End If End If
' Try to find an account that matches the GLN ' Try to find an account that matches the GLN
Dim oAlternateField = pParams.GetOrDefault("AltField", String.Empty) Dim oAlternateField = pParams.GetOrDefault("AltField", String.Empty)
Dim oAccount = Winline.TryGetAccount(oNumberItem.Original, pMandator, "c260", oAlternateField) Dim oAccount = Winline.TryGetAccount(oNumberItem.Original, pMandator, "c260", oAlternateField)
' If an account was found, set it for External and Final value ' If an account was found, set it for External and Final value
If oAccount IsNot Nothing Then If oAccount IsNot Nothing Then
oNumberItem.External = oAccount.Id oNumberItem.External = oAccount.Id
oNumberItem.Final = oAccount.Id oNumberItem.Final = oAccount.Id
If oContainsAccountName Then If oContainsAccountName Then
oNameItem.External = oAccount.Name oNameItem.External = oAccount.Name
oNameItem.Final = oAccount.Name oNameItem.Final = oAccount.Name
Else
' TODO: What to to if name field is missing or not set?
'oRow.Fields.Add(pNameField, New DocumentRow.FieldValue() With {
' .External = oAccount.Name,
' .Final = oAccount.Name
'})
End If
Else Else
' TODO: What to to if name field is missing or not set? ' If no account was found and the field is required,
'oRow.Fields.Add(pNameField, New DocumentRow.FieldValue() With { ' mark it as error. Otherwise, do nothing.
' .External = oAccount.Name, If oNumberItem.IsRequired Then
' .Final = oAccount.Name oNumberItem.Error = FieldError.AccountNotFound
'}) End If
End If End If
Else Catch ex As Exception
' If no account was found and the field is required, Logger.Error(ex)
' mark it as error. Otherwise, do nothing. Throw ex
If oNumberItem.IsRequired Then End Try
oNumberItem.Error = FieldError.AccountNotFound
End If
End If
End Sub End Sub
Private Function WrapFileInfo(pFileInfo As FileInfo) As Document 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} Return New Document With {.File = pFileInfo}
End Function End Function
Private Function ParseFunctionParamsAsDict(pParams As String) As Dictionary(Of String, String) Private Function ParseFunctionParamsAsDict(pParams As String) As Dictionary(Of String, String)
Dim oParamsDict As New Dictionary(Of String, String) Try
Dim oParamsDict As New Dictionary(Of String, String)
If pParams <> String.Empty Then If pParams <> String.Empty Then
Dim oParamList = pParams.Split("|").ToList() Dim oParamList = pParams.Split("|").ToList()
For Each oParam In oParamList For Each oParam In oParamList
Dim oParamSplit = oParam.Split("=") Dim oParamSplit = oParam.Split("=")
oParamsDict.Add(oParamSplit(0), oParamSplit(1)) If oParamSplit.Count = 2 Then
Next oParamsDict.Add(oParamSplit(0), oParamSplit(1))
End If End If
Next
End If
Return oParamsDict Return oParamsDict
Catch ex As Exception
Logger.Error(ex)
Return New Dictionary(Of String, String)
End Try
End Function End Function
End Class End Class

View File

@ -219,15 +219,21 @@ Namespace Winline
Async Function ExportDocumentFromWinline(pDocument As Entities.ExportDocument, pTemplate As Template, pMandator As Mandator, Optional pIsTest As Boolean = False) As Task(Of Boolean) Async Function ExportDocumentFromWinline(pDocument As Entities.ExportDocument, pTemplate As Template, pMandator As Mandator, Optional pIsTest As Boolean = False) As Task(Of Boolean)
Dim oWS = Config Dim oWS = Config
Logger.Info("Exporting document from Winline")
' --- Build all teh filenamez and pathz ' --- Build all teh filenamez and pathz
Dim oBaseFileName As String = FileEx.GetDateTimeString() Dim oBaseFileName As String = FileEx.GetDateTimeString()
Dim oFileName = $"{pTemplate.Name}-{oBaseFileName}.xml" Dim oFileName = $"{pTemplate.Name}-{oBaseFileName}.xml"
'Dim oFileName = FileEx.GetFilenameWithPrefix(oBaseFileName, pTemplate.Name, "xml") 'Dim oFileName = FileEx.GetFilenameWithPrefix(oBaseFileName, pTemplate.Name, "xml")
Logger.Info("Filename will be [{0}]", oFileName)
' Save the filename to the document ' Save the filename to the document
pDocument.FilenameExport = oFileName pDocument.FilenameExport = oFileName
RaiseEvent WebServiceProgress(Me, "Dateien schreiben") RaiseEvent WebServiceProgress(Me, "Abfrage vorbereiten")
Logger.Debug("Preparing WebService call")
' --- Prepare URL and HTTP Client ' --- Prepare URL and HTTP Client
Dim oTemplateType = 30 Dim oTemplateType = 30
@ -242,6 +248,8 @@ Namespace Winline
oActionCode = 0 oActionCode = 0
End If End If
Logger.Debug("This is a test: [{0}]", pIsTest)
Dim oURL As String = $"{oWS.BaseUrl}/ewlservice/export?User={oWS.Username}&Password={oWS.Password}&Company={pMandator.Id}&Type={oTemplateType}&Vorlage={oTemplateName}&ActionCode={oActionCode}&Key={oKey}" Dim oURL As String = $"{oWS.BaseUrl}/ewlservice/export?User={oWS.Username}&Password={oWS.Password}&Company={pMandator.Id}&Type={oTemplateType}&Vorlage={oTemplateName}&ActionCode={oActionCode}&Key={oKey}"
Dim oClient As New HttpClient() Dim oClient As New HttpClient()
@ -252,6 +260,8 @@ Namespace Winline
' --- Bring the action! ' --- Bring the action!
Try Try
Dim oResponse As HttpResponseMessage = Await oClient.GetAsync(oURL) Dim oResponse As HttpResponseMessage = Await oClient.GetAsync(oURL)
Logger.Info("Request ended with code: [{0}]", oResponse.StatusCode)
Await HandleExportResponse(oResponse, pDocument, pTemplate, pMandator, oBaseFileName) Await HandleExportResponse(oResponse, pDocument, pTemplate, pMandator, oBaseFileName)
Return True Return True
@ -268,12 +278,14 @@ Namespace Winline
Private Async Function HandleExportResponse(pResponse As HttpResponseMessage, pDocument As Entities.ExportDocument, pTemplate As Template, pMandator As Mandator, pBaseFileName As String) As Task Private Async Function HandleExportResponse(pResponse As HttpResponseMessage, pDocument As Entities.ExportDocument, pTemplate As Template, pMandator As Mandator, pBaseFileName As String) As Task
pResponse.EnsureSuccessStatusCode() pResponse.EnsureSuccessStatusCode()
Dim oResponseBody As String = Await pResponse.Content.ReadAsStringAsync() Dim oResponseBody As String = Await pResponse.Content.ReadAsStringAsync()
Dim oContentType = pResponse.Content.Headers.ContentType.MediaType Dim oContentType = pResponse.Content.Headers.ContentType.MediaType
Dim oSerializer = Serializer.GetSerializer(GetType(Templates.Entities.MESOWebServiceResult)) Dim oSerializer = Serializer.GetSerializer(GetType(Templates.Entities.MESOWebServiceResult))
RaiseEvent WebServiceProgress(Me, "Antwort verarbeiten") RaiseEvent WebServiceProgress(Me, "Antwort verarbeiten")
Logger.Debug("Postprocessing response.")
oResponseBody = ApplyItemFunctionsForExport(pDocument, pTemplate, pMandator, oResponseBody) oResponseBody = ApplyItemFunctionsForExport(pDocument, pTemplate, pMandator, oResponseBody)
Select Case oContentType Select Case oContentType
@ -300,6 +312,8 @@ Namespace Winline
oDoc.LoadXml(oResponseBody) oDoc.LoadXml(oResponseBody)
For Each oTable In pTemplate.Tables For Each oTable In pTemplate.Tables
Logger.Debug("Processing Table [{0}]", oTable.Name)
For Each oItem As Template.Column In oTable.Columns For Each oItem As Template.Column In oTable.Columns
Dim oTableName As String = oTable.Name Dim oTableName As String = oTable.Name
Dim oItemName As String = oItem.Name Dim oItemName As String = oItem.Name
@ -308,17 +322,21 @@ Namespace Winline
Continue For Continue For
End If End If
Logger.Debug("Processing item [{0}]", oItemName)
Dim oFunction = oItem.Config.Function.Name Dim oFunction = oItem.Config.Function.Name
Dim oPath = $"//MESOWebService/{oTableName}/{oItemName}" Dim oPath = $"//MESOWebService/{oTableName}/{oItemName}"
Dim oNodes As XmlNodeList = oDoc.SelectNodes(oPath) Dim oNodes As XmlNodeList = oDoc.SelectNodes(oPath)
Logger.Debug("Calling function [{0}] on note [{1}]", oFunction, oPath)
For Each oNode As XmlNode In oNodes For Each oNode As XmlNode In oNodes
If oItem.Config.Function.Name = "GLN" Then If oItem.Config.Function.Name = "GLN" Then
Dim oGLN = Winline.TryGetGLN(oNode.InnerText, pMandator) Dim oGLN = Winline.TryGetGLN(oNode.InnerText, pMandator)
If oGLN Is Nothing Then If oGLN Is Nothing Then
Throw New Exceptions.MissingAttributeException("GLN") Throw New MissingAttributeException("GLN")
End If End If
oNode.InnerText = oGLN oNode.InnerText = oGLN
@ -327,7 +345,11 @@ Namespace Winline
Dim oEAN = Winline.TryGetEAN(oNode.InnerText, pMandator) Dim oEAN = Winline.TryGetEAN(oNode.InnerText, pMandator)
If oEAN Is Nothing Then If oEAN Is Nothing Then
Throw New Exceptions.MissingAttributeException("EAN") ' 21.04.2022: Relax the EAN Check
' Since it is possible to have articles without a proper EAN in export,
' we dont throw here, but leave the original value in case of a failure.
' Throw New Exceptions.MissingAttributeException("EAN")
Logger.Warn("EAN could not be retrieved for Node {0}. Skipping.", oNode.Name)
End If End If
oNode.InnerText = oEAN oNode.InnerText = oEAN
@ -337,7 +359,7 @@ Namespace Winline
Dim oValue = Database.GetScalarValue(oSQL) Dim oValue = Database.GetScalarValue(oSQL)
If oValue Is Nothing Then If oValue Is Nothing Then
Throw New Exceptions.MissingAttributeException("SQL") Throw New MissingAttributeException("SQL")
End If End If
oNode.InnerText = oValue oNode.InnerText = oValue