2022-04-20 11:46:14 +02:00

976 lines
42 KiB
VB.net

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
Namespace Winline
Public Class WinlineData
Inherits BaseClass
Private ReadOnly Property Config As GeneralConfig
Private ReadOnly Property MandatorConfig As MandatorConfig
Private ReadOnly Property MappingConfig As MappingConfig
Private ReadOnly Property Patterns As Patterns
Public Property Articles As New List(Of Article)
Public Property Accounts As New List(Of Account)
Public Property PackingUnits As New List(Of PackingUnit)
Public Property Mandators As New List(Of Mandator)
Public Property DocumentKinds As New List(Of DocumentKind)
Public Property Years As List(Of Integer)
Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pConfig As GeneralConfig, pMappingConfig As MappingConfig, pMandatorConfig As MandatorConfig)
MyBase.New(pLogConfig, pDatabase)
Patterns = New Patterns(pLogConfig, pConfig)
Config = pConfig
MandatorConfig = pMandatorConfig
MappingConfig = pMappingConfig
End Sub
''' <summary>
''' Winline Doctype.
'''
''' Used for filtering Documents when exporting and determining the type of document (sales/purchasing)
''' </summary>
Public Enum DocumentType
Undefined = 0
OutgoingOffer = 1
OutgoingOrder = 2
OutgoingDeliveryNote = 3
OutgoingInvoice = 4
IncomingOffer = 5
IncomingOrder = 6
IncomingDeliveryNote = 7
IncomingInvoice = 8
End Enum
Public Enum DocumentTypeCategory
Undefined = 0
Outgoing = 1
Incoming = 2
End Enum
Public Class GetDocumentArgs
Public Property Account As Account
Public Property Kinds As List(Of DocumentKind)
Public Property DateFrom As Date
Public Property DateTo As Date
Public Property DocNumberFrom As String
Public Property DocNumberTo As String
Public Property ShowExported As Boolean
Public Property Year As Integer
End Class
Public Async Function LoadArticles(pMandator As Mandator) As Task
Logger.Info("Loading Articles for Mandator [{0}]", pMandator)
Dim oYear = Config.GetWinLineYear()
Try
Dim oSQL = $"
SELECT DISTINCT
[c002], -- Artikelnummer
[c003], -- Bezeichnung
[c075] -- EAN
FROM [{pMandator.Server}].[{pMandator.Database}].[dbo].[v021]
WHERE
mesocomp = '{pMandator.Id}'
AND mesoyear = {oYear}"
Dim oTable = Await Database.GetDatatableAsync(oSQL)
Dim oArticles As New List(Of Article)
For Each oRow As DataRow In oTable.Rows
Dim oArticleId As String = ItemEx(oRow, V21_ARTICLENUMBER, String.Empty)
Dim oArticleDescription As String = ItemEx(oRow, V21_ARTICLEDESCRIPTION, String.Empty)
Dim oEAN As String = ItemEx(oRow, V21_EAN, String.Empty)
oArticles.Add(New Article With {
.Id = oArticleId,
.Name = oArticleDescription,
.EAN = oEAN,
.Mandator = pMandator
})
Next
Articles.AddRange(oArticles)
Logger.Info("[{0}] Articles loaded for Mandator [{1}]", oArticles.Count, pMandator)
Catch ex As Exception
Logger.Warn("Could not load Articles for Mandator [{0}]", pMandator)
Logger.Error(ex)
End Try
End Function
Public Async Function LoadPackingUnits(pMandator As Mandator) As Task
Logger.Info("Loading Packing Units for Mandator [{0}]", pMandator)
Dim oYear = Config.GetWinLineYear()
Try
Dim oSQL = $"
SELECT DISTINCT
[c002], -- Name
[c003], -- Description
[c004], -- Description 2
[c005], -- Unit
[c006], -- Value/Factor
[c007] -- Flag (?)
FROM [{pMandator.Server}].[{pMandator.Database}].[dbo].[t346]
WHERE
mesocomp = '{pMandator.Id}'
AND mesoyear = {oYear}"
Dim oTable = Await Database.GetDatatableAsync(oSQL)
Dim oPackingUnits As New List(Of PackingUnit)
For Each oRow As DataRow In oTable.Rows
Dim oName As String = ItemEx(oRow, "c002", String.Empty)
Dim oDescription As String = ItemEx(oRow, "c003", String.Empty)
Dim oDescription2 As String = ItemEx(oRow, "c004", String.Empty)
Dim oUnit As Decimal = ItemEx(oRow, "c005", 0.0)
Dim oFactor As Decimal = ItemEx(oRow, "c006", 0.0)
Dim oFlag As Integer = ItemEx(oRow, "c007", 0)
oPackingUnits.Add(New PackingUnit With {
.Name = oName,
.Description = oDescription,
.Description2 = oDescription2,
.Unit = oUnit,
.Factor = oFactor,
.Flag = oFlag,
.Mandator = pMandator
})
Next
PackingUnits.AddRange(oPackingUnits)
If oPackingUnits.Count = 0 Then
Logger.Warn("No Packing Units loaded for Mandator [{0}]", pMandator)
End If
Logger.Info("[{0}] Packing Units loaded for Mandator [{1}]", oPackingUnits.Count, pMandator)
Catch ex As Exception
Logger.Warn("Could not load Packing Units for Mandator [{0}]", pMandator)
Logger.Error(ex)
End Try
End Function
Public Async Function LoadAccounts(pMandator As Mandator) As Task
Logger.Info("Loading Accounts for Mandator [{0}]", pMandator)
Dim oYear = Config.GetWinLineYear()
Try
Dim oSQL = $"
SELECT DISTINCT
[c002], -- Kundennummer
[c003], -- Kundenname
[c050], -- Straße
[c052], -- Ort
[c051], -- PLZ
[c260] -- GLN
FROM [{pMandator.Server}].[{pMandator.Database}].[dbo].[v050]
WHERE
c139 IS NULL
AND mesocomp = '{pMandator.Id}'
AND mesoyear = {oYear}"
Dim oTable = Await Database.GetDatatableAsync(oSQL)
Dim oAccounts As New List(Of Account)
For Each oRow As DataRow In oTable.Rows
Dim oAccountNumber As String = ItemEx(oRow, V50_ACCOUNTNUMBER, String.Empty)
Dim oAccountName As String = ItemEx(oRow, V50_ACCOUNTNAME, String.Empty)
Dim oStreetName As String = ItemEx(oRow, V50_STREETNAME, String.Empty)
Dim oZipCode As String = ItemEx(oRow, V50_ZIPCODE, String.Empty)
Dim oCityName As String = ItemEx(oRow, V50_CITYNAME, String.Empty)
Dim oGLN As String = ItemEx(oRow, V50_GLN, String.Empty)
oAccounts.Add(New Account With {
.Id = oAccountNumber,
.Name = oAccountName,
.StreetName = oStreetName,
.ZipCode = oZipCode,
.CityName = oCityName,
.GLN = oGLN,
.Mandator = pMandator
})
Next
Accounts.AddRange(oAccounts)
If oAccounts.Count = 0 Then
Logger.Warn("No Accounts loaded for Mandator [{0}]", pMandator)
End If
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 Function
Public Async Function LoadMandators() As Task
Try
Dim oSQL = "SELECT [c000], [c003], [c004] FROM [cwlsystem].[dbo].[T001SRV] (NOLOCK)"
Dim oTable = Await Database.GetDatatableAsync(oSQL)
Mandators.Clear()
For Each oRow As DataRow In oTable.Rows
Dim oDbInfo = SplitConnectionInfo(oRow)
Dim oMandator = New Mandator With {
.Id = ItemEx(oRow, T01_MANDATORID, String.Empty),
.Name = ItemEx(oRow, T01_MANDATORNAME, String.Empty),
.Database = oDbInfo.Item1,
.Server = oDbInfo.Item2
}
Dim oMandatorConfig As MandatorConfigItem = MandatorConfig.Items.
Where(Function(item) item.Name = oMandator.Id).
SingleOrDefault()
If oMandatorConfig IsNot Nothing Then
oMandator.IsWhitelisted = True
oMandator.Order = oMandatorConfig.OrderKey
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 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
Dim oYear As Integer = Config.GetWinLineYear()
Try
' TODO: This is Schaum specific, maybe move to config later
Dim oSQL = $"
SELECT
[c030],
[c001],
[mesocomp]
FROM [{pMandator.Database}].[dbo].[t357] (NOLOCK)
WHERE (
[c001] LIKE 'Werk%(VK)' OR
[c001] LIKE 'Werk%(WK)'
)
AND [mesocomp] = '{pMandator.Id}' AND [mesoyear] = {oYear}"
Dim oTable As DataTable = Await Database.GetDatatableAsync(oSQL)
Dim oKinds As New List(Of DocumentKind)
For Each oRow As DataRow In oTable.Rows
oKinds.Add(New DocumentKind With {
.Id = ItemEx(oRow, T357_KINDID, String.Empty),
.Name = ItemEx(oRow, T357_KINDNAME, String.Empty),
.Mandator = pMandator
})
Next
DocumentKinds.AddRange(oKinds)
Logger.Info("[{0}] DocumentKinds loaded for [{1}]", Mandators.Count, pMandator)
Catch ex As Exception
Logger.Warn("Could not load DocumentKinds")
Logger.Error(ex)
End Try
End Function
Public Function TryGetAccount(pGLN As String, pMandator As Mandator) As Account
Return TryGetAccount(pGLN, pMandator, "c260", String.Empty)
End Function
Public Function TryGetAccount(pGLN As String, pMandator As Mandator, pSearchField As String) As Account
Return TryGetAccount(pGLN, pMandator, pSearchField, String.Empty)
End Function
Public Function TryGetAccount(pIdentifier As String, pMandator As Mandator, pSearchField As String, pAlternativeField As String) As Account
Try
If pIdentifier Is Nothing OrElse pIdentifier = String.Empty Then
Return Nothing
End If
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL = $"
SELECT
[c002], -- Kundennummer
[c003], -- Kundenname
[c050], -- Straße
[c052], -- Ort
[c051], -- PLZ
* -- Everything else
FROM [{pMandator.Database}].[dbo].[v050]
WHERE [c004] IN (2, 3) -- KontoTyp Debitor/Kreditor
AND [{pSearchField}] = '{pIdentifier}'
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}]", pIdentifier, 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}]", pIdentifier, pMandator.Id)
Return Nothing
End If
Dim oRow As DataRow = oTable.Rows.Item(0)
Dim oAccountNumber As String = ItemEx(oRow, V50_ACCOUNTNUMBER, String.Empty)
Dim oAccountName As String = ItemEx(oRow, V50_ACCOUNTNAME, String.Empty)
Dim oStreetName As String = ItemEx(oRow, V50_STREETNAME, String.Empty)
Dim oZipCode As String = ItemEx(oRow, V50_ZIPCODE, String.Empty)
Dim oCityName As String = ItemEx(oRow, V50_CITYNAME, String.Empty)
If pAlternativeField <> String.Empty Then
Dim oAlternativeValue = ItemEx(oRow, pAlternativeField, String.Empty)
If oAlternativeValue <> String.Empty Then
Return TryGetAccount(oAlternativeValue, pMandator, "c002")
End If
End If
Return New Account With {
.Id = oAccountNumber,
.Name = oAccountName,
.StreetName = oStreetName,
.CityName = oCityName,
.ZipCode = oZipCode,
.Mandator = pMandator
}
Catch ex As Exception
Logger.Warn("Error while trying to get account for GLN [{0}]", pIdentifier)
Logger.Error(ex)
Return Nothing
End Try
End Function
Public Function TryGetGLN(pAccountId As String, pMandator As Mandator) As String
Try
If pAccountId Is Nothing OrElse pAccountId = String.Empty Then
Return Nothing
End If
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL = $"
SELECT
[c260] -- GLN
FROM [{pMandator.Database}].[dbo].[v050]
WHERE [c004] IN (2, 3) -- KontoTyp Debitor/Kreditor
AND [c002] = '{pAccountId}'
AND [mesocomp] = '{pMandator.Id}' and [mesoyear] = {oYear}"
Dim oGLN As String = Database.GetScalarValue(oSQL)
' GLN not found in this Mandator, continue to next one
If oGLN Is Nothing Then
Logger.Debug("Account [{0}] was not found in Mandator: [{1}]", pAccountId, pMandator.Id)
Return Nothing
End If
Return oGLN
Catch ex As Exception
Logger.Warn("Error while trying to get GLN for Account [{0}]", pAccountId)
Logger.Error(ex)
Return Nothing
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)
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)
Try
Dim oUserName = Environment.UserName
Dim oYear As Integer = Config.GetWinLineYear()
Dim oDebug = Convert.ToInt32(LogConfig.Debug)
' TODO: pGroupPropertyID in config
' TODO: pTempTableSuffix in config (nice to have)
Dim oDateFrom = pDocumentDate.AddDays(pWaitingDays * -1)
Dim oDateTo = pDocumentDate
Dim oSQL As String = $"
EXEC [{pMandator.Database}].[dbo].[PRCUST_GET_ACCOUNT_PRICE_CONDITION_VALUES]
@pAccountNr = '{pAccountNumber}',
@pGroupNr = '*',
@pProductNr = '{pArticle}',
@pProductQuantity = '<={pQuantity}',
@pProductPriceDateFrom = '{oDateFrom:dd.MM.yyyy}',
@pProductPriceDateTo = '{oDateTo:dd.MM.yyyy}',
@pmesocomp = '{pMandator.Id}',
@pmesoyear = {oYear},
@pGroupPropertyID = 1008,
@pTempTableSuffix = 'MT_USER_{oUserName}',
@pBatchID = NULL,
@pPrintDebug = 0,
@pLog2DB = {oDebug},
@pComment = 'Multitool/{pTemplate.Name}',
@pResultType = 'CalcPricing'
"
Dim oTable As DataTable = Await Database.GetDatatableAsync(oSQL)
If oTable.Rows.Count = 0 Then
Logger.Debug("Price for article [{0}] and Account [{1}] was not found in Mandator: [{2}]", pArticle, pAccountNumber, pMandator.Id)
Return Nothing
End If
Dim oRow As DataRow = oTable.Rows.Item(0)
Dim oPrice As Double = oRow.Item("PRICE")
Dim oPackingUnit As PackingUnit = MaybeGetPackingUnit(pTemplate, oRow, pMandator)
If oPackingUnit IsNot Nothing AndAlso oPackingUnit.Factor > 0 Then
oPrice *= oPackingUnit.Factor
End If
Return oPrice
Catch ex As Exception
Logger.Warn("Error while trying to get Price for Article [{0}] and Account [{1}]", pArticle, pAccountNumber)
Logger.Error(ex)
Return Nothing
End Try
End Function
Private Function MaybeGetPackingUnit(pTemplate As Template, oRow As DataRow, pMandator As Mandator) As PackingUnit
Dim oPackingUnit As PackingUnit = Nothing
Select Case pTemplate.DocTypeCategory
Case DocumentTypeCategory.Incoming
Dim oPackingUnitPurchasingName = oRow.ItemEx("PACKINGUNIT_PURCHASING", "")
Dim oPackingUnitPurchasing = PackingUnits.
Where(Function(unit) unit.Name.Equals(oPackingUnitPurchasingName) And unit.Mandator.Equals(pMandator)).
FirstOrDefault()
oPackingUnit = oPackingUnitPurchasing
Case DocumentTypeCategory.Outgoing
Dim oPackingUnitSalesName = oRow.ItemEx("PACKINGUNIT_SALES", "")
Dim oPackingUnitSales = PackingUnits.
Where(Function(unit) unit.Name.Equals(oPackingUnitSalesName) And unit.Mandator.Equals(pMandator)).
FirstOrDefault()
oPackingUnit = oPackingUnitSales
End Select
Return oPackingUnit
End Function
''' <summary>
''' This function is completely SCHAUM related.
''' </summary>
Public Async Function TryGetWaitingDays(pDocumentKind As Integer, pMandator As Mandator) As Task(Of Integer)
Try
Dim oSql = $"
SELECT [Karenztage].[u012] FROM [{pMandator.Database}].[dbo].[t670] As [Werksdefinition]
INNER JOIN [{pMandator.Database}].[dbo].[t670] AS [Werkszuordnung] ON [Werksdefinition].[u007] = [Werkszuordnung].[u007]
INNER JOIN [{pMandator.Database}].[dbo].[t670] AS [Karenztage] ON [Werksdefinition].[u000] = [Karenztage].[u032]
WHERE [Werksdefinition].[u011] In ({pDocumentKind},{pDocumentKind}*10)
AND [Werkszuordnung].[u006] = '%ConditionAccountNr%'
AND [Karenztage].[u002] = 'Karenztage'
"
Dim oWaitingDays As Integer = Await Database.GetScalarValueAsync(oSql)
If IsNothing(oWaitingDays) Then
oWaitingDays = 0
End If
Return oWaitingDays
Catch ex As Exception
Logger.Error(ex)
Return 0
End Try
End Function
Public Function TryGetArticleNumber(pEAN As String, pMandator As Mandator) As String
Try
Dim oYear As Integer = Config.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 = ItemEx(oRow, V21_MAINARTICLENUMBER, String.Empty)
Return oArticleNumber
Catch ex As Exception
Logger.Error(ex)
Return Nothing
End Try
End Function
Public Function TryGetEAN(pArticleNumber As String, pMandator As Mandator) As String
Try
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL As String = $"
SELECT
[c075] -- EAN-Nummer
FROM [{pMandator.Database}].[dbo].[v021]
WHERE [c011] = '{pArticleNumber}'
AND [mesocomp] = '{pMandator.Id}' AND [mesoyear] = {oYear}"
Dim oEAN As String = Database.GetScalarValue(oSQL)
' EAN not found in this Mandator, continue to next one
If oEAN Is Nothing Then
Logger.Debug("ArticleNumber [{0}] was not found in Mandator: [{1}]", pArticleNumber, pMandator.Id)
Return Nothing
End If
Return oEAN
Catch ex As Exception
Logger.Error(ex)
Return Nothing
End Try
End Function
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 = Config.GetWinLineYear()
Dim oSQL As String = $"
SELECT
[c000], -- Key
[c001], -- Name
[c063] -- Kontaktnummer
FROM [{pMandator.Database}].[dbo].[t045]
WHERE [c063] LIKE '{pAccountNumber}-%'
AND [mesocomp] = '{pMandator.Id}' AND [mesoyear] = {oYear}"
Dim oTable As DataTable = Database.GetDatatable(oSQL)
' Contact not found in this Mandator, continue to next one
If oTable.Rows.Count = 0 Then
Logger.Debug("Contact for Account [{0}] was not found in Mandator: [{1}]", pAccountNumber, pMandator.Id)
Return Nothing
End If
For Each oRow In oTable.Rows
oContacts.Add(New Contact With {
.Id = ItemEx(Of String)(oRow, T45_KEY, Nothing),
.Name = ItemEx(Of String)(oRow, T45_NAME, Nothing),
.Number = ItemEx(Of String)(oRow, T45_CONTACTNUMBER, Nothing)
})
Next
Return oContacts
Catch ex As Exception
Logger.Error(ex)
Return Nothing
End Try
End Function
Public Function GetReplacementArticleNumber(pArticleNumber As String, pMandator As Mandator)
Try
Dim oYear As Integer = Config.GetWinLineYear()
Dim oSQL As String = $"
SELECT
[c011], -- Artikelnummer
[c003], -- Artikelbezeichnung
[c075], -- EAN-Nummer
[c123] -- Ersatzartikelnummer
FROM [{pMandator.Database}].[dbo].[v021]
WHERE [c011] = '{pArticleNumber}'
AND [mesocomp] = '{pMandator.Id}' AND [mesoyear] = {oYear}"
Dim oTable As DataTable = Database.GetDatatable(oSQL)
' ArticleNumber not found in this Mandator, continue to next one
If oTable.Rows.Count = 0 Then
Logger.Debug("ArticleNumber [{0}] was not found in Mandator: [{1}]", pArticleNumber, pMandator.Id)
Return Nothing
End If
' Duplicate EAN, exit and do nothing about this number
If oTable.Rows.Count > 1 Then
Logger.Warn("ArticleNumber [{0}] was found more than once", pArticleNumber)
Return Nothing
End If
Dim oRow As DataRow = oTable.Rows.Item(0)
Dim oReplacementArticleNumber = ItemEx(Of String)(oRow, V21_REPLACEMENTARTICLENUMBER, Nothing)
If oReplacementArticleNumber Is Nothing Then
Return pArticleNumber
End If
Return GetReplacementArticleNumber(oReplacementArticleNumber, pMandator)
Catch ex As Exception
Logger.Error(ex)
Return Nothing
End Try
End Function
Public Function FindMatchingMandatorFromOrder(pData As Documents.Document) As Mandator
Dim oPositions = pData.Rows.
Where(Function(r) r.TableName.ToUpper.EndsWith("T026")).
ToList()
Dim oEANNumbers = oPositions.
Select(Function(p)
If p.Fields.ContainsKey("Artikelnummer") Then
Return p.Fields.Item("Artikelnummer").Original
Else
Return Nothing
End If
End Function).
Where(Function(ean) ean IsNot Nothing).
Distinct().
ToList()
Dim oYear = Config.GetWinLineYear()
Dim oMandatorId As String = String.Empty
Dim oWhitelistedMandators = Mandators.
Where(Function(m) m.IsWhitelisted = True).
OrderBy(Function(m) m.Order).
ToList()
For Each oEANNumber In oEANNumbers
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] = '{oEANNumber}'
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}]", oEANNumber, 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}]", oEANNumber, oMandator.Id)
Exit For
End If
Dim oRow As DataRow = oTable.Rows.Item(0)
Dim oArticleNumber As String = ItemEx(oRow, V21_MAINARTICLENUMBER, String.Empty)
' EAN was found, now we need to check it against the Regex of the current Mandantor, if one exists
Dim oMappingConfigItems = MappingConfig.Items.
Where(Function(item) item.DestinationName = "MANDATOR" And item.DestinationValue = oMandator.Id And item.SourceName = "ARTICLE").
ToList()
Logger.Debug("Processing [{0}] Mappings for Articlenumber [{1}]", oMappingConfigItems.Count, oArticleNumber)
' If not match was found, continune to next mandator.
' For a catch all mandator, a regex like ".+" is needed.
For Each oItem In oMappingConfigItems
Try
Dim oRegex As New Regex(oItem.SourceRegex)
Dim oMatch = oRegex.Match(oArticleNumber)
' If ArticleNumber matches the regex, we assign it and exit
If oMatch.Success Then
Return oMandator
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
Next ' CONFIG ITEM
Next ' MANDATOR
Next ' EAN
Return Nothing
End Function
Public Function GetDocuments(pMandator As Mandator, pTemplate As Template, pDocumentType As DocumentType, pOptions As GetDocumentArgs) As List(Of ExportDocument)
Try
Dim oYear As Integer = Config.GetWinLineYear()
If pOptions.Year > 0 Then
oYear = Config.GetWinLineYear(pOptions.Year)
End If
Dim oTypeConstraint
Select Case pDocumentType
Case DocumentType.OutgoingOffer
oTypeConstraint = $"T.c137 = 2 AND c139 = 1 AND "
Case DocumentType.OutgoingOrder
oTypeConstraint = $"T.c137 = 2 AND c139 = 2 AND "
Case DocumentType.OutgoingDeliveryNote
oTypeConstraint = $"T.c137 = 2 AND (c139 = 3 OR c139 = -3) AND "
Case DocumentType.OutgoingInvoice
oTypeConstraint = $"T.c137 = 2 AND c139 = 4 AND "
Case DocumentType.IncomingOffer
oTypeConstraint = $"T.c137 = 3 AND c139 = 1 AND "
Case DocumentType.IncomingOrder
oTypeConstraint = $"T.c137 = 3 AND c139 = 2 AND "
Case DocumentType.IncomingDeliveryNote
oTypeConstraint = $"T.c137 = 3 AND c139 = 3 AND "
Case DocumentType.IncomingInvoice
oTypeConstraint = $"T.c137 = 3 AND c139 = 4 AND "
Case Else
oTypeConstraint = ""
End Select
Dim oAccountConstraint = ""
If pOptions.Account IsNot Nothing Then
oAccountConstraint = $"T.c021 = '{pOptions.Account.Id}' AND "
End If
Dim oKindConstraint = ""
If pOptions.Kinds IsNot Nothing AndAlso pOptions.Kinds.Count > 0 Then
Dim oKindIdList = pOptions.Kinds.Select(Function(kind) kind.Id)
Dim oKindIdString = String.Join(",", oKindIdList)
oKindConstraint = $"T.c035 IN ({oKindIdString}) AND "
End If
Dim oDateFromConstraint = ""
If pOptions.DateFrom <> Date.MinValue Then
oDateFromConstraint = $"T2.DATE >= CAST('{pOptions.DateFrom:yyyy-MM-dd}' as date) AND "
End If
Dim oDateToConstraint = ""
If pOptions.DateTo <> Date.MinValue Then
oDateToConstraint = $"T2.DATE <= CAST('{pOptions.DateTo:yyyy-MM-dd}' as date) AND "
End If
Dim oDocNumberConstraint = ""
If pOptions.DocNumberFrom <> String.Empty Then
oDocNumberConstraint &= $"T.c044 >= '{pOptions.DocNumberFrom}' AND "
End If
If pOptions.DocNumberTo <> String.Empty Then
oDocNumberConstraint &= $"T.c044 <= '{pOptions.DocNumberTo}' AND "
End If
' Build the constraint so that the default view will show all documents that do not have an exported
' flag set to the current document type.
' Ex. Search for orders will not show exported flag = 2 by default
Dim oDocType As Integer = Math.Abs(Convert.ToInt32(pDocumentType))
Dim oExportedConstraint = $"(T.U010 IS NULL OR T.U010 <> {oDocType}) AND"
If pOptions.ShowExported Then
oExportedConstraint = ""
End If
Dim oSql = $"
SELECT
T2.DATE,
T.c139 DOCUMENT_TYPE,
T.c035 DOCUMENT_KIND,
T.c021 ACCOUNT_NUMBER,
T.c022 RUNNING_NUMBER,
T.c043 OFFER_NUMBER,
T.c027 OFFER_DATE,
T.c044 ORDER_NUMBER,
T.c028 ORDER_DATE,
T.c045 DELIVERY_NUMBER,
T.c029 DELIVERY_DATE,
T.c055 INVOICE_NUMBER,
T.c032 INVOICE_DATE,
T.c100 GROSS_AMOUNT,
T.c114 NET_AMOUNT,
T.U010 ALREADY_EXPORTED,
T.U011 EXPORTED_WHO,
T.U012 EXPORTED_WHEN,
T.U013 EXPORTED_FILE
FROM [{pMandator.Database}].[dbo].[T025] T
INNER JOIN (SELECT * FROM (
SELECT c021, c022, mesoyear, mesocomp, c027 [DATE] FROM [{pMandator.Database}].[dbo].[T025]
WHERE c139 = 1 OR c139 = -1
UNION
SELECT c021, c022, mesoyear, mesocomp, c028 [DATE] FROM [{pMandator.Database}].[dbo].[T025]
WHERE c139 = 2 OR c139 = -2
UNION
SELECT c021, c022, mesoyear, mesocomp, c029 [DATE] FROM [{pMandator.Database}].[dbo].[T025]
WHERE c139 = 3 OR c139 = -3
UNION
SELECT c021, c022, mesoyear, mesocomp, c032 [DATE] FROM [{pMandator.Database}].[dbo].[T025]
WHERE c139 = 4 OR c139 = -4
) QUERY) T2 ON T.c021 = T2.c021 AND T.c022 = T2.c022 AND T.mesoyear = T2.mesoyear AND T.mesocomp = T2.mesocomp
WHERE
{oTypeConstraint}
{oAccountConstraint}
{oKindConstraint}
{oExportedConstraint}
{oDocNumberConstraint}
{oDateFromConstraint}
{oDateToConstraint}
T.[mesocomp] = '{pMandator.Id}' AND T.[mesoyear] = {oYear}"
Dim oTable As DataTable = Database.GetDatatable(oSql)
Dim oDocuments As New List(Of ExportDocument)
For Each oRow As DataRow In oTable.Rows
Try
Dim oDocument = GetDocumentFromDataRow(oRow)
oDocument.Schema = pTemplate
oDocuments.Add(oDocument)
Catch ex As Exception
Logger.Error(ex)
End Try
Next
Return oDocuments
Catch ex As Exception
Logger.Warn("Error while loading documents for mandator [{0}] and document type [{1}]", pMandator, pDocumentType)
Logger.Error(ex)
Return Nothing
End Try
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)
Return Await Database.ExecuteNonQueryAsync(oSql)
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
Private Function GetDocumentFromDataRow(pDataRow As DataRow) As ExportDocument
Dim oAccountNumber = pDataRow.Item("ACCOUNT_NUMBER")
Dim oRunningNumber As String = pDataRow.Item("RUNNING_NUMBER")
Dim oDocumentType As Integer = pDataRow.Item("DOCUMENT_TYPE")
Dim oDocumentKind As Integer = pDataRow.Item("DOCUMENT_KIND")
Dim oGrossAmount As Double = pDataRow.Item("GROSS_AMOUNT")
Dim oNetAmount As Double = pDataRow.Item("NET_AMOUNT")
Dim oExported As Boolean = pDataRow.ItemEx("ALREADY_EXPORTED", False)
Dim oExportedWho As String = pDataRow.ItemEx("EXPORTED_WHO", "")
Dim oExportedWhen As Date = pDataRow.ItemEx(Of Date)("EXPORTED_WHEN", Nothing)
Dim oExportFile As String = pDataRow.ItemEx("EXPORTED_FILE", "")
Dim oDocumentNumber As String = Nothing
Dim oDocumentDate As Date = Nothing
Dim oDocumentDateColumn As String = Nothing
Dim oAccount = Accounts.
Where(Function(acc) acc.Id = oAccountNumber).
FirstOrDefault()
Dim oKind = DocumentKinds.
Where(Function(kind) kind.Id = oDocumentKind).
FirstOrDefault()
Select Case oDocumentType
Case 1
oDocumentNumber = pDataRow.Item("OFFER_NUMBER")
oDocumentDate = pDataRow.Item("OFFER_DATE")
oDocumentDateColumn = "c027"
Case 2
oDocumentNumber = pDataRow.Item("ORDER_NUMBER")
oDocumentDate = pDataRow.Item("ORDER_DATE")
oDocumentDateColumn = "c028"
Case 3
oDocumentNumber = pDataRow.Item("DELIVERY_NUMBER")
oDocumentDate = pDataRow.Item("DELIVERY_DATE")
oDocumentDateColumn = "c029"
Case 4
oDocumentNumber = pDataRow.Item("INVOICE_NUMBER")
oDocumentDate = pDataRow.Item("INVOICE_DATE")
oDocumentDateColumn = "c032"
End Select
Dim oDocument As New ExportDocument With {
.Account = oAccount,
.RunningNumber = oRunningNumber,
.Number = oDocumentNumber,
.[Date] = oDocumentDate,
.DateColumn = oDocumentDateColumn,
.Kind = oKind,
.GrossAmount = oGrossAmount,
.NetAmount = oNetAmount,
.IsExported = oExported,
.ExportedWhen = oExportedWhen,
.ExportedWho = oExportedWho,
.FilenameExport = oExportFile
}
Return oDocument
End Function
''' <summary>
''' Turns a database info like "SQLCWLDATEN on SERVER\INSTANCE" into a Tuple of two strings
''' </summary>
''' <param name="pRow"></param>
''' <returns></returns>
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