Improve Error handling across the board
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
Public Const FUNCTION_PRICE = "PRICE"
|
||||
Public Const FUNCTION_SQL = "SQL"
|
||||
Public Const FUNCTION_FIELD = "FIELD"
|
||||
Public Const FUNCTION_RUNNINGNUMBER = "RUNNINGNUMBER"
|
||||
|
||||
Public Const TEMPLATE_TYPE_DATE = "xs:date"
|
||||
Public Const TEMPLATE_TYPE_INTEGER = "xs:integer"
|
||||
@@ -56,17 +57,38 @@
|
||||
[Decimal]
|
||||
End Enum
|
||||
|
||||
Public Enum FieldError
|
||||
Public Enum FieldErrorType
|
||||
None
|
||||
MissingValue
|
||||
AccountNotFound
|
||||
ArticleNotFound
|
||||
End Enum
|
||||
|
||||
Public Enum DocumentError
|
||||
Public Class FieldError
|
||||
Public Type As FieldErrorType
|
||||
Public Message As String
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
Return $"{Message} ({Type})"
|
||||
End Function
|
||||
End Class
|
||||
|
||||
|
||||
Public Enum DocumentErrorType
|
||||
MandatorNotFound
|
||||
MissingXmlAttribute
|
||||
AttributeValidationFailed
|
||||
End Enum
|
||||
|
||||
Public Class DocumentError
|
||||
Public Type As DocumentErrorType
|
||||
Public Message As String
|
||||
|
||||
Public Overrides Function ToString() As String
|
||||
Return $"{Message} ({Type})"
|
||||
End Function
|
||||
End Class
|
||||
|
||||
Public Enum XmlFunction
|
||||
None = 0
|
||||
GLN = 1
|
||||
|
||||
@@ -26,6 +26,8 @@ Namespace Documents
|
||||
''' </summary>
|
||||
Public Property Selected As Boolean = False
|
||||
|
||||
Private DocumentErrors As New List(Of DocumentError)
|
||||
|
||||
Public ReadOnly Property HasErrors As Boolean
|
||||
Get
|
||||
Return Errors.Count > 0
|
||||
@@ -34,8 +36,11 @@ Namespace Documents
|
||||
|
||||
Public ReadOnly Property Errors As List(Of String)
|
||||
Get
|
||||
Dim oRowErrors = Rows.SelectMany(Function(row) row.Errors).ToList()
|
||||
Dim oDocumentErrors As List(Of String) = GetDocumentErrors().
|
||||
Dim oRowErrors = Rows.
|
||||
SelectMany(Function(row) row.Errors, Function(row, err) err.ToString).
|
||||
ToList()
|
||||
|
||||
Dim oDocumentErrors As List(Of String) = DocumentErrors.
|
||||
Select(Function(err) err.ToString()).
|
||||
ToList()
|
||||
Return oDocumentErrors.
|
||||
@@ -44,6 +49,13 @@ Namespace Documents
|
||||
End Get
|
||||
End Property
|
||||
|
||||
Public Sub AddDocumentError(pDocumentError As DocumentErrorType, pMessage As String)
|
||||
DocumentErrors.Add(New DocumentError With {
|
||||
.Type = pDocumentError,
|
||||
.Message = pMessage
|
||||
})
|
||||
End Sub
|
||||
|
||||
Public ReadOnly Property MandatorId As String
|
||||
Get
|
||||
Return Mandator?.Id
|
||||
@@ -84,19 +96,12 @@ Namespace Documents
|
||||
End Function
|
||||
|
||||
Public Overrides Function Equals(obj As Object) As Boolean
|
||||
Return FullName = DirectCast(obj, Document).FullName
|
||||
End Function
|
||||
|
||||
Private Function GetDocumentErrors() As List(Of DocumentError)
|
||||
Dim oErrors As New List(Of DocumentError)
|
||||
|
||||
If Mandator Is Nothing Then
|
||||
oErrors.Add(DocumentError.MandatorNotFound)
|
||||
If obj Is Nothing Then
|
||||
Return False
|
||||
End If
|
||||
|
||||
Return oErrors
|
||||
Return FullName = DirectCast(obj, Document).FullName
|
||||
End Function
|
||||
|
||||
End Class
|
||||
|
||||
End Namespace
|
||||
@@ -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)
|
||||
|
||||
@@ -35,11 +35,11 @@ Namespace Documents
|
||||
End Get
|
||||
End Property
|
||||
|
||||
Public ReadOnly Property Errors As List(Of String)
|
||||
Public ReadOnly Property Errors As List(Of FieldError)
|
||||
Get
|
||||
Return Fields.
|
||||
Where(Function(f) f.Value.HasError).
|
||||
Select(Function(f) $"{f.Key} has Error: {f.Value.Error}").ToList()
|
||||
SelectMany(Function(f) f.Value.Errors).ToList()
|
||||
End Get
|
||||
End Property
|
||||
|
||||
@@ -57,11 +57,8 @@ Namespace Documents
|
||||
Private _Original As String = ""
|
||||
|
||||
Public Property DataType As ColumnType = ColumnType.String
|
||||
Public Property [Error] As FieldError = FieldError.None
|
||||
|
||||
Public Sub New()
|
||||
|
||||
End Sub
|
||||
Public Property Errors As New List(Of FieldError)
|
||||
|
||||
Public Property Original As String
|
||||
Get
|
||||
@@ -107,9 +104,17 @@ Namespace Documents
|
||||
End Select
|
||||
End Function
|
||||
|
||||
Public Sub AddFieldError(pType As FieldErrorType, pMessage As String)
|
||||
Errors.Add(New FieldError() With {
|
||||
.Type = pType,
|
||||
.Message = pMessage
|
||||
})
|
||||
End Sub
|
||||
|
||||
Public ReadOnly Property HasError As Boolean
|
||||
Get
|
||||
Return [Error] <> FieldError.None Or (IsRequired And Final = String.Empty)
|
||||
' Required check was moved to DocumentLoader
|
||||
Return Errors.Count > 0 'Or (IsRequired And Final = String.Empty)
|
||||
End Get
|
||||
End Property
|
||||
|
||||
|
||||
@@ -57,18 +57,12 @@
|
||||
MyBase.New(message)
|
||||
End Sub
|
||||
End Class
|
||||
Public Class NoMandatorException
|
||||
|
||||
Public Class LengthExceededException
|
||||
Inherits MultiToolException
|
||||
|
||||
Public Sub New(message As String)
|
||||
MyBase.New(message)
|
||||
End Sub
|
||||
End Class
|
||||
Public Class MalformedXmlException
|
||||
Inherits MultiToolException
|
||||
|
||||
Public Sub New(message As String)
|
||||
MyBase.New(message)
|
||||
Public Sub New(attribute As String)
|
||||
MyBase.New(attribute)
|
||||
End Sub
|
||||
End Class
|
||||
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports System.Text.RegularExpressions
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports DigitalData.Modules.Database
|
||||
Imports MultiTool.Common.Winline.Entities
|
||||
Imports System.Text.RegularExpressions
|
||||
Imports MultiTool.Common.Templates
|
||||
Imports MultiTool.Common.Constants
|
||||
Imports DigitalData.Modules.Language
|
||||
Imports DigitalData.Modules.Filesystem
|
||||
Imports MultiTool.Common.Winline.Entities
|
||||
Imports MultiTool.Common.Constants
|
||||
Imports MultiTool.Common.Templates
|
||||
Imports MultiTool.Common.Exceptions
|
||||
Imports MultiTool.Common.Documents
|
||||
|
||||
Namespace Winline
|
||||
Public Class WinlineData
|
||||
@@ -14,6 +17,7 @@ Namespace Winline
|
||||
Private ReadOnly Property MandatorConfig As MandatorConfig
|
||||
Private ReadOnly Property MappingConfig As MappingConfig
|
||||
Private ReadOnly Property Patterns As Patterns
|
||||
Private ReadOnly Property FileEx As File
|
||||
|
||||
Public Property Articles As New List(Of Article)
|
||||
Public Property Accounts As New List(Of Account)
|
||||
@@ -29,6 +33,8 @@ Namespace Winline
|
||||
Config = pConfig
|
||||
MandatorConfig = pMandatorConfig
|
||||
MappingConfig = pMappingConfig
|
||||
FileEx = New File(pLogConfig)
|
||||
Years = LoadEconomicYears()
|
||||
End Sub
|
||||
|
||||
''' <summary>
|
||||
@@ -65,8 +71,14 @@ Namespace Winline
|
||||
Public Property Year As Integer
|
||||
End Class
|
||||
|
||||
Private Function LoadEconomicYears() As IEnumerable(Of Integer)
|
||||
Dim oCurrentYear = Now.Year
|
||||
Dim oRange As IEnumerable(Of Integer) = Enumerable.Range(oCurrentYear - 10, 12).ToList()
|
||||
Return oRange
|
||||
End Function
|
||||
|
||||
Public Async Function LoadArticles(pMandator As Mandator) As Task
|
||||
|
||||
Public Async Function LoadArticlesAsync(pMandator As Mandator) As Task
|
||||
Logger.Info("Loading Articles for Mandator [{0}]", pMandator)
|
||||
Dim oYear = Config.GetWinLineYear()
|
||||
|
||||
@@ -104,7 +116,7 @@ Namespace Winline
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Async Function LoadPackingUnits(pMandator As Mandator) As Task
|
||||
Public Async Function LoadPackingUnitsAsync(pMandator As Mandator) As Task
|
||||
Logger.Info("Loading Packing Units for Mandator [{0}]", pMandator)
|
||||
Dim oYear = Config.GetWinLineYear()
|
||||
|
||||
@@ -155,7 +167,7 @@ Namespace Winline
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Async Function LoadAccounts(pMandator As Mandator) As Task
|
||||
Public Async Function LoadAccountsAsync(pMandator As Mandator) As Task
|
||||
Logger.Info("Loading Accounts for Mandator [{0}]", pMandator)
|
||||
Dim oYear = Config.GetWinLineYear()
|
||||
|
||||
@@ -207,7 +219,7 @@ Namespace Winline
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Async Function LoadMandators() As Task
|
||||
Public Async Function LoadMandatorsAsync() As Task
|
||||
Try
|
||||
Dim oSQL = "SELECT [c000], [c003], [c004] FROM [cwlsystem].[dbo].[T001SRV] (NOLOCK)"
|
||||
Dim oTable = Await Database.GetDatatableAsync(oSQL)
|
||||
@@ -241,13 +253,9 @@ Namespace Winline
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Sub LoadEconomicYears()
|
||||
Dim oCurrentYear = Now.Year
|
||||
Dim oRange As IEnumerable(Of Integer) = Enumerable.Range(oCurrentYear - 10, 12).ToList()
|
||||
Years = oRange
|
||||
End Sub
|
||||
|
||||
Public Async Function LoadDocumentKinds(pMandator As Mandator) As Task
|
||||
|
||||
Public Async Function LoadDocumentKindsAsync(pMandator As Mandator) As Task
|
||||
Dim oYear As Integer = Config.GetWinLineYear()
|
||||
|
||||
Try
|
||||
@@ -388,11 +396,11 @@ Namespace Winline
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Async Function TryGetArticlePrice(pArticle As String, pAccountNumber As String, pQuantity As String, pDocumentDate As Date, pMandator As Mandator, pTemplate As Template) As Task(Of Double)
|
||||
Return Await TryGetArticlePrice(pArticle, pAccountNumber, pQuantity, pDocumentDate, pMandator, pTemplate, 0)
|
||||
Public Async Function TryGetArticlePriceAsync(pArticle As String, pAccountNumber As String, pQuantity As String, pDocumentDate As Date, pMandator As Mandator, pTemplate As Template) As Task(Of Double)
|
||||
Return Await TryGetArticlePriceAsync(pArticle, pAccountNumber, pQuantity, pDocumentDate, pMandator, pTemplate, 0)
|
||||
End Function
|
||||
|
||||
Public Async Function TryGetArticlePrice(pArticle As String, pAccountNumber As String, pQuantity As String, pDocumentDate As Date, pMandator As Mandator, pTemplate As Template, pWaitingDays As Integer) As Task(Of Double)
|
||||
Public Async Function TryGetArticlePriceAsync(pArticle As String, pAccountNumber As String, pQuantity As String, pDocumentDate As Date, pMandator As Mandator, pTemplate As Template, pWaitingDays As Integer) As Task(Of Double)
|
||||
Try
|
||||
Dim oUserName = Environment.UserName
|
||||
Dim oYear As Integer = Config.GetWinLineYear()
|
||||
@@ -475,7 +483,7 @@ Namespace Winline
|
||||
''' <summary>
|
||||
''' This function is completely SCHAUM related.
|
||||
''' </summary>
|
||||
Public Async Function TryGetWaitingDays(pDocumentKind As Integer, pMandator As Mandator) As Task(Of Integer)
|
||||
Public Async Function TryGetWaitingDaysAsync(pDocumentKind As Integer, pMandator As Mandator) As Task(Of Integer)
|
||||
Try
|
||||
Dim oSql = $"
|
||||
SELECT [Karenztage].[u012] FROM [{pMandator.Database}].[dbo].[t670] As [Werksdefinition]
|
||||
@@ -894,6 +902,69 @@ Namespace Winline
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Private ReadOnly RunningNumberVersionRegex As Regex = New Regex("~\d{1,3}$")
|
||||
Private ReadOnly RunningNumberMaximumLength As Integer = 20
|
||||
|
||||
Public Async Function GetVersionedRunningNumberAsync(pDocument As Document, pMandator As Mandator, pAccountNumber As String, pRunningNumber As String) As Task(Of String)
|
||||
Try
|
||||
Dim oYear As Integer = Config.GetWinLineYear()
|
||||
Dim oSql As String = $"
|
||||
SELECT COUNT(*) FROM [{pMandator.Database}].[dbo].[v250]
|
||||
WHERE
|
||||
[c021] = '{pAccountNumber}' AND -- Account '
|
||||
[c022] = '{pRunningNumber}' AND -- Running Number '
|
||||
--[c035] = '4711' -- Belegart, needed?
|
||||
[c144] IS NULL AND -- Stornonummer Angebot
|
||||
[c145] IS NULL AND -- Stornonummer Auftrag
|
||||
[c146] IS NULL AND -- Stornonummer Lieferschein
|
||||
[c147] IS NULL AND -- Stornonummer Faktura
|
||||
[mesocomp] = '{pMandator.Id}' --AND [mesoyear] = {oYear}
|
||||
"
|
||||
|
||||
Dim oExistingCount = Await Database.GetScalarValueAsync(oSql)
|
||||
|
||||
If oExistingCount = 0 Then
|
||||
Logger.Debug("Running number [{0}] does not exist yet. Returning.")
|
||||
Return pRunningNumber
|
||||
Else
|
||||
Logger.Debug("Running number [{0}] already exists. Checking again.")
|
||||
Dim oVersionResult = FileEx.GetVersionedString(pRunningNumber, "~"c)
|
||||
|
||||
Dim oFinalLength As Integer = oVersionResult.Item1.Count + oVersionResult.Item2.ToString.Count + 1
|
||||
|
||||
If oFinalLength > RunningNumberMaximumLength Then
|
||||
Logger.Warn("Running number is too long ({0} chars total) and cannot be versioned. Versioning needs at least 2 characters.", oFinalLength)
|
||||
pDocument.AddDocumentError(DocumentErrorType.AttributeValidationFailed, "Das Feld Laufnummer hat die zulässige Länge überschritten.")
|
||||
Return pRunningNumber
|
||||
End If
|
||||
|
||||
Return Await GetVersionedRunningNumberAsync(pDocument, pMandator, pAccountNumber, $"{oVersionResult.Item1}~{oVersionResult.Item2}")
|
||||
End If
|
||||
|
||||
Catch ex As MultiToolException
|
||||
Logger.Error(ex)
|
||||
Throw ex
|
||||
|
||||
Catch ex As Exception
|
||||
Logger.Warn("Error while getting versioned running number for mandator [{0}] and running number [{1}]", pMandator, pRunningNumber)
|
||||
Logger.Error(ex)
|
||||
Return Nothing
|
||||
End Try
|
||||
End Function
|
||||
|
||||
Public Function VersionNumber(pNumber As String) As String
|
||||
Dim oRunningNumberBase As String
|
||||
|
||||
If RunningNumberVersionRegex.IsMatch(pNumber) Then
|
||||
Dim oSplitNumber = pNumber.Split("~")
|
||||
oRunningNumberBase = oSplitNumber.First()
|
||||
Dim oRunningNumberVersion As Integer = Integer.Parse(oSplitNumber.Last())
|
||||
Return $"{oRunningNumberBase}~{oRunningNumberVersion + 1}"
|
||||
Else
|
||||
Return $"{pNumber}~2"
|
||||
End If
|
||||
End Function
|
||||
|
||||
Public Async Function ExecuteFinalSQL(pDocument As ExportDocument, pTemplate As Template, pMandator As Mandator) As Task(Of Boolean)
|
||||
Try
|
||||
Dim oSql As String = Patterns.ReplaceForExport(pDocument, pMandator, pTemplate.FinalSQL)
|
||||
|
||||
Reference in New Issue
Block a user