MultiTool/EDIDocumentImport/DocumentLoader.vb
Jonathan Jenne 3abf4b6e87 WIP
2021-08-16 16:34:55 +02:00

243 lines
9.7 KiB
VB.net

Imports System.IO
Imports System.Xml
Imports System.Xml.Serialization
Imports System.Xml.XPath
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Language
Imports EDIDocumentImport.DocumentInfo
Imports System.Text.RegularExpressions
Imports EDIDocumentImport.WinLineInfo
Public Class DocumentLoader
Inherits Base
Private ReadOnly Config As Config
Private ReadOnly Database As MSSQLServer
Private ReadOnly Winline As WinLineInfo
Private ReadOnly Serializer As Serializer
Public Files As New List(Of Document)
Public Sub New(pLogConfig As LogConfig, pConfig As Config, pDatabase As MSSQLServer, pWinline As WinLineInfo)
MyBase.New(pLogConfig, pLogConfig.GetLogger())
Serializer = New Serializer(pLogConfig)
Config = pConfig
Database = pDatabase
Winline = pWinline
End Sub
Public Function LoadFiles() As Boolean
If Config.InputDirectory = String.Empty Then
Throw New ArgumentNullException("InputDirectory")
End If
Logger.Info("Loading files from directory [{0}]", Config.InputDirectory)
Try
Dim oDirectory As New DirectoryInfo(Config.InputDirectory)
Dim oFiles = oDirectory.GetFiles()
Logger.Debug("Found [{0}] files in directory [{1}]", oFiles.Count, oDirectory)
Files = oFiles.
Select(AddressOf WrapFileInfo).
Select(AddressOf LoadDocumentData).
Select(Function(oDocument)
Return MatchDataFromWinLine(oDocument, Winline.Mandators)
End Function).
ToList()
Return True
Catch ex As Exception
Logger.Error(ex)
Throw New IO.IOException($"Could not load files from directory {Config.InputDirectory}", ex)
End Try
End Function
Private Function FindMatchingMandatorFromOrder(pData As Orders.Input.MESOWebService) As Mandator
Dim oPositions As List(Of Orders.Input.MESOWebServiceEXIMVRG_ordersT026) = pData.Items.
Where(Function(i) TypeOf i Is Orders.Input.MESOWebServiceEXIMVRG_ordersT026).
Select(Of Orders.Input.MESOWebServiceEXIMVRG_ordersT026)(Function(i) i).
ToList()
Dim oYear = Winline.GetWinLineYear()
Dim oMandatorId As String = String.Empty
Dim oWhitelistedMandators = Winline.Mandators.
Where(Function(m) m.IsWhitelisted = True).
ToList()
For Each oPos In oPositions
For Each oMandator In oWhitelistedMandators
Dim oSQL As String = $"
SELECT
[c011], -- Artikelnummer
[c003], -- Artikelbezeichnung
[c075], -- EAN-Nummer
[c123] -- Ersatzartikelnummer
FROM [{oMandator.Database}].[dbo].[v021]
WHERE [c075] = '{oPos.Artikelnummer}'
AND [mesocomp] = '{oMandator.Id}' AND [mesoyear] = {oYear}"
Dim oTable As DataTable = Database.GetDatatable(oSQL)
' EAN not found in this Mandator, continue to next one
If oTable.Rows.Count = 0 Then
Logger.Debug("EAN [{0}] was not found in Mandator: [{1}]", oPos.Artikelnummer, oMandator.Id)
Continue For
End If
' Duplicate EAN, exit and do nothing about this manda
If oTable.Rows.Count > 1 Then
Logger.Warn("EAN [{0}] was found more than once. Skipping Mandator [{1}]", oPos.Artikelnummer, oMandator.Id)
Exit For
End If
Dim oRow As DataRow = oTable.Rows.Item(0)
Dim oArticleNumber As String = Utils.NotNull(oRow.Item(WinLineInfo.V21_ARTICLENUMBER), String.Empty)
' EAN was found, now we need to check it against the Regex of the current Mandantor, if one exists
If oMandator.Regex <> String.Empty Then
Try
Dim oRegex As New Regex(oMandator.Regex)
Dim oMatch = oRegex.Match(oArticleNumber)
' If ArticleNumber matches the regex, we assign it and exit
If oMatch.Success Then
oMandatorId = oMandator.Id
Exit For
Else
' If it does not match, continue to the next mandator
End If
Catch ex As Exception
Logger.Error(ex)
Logger.Warn("Regex [{0}] could not be parsed. Skipping.", oMandator.Regex)
End Try
Else
' If no regex was found, we assume the number matches
oMandatorId = oMandator.Id
End If
Next
Next
If oMandatorId = String.Empty Then
Return Nothing
Else
Return oWhitelistedMandators.
Where(Function(m) m.Id = oMandatorId).
Take(1).
SingleOrDefault()
End If
End Function
Private Function MatchDataFromWinLine(pDocument As DocumentInfo.Document, pMandators As List(Of WinLineInfo.Mandator)) As DocumentInfo.Document
Dim oMandators As List(Of WinLineInfo.Mandator) = pMandators.
Where(Function(m) m.IsWhitelisted = True).
OrderBy(Function(m) m.Order).
ToList()
If TypeOf pDocument.Data Is Orders.Input.MESOWebService Then
Dim oMandator = FindMatchingMandatorFromOrder(pDocument.Data)
Dim oData As Orders.Input.MESOWebService = MatchOrderData(pDocument.Data, oMandator)
If oMandator Is Nothing Then
Logger.Warn("Mandator not found for File [{0}]", pDocument.File.Name)
End If
pDocument.Mandator = oMandator
pDocument.Data = oData
End If
Return pDocument
End Function
Private Function MatchOrderData(pData As Orders.Input.MESOWebService, pMandator As WinLineInfo.Mandator) As Orders.Input.MESOWebService
Dim oYear = Winline.GetWinLineYear()
If pMandator Is Nothing Then
Return pData
End If
Dim oHead As Orders.Input.MESOWebServiceEXIMVRG_ordersT025 = pData.Items.
Where(Function(h) TypeOf h Is Orders.Input.MESOWebServiceEXIMVRG_ordersT025).
SetValue(Sub(h)
Dim oAccountNumber = Winline.TryGetAccountNumber(h.Fakt_Kontonummer, pMandator)
If oAccountNumber IsNot Nothing Then
h.Fakt_Kontonummer = oAccountNumber
End If
Dim oAccountNumber2 = Winline.TryGetAccountNumber(h.Lief_Kontonummer, pMandator)
If oAccountNumber2 IsNot Nothing Then
h.Lief_Kontonummer = oAccountNumber2
End If
End Sub).
FirstOrDefault()
Dim oPositions As List(Of Orders.Input.MESOWebServiceEXIMVRG_ordersT026) = pData.Items.
Where(Function(p) TypeOf p Is Orders.Input.MESOWebServiceEXIMVRG_ordersT026).
SetValue(Sub(p)
Dim oArticleNumber = Winline.TryGetArticleNumber(p.Artikelnummer, pMandator)
If oArticleNumber IsNot Nothing Then
p.Artikelnummer = oArticleNumber
End If
End Sub).
Select(Of Orders.Input.MESOWebServiceEXIMVRG_ordersT026)(Function(i) i).
ToList()
pData.Items = New List(Of Object) From {oHead}.
Concat(oPositions).
ToArray()
Return pData
End Function
Private Function WrapFileInfo(pFileInfo As FileInfo) As Document
Return New Document With {.File = pFileInfo}
End Function
Private Function LoadDocumentData(pDocument As Document) As Document
Using oFileStream As New FileStream(pDocument.FullName, FileMode.Open, FileAccess.Read, FileShare.Read)
Try
Dim oXmlDocument = New XPathDocument(oFileStream)
Dim oNavigator = oXmlDocument.CreateNavigator()
Dim oTemplateName = GetTemplateName(oNavigator)
Dim oDocumentType = GetDocumentTypeFromTemplateName(oTemplateName)
Dim oSchemaType = GetDocumentSchemaFromDocumentType(oDocumentType)
' Read data the first time, working copy
Using oReader = oNavigator.ReadSubtree()
Dim oSerializer = Serializer.GetSerializer(oSchemaType)
pDocument.Data = oSerializer.Deserialize(oReader)
End Using
' Read data the second time, archive copy
Using oReader = oNavigator.ReadSubtree()
Dim oSerializer = Serializer.GetSerializer(oSchemaType)
pDocument.DataOriginal = oSerializer.Deserialize(oReader)
End Using
pDocument.Type = oDocumentType
Return pDocument
Catch ex As Exception
Logger.Error(ex)
Dim oException As Exception = ex
If ex.InnerException IsNot Nothing Then
oException = ex.InnerException
End If
Throw oException
End Try
End Using
End Function
Private Function GetTemplateName(pDocument As XPathNavigator) As String
Dim oTemplateName = pDocument.
SelectSingleNode("//MESOWebService").
GetAttribute("Template", "")
Return oTemplateName
End Function
End Class