From 85318a3e818e0ba86f7af4e330388e3dfd16ce4e Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Thu, 21 Apr 2022 15:50:30 +0200 Subject: [PATCH] Better Logging and Error Handling --- MultiTool.Common/Documents/DocumentLoader.vb | 117 ++++++++++++------- MultiTool.Common/Winline/WebServiceData.vb | 30 ++++- 2 files changed, 102 insertions(+), 45 deletions(-) diff --git a/MultiTool.Common/Documents/DocumentLoader.vb b/MultiTool.Common/Documents/DocumentLoader.vb index cace409..1643a79 100644 --- a/MultiTool.Common/Documents/DocumentLoader.vb +++ b/MultiTool.Common/Documents/DocumentLoader.vb @@ -116,6 +116,7 @@ Namespace Documents Private Function IncludeSchema(pDocument As Document, pTemplate As Template) As Document + Logger.Debug("Adding schema to Document object.") pDocument.Schema = pTemplate Return pDocument End Function @@ -133,8 +134,23 @@ Namespace Documents ''' ''' Private Function LoadDocumentData(pDocument As Document, pTemplate As Template, pTemplateConfig As TemplateConfig) As Document - Dim oText As String = IO.File.ReadAllText(pDocument.FullName) - Dim oDoc = XDocument.Parse(oText) + Logger.Debug("Loading file contents") + + 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") If oRootElement Is Nothing Then @@ -181,6 +197,8 @@ Namespace Documents Where(Function(t) t.Name = oTopLevelElement.Name). FirstOrDefault() + Logger.Debug("Creating fields from [{0}] columns for Table [{1}]", oTable.Columns, oTable.Name) + For Each oColumn In oTable.Columns Dim oSubElement = oSubElements. Where(Function(e) e.Name = oColumn.Name). @@ -190,6 +208,8 @@ Namespace Documents Dim oRequired = oColumn.IsRequired 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 'If oTemplateField.DataType = Constants.ColumnType.Date Then ' Dim oDate = Date.ParseExact(oValue, "yyyy-MM-dd", CultureInfo.InvariantCulture) @@ -205,6 +225,8 @@ Namespace Documents .SortKey = oColumnSortKey }) Else + Logger.Debug("Creating new field from Configuration: [{0}]", oColumn.Name) + Dim oColumnError = FieldError.None If oColumn.Config?.IsRequired Then oColumnError = FieldError.MissingValue @@ -542,59 +564,72 @@ Namespace Documents End Sub 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 - Dim oNumberItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNumberField) - Dim oNameItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNameField) - Dim oContainsAccountName As Boolean = Not IsNothing(oNameItem) + Try + ' Try to read the Account number (which is a GLN really) and account Name + Dim oNumberItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNumberField) + Dim oNameItem As DocumentRow.FieldValue = oRow.Fields.GetOrDefault(pNameField) + Dim oContainsAccountName As Boolean = Not IsNothing(oNameItem) - If oNumberItem Is Nothing Then - Exit Sub - End If + If oNumberItem Is Nothing Then + Exit Sub + End If - ' Try to find an account that matches the GLN - Dim oAlternateField = pParams.GetOrDefault("AltField", String.Empty) - Dim oAccount = Winline.TryGetAccount(oNumberItem.Original, pMandator, "c260", oAlternateField) + ' Try to find an account that matches the GLN + Dim oAlternateField = pParams.GetOrDefault("AltField", String.Empty) + Dim oAccount = Winline.TryGetAccount(oNumberItem.Original, pMandator, "c260", oAlternateField) - ' If an account was found, set it for External and Final value - If oAccount IsNot Nothing Then - oNumberItem.External = oAccount.Id - oNumberItem.Final = oAccount.Id + ' If an account was found, set it for External and Final value + If oAccount IsNot Nothing Then + oNumberItem.External = oAccount.Id + oNumberItem.Final = oAccount.Id - If oContainsAccountName Then - oNameItem.External = oAccount.Name - oNameItem.Final = oAccount.Name + If oContainsAccountName Then + oNameItem.External = 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 - ' 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 - ' 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 + ' 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 + End If End If - End If + Catch ex As Exception + Logger.Error(ex) + Throw ex + 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} End Function Private Function ParseFunctionParamsAsDict(pParams As String) As Dictionary(Of String, String) - Dim oParamsDict As New Dictionary(Of String, String) - - If pParams <> String.Empty Then - Dim oParamList = pParams.Split("|").ToList() - For Each oParam In oParamList - Dim oParamSplit = oParam.Split("=") - oParamsDict.Add(oParamSplit(0), oParamSplit(1)) - Next - End If + Try + Dim oParamsDict As New Dictionary(Of String, String) + + If pParams <> String.Empty Then + Dim oParamList = pParams.Split("|").ToList() + For Each oParam In oParamList + Dim oParamSplit = oParam.Split("=") + If oParamSplit.Count = 2 Then + oParamsDict.Add(oParamSplit(0), oParamSplit(1)) + 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 Class diff --git a/MultiTool.Common/Winline/WebServiceData.vb b/MultiTool.Common/Winline/WebServiceData.vb index 8aacb3e..8057ee5 100644 --- a/MultiTool.Common/Winline/WebServiceData.vb +++ b/MultiTool.Common/Winline/WebServiceData.vb @@ -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) Dim oWS = Config + Logger.Info("Exporting document from Winline") + ' --- Build all teh filenamez and pathz Dim oBaseFileName As String = FileEx.GetDateTimeString() Dim oFileName = $"{pTemplate.Name}-{oBaseFileName}.xml" 'Dim oFileName = FileEx.GetFilenameWithPrefix(oBaseFileName, pTemplate.Name, "xml") + Logger.Info("Filename will be [{0}]", oFileName) + ' Save the filename to the document pDocument.FilenameExport = oFileName - RaiseEvent WebServiceProgress(Me, "Dateien schreiben") + RaiseEvent WebServiceProgress(Me, "Abfrage vorbereiten") + + Logger.Debug("Preparing WebService call") ' --- Prepare URL and HTTP Client Dim oTemplateType = 30 @@ -242,6 +248,8 @@ Namespace Winline oActionCode = 0 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 oClient As New HttpClient() @@ -252,6 +260,8 @@ Namespace Winline ' --- Bring the action! Try Dim oResponse As HttpResponseMessage = Await oClient.GetAsync(oURL) + Logger.Info("Request ended with code: [{0}]", oResponse.StatusCode) + Await HandleExportResponse(oResponse, pDocument, pTemplate, pMandator, oBaseFileName) 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 pResponse.EnsureSuccessStatusCode() + Dim oResponseBody As String = Await pResponse.Content.ReadAsStringAsync() Dim oContentType = pResponse.Content.Headers.ContentType.MediaType Dim oSerializer = Serializer.GetSerializer(GetType(Templates.Entities.MESOWebServiceResult)) RaiseEvent WebServiceProgress(Me, "Antwort verarbeiten") + Logger.Debug("Postprocessing response.") oResponseBody = ApplyItemFunctionsForExport(pDocument, pTemplate, pMandator, oResponseBody) Select Case oContentType @@ -300,6 +312,8 @@ Namespace Winline oDoc.LoadXml(oResponseBody) For Each oTable In pTemplate.Tables + Logger.Debug("Processing Table [{0}]", oTable.Name) + For Each oItem As Template.Column In oTable.Columns Dim oTableName As String = oTable.Name Dim oItemName As String = oItem.Name @@ -308,17 +322,21 @@ Namespace Winline Continue For End If + Logger.Debug("Processing item [{0}]", oItemName) + Dim oFunction = oItem.Config.Function.Name Dim oPath = $"//MESOWebService/{oTableName}/{oItemName}" Dim oNodes As XmlNodeList = oDoc.SelectNodes(oPath) + Logger.Debug("Calling function [{0}] on note [{1}]", oFunction, oPath) + For Each oNode As XmlNode In oNodes If oItem.Config.Function.Name = "GLN" Then Dim oGLN = Winline.TryGetGLN(oNode.InnerText, pMandator) If oGLN Is Nothing Then - Throw New Exceptions.MissingAttributeException("GLN") + Throw New MissingAttributeException("GLN") End If oNode.InnerText = oGLN @@ -327,7 +345,11 @@ Namespace Winline Dim oEAN = Winline.TryGetEAN(oNode.InnerText, pMandator) 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 oNode.InnerText = oEAN @@ -337,7 +359,7 @@ Namespace Winline Dim oValue = Database.GetScalarValue(oSQL) If oValue Is Nothing Then - Throw New Exceptions.MissingAttributeException("SQL") + Throw New MissingAttributeException("SQL") End If oNode.InnerText = oValue