Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Language Imports DigitalData.Modules.Database Imports ImporterShared Imports System.Text.RegularExpressions Namespace Winline Public Class Data Inherits BaseClass Private ReadOnly Database As MSSQLServer Private ReadOnly Config As Config Public Accounts As New List(Of Account) Public Mandators As New List(Of Mandator) Public Years As List(Of Integer) Public Const V21_ARTICLENUMBER = "c011" Public Const V50_ACCOUNTNUMBER = "c002" Public Const V50_ACCOUNTNAME = "c003" Public Const V05_ACCOUNTID = "c002" Public Const V05_ACCOUNTNAME = "c003" Public Const T357_KINDID = "c030" Public Const T357_KINDNAME = "c001" Public Const T01_DATABASEINFO = "c004" Public Const T01_MANDATORID = "c000" Public Const T01_MANDATORNAME = "c003" Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pConfig As Config) MyBase.New(pLogConfig, pLogConfig.GetLogger()) Database = pDatabase Config = pConfig End Sub Public Function GetWinLineYear(pYear As Integer) Return (pYear - 1900) * 12 End Function Public Function GetWinLineYear() Return GetWinLineYear(Config.GetYear) End Function Public Sub LoadAccounts(pMandator As Mandator) Logger.Info("Loading Accounts for Mandator [{0}]", pMandator) Try Dim oSQL = $"SELECT DISTINCT [c002], [c003] FROM [{pMandator.Server}].[{pMandator.Database}].[dbo].[v005] WHERE c139 IS NULL" Dim oTable = Database.GetDatatable(oSQL) Dim oAccounts As New List(Of Account) For Each oRow As DataRow In oTable.Rows oAccounts.Add(New Account With { .Id = oRow.Item(V05_ACCOUNTID), .Name = oRow.Item(V05_ACCOUNTNAME), .Mandator = pMandator.Id }) Next Accounts.AddRange(oAccounts) Logger.Info("[{0}] Accounts loaded for Mandator [{1}]", oAccounts.Count, pMandator) Catch ex As Exception Logger.Warn("Could not load Accounts for Mandator [{0}]", pMandator) Logger.Error(ex) End Try End Sub Public Sub LoadMandators() Try Dim oSQL = "SELECT [c000], [c003], [c004] FROM [cwlsystem].[dbo].[T001SRV] (NOLOCK)" Dim oTable = Database.GetDatatable(oSQL) Mandators.Clear() For Each oRow As DataRow In oTable.Rows Dim oDbInfo = SplitConnectionInfo(oRow) Dim oMandator = New Mandator With { .Id = oRow.Item(T01_MANDATORID), .Name = oRow.Item(T01_MANDATORNAME), .Database = oDbInfo.Item1, .Server = oDbInfo.Item2 } Dim oMandatorConfig As Config.MandatorConfig = Config.Mandators. Where(Function(m) oMandator.Id = m.Name). SingleOrDefault() If oMandatorConfig IsNot Nothing Then oMandator.IsWhitelisted = True oMandator.Regex = oMandatorConfig.ArticleRegex oMandator.Order = oMandatorConfig.Order End If Mandators.Add(oMandator) Next Logger.Info("[{0}] Mandators loaded", Mandators.Count) Catch ex As Exception Logger.Warn("Could not load Mandators") Logger.Error(ex) End Try End Sub Public Sub LoadEconomicYears() Dim oCurrentYear = Now.Year Dim oRange As IEnumerable(Of Integer) = Enumerable.Range(oCurrentYear - 10, 12).ToList() Years = oRange End Sub Public Function GetDocumentKinds(pMandator As Mandator, pYear As Integer) As List(Of DocumentKind) Dim oDocumentKinds As New List(Of DocumentKind) Try Dim oSQL = $" SELECT [c030], [c001] FROM [t357] (NOLOCK) WHERE ( [c001] LIKE 'Werk%(VK)' OR [c001] LIKE 'Werk%(WK)' ) AND [mesocomp] = '{pMandator.Id}' AND [mesoyear] = {pYear}" Dim oTable As DataTable = Database.GetDatatable(oSQL) If oTable.Rows.Count = 0 Then Logger.Warn("No DocumentKinds found") Return oDocumentKinds End If For Each oRow As DataRow In oTable.Rows oDocumentKinds.Add(New DocumentKind With { .Id = oRow.Item(T357_KINDID), .Name = oRow.Item(T357_KINDNAME) }) Next Return oDocumentKinds Catch ex As Exception Logger.Warn("Could not load DocumentKinds") Logger.Error(ex) Return oDocumentKinds End Try End Function Public Function TryGetAccount(pGLN As String, pMandator As Mandator) As Account Try If pGLN Is Nothing OrElse pGLN = String.Empty Then Return Nothing End If Dim oYear As Integer = GetWinLineYear() Dim oSQL = $" SELECT [c002], -- Kundennummer [c003] -- Kundenname FROM [{pMandator.Database}].[dbo].[v050] WHERE [c004] = 2 -- KontoTyp AND [c260] = '{pGLN}' AND [mesocomp] = '{pMandator.Id}' and [mesoyear] = {oYear}" Dim oTable As DataTable = Database.GetDatatable(oSQL) ' GLN not found in this Mandator, continue to next one If oTable.Rows.Count = 0 Then Logger.Debug("GLN [{0}] was not found in Mandator: [{1}]", pGLN, pMandator.Id) Return Nothing End If ' Duplicate GLN, exit and do nothing about this number If oTable.Rows.Count > 1 Then Logger.Warn("GLN [{0}] was found more than once in Mandator: [{1}]", pGLN, pMandator.Id) Return Nothing End If Dim oRow As DataRow = oTable.Rows.Item(0) Dim oAccountNumber As String = Utils.NotNull(oRow.Item(V50_ACCOUNTNUMBER), String.Empty) Dim oAccountName As String = Utils.NotNull(oRow.Item(V50_ACCOUNTNAME), String.Empty) Return New Account With { .Id = oAccountNumber, .Name = oAccountName, .Mandator = pMandator.Id } Catch ex As Exception Logger.Warn("Error while trying to get account for GLN [{0}]", pGLN) Logger.Error(ex) Return Nothing End Try End Function Public Function TryGetArticleNumber(pEAN As String, pMandator As Mandator) As String Try Dim oYear As Integer = GetWinLineYear() Dim oSQL As String = $" SELECT [c011], -- Artikelnummer [c003], -- Artikelbezeichnung [c075], -- EAN-Nummer [c123] -- Ersatzartikelnummer FROM [{pMandator.Database}].[dbo].[v021] WHERE [c075] = '{pEAN}' AND [mesocomp] = '{pMandator.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}]", pEAN, pMandator.Id) Return Nothing End If ' Duplicate EAN, exit and do nothing about this number If oTable.Rows.Count > 1 Then Logger.Warn("EAN [{0}] was found more than once", pEAN) Return Nothing End If Dim oRow As DataRow = oTable.Rows.Item(0) Dim oArticleNumber As String = Utils.NotNull(oRow.Item(V21_ARTICLENUMBER), String.Empty) Return oArticleNumber Catch ex As Exception Logger.Error(ex) Return Nothing End Try End Function Public Function FindMatchingMandatorFromOrder(pData As Schemas.Orders.Input.MESOWebService) As Mandator Dim oPositions As List(Of Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT026) = pData.Items. Where(Function(i) TypeOf i Is Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT026). Select(Of Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT026)(Function(i) i). ToList() Dim oYear = GetWinLineYear() Dim oMandatorId As String = String.Empty Dim oWhitelistedMandators = 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(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 ''' ''' Turns a database info like "SQLCWLDATEN on SERVER\INSTANCE" into a Tuple of two strings ''' ''' ''' Private Function SplitConnectionInfo(pRow As DataRow) As Tuple(Of String, String) Dim oDbInfo = pRow.Item(T01_DATABASEINFO).ToString() Dim oSplittedInfo = SplitAtString(oDbInfo.ToUpper, "ON") Dim oServer = oSplittedInfo.Item(1).Trim() Dim oDatabase = oSplittedInfo.Item(0).Trim() If oDatabase.StartsWith("SQL") Then oDatabase = oDatabase.Remove(0, 3) End If Return New Tuple(Of String, String)(oDatabase, oServer) End Function Private Function SplitAtString(pStringToSplit As String, pDelimiter As String) As List(Of String) Dim oDelimiter As String() = New String(0) {pDelimiter} Return pStringToSplit. Split(oDelimiter, StringSplitOptions.None). ToList() End Function End Class End Namespace