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 Public Config As Config Private Database As MSSQLServer Private Winline As WinLineInfo 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()) 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) 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() 'Dim oAccountNumber = Winline.TryGetAccountNumber(oHead.Fakt_Kontonummer, oMandator) 'If oAccountNumber IsNot Nothing Then ' oHead.Fakt_Kontonummer = oAccountNumber 'End If 'Dim oAccountNumber2 = Winline.TryGetAccountNumber(oHead.Lief_Kontonummer, oMandator) 'If oAccountNumber2 IsNot Nothing Then ' oHead.Lief_Kontonummer = oAccountNumber2 'End If 'For Each oPos In oPositions ' Dim oArticleNumber = Winline.TryGetArticleNumber(oPos.Artikelnummer, oMandator) ' If oArticleNumber Then ' oPos.Artikelnummer = oArticleNumber ' End If 'Next 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 = GetSerializer(oSchemaType) pDocument.Data = oSerializer.Deserialize(oReader) End Using ' Read data the second time, archive copy Using oReader = oNavigator.ReadSubtree() Dim oSerializer = 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 GetSerializer(pSchemaType As Type) As XmlSerializer Dim oSerializer As New XmlSerializer(pSchemaType) AddHandler oSerializer.UnknownAttribute, Sub(sender As Object, e As XmlAttributeEventArgs) Logger.Debug("Unknown Attribute: {0}", e.Attr) End Sub AddHandler oSerializer.UnknownElement, Sub(sender As Object, e As XmlElementEventArgs) Logger.Debug("Unknown Element: {0}", e.Element) End Sub AddHandler oSerializer.UnknownNode, Sub(sender As Object, e As XmlNodeEventArgs) Logger.Debug("Unknown Node: {0}", e.Name) End Sub AddHandler oSerializer.UnreferencedObject, Sub(sender As Object, e As UnreferencedObjectEventArgs) Logger.Debug("Unreferenced Object: {0}", e.UnreferencedId) End Sub Return oSerializer End Function Private Function GetTemplateName(pDocument As XPathNavigator) As String Dim oTemplateName = pDocument. SelectSingleNode("//MESOWebService"). GetAttribute("Template", "") Return oTemplateName End Function End Class