Report, Dynamic SQL

This commit is contained in:
Jonathan Jenne
2021-11-23 16:26:11 +01:00
parent cdff23b646
commit 2a1a119ff2
19 changed files with 2192 additions and 803 deletions

View File

@@ -1,4 +1,5 @@
Imports System.IO
Imports System.Text.RegularExpressions
Imports DigitalData.Modules.Logging
Imports MultiTool.Shared.Exceptions
Imports MultiTool.Shared.Templates
@@ -10,6 +11,8 @@ Namespace Documents
Inherits BaseClass
Private ReadOnly Winline As WinlineData
Private ReadOnly MappingConfig As MappingConfig
Private ReadOnly TemplateConfig As TemplateConfig
Public Property Files As New List(Of Document)
Public Event FileLoadComplete As EventHandler(Of FileLoadInfo)
@@ -19,9 +22,11 @@ Namespace Documents
Public FilesTotal As Integer
End Structure
Public Sub New(pLogConfig As LogConfig, pWinline As WinlineData)
Public Sub New(pLogConfig As LogConfig, pWinline As WinlineData, pMappingConfig As MappingConfig, pTemplateConfig As TemplateConfig)
MyBase.New(pLogConfig, pLogConfig.GetLogger())
Winline = pWinline
MappingConfig = pMappingConfig
TemplateConfig = pTemplateConfig
End Sub
@@ -77,7 +82,7 @@ Namespace Documents
Return oFileList.
Select(AddressOf WrapFileInfo).
Select(Function(d) IncludeSchema(d, pTemplate)).
Select(Function(d) LoadDocumentData(d, pTemplate)).
Select(Function(d) LoadDocumentData(d, pTemplate, TemplateConfig)).
Select(Function(d) MatchDataFromWinLine(d, Winline.Mandators, pMandator, pTemplate)).
SingleOrDefault()
Catch ex As Exception
@@ -106,33 +111,33 @@ Namespace Documents
''' </MESOWebService>
'''
''' </example>
Private Function LoadDocumentData(pDocument As Document, pTemplate As Template) 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)
Dim oDoc = XDocument.Parse(oText)
Dim oRootElement As XElement = XmlData.GetElement(oDoc, "MESOWebService")
If oRootElement Is Nothing Then
Throw New Exceptions.MalformedXmlException("Datei enthält kein MESOWebService-Element")
Throw New MalformedXmlException("Datei enthält kein MESOWebService-Element")
End If
Dim oTemplateName = XmlData.GetElementAttribute(oRootElement, "Template")
If oTemplateName Is Nothing Then
Throw New Exceptions.MalformedXmlException("Datei enthält kein Template-Attribut")
Throw New MalformedXmlException("Datei enthält kein Template-Attribut")
End If
Dim oTemplateType = XmlData.GetElementAttribute(oRootElement, "TemplateType")
If oTemplateType Is Nothing Then
Throw New Exceptions.MalformedXmlException("Datei enthält kein TemplateType-Attribut")
Throw New MalformedXmlException("Datei enthält kein TemplateType-Attribut")
End If
Dim oOption = XmlData.GetElementAttribute(oRootElement, "option")
If oOption Is Nothing Then
Throw New Exceptions.MalformedXmlException("Datei enthält kein option-Attribut")
Throw New MalformedXmlException("Datei enthält kein option-Attribut")
End If
Dim oPrintVoucher = XmlData.GetElementAttribute(oRootElement, "printVoucher")
If oPrintVoucher Is Nothing Then
Throw New Exceptions.MalformedXmlException("Datei enthält kein printVoucher-Attribut")
Throw New MalformedXmlException("Datei enthält kein printVoucher-Attribut")
End If
' The first level of Elements are the document Rows
@@ -155,7 +160,6 @@ Namespace Documents
Where(Function(t) t.Name = oTopLevelElement.Name).
FirstOrDefault()
For Each oColumn In oTable.Columns
Dim oSubElement = oSubElements.
Where(Function(e) e.Name = oColumn.Name).
@@ -175,7 +179,7 @@ Namespace Documents
.Original = oValue,
.Final = oValue,
.DataType = oColumn.DataType,
.Required = oRequired,
.IsRequired = oRequired,
.SortKey = oColumnSortKey
})
Else
@@ -193,46 +197,15 @@ Namespace Documents
oColumnSortKey += 1
Next
'For Each oSubElement As XElement In oSubElements
' Dim oTemplateField = oTable.Columns.
' Where(Function(c) c.Name = oSubElement.Name).
' SingleOrDefault()
' Dim oRequired = oTemplateField.IsRequired
' Dim oValue = oSubElement.Value.Trim()
' ' 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)
' ' oValue = oDate.ToString("d")
' 'End If
' oFields.Add(oSubElement.Name.ToString, New DocumentRow.FieldValue With {
' .Original = oValue,
' .Final = oValue,
' .DataType = oTemplateField.DataType,
' .Required = oRequired
' })
'Next
'' All fields in the schema are generated,
'' only creating the ones with values leads to wrong visual cues when asking for
'' docs/rows/fields with errors
'For Each oColumn In oTable.Columns
' If oFields.ContainsKey(oColumn.Name) Then
' Continue For
' End If
' Dim oColumnError = DocumentRow.FieldError.None
' If oColumn.Config?.IsRequired Then
' oColumnError = DocumentRow.FieldError.MissingValue
' End If
' oFields.Add(oColumn.Name, New DocumentRow.FieldValue With {
' .[Error] = oColumnError
' })
'Next
' Create Virtual fields
Dim oVirtualColumns = pTemplateConfig.Items.Where(Function(item) item.IsVirtual And item.Table = oTable.Name).ToList()
For Each oColumn In oVirtualColumns
oFields.Add(oColumn.Name, New DocumentRow.FieldValue With {
.DataType = oColumn.Type,
.IsRequired = oColumn.IsRequired,
.SortKey = oColumn.OrderKey
})
Next
' Create a DocumentRow object for each Top Level Element
Dim oRow = New DocumentRow With {
@@ -272,22 +245,21 @@ Namespace Documents
If oMandator Is Nothing Then
Logger.Warn("Mandator not found for File [{0}]", pDocument.File.Name)
Else
pDocument = MatchDocumentData(pDocument, oMandator, pTemplate)
pDocument = MatchDocumentDataFromHardcodedMappings(pDocument, oMandator, pTemplate)
pDocument = MatchDocumentDataFromDynamicMappings(pDocument, oMandator, MappingConfig)
End If
pDocument.Mandator = oMandator
Return pDocument
End Function
Private Function MatchDocumentData(pDocument As Document, pMandator As Mandator, pTemplate As Template) As Document
Dim oYear = Winline.GetWinLineYear()
Private Function MatchDocumentDataFromHardcodedMappings(pDocument As Document, pMandator As Mandator, pTemplate As Template) As Document
If pMandator Is Nothing Then
Return pDocument
End If
For Each oRow As DocumentRow In pDocument.Rows
Dim oTable = pTemplate.Tables.Where(Function(t) t.Name = oRow.Name).SingleOrDefault()
Dim oTable = pTemplate.Tables.Where(Function(table) table.Name = oRow.Name).SingleOrDefault()
For Each oField In oRow.Fields
If oTable Is Nothing Then
@@ -308,12 +280,68 @@ Namespace Documents
If oFunctionName = "EAN" Then
SetArticleByEAN(oRow, pMandator, oField.Key)
End If
Next
Next
Return pDocument
End Function
Private Function MatchDocumentDataFromDynamicMappings(pDocument As Document, pMandator As Mandator, pMappingConfig As MappingConfig) As Document
If pMandator Is Nothing Then
Return pDocument
End If
' We only want the mapping config for things in the xml file.
' that excludes things like setting the mandator.
Dim oFilteredMappingConfig = MappingConfig.Items.
Where(Function(item) item.DestinationItem <> String.Empty).
ToList()
For Each oMapping As MappingConfigItem In oFilteredMappingConfig
' Get Source Value
Dim oField As KeyValuePair(Of String, DocumentRow.FieldValue) = pDocument.Rows.
SelectMany(Function(row) row.Fields).
Where(Function(field) field.Key = oMapping.SourceItem).
FirstOrDefault()
' Test on Regex
Dim oRegex As New Regex(oMapping.SourceRegex)
If oRegex.IsMatch(oField.Value.Final) Then
pDocument.Rows.
SelectMany(Function(row) row.Fields).
Where(Function(field) field.Key = oMapping.DestinationItem).
SetValue(Sub(field)
field.Value.Final = oMapping.DestinationValue
End Sub)
Else
' don't do anything
End If
'Dim oRow = pDocument.Rows.Where(Function(row)
' Dim oTempRow = row.Fields.Where(Function(field) field.Key = oMapping.SourceItem).FirstOrDefault()
' If IsNothing(oTempRow) Then
' Return False
' Else Return True
' End If
' End Function).FirstOrDefault()
'Dim oField = oRow.Fields.Where(Function(field) field.Key = oMapping.SourceItem).FirstOrDefault()
Console.WriteLine()
Next
Return pDocument
End Function
Private Sub SetArticleByEAN(pRow As DocumentRow, pMandator As Mandator, pArticleField As String)
Dim oNumberItem As DocumentRow.FieldValue = pRow.Fields.GetOrDefault(pArticleField)
Dim oArticleNumber = Winline.TryGetArticleNumber(oNumberItem.Original, pMandator)

View File

@@ -56,12 +56,13 @@
Public Property Original As String = ""
Public Property External As String = ""
Public Property Final As String = ""
Public Property Required As Boolean = False
Public Property IsRequired As Boolean = False
Public Property IsVirtual As Boolean = False
Public Property SortKey As Integer = 0
Public ReadOnly Property HasError As Boolean
Get
Return Required = True And (
Return IsRequired = True And (
[Error] <> FieldError.None Or Final = String.Empty
)
End Get

View File

@@ -23,5 +23,15 @@
Return Now.Year
End Function
<DebuggerStepThrough>
Public Function GetWinLineYear()
Return GetWinLineYear(GetYear)
End Function
<DebuggerStepThrough>
Public Function GetWinLineYear(pYear As Integer)
Return (pYear - 1900) * 12
End Function
End Class
End Namespace

View File

@@ -1,5 +1,11 @@
Namespace Templates
Public Class MappingConfig
Public Class Entity
Public Const MANDATOR = "MANDATOR"
Public Const DOCUMENTTYPE = "DOCUMENTTYPE"
Public Const ARTICLE = "ARTICLE"
End Class
Public Property Items As New List(Of MappingConfigItem)
End Class

View File

@@ -12,6 +12,7 @@ Namespace Templates
Public Property IsReadOnly As Boolean
Public Property IsVisible As Boolean
Public Property IsRequired As Boolean
Public Property IsVirtual As Boolean
Public Property [Function] As ColumnFunction

View File

@@ -170,6 +170,7 @@ Namespace Templates
.IsReadOnly = oRow.ItemEx("IS_READ_ONLY", False),
.IsVisible = oRow.ItemEx("IS_VISIBLE", True),
.IsRequired = oRow.ItemEx("IS_REQUIRED", False),
.IsVirtual = oRow.ItemEx("IS_VIRTUAL", False),
.IsHead = oRow.ItemEx("IS_HEAD", True),
.[Function] = New TemplateConfigItem.ColumnFunction With {
.Id = oRow.ItemEx("FUNCTION_ID", 0),

View File

@@ -162,11 +162,6 @@ Namespace Winline
End Function
Private Function GetBytesFromDocument(pDocument As Document) As Byte()
' TODO: should "Lief_Name" be included here?
Dim oFilteredFields As New List(Of String) From {
"Fakt_Name"
}
Using oStream As New IO.MemoryStream()
Dim w = XmlWriter.Create(oStream)
@@ -187,7 +182,7 @@ Namespace Winline
Continue For
End If
If oFilteredFields.Contains(oField.Key) Then
If oField.Value.IsVirtual Then
Continue For
End If

View File

@@ -29,19 +29,9 @@ Namespace Winline
MappingConfig = pMappingConfig
End Sub
<DebuggerStepThrough>
Public Function GetWinLineYear(pYear As Integer)
Return (pYear - 1900) * 12
End Function
<DebuggerStepThrough>
Public Function GetWinLineYear()
Return GetWinLineYear(Config.GetYear)
End Function
Public Async Function LoadArticles(pMandator As Mandator) As Task
Logger.Info("Loading Articles for Mandator [{0}]", pMandator)
Dim oYear = GetWinLineYear()
Dim oYear = Config.GetWinLineYear()
Try
Dim oSQL = $"
@@ -80,7 +70,7 @@ Namespace Winline
Public Async Function LoadAccounts(pMandator As Mandator) As Task
Logger.Info("Loading Accounts for Mandator [{0}]", pMandator)
Dim oYear = GetWinLineYear()
Dim oYear = Config.GetWinLineYear()
Try
Dim oSQL = $"
@@ -167,7 +157,7 @@ Namespace Winline
End Sub
Public Async Function LoadDocumentKinds(pMandator As Mandator) As Task
Dim oYear As Integer = GetWinLineYear()
Dim oYear As Integer = Config.GetWinLineYear()
Try
' TODO: This is Schaum specific, maybe move to config later
@@ -208,7 +198,7 @@ Namespace Winline
Return Nothing
End If
Dim oYear As Integer = GetWinLineYear()
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL = $"
SELECT
[c002], -- Kundennummer
@@ -260,7 +250,7 @@ Namespace Winline
Public Function TryGetArticleNumber(pEAN As String, pMandator As Mandator) As String
Try
Dim oYear As Integer = GetWinLineYear()
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL As String = $"
SELECT
[c011], -- Artikelnummer
@@ -300,7 +290,7 @@ Namespace Winline
Public Function GetContacts(pAccountNumber As String, pMandator As Mandator) As List(Of Contact)
Try
Dim oContacts As New List(Of Contact)
Dim oYear As Integer = GetWinLineYear()
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL As String = $"
SELECT
[c000], -- Key
@@ -335,7 +325,7 @@ Namespace Winline
Public Function GetReplacementArticleNumber(pArticleNumber As String, pMandator As Mandator)
Try
Dim oYear As Integer = GetWinLineYear()
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL As String = $"
SELECT
[c011], -- Artikelnummer
@@ -391,7 +381,7 @@ Namespace Winline
Distinct().
ToList()
Dim oYear = GetWinLineYear()
Dim oYear = Config.GetWinLineYear()
Dim oMandatorId As String = String.Empty
' TODO: Instead load whitelisted mandators from database