diff --git a/EDIDocumentImport/DocumentInfo.vb b/EDIDocumentImport/DocumentInfo.vb deleted file mode 100644 index 4993a5e..0000000 --- a/EDIDocumentImport/DocumentInfo.vb +++ /dev/null @@ -1,68 +0,0 @@ -Imports System.IO -Imports EDIDocumentImport.WinLineInfo - -Public Class DocumentInfo - - Public Class Document - Public File As FileInfo - Public Type As DocumentType - Public Mandator As Mandator - - Public Data As Object - Public DataOriginal As Object - Public DataOutput As Object - Public DataString As String - - Public Selected As Boolean = False - - Public ReadOnly Property FullName As String - Get - Return File?.FullName - End Get - End Property - - Public ReadOnly Property Name As String - Get - Return File?.Name - End Get - End Property - End Class - - Enum DocumentType - Order ' Auftrag - OrderResponse ' Bestellbestätigung - DispatchNotification ' Lieferavis/ Eingangs Lieferschein - Invoice ' Rechnung - End Enum - - Public Class SchemaTypes - Public Property RootSchemaType As Type - Public Property HeadSchemaType As Type - Public Property PositionSchemaType As Type - End Class - - Public Shared Property TypeMatchingTable As New Dictionary(Of String, DocumentType) From { - {"orders", DocumentType.Order}, - {"ordrsp", DocumentType.OrderResponse}, - {"desadv", DocumentType.DispatchNotification}, - {"invoic", DocumentType.Invoice} - } - - Public Shared Property SchemaMatchingTable As New Dictionary(Of DocumentType, Type) From { - {DocumentType.Order, GetType(Orders.Input.MESOWebService)} - } - - Public Shared Function GetDocumentTypeFromTemplateName(pTemplateName As String) As DocumentType - Return TypeMatchingTable. - Where(Function(kv) pTemplateName.Contains(kv.Key)). - Select(Function(kv) kv.Value). - FirstOrDefault() - End Function - - Public Shared Function GetDocumentSchemaFromDocumentType(pDocumentType As DocumentType) As Type - Return SchemaMatchingTable. - Where(Function(kv) pDocumentType = kv.Key). - Select(Function(kv) kv.Value). - FirstOrDefault() - End Function -End Class diff --git a/EDIDocumentImport/DocumentLoader.vb b/EDIDocumentImport/DocumentLoader.vb deleted file mode 100644 index e6a6437..0000000 --- a/EDIDocumentImport/DocumentLoader.vb +++ /dev/null @@ -1,242 +0,0 @@ -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 diff --git a/EDIDocumentImport/Exceptions.vb b/EDIDocumentImport/Exceptions.vb new file mode 100644 index 0000000..28c8192 --- /dev/null +++ b/EDIDocumentImport/Exceptions.vb @@ -0,0 +1,9 @@ +Public Class Exceptions + Public Class NoMandatorException + Inherits ApplicationException + + Public Sub New(message As String) + MyBase.New(message) + End Sub + End Class +End Class diff --git a/EDIDocumentImport/EDIDocumentImporter.vbproj b/EDIDocumentImport/ImporterForm.vbproj similarity index 93% rename from EDIDocumentImport/EDIDocumentImporter.vbproj rename to EDIDocumentImport/ImporterForm.vbproj index 99beecc..c32d195 100644 --- a/EDIDocumentImport/EDIDocumentImporter.vbproj +++ b/EDIDocumentImport/ImporterForm.vbproj @@ -6,9 +6,9 @@ AnyCPU {7AAEC958-955D-4F77-964C-38658684E424} WinExe - EDIDocumentImport.My.MyApplication - EDIDocumentImport - EDIDocumentImport + ImporterForm.My.MyApplication + ImporterForm + ImporterForm 512 WindowsForms v4.6.1 @@ -22,7 +22,7 @@ true true bin\Debug\ - EDIDocumentImport.xml + ImporterForm.xml 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 @@ -32,7 +32,7 @@ true true bin\Release\ - EDIDocumentImport.xml + ImporterForm.xml 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 @@ -148,18 +148,14 @@ - - - - + frmMain.vb Form - True @@ -182,12 +178,6 @@ Component - - - - - - @@ -237,7 +227,10 @@ - + + {dd1ac3b9-7595-4d3c-b9bb-97c46a480fa0} + ImporterShared + \ No newline at end of file diff --git a/EDIDocumentImport/My Project/Application.Designer.vb b/EDIDocumentImport/My Project/Application.Designer.vb index 34a301c..2f92bb4 100644 --- a/EDIDocumentImport/My Project/Application.Designer.vb +++ b/EDIDocumentImport/My Project/Application.Designer.vb @@ -32,7 +32,7 @@ Namespace My _ Protected Overrides Sub OnCreateMainForm() - Me.MainForm = Global.EDIDocumentImport.frmMain + Me.MainForm = Global.ImporterForm.frmMain End Sub End Class End Namespace diff --git a/EDIDocumentImport/My Project/Resources.Designer.vb b/EDIDocumentImport/My Project/Resources.Designer.vb index 4b30301..695c9ba 100644 --- a/EDIDocumentImport/My Project/Resources.Designer.vb +++ b/EDIDocumentImport/My Project/Resources.Designer.vb @@ -39,7 +39,7 @@ Namespace My.Resources Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager Get If Object.ReferenceEquals(resourceMan, Nothing) Then - Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("EDIDocumentImport.Resources", GetType(Resources).Assembly) + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("ImporterForm.Resources", GetType(Resources).Assembly) resourceMan = temp End If Return resourceMan diff --git a/EDIDocumentImport/My Project/Settings.Designer.vb b/EDIDocumentImport/My Project/Settings.Designer.vb index db35352..54e58f6 100644 --- a/EDIDocumentImport/My Project/Settings.Designer.vb +++ b/EDIDocumentImport/My Project/Settings.Designer.vb @@ -1,10 +1,10 @@ '------------------------------------------------------------------------------ ' -' This code was generated by a tool. -' Runtime Version:4.0.30319.42000 +' Dieser Code wurde von einem Tool generiert. +' Laufzeitversion:4.0.30319.42000 ' -' Changes to this file may cause incorrect behavior and will be lost if -' the code is regenerated. +' Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +' der Code erneut generiert wird. ' '------------------------------------------------------------------------------ @@ -13,42 +13,42 @@ Option Explicit On Namespace My - - _ + + _ Partial Friend NotInheritable Class MySettings Inherits Global.System.Configuration.ApplicationSettingsBase - - Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) - -#Region "My.Settings Auto-Save Functionality" + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings()),MySettings) + +#Region "Automatische My.Settings-Speicherfunktion" #If _MyType = "WindowsForms" Then - Private Shared addedHandler As Boolean + Private Shared addedHandler As Boolean - Private Shared addedHandlerLockObject As New Object + Private Shared addedHandlerLockObject As New Object - _ - Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) - If My.Application.SaveMySettingsOnExit Then - My.Settings.Save() - End If - End Sub + _ + Private Shared Sub AutoSaveSettings(sender As Global.System.Object, e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub #End If #End Region - + Public Shared ReadOnly Property [Default]() As MySettings Get - + #If _MyType = "WindowsForms" Then - If Not addedHandler Then - SyncLock addedHandlerLockObject - If Not addedHandler Then - AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings - addedHandler = True - End If - End SyncLock - End If + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If #End If Return defaultInstance End Get @@ -57,16 +57,16 @@ Namespace My End Namespace Namespace My - - _ + + _ Friend Module MySettingsProperty - - _ - Friend ReadOnly Property Settings() As Global.EDIDocumentImport.My.MySettings + + _ + Friend ReadOnly Property Settings() As Global.ImporterForm.My.MySettings Get - Return Global.EDIDocumentImport.My.MySettings.Default + Return Global.ImporterForm.My.MySettings.Default End Get End Property End Module diff --git a/EDIDocumentImport/Reports/OrderReport.Designer.vb b/EDIDocumentImport/Reports/OrderReport.Designer.vb index f23eff8..60f63bb 100644 --- a/EDIDocumentImport/Reports/OrderReport.Designer.vb +++ b/EDIDocumentImport/Reports/OrderReport.Designer.vb @@ -701,7 +701,7 @@ Partial Public Class OrderReport ' 'ObjectDataSource1 ' - Me.ObjectDataSource1.DataSource = GetType(EDIDocumentImport.Orders.ReportSource) + Me.ObjectDataSource1.DataSource = GetType(ImporterShared.Schemas.Orders.ReportSource) Me.ObjectDataSource1.Name = "ObjectDataSource1" ' 'OrderReport2 diff --git a/EDIDocumentImport/WinLineInfo.vb b/EDIDocumentImport/WinLineInfo.vb deleted file mode 100644 index bc8751a..0000000 --- a/EDIDocumentImport/WinLineInfo.vb +++ /dev/null @@ -1,201 +0,0 @@ -Imports DigitalData.Modules.Logging -Imports DigitalData.Modules.Database -Imports DigitalData.Modules.Language - -Public Class WinLineInfo - Inherits Base - - Private Database As MSSQLServer - Private 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 Class Account - Public Property Id As String - Public Property Name As String - Public Property Mandator As String - Public Overrides Function ToString() As String - Return $"{Name} ({Id})" - End Function - End Class - - Public Class Mandator - Public Property Id As String - Public Property Name As String - Public Property Database As String - Public Property Server As String - Public Property Regex As String - Public Property Order As Integer - Public Property IsWhitelisted As Boolean - - Public Overrides Function ToString() As String - Return $"{Name} ({Id})" - End Function - End Class - - 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) - Dim oSQL = $"SELECT [c002], [c003] FROM [{pMandator.Server}].[{pMandator.Database}].[dbo].[v005] WHERE c139 IS NULL" - Dim oTable = Database.GetDatatable(oSQL) - - For Each oRow As DataRow In oTable.Rows - Accounts.Add(New Account With { - .Id = oRow.Item("c002"), - .Name = oRow.Item("c003"), - .Mandator = pMandator.Id - }) - Next - End Sub - - Public Sub LoadMandators() - 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("c000"), - .Name = oRow.Item("c003"), - .Database = oDbInfo.Item1, - .Server = oDbInfo.Item2 - } - - Dim oMandatorConfig As Config.Mandator = 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 - 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 TryGetAccountNumber(pGLN As String, pMandator As Mandator) As String - Try - Dim oYear As Integer = GetWinLineYear() - Dim oSQL = $" - SELECT - [c002], -- Kundennummer - [c003] -- Kundenname - FROM [{pMandator.Database}].[dbo].[v050] - WHERE [c004] = 2 -- Was für ein Konto?? - 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 oArticleNumber As String = Utils.NotNull(oRow.Item(V50_ACCOUNTNUMBER), String.Empty) - Return oArticleNumber - Catch ex As Exception - 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 - - ''' - ''' Turns a database info like "CWLDATEN on SERVER\INSTANCE" into a Tuple of two strings - ''' - ''' - ''' - Private Function SplitConnectionInfo(pRow As DataRow) As Tuple(Of String, String) - Dim oDbInfo = pRow.Item("c004").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 diff --git a/EDIDocumentImport/WinLineWebService.vb b/EDIDocumentImport/WinLineWebService.vb deleted file mode 100644 index e97eade..0000000 --- a/EDIDocumentImport/WinLineWebService.vb +++ /dev/null @@ -1,139 +0,0 @@ -Imports DigitalData.Modules.Database -Imports DigitalData.Modules.Logging -Imports DigitalData.Modules.Filesystem -Imports AutoMapper -Imports AutoMapper.Configuration -Imports System.Globalization -Imports System.Xml.Serialization -Imports System.IO -Imports System.Xml -Imports System.Net - -Public Class WinLineWebService - Inherits Base - - Private ReadOnly Database As MSSQLServer - Private ReadOnly Config As Config - Private ReadOnly Serializer As Serializer - Private ReadOnly Mapper As AutoMapper.Mapper - Private ReadOnly MapperConfig As MapperConfiguration - Private ReadOnly FileEx As DigitalData.Modules.Filesystem.File - - Public Sub New(pLogConfig As LogConfig, pDatabase As MSSQLServer, pConfig As Config) - MyBase.New(pLogConfig, pLogConfig.GetLogger()) - FileEx = New DigitalData.Modules.Filesystem.File(pLogConfig) - Serializer = New Serializer(pLogConfig) - Database = pDatabase - Config = pConfig - MapperConfig = New MapperConfiguration(CreateMapperConfig()) - MapperConfig.AssertConfigurationIsValid() - Mapper = MapperConfig.CreateMapper() - End Sub - - Private Function CreateMapperConfig() As MapperConfigurationExpression - Dim oConfig As New MapperConfigurationExpression() - - oConfig.CreateMap(Of String, Integer)().ConvertUsing(New IntegerTypeConverter()) - oConfig.CreateMap(Of String, Decimal)().ConvertUsing(New DecimalTypeConverter()) - oConfig.CreateMap(Of String, DateTime)().ConvertUsing(New DateTimeTypeConverter()) - oConfig.CreateMap(Of Orders.Input.MESOWebService, Orders.Output.MESOWebService)() - oConfig.CreateMap(Of Orders.Input.MESOWebServiceEXIMVRG_ordersT025, Orders.Output.MESOWebServiceEXIMVRG_ordersT025)() - oConfig.CreateMap(Of Orders.Input.MESOWebServiceEXIMVRG_ordersT026, Orders.Output.MESOWebServiceEXIMVRG_ordersT026)() - - Return oConfig - End Function - - Public Function TransferDocumentToWinLine(pDocument As DocumentInfo.Document) As Boolean - If TypeOf pDocument.Data Is Orders.Input.MESOWebService Then - TransferOrderToWinline(pDocument) - End If - - Return True - End Function - - Private Function TransferOrderToWinline(pDocument As DocumentInfo.Document) - Dim oOrderOutput = TransformOrderToOutput(pDocument.Data) - Dim oWS As Config.WebServiceConfig = Config.Webservice - Dim oFilePath = SerializeOrder(oOrderOutput) - Dim oXmlString = IO.File.ReadAllText(oFilePath) - pDocument.DataOutput = oOrderOutput - - Dim oURL As String = $"{oWS.BaseUrl}/ewlservice/import?User={oWS.Username}&Password={oWS.Password}&Company={pDocument.Mandator.Id}&Type=30&Vorlage=EXIM-VRG_orders&ActionCode=1&Byref=0Data={oXmlString}" - Dim oRequest = WebRequest.Create(oURL) - oRequest.Method = "POST" - - Logger.Info("Creating HTTP Request to [{0}]", oWS.BaseUrl) - - ' TODO: Make better lol - - Using oResponse = oRequest.GetResponse() - Using oStream = oResponse.GetResponseStream() - Using oReader As New StreamReader(oStream) - Dim oData = oReader.ReadToEnd() - - End Using - End Using - End Using - - Return True - End Function - - Private Function TransformOrderToOutput(pData As Orders.Input.MESOWebService) As Orders.Output.MESOWebService - Dim oData As Orders.Input.MESOWebService = pData - Dim oResult As Orders.Output.MESOWebService = Mapper.Map(Of Orders.Output.MESOWebService)(oData) - - Dim oItems = oData.Items. - Select(Function(i) - If TypeOf i Is Orders.Input.MESOWebServiceEXIMVRG_ordersT025 Then - Return Mapper.Map(Of Orders.Output.MESOWebServiceEXIMVRG_ordersT025)(i) - Else - Return Mapper.Map(Of Orders.Output.MESOWebServiceEXIMVRG_ordersT026)(i) - End If - End Function). - ToList() - - oResult.Items = oItems.ToArray() - Return oResult - End Function - - Private Function SerializeOrder(pData As Orders.Output.MESOWebService) As String - Dim oSerializer = Serializer.GetSerializer(GetType(Orders.Output.MESOWebService)) - Dim oSettings As New XmlWriterSettings With { - .Indent = True - } - - Dim oPath As String = Path.Combine(FileEx.GetAppDataPath("Digital Data", "EDI Document Importer"), "WebService") - Dim oFileName As String = $"{Now:yyyy-MM-dd-f}.xml" - Dim oFilePath As String = Path.Combine(oPath, oFileName) - - If Directory.Exists(oPath) = False Then - Directory.CreateDirectory(oPath) - End If - - Using oWriter = XmlWriter.Create(oFilePath, oSettings) - oSerializer.Serialize(oWriter, pData) - End Using - - Return oFilePath - End Function - - Private Class DateTimeTypeConverter - Implements ITypeConverter(Of String, DateTime) - - Public Function Convert(source As String, destination As Date, context As ResolutionContext) As Date Implements ITypeConverter(Of String, Date).Convert - Return System.Convert.ToDateTime(source) - End Function - End Class - Private Class IntegerTypeConverter - Implements ITypeConverter(Of String, Integer) - Public Function Convert(source As String, destination As Integer, context As ResolutionContext) As Integer Implements ITypeConverter(Of String, Integer).Convert - Return System.Convert.ToInt32(source) - End Function - End Class - Private Class DecimalTypeConverter - Implements ITypeConverter(Of String, Decimal) - Public Function Convert(source As String, destination As Decimal, context As ResolutionContext) As Decimal Implements ITypeConverter(Of String, Decimal).Convert - Return System.Convert.ToDecimal(source, CultureInfo.InvariantCulture) - End Function - End Class -End Class diff --git a/EDIDocumentImport/frmMain.Designer.vb b/EDIDocumentImport/frmMain.Designer.vb index c7729e1..f7a4721 100644 --- a/EDIDocumentImport/frmMain.Designer.vb +++ b/EDIDocumentImport/frmMain.Designer.vb @@ -177,7 +177,7 @@ Partial Class frmMain ' Me.btnLoadDocuments.Caption = "Dokumente einlesen" Me.btnLoadDocuments.Id = 1 - Me.btnLoadDocuments.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.import + Me.btnLoadDocuments.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.import Me.btnLoadDocuments.Name = "btnLoadDocuments" ' 'txtFilesLoaded @@ -190,42 +190,42 @@ Partial Class frmMain ' Me.BarButtonItem1.Caption = "Eingangsverzeichnis öffnen" Me.BarButtonItem1.Id = 5 - Me.BarButtonItem1.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.open2 + Me.BarButtonItem1.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.open2 Me.BarButtonItem1.Name = "BarButtonItem1" ' 'BarButtonItem2 ' Me.BarButtonItem2.Caption = "Ausgangsverzeichnis öffnen" Me.BarButtonItem2.Id = 6 - Me.BarButtonItem2.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.open + Me.BarButtonItem2.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.open Me.BarButtonItem2.Name = "BarButtonItem2" ' 'BarButtonItem3 ' Me.BarButtonItem3.Caption = "Konfigurationsverzeichnis öffnen" Me.BarButtonItem3.Id = 7 - Me.BarButtonItem3.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.pagesetup + Me.BarButtonItem3.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.pagesetup Me.BarButtonItem3.Name = "BarButtonItem3" ' 'checkShowXml ' Me.checkShowXml.Caption = "XML Datei anzeigen" Me.checkShowXml.Id = 9 - Me.checkShowXml.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.showallfieldcodes + Me.checkShowXml.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.showallfieldcodes Me.checkShowXml.Name = "checkShowXml" ' 'BarButtonItem4 ' Me.BarButtonItem4.Caption = "Aktuelle Zeile übermitteln" Me.BarButtonItem4.Id = 10 - Me.BarButtonItem4.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.bo_validation + Me.BarButtonItem4.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.bo_validation Me.BarButtonItem4.Name = "BarButtonItem4" ' 'BarButtonItem5 ' Me.BarButtonItem5.Caption = "Markierte Zeilen übermitteln" Me.BarButtonItem5.Id = 11 - Me.BarButtonItem5.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.itemtypechecked + Me.BarButtonItem5.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.itemtypechecked Me.BarButtonItem5.Name = "BarButtonItem5" ' 'txtVersion @@ -239,28 +239,28 @@ Partial Class frmMain ' Me.BarButtonItem6.Caption = "Zeile löschen" Me.BarButtonItem6.Id = 13 - Me.BarButtonItem6.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.deletetablerows + Me.BarButtonItem6.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.deletetablerows Me.BarButtonItem6.Name = "BarButtonItem6" ' 'BarButtonItem7 ' Me.BarButtonItem7.Caption = "Artikel ersetzen" Me.BarButtonItem7.Id = 14 - Me.BarButtonItem7.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.tableproperties + Me.BarButtonItem7.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.tableproperties Me.BarButtonItem7.Name = "BarButtonItem7" ' 'BarButtonItem8 ' Me.BarButtonItem8.Caption = "Logverzeichnis öffnen" Me.BarButtonItem8.Id = 15 - Me.BarButtonItem8.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.singlepageview + Me.BarButtonItem8.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.singlepageview Me.BarButtonItem8.Name = "BarButtonItem8" ' 'btnPreviewReport ' Me.btnPreviewReport.Caption = "Belegvorschau für aktuelle Zeile öffnen" Me.btnPreviewReport.Id = 16 - Me.btnPreviewReport.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.preview + Me.btnPreviewReport.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.preview Me.btnPreviewReport.Name = "btnPreviewReport" ' 'btnReportPreview @@ -273,7 +273,7 @@ Partial Class frmMain ' Me.btnReloadDocument.Caption = "Aktuelles Dokument erneut laden" Me.btnReloadDocument.Id = 18 - Me.btnReloadDocument.ImageOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.paymentrefund + Me.btnReloadDocument.ImageOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.paymentrefund Me.btnReloadDocument.Name = "btnReloadDocument" ' 'RibbonPage1 @@ -907,7 +907,7 @@ Partial Class frmMain Me.Controls.Add(Me.SplitContainerControl3) Me.Controls.Add(Me.RibbonStatusBar) Me.Controls.Add(Me.RibbonControl) - Me.IconOptions.SvgImage = Global.EDIDocumentImport.My.Resources.Resources.tilelabels + Me.IconOptions.SvgImage = Global.ImporterForm.My.Resources.Resources.tilelabels Me.Name = "frmMain" Me.Ribbon = Me.RibbonControl Me.StatusBar = Me.RibbonStatusBar diff --git a/EDIDocumentImport/frmMain.vb b/EDIDocumentImport/frmMain.vb index dd3955b..68cd90c 100644 --- a/EDIDocumentImport/frmMain.vb +++ b/EDIDocumentImport/frmMain.vb @@ -1,36 +1,39 @@ Imports System.IO -Imports System.Globalization Imports DevExpress.XtraGrid.Views.Grid Imports DevExpress.XtraGrid.Columns Imports DevExpress.XtraRichEdit +Imports DevExpress.XtraEditors +Imports DevExpress.XtraReports.UI Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Database Imports DigitalData.Modules.Config Imports DigitalData.Controls.SQLConfig Imports DigitalData.GUIs.Common -Imports EDIDocumentImport.DocumentInfo -Imports EDIDocumentImport.DocumentPositions -Imports DevExpress.XtraEditors -Imports DevExpress.XtraReports.UI -Imports EDIDocumentImport.WinLineInfo +Imports ImporterShared.Documents +Imports ImporterShared.Winline +Imports ImporterShared.Schemas +Imports ImporterForm.DocumentPositions Public Class frmMain Public LogConfig As LogConfig Public Logger As Logger - Public ConfigManager As ConfigManager(Of Config) + Public ConfigManager As ConfigManager(Of ImporterShared.Config) Public Database As MSSQLServer Public DocumentLoader As DocumentLoader Public GridBuilder As GridBuilder - Public Winline As WinLineInfo - Public WebService As WinLineWebService + Public Winline As Data + Public WebService As WebService Private Sub frmMain_Load(sender As Object, e As EventArgs) Handles MyBase.Load Try txtVersion.Caption = String.Format(txtVersion.Caption, Application.ProductVersion) LogConfig = New LogConfig(LogConfig.PathType.AppData, Nothing, Nothing, "Digital Data", "EDI Document Importer") - ConfigManager = New ConfigManager(Of Config)(LogConfig, Application.UserAppDataPath, Application.CommonAppDataPath, Application.StartupPath) + ConfigManager = New ConfigManager(Of ImporterShared.Config)(LogConfig, + Application.UserAppDataPath, + Application.CommonAppDataPath, + Application.StartupPath) Logger = LogConfig.GetLogger() ' If ConnectionString does not exist, show SQL Config Form @@ -49,8 +52,8 @@ Public Class frmMain ' Initialize Database Dim oConnectionString = MSSQLServer.DecryptConnectionString(ConfigManager.Config.ConnectionString) Database = New MSSQLServer(LogConfig, oConnectionString) - Winline = New WinLineInfo(LogConfig, Database, ConfigManager.Config) - WebService = New WinLineWebService(LogConfig, Database, ConfigManager.Config) + Winline = New Data(LogConfig, Database, ConfigManager.Config) + WebService = New WebService(LogConfig, ConfigManager.Config) ' Load WinLine Data Winline.Mandators.Clear() @@ -72,7 +75,7 @@ Public Class frmMain GridBuilder.WithDefaults() ' Construct classes related to the xml data - DocumentLoader = New DocumentLoader(LogConfig, ConfigManager.Config, Database, Winline) + DocumentLoader = New DocumentLoader(LogConfig, Winline) Catch ex As Exception Logger.Error(ex) MsgBox(ex.Message, MsgBoxStyle.Critical, Text) @@ -81,7 +84,7 @@ Public Class frmMain Private Sub btnLoadDocuments_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles btnLoadDocuments.ItemClick Try - If DocumentLoader.LoadFiles() = True Then + If DocumentLoader.LoadFiles(ConfigManager.Config.InputDirectory) = True Then RibbonGroupData.Enabled = True RibbonGroupDocument.Enabled = True @@ -118,7 +121,12 @@ Public Class frmMain End Select Catch ex As Xml.XmlException - Dim oMessage As String = $"Fehler beim Verarbeiten des Dokuments {oDocument.Name}:{vbNewLine}{ex.Message}" + Dim oMessage As String = $"Fehler beim Laden des Dokuments {oDocument.Name}:{vbNewLine}{ex.Message}" + MsgBox(oMessage, MsgBoxStyle.Critical, Text) + Logger.Error(ex) + + Catch ex As Exceptions.NoMandatorException + Dim oMessage As String = $"Fehler beim Laden des Dokuments {oDocument.Name}:{vbNewLine}{ex.Message}" MsgBox(oMessage, MsgBoxStyle.Critical, Text) Logger.Error(ex) @@ -131,12 +139,13 @@ Public Class frmMain End Sub Private Sub ShowDocument(pDocument As Document, pData As Orders.Input.MESOWebService, pDataOriginal As Orders.Input.MESOWebService) + If pDocument.Mandator Is Nothing Then + Throw New Exceptions.NoMandatorException("Es konnte kein Mandant gefunden werden") + End If + Dim oHead = GetOrderHead(pData) Dim oHeadOriginal = GetOrderHead(pDataOriginal) - Dim oPositions = GetOrderPositions(pData) - Dim oPositionsOriginal = GetOrderPositions(pDataOriginal) - ' ====== Head Data ====== ' Original, Unreplaced Data @@ -151,11 +160,8 @@ Public Class frmMain txtDocumentReference.Text = oHead.Auftragsreferenz dateOrderDate.EditValue = oHead.Datum_AuftragBestellung - - - Dim oMandator = Winline.Mandators. - Where(Function(m) m.Id = pDocument.Mandator.Id). + Where(Function(m) m.Id = pDocument.Mandator). SingleOrDefault() If oMandator Is Nothing Then @@ -194,9 +200,17 @@ Public Class frmMain ' Where(Function(oAccount) oAccount.Id = oHead.Fakt_Kontonummer And oAccount.Mandator = cmbMandator.EditValue). ' SingleOrDefault() - ' ====== Position Data ====== + LoadPositionViewAndColumns(GridViewPositions, DocumentType.Order) + LoadPositionData(pData, pDataOriginal) + GridViewPositions.BestFitColumns() + End Sub + + Public Sub LoadPositionData(pData As Orders.Input.MESOWebService, pDataOriginal As Orders.Input.MESOWebService) + Dim oPositions = GetOrderPositions(pData) + Dim oPositionsOriginal = GetOrderPositions(pDataOriginal) Dim oPositionList As New List(Of OrderPosition) + For Each oPosition In oPositions Dim oPositionOriginal = oPositionsOriginal. Where(Function(p) p.Zeilennummer = oPosition.Zeilennummer). @@ -215,13 +229,10 @@ Public Class frmMain }) Next - LoadViewAndColumns(GridViewPositions, DocumentType.Order) GridControlPositions.DataSource = oPositionList - GridViewPositions.BestFitColumns() - End Sub - Public Sub LoadViewAndColumns(pView As GridView, pDocumentType As DocumentType) + Public Sub LoadPositionViewAndColumns(pView As GridView, pDocumentType As DocumentType) Dim oColumns As List(Of GridColumn) ' Create columns list depending on DocumentType @@ -326,7 +337,7 @@ Public Class frmMain Return oPositions End Function - Private Function GetFocusedDocument() As DocumentInfo.Document + Private Function GetFocusedDocument() As Document Dim oRowHandles = GridViewFiles.GetSelectedRows().ToList() Dim oDocument As Document = GridViewFiles.GetRow(oRowHandles.First()) Return oDocument diff --git a/EDIDocumentImporter.sln b/EDIDocumentImporter.sln index a1e55c2..458fc4f 100644 --- a/EDIDocumentImporter.sln +++ b/EDIDocumentImporter.sln @@ -3,7 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.31005.135 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "EDIDocumentImporter", "EDIDocumentImport\EDIDocumentImporter.vbproj", "{7AAEC958-955D-4F77-964C-38658684E424}" +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ImporterForm", "EDIDocumentImport\ImporterForm.vbproj", "{7AAEC958-955D-4F77-964C-38658684E424}" +EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ImporterShared", "ImporterShared\ImporterShared.vbproj", "{DD1AC3B9-7595-4D3C-B9BB-97C46A480FA0}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -15,6 +17,10 @@ Global {7AAEC958-955D-4F77-964C-38658684E424}.Debug|Any CPU.Build.0 = Debug|Any CPU {7AAEC958-955D-4F77-964C-38658684E424}.Release|Any CPU.ActiveCfg = Release|Any CPU {7AAEC958-955D-4F77-964C-38658684E424}.Release|Any CPU.Build.0 = Release|Any CPU + {DD1AC3B9-7595-4D3C-B9BB-97C46A480FA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DD1AC3B9-7595-4D3C-B9BB-97C46A480FA0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DD1AC3B9-7595-4D3C-B9BB-97C46A480FA0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DD1AC3B9-7595-4D3C-B9BB-97C46A480FA0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/EDIDocumentImport/Base.vb b/ImporterShared/BaseClass.vb similarity index 91% rename from EDIDocumentImport/Base.vb rename to ImporterShared/BaseClass.vb index 732eeae..61d97ae 100644 --- a/EDIDocumentImport/Base.vb +++ b/ImporterShared/BaseClass.vb @@ -1,6 +1,6 @@ Imports DigitalData.Modules.Logging -Public Class Base +Public Class BaseClass Public ReadOnly LogConfig As LogConfig Public ReadOnly Logger As Logger diff --git a/EDIDocumentImport/Config.vb b/ImporterShared/Config.vb similarity index 90% rename from EDIDocumentImport/Config.vb rename to ImporterShared/Config.vb index 2a1d32e..bf6ca69 100644 --- a/EDIDocumentImport/Config.vb +++ b/ImporterShared/Config.vb @@ -1,6 +1,6 @@ Public Class Config Public Property ConnectionString As String = "" - Public Property Mandators As New List(Of Mandator) + Public Property Mandators As New List(Of MandatorConfig) Public Property InputDirectory As String = "" Public Property OutputDirectory As String = "" Public Property Webservice As New WebServiceConfig() @@ -12,7 +12,7 @@ Public Property Password As String = "Password" End Class - Public Class Mandator + Public Class MandatorConfig Public Property Order As Integer Public Property Name As String Public Property ArticleRegex As String diff --git a/ImporterShared/Documents/Document.vb b/ImporterShared/Documents/Document.vb new file mode 100644 index 0000000..18fe299 --- /dev/null +++ b/ImporterShared/Documents/Document.vb @@ -0,0 +1,44 @@ +Imports System.IO +Imports EDIDocumentImport.Data + +Namespace Documents + Public Class Document + Public File As FileInfo + Public Type As DocumentType + Public Mandator As String + + Public Data As Object + Public DataOriginal As Object + Public DataOutput As Object + Public DataString As String + + Public Selected As Boolean = False + + Public ReadOnly Property FullName As String + Get + Return File?.FullName + End Get + End Property + + Public ReadOnly Property Name As String + Get + Return File?.Name + End Get + End Property + + Public Shared Function GetDocumentTypeFromTemplateName(pTemplateName As String) As DocumentType + Return DocumentMatch.TypeMatchingTable. + Where(Function(kv) pTemplateName.Contains(kv.Key)). + Select(Function(kv) kv.Value). + FirstOrDefault() + End Function + + Public Shared Function GetDocumentSchemaFromDocumentType(pDocumentType As DocumentType) As Type + Return DocumentMatch.SchemaMatchingTable. + Where(Function(kv) pDocumentType = kv.Key). + Select(Function(kv) kv.Value). + FirstOrDefault() + End Function + End Class + +End Namespace \ No newline at end of file diff --git a/ImporterShared/Documents/DocumentLoader.vb b/ImporterShared/Documents/DocumentLoader.vb new file mode 100644 index 0000000..dcc8712 --- /dev/null +++ b/ImporterShared/Documents/DocumentLoader.vb @@ -0,0 +1,166 @@ +Imports System.IO +Imports System.Text.RegularExpressions +Imports System.Xml.Serialization +Imports System.Xml.XPath +Imports DigitalData.Modules.Language +Imports DigitalData.Modules.Logging +Imports ImporterShared.Documents + +Namespace Documents + Public Class DocumentLoader + Inherits BaseClass + + Private ReadOnly Winline As Winline.Data + Private ReadOnly Serializer As Serializer + + Public Files As New List(Of Document) + + Public Sub New(pLogConfig As LogConfig, pWinline As Winline.Data) + MyBase.New(pLogConfig, pLogConfig.GetLogger()) + Winline = pWinline + Serializer = New Serializer(pLogConfig) + End Sub + + Public Function LoadFiles(pInputDirectory) As Boolean + If pInputDirectory = String.Empty Then + Throw New ArgumentNullException("InputDirectory") + End If + + Logger.Info("Loading files from directory [{0}]", pInputDirectory) + + Try + Dim oDirectory As New DirectoryInfo(pInputDirectory) + 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 {pInputDirectory}", ex) + + End Try + End Function + + + Private Function MatchDataFromWinLine(pDocument As Document, pMandators As List(Of Winline.Mandator)) As Document + Dim oMandators As List(Of Winline.Mandator) = pMandators. + Where(Function(m) m.IsWhitelisted = True). + OrderBy(Function(m) m.Order). + ToList() + + If TypeOf pDocument.Data Is Schemas.Orders.Input.MESOWebService Then + Dim oMandator = Winline.FindMatchingMandatorFromOrder(pDocument.Data) + Dim oData As Schemas.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.Id + pDocument.Data = oData + End If + + Return pDocument + End Function + + Private Function MatchOrderData(pData As Schemas.Orders.Input.MESOWebService, pMandator As Winline.Mandator) As Schemas.Orders.Input.MESOWebService + Dim oYear = Winline.GetWinLineYear() + + If pMandator Is Nothing Then + Return pData + End If + + Dim oHead As Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT025 = pData.Items. + Where(Function(h) TypeOf h Is Schemas.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 Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT026) = pData.Items. + Where(Function(p) TypeOf p Is Schemas.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 Schemas.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 = DocumentMatch.GetDocumentTypeFromTemplateName(oTemplateName) + Dim oSchemaType = DocumentMatch.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 + +End Namespace \ No newline at end of file diff --git a/ImporterShared/Documents/DocumentMatch.vb b/ImporterShared/Documents/DocumentMatch.vb new file mode 100644 index 0000000..644dfc3 --- /dev/null +++ b/ImporterShared/Documents/DocumentMatch.vb @@ -0,0 +1,28 @@ +Namespace Documents + Public Class DocumentMatch + Public Shared Property TypeMatchingTable As New Dictionary(Of String, DocumentType) From { + {"orders", DocumentType.Order}, + {"ordrsp", DocumentType.OrderResponse}, + {"desadv", DocumentType.DispatchNotification}, + {"invoic", DocumentType.Invoice} + } + + Public Shared Property SchemaMatchingTable As New Dictionary(Of DocumentType, Type) From { + {DocumentType.Order, GetType(Schemas.Orders.Input.MESOWebService)} + } + + Public Shared Function GetDocumentTypeFromTemplateName(pTemplateName As String) As DocumentType + Return TypeMatchingTable. + Where(Function(kv) pTemplateName.Contains(kv.Key)). + Select(Function(kv) kv.Value). + FirstOrDefault() + End Function + + Public Shared Function GetDocumentSchemaFromDocumentType(pDocumentType As DocumentType) As Type + Return SchemaMatchingTable. + Where(Function(kv) pDocumentType = kv.Key). + Select(Function(kv) kv.Value). + FirstOrDefault() + End Function + End Class +End Namespace \ No newline at end of file diff --git a/ImporterShared/Documents/DocumentType.vb b/ImporterShared/Documents/DocumentType.vb new file mode 100644 index 0000000..680b1bd --- /dev/null +++ b/ImporterShared/Documents/DocumentType.vb @@ -0,0 +1,8 @@ +Namespace Documents + Public Enum DocumentType + Order ' Auftrag + OrderResponse ' Bestellbestätigung + DispatchNotification ' Lieferavis/ Eingangs Lieferschein + Invoice ' Rechnung + End Enum +End Namespace diff --git a/EDIDocumentImport/IEnumerableEx.vb b/ImporterShared/IEnumerableEx.vb similarity index 100% rename from EDIDocumentImport/IEnumerableEx.vb rename to ImporterShared/IEnumerableEx.vb diff --git a/ImporterShared/ImporterShared.vbproj b/ImporterShared/ImporterShared.vbproj new file mode 100644 index 0000000..7a5b2a6 --- /dev/null +++ b/ImporterShared/ImporterShared.vbproj @@ -0,0 +1,146 @@ + + + + + Debug + AnyCPU + {DD1AC3B9-7595-4D3C-B9BB-97C46A480FA0} + Library + ImporterShared + ImporterShared + 512 + Windows + v4.6.1 + true + + + true + full + true + true + bin\Debug\ + ImporterShared.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + pdbonly + false + true + true + bin\Release\ + ImporterShared.xml + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + ..\packages\AutoMapper.10.1.1\lib\net461\AutoMapper.dll + + + + ..\..\DDMonorepo\Modules.Database\bin\Debug\DigitalData.Modules.Database.dll + + + ..\..\DDMonorepo\Modules.Filesystem\bin\Debug\DigitalData.Modules.Filesystem.dll + + + ..\..\DDMonorepo\Modules.Language\bin\Release\DigitalData.Modules.Language.dll + + + ..\..\DDMonorepo\Modules.Logging\bin\Release\DigitalData.Modules.Logging.dll + + + + ..\packages\NLog.4.7.10\lib\net45\NLog.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + True + Application.myapp + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + + + + + + + + VbMyResourcesResXFileCodeGenerator + Resources.Designer.vb + My.Resources + Designer + + + + + MyApplicationCodeGenerator + Application.Designer.vb + + + SettingsSingleFileGenerator + My + Settings.Designer.vb + + + + + + \ No newline at end of file diff --git a/ImporterShared/Mapper.vb b/ImporterShared/Mapper.vb new file mode 100644 index 0000000..e446b1c --- /dev/null +++ b/ImporterShared/Mapper.vb @@ -0,0 +1,47 @@ +Imports System.Globalization +Imports AutoMapper +Imports AutoMapper.Configuration + +Public Class Mapper + Private Shared MapperConfig As Object + + Public Shared Function GetMapper() + MapperConfig = New MapperConfiguration(CreateMapperConfig()) + MapperConfig.AssertConfigurationIsValid() + Return MapperConfig.CreateMapper() + End Function + + Private Shared Function CreateMapperConfig() As MapperConfigurationExpression + Dim oConfig As New MapperConfigurationExpression() + + oConfig.CreateMap(Of String, Integer)().ConvertUsing(New IntegerTypeConverter()) + oConfig.CreateMap(Of String, Decimal)().ConvertUsing(New DecimalTypeConverter()) + oConfig.CreateMap(Of String, DateTime)().ConvertUsing(New DateTimeTypeConverter()) + oConfig.CreateMap(Of Schemas.Orders.Input.MESOWebService, Schemas.Orders.Output.MESOWebService)() + oConfig.CreateMap(Of Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT025, Schemas.Orders.Output.MESOWebServiceEXIMVRG_ordersT025)() + oConfig.CreateMap(Of Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT026, Schemas.Orders.Output.MESOWebServiceEXIMVRG_ordersT026)() + + Return oConfig + End Function + + Private Class DateTimeTypeConverter + Implements ITypeConverter(Of String, DateTime) + + Public Function Convert(source As String, destination As Date, context As ResolutionContext) As Date Implements ITypeConverter(Of String, Date).Convert + Return System.Convert.ToDateTime(source) + End Function + End Class + Private Class IntegerTypeConverter + Implements ITypeConverter(Of String, Integer) + Public Function Convert(source As String, destination As Integer, context As ResolutionContext) As Integer Implements ITypeConverter(Of String, Integer).Convert + Return System.Convert.ToInt32(source) + End Function + End Class + Private Class DecimalTypeConverter + Implements ITypeConverter(Of String, Decimal) + Public Function Convert(source As String, destination As Decimal, context As ResolutionContext) As Decimal Implements ITypeConverter(Of String, Decimal).Convert + Return System.Convert.ToDecimal(source, CultureInfo.InvariantCulture) + End Function + End Class + +End Class diff --git a/ImporterShared/My Project/Application.Designer.vb b/ImporterShared/My Project/Application.Designer.vb new file mode 100644 index 0000000..88dd01c --- /dev/null +++ b/ImporterShared/My Project/Application.Designer.vb @@ -0,0 +1,13 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + diff --git a/ImporterShared/My Project/Application.myapp b/ImporterShared/My Project/Application.myapp new file mode 100644 index 0000000..758895d --- /dev/null +++ b/ImporterShared/My Project/Application.myapp @@ -0,0 +1,10 @@ + + + false + false + 0 + true + 0 + 1 + true + diff --git a/ImporterShared/My Project/AssemblyInfo.vb b/ImporterShared/My Project/AssemblyInfo.vb new file mode 100644 index 0000000..e943572 --- /dev/null +++ b/ImporterShared/My Project/AssemblyInfo.vb @@ -0,0 +1,35 @@ +Imports System +Imports System.Reflection +Imports System.Runtime.InteropServices + +' Allgemeine Informationen über eine Assembly werden über die folgenden +' Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, +' die einer Assembly zugeordnet sind. + +' Werte der Assemblyattribute überprüfen + + + + + + + + + + +'Die folgende GUID wird für die typelib-ID verwendet, wenn dieses Projekt für COM verfügbar gemacht wird. + + +' Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: +' +' Hauptversion +' Nebenversion +' Buildnummer +' Revision +' +' Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, +' indem Sie "*" wie unten gezeigt eingeben: +' + + + diff --git a/ImporterShared/My Project/Resources.Designer.vb b/ImporterShared/My Project/Resources.Designer.vb new file mode 100644 index 0000000..e109cc5 --- /dev/null +++ b/ImporterShared/My Project/Resources.Designer.vb @@ -0,0 +1,62 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My.Resources + + 'This class was auto-generated by the StronglyTypedResourceBuilder + 'class via a tool like ResGen or Visual Studio. + 'To add or remove a member, edit your .ResX file then rerun ResGen + 'with the /str option, or rebuild your VS project. + ''' + ''' A strongly-typed resource class, for looking up localized strings, etc. + ''' + _ + Friend Module Resources + + Private resourceMan As Global.System.Resources.ResourceManager + + Private resourceCulture As Global.System.Globalization.CultureInfo + + ''' + ''' Returns the cached ResourceManager instance used by this class. + ''' + _ + Friend ReadOnly Property ResourceManager() As Global.System.Resources.ResourceManager + Get + If Object.ReferenceEquals(resourceMan, Nothing) Then + Dim temp As Global.System.Resources.ResourceManager = New Global.System.Resources.ResourceManager("ImporterShared.Resources", GetType(Resources).Assembly) + resourceMan = temp + End If + Return resourceMan + End Get + End Property + + ''' + ''' Overrides the current thread's CurrentUICulture property for all + ''' resource lookups using this strongly typed resource class. + ''' + _ + Friend Property Culture() As Global.System.Globalization.CultureInfo + Get + Return resourceCulture + End Get + Set(ByVal value As Global.System.Globalization.CultureInfo) + resourceCulture = value + End Set + End Property + End Module +End Namespace diff --git a/ImporterShared/My Project/Resources.resx b/ImporterShared/My Project/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/ImporterShared/My Project/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/ImporterShared/My Project/Settings.Designer.vb b/ImporterShared/My Project/Settings.Designer.vb new file mode 100644 index 0000000..3ec5544 --- /dev/null +++ b/ImporterShared/My Project/Settings.Designer.vb @@ -0,0 +1,73 @@ +'------------------------------------------------------------------------------ +' +' This code was generated by a tool. +' Runtime Version:4.0.30319.42000 +' +' Changes to this file may cause incorrect behavior and will be lost if +' the code is regenerated. +' +'------------------------------------------------------------------------------ + +Option Strict On +Option Explicit On + + +Namespace My + + _ + Partial Friend NotInheritable Class MySettings + Inherits Global.System.Configuration.ApplicationSettingsBase + + Private Shared defaultInstance As MySettings = CType(Global.System.Configuration.ApplicationSettingsBase.Synchronized(New MySettings), MySettings) + +#Region "My.Settings Auto-Save Functionality" +#If _MyType = "WindowsForms" Then + Private Shared addedHandler As Boolean + + Private Shared addedHandlerLockObject As New Object + + _ + Private Shared Sub AutoSaveSettings(ByVal sender As Global.System.Object, ByVal e As Global.System.EventArgs) + If My.Application.SaveMySettingsOnExit Then + My.Settings.Save() + End If + End Sub +#End If +#End Region + + Public Shared ReadOnly Property [Default]() As MySettings + Get + +#If _MyType = "WindowsForms" Then + If Not addedHandler Then + SyncLock addedHandlerLockObject + If Not addedHandler Then + AddHandler My.Application.Shutdown, AddressOf AutoSaveSettings + addedHandler = True + End If + End SyncLock + End If +#End If + Return defaultInstance + End Get + End Property + End Class +End Namespace + +Namespace My + + _ + Friend Module MySettingsProperty + + _ + Friend ReadOnly Property Settings() As Global.ImporterShared.My.MySettings + Get + Return Global.ImporterShared.My.MySettings.Default + End Get + End Property + End Module +End Namespace diff --git a/ImporterShared/My Project/Settings.settings b/ImporterShared/My Project/Settings.settings new file mode 100644 index 0000000..85b890b --- /dev/null +++ b/ImporterShared/My Project/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/EDIDocumentImport/Schemas/Orders/Input.vb b/ImporterShared/Schemas/Orders/Input.vb similarity index 72% rename from EDIDocumentImport/Schemas/Orders/Input.vb rename to ImporterShared/Schemas/Orders/Input.vb index e371579..b35f1b1 100644 --- a/EDIDocumentImport/Schemas/Orders/Input.vb +++ b/ImporterShared/Schemas/Orders/Input.vb @@ -16,696 +16,696 @@ Imports System.Xml.Serialization ' 'This source code was auto-generated by xsd, Version=4.8.3928.0. ' -Namespace Orders.Input - +Namespace Schemas.Orders.Input + ''' - _ + Partial Public Class MESOWebService - + Private itemsField() As Object - + Private templateTypeField As String - + Private templateField As String - + Private optionField As String - + Private amountField As String - + Private extEntryField As String - + Private printVoucherField As String - + Private extInsertField As String - + Private changeLotSizeField As String - + ''' - _ + Public Property Items() As Object() Get Return Me.itemsField End Get Set - Me.itemsField = value + Me.itemsField = Value End Set End Property - + ''' - _ + Public Property TemplateType() As String Get Return Me.templateTypeField End Get Set - Me.templateTypeField = value + Me.templateTypeField = Value End Set End Property - + ''' - _ + Public Property Template() As String Get Return Me.templateField End Get Set - Me.templateField = value + Me.templateField = Value End Set End Property - + ''' - _ + Public Property [option]() As String Get Return Me.optionField End Get Set - Me.optionField = value + Me.optionField = Value End Set End Property - + ''' - _ + Public Property amount() As String Get Return Me.amountField End Get Set - Me.amountField = value + Me.amountField = Value End Set End Property - + ''' - _ + Public Property extEntry() As String Get Return Me.extEntryField End Get Set - Me.extEntryField = value + Me.extEntryField = Value End Set End Property - + ''' - _ + Public Property printVoucher() As String Get Return Me.printVoucherField End Get Set - Me.printVoucherField = value + Me.printVoucherField = Value End Set End Property - + ''' - _ + Public Property extInsert() As String Get Return Me.extInsertField End Get Set - Me.extInsertField = value + Me.extInsertField = Value End Set End Property - + ''' - _ + Public Property ChangeLotSize() As String Get Return Me.changeLotSizeField End Get Set - Me.changeLotSizeField = value + Me.changeLotSizeField = Value End Set End Property End Class - + ''' - _ + Partial Public Class MESOWebServiceEXIMVRG_ordersT025 - + Private bELEGKEYField As String - + Private fakt_KontonummerField As String - + Private laufnummerField As String - + Private fakt_NameField As String - + Private fakt_StrasseField As String - + Private fakt_PLZField As String - + Private fakt_OrtField As String - + Private fakt_AnsprechpartnerField As String - + Private lief_KontonummerField As String - + Private lief_NameField As String - + Private lief_StrasseField As String - + Private lief_PLZField As String - + Private lief_OrtField As String - + Private belegartField As String - + Private datum_AuftragBestellungField As String - + Private datum_AuftragBestellungFieldSpecified As Boolean - + Private auftragsBestellnummerField As String - + Private leistungsdatumField As String - + Private leistungsdatumFieldSpecified As Boolean - + Private auftragsreferenzField As String - + Private infotextField As String - + ''' - _ + Public Property BELEGKEY() As String Get Return Me.bELEGKEYField End Get Set - Me.bELEGKEYField = value + Me.bELEGKEYField = Value End Set End Property - + ''' - _ + Public Property Fakt_Kontonummer() As String Get Return Me.fakt_KontonummerField End Get Set - Me.fakt_KontonummerField = value + Me.fakt_KontonummerField = Value End Set End Property - + ''' - _ + Public Property Laufnummer() As String Get Return Me.laufnummerField End Get Set - Me.laufnummerField = value + Me.laufnummerField = Value End Set End Property - + ''' - _ + Public Property Fakt_Name() As String Get Return Me.fakt_NameField End Get Set - Me.fakt_NameField = value + Me.fakt_NameField = Value End Set End Property - + ''' - _ + Public Property Fakt_Strasse() As String Get Return Me.fakt_StrasseField End Get Set - Me.fakt_StrasseField = value + Me.fakt_StrasseField = Value End Set End Property - + ''' - _ + Public Property Fakt_PLZ() As String Get Return Me.fakt_PLZField End Get Set - Me.fakt_PLZField = value + Me.fakt_PLZField = Value End Set End Property - + ''' - _ + Public Property Fakt_Ort() As String Get Return Me.fakt_OrtField End Get Set - Me.fakt_OrtField = value + Me.fakt_OrtField = Value End Set End Property - + ''' - _ + Public Property Fakt_Ansprechpartner() As String Get Return Me.fakt_AnsprechpartnerField End Get Set - Me.fakt_AnsprechpartnerField = value + Me.fakt_AnsprechpartnerField = Value End Set End Property - + ''' - _ + Public Property Lief_Kontonummer() As String Get Return Me.lief_KontonummerField End Get Set - Me.lief_KontonummerField = value + Me.lief_KontonummerField = Value End Set End Property - + ''' - _ + Public Property Lief_Name() As String Get Return Me.lief_NameField End Get Set - Me.lief_NameField = value + Me.lief_NameField = Value End Set End Property - + ''' - _ + Public Property Lief_Strasse() As String Get Return Me.lief_StrasseField End Get Set - Me.lief_StrasseField = value + Me.lief_StrasseField = Value End Set End Property - + ''' - _ + Public Property Lief_PLZ() As String Get Return Me.lief_PLZField End Get Set - Me.lief_PLZField = value + Me.lief_PLZField = Value End Set End Property - + ''' - _ + Public Property Lief_Ort() As String Get Return Me.lief_OrtField End Get Set - Me.lief_OrtField = value + Me.lief_OrtField = Value End Set End Property - + ''' - _ + Public Property Belegart() As String Get Return Me.belegartField End Get Set - Me.belegartField = value + Me.belegartField = Value End Set End Property - + ''' - _ + Public Property Datum_AuftragBestellung() As String Get Return Me.datum_AuftragBestellungField End Get Set - Me.datum_AuftragBestellungField = value + Me.datum_AuftragBestellungField = Value End Set End Property - + ''' - _ + Public Property Datum_AuftragBestellungSpecified() As Boolean Get Return Me.datum_AuftragBestellungFieldSpecified End Get Set - Me.datum_AuftragBestellungFieldSpecified = value + Me.datum_AuftragBestellungFieldSpecified = Value End Set End Property - + ''' - _ + Public Property AuftragsBestellnummer() As String Get Return Me.auftragsBestellnummerField End Get Set - Me.auftragsBestellnummerField = value + Me.auftragsBestellnummerField = Value End Set End Property - + ''' - _ + Public Property Leistungsdatum() As String Get Return Me.leistungsdatumField End Get Set - Me.leistungsdatumField = value + Me.leistungsdatumField = Value End Set End Property - + ''' - _ + Public Property LeistungsdatumSpecified() As Boolean Get Return Me.leistungsdatumFieldSpecified End Get Set - Me.leistungsdatumFieldSpecified = value + Me.leistungsdatumFieldSpecified = Value End Set End Property - + ''' - _ + Public Property Auftragsreferenz() As String Get Return Me.auftragsreferenzField End Get Set - Me.auftragsreferenzField = value + Me.auftragsreferenzField = Value End Set End Property - + ''' - _ + Public Property Infotext() As String Get Return Me.infotextField End Get Set - Me.infotextField = value + Me.infotextField = Value End Set End Property End Class - + ''' - _ + Partial Public Class MESOWebServiceEXIMVRG_ordersT026 - + Private bELEGKEYField As String - + Private zeilennummerField As String - + Private datentypField As String - + Private artikelnummerField As String - + Private bezeichnungField As String - + Private notizblockField As String - + Private lieferantenartikelnummerField As String - + Private menge_bestelltField As String - + Private menge_bestelltFieldSpecified As Boolean - + Private menge_geliefertField As String - + Private colliField As String - + Private einzelpreisField As String - + Private einzelpreisFieldSpecified As Boolean - + Private zeilenrabatt1Field As String - + Private zeilenrabatt1FieldSpecified As Boolean - + Private zeilenrabatt2Field As String - + Private zeilenrabatt2FieldSpecified As Boolean - + Private zeilenrabatt3Field As String - + Private zeilenrabatt3FieldSpecified As Boolean - + Private zeilenrabatt4Field As String - + Private zeilenrabatt4FieldSpecified As Boolean - + ''' - _ + Public Property BELEGKEY() As String Get Return Me.bELEGKEYField End Get Set - Me.bELEGKEYField = value + Me.bELEGKEYField = Value End Set End Property - + ''' - _ + Public Property Zeilennummer() As String Get Return Me.zeilennummerField End Get Set - Me.zeilennummerField = value + Me.zeilennummerField = Value End Set End Property - + ''' - _ + Public Property Datentyp() As String Get Return Me.datentypField End Get Set - Me.datentypField = value + Me.datentypField = Value End Set End Property - + ''' - _ + Public Property Artikelnummer() As String Get Return Me.artikelnummerField End Get Set - Me.artikelnummerField = value + Me.artikelnummerField = Value End Set End Property - + ''' - _ + Public Property Bezeichnung() As String Get Return Me.bezeichnungField End Get Set - Me.bezeichnungField = value + Me.bezeichnungField = Value End Set End Property - + ''' - _ + Public Property Notizblock() As String Get Return Me.notizblockField End Get Set - Me.notizblockField = value + Me.notizblockField = Value End Set End Property - + ''' - _ + Public Property Lieferantenartikelnummer() As String Get Return Me.lieferantenartikelnummerField End Get Set - Me.lieferantenartikelnummerField = value + Me.lieferantenartikelnummerField = Value End Set End Property - + ''' - _ + Public Property Menge_bestellt() As String Get Return Me.menge_bestelltField End Get Set - Me.menge_bestelltField = value + Me.menge_bestelltField = Value End Set End Property - + ''' - _ + Public Property Menge_bestelltSpecified() As Boolean Get Return Me.menge_bestelltFieldSpecified End Get Set - Me.menge_bestelltFieldSpecified = value + Me.menge_bestelltFieldSpecified = Value End Set End Property - + ''' - _ + Public Property Menge_geliefert() As String Get Return Me.menge_geliefertField End Get Set - Me.menge_geliefertField = value + Me.menge_geliefertField = Value End Set End Property - + ''' - _ + Public Property Colli() As String Get Return Me.colliField End Get Set - Me.colliField = value + Me.colliField = Value End Set End Property - + ''' - _ + Public Property Einzelpreis() As String Get Return Me.einzelpreisField End Get Set - Me.einzelpreisField = value + Me.einzelpreisField = Value End Set End Property - + ''' - _ + Public Property EinzelpreisSpecified() As Boolean Get Return Me.einzelpreisFieldSpecified End Get Set - Me.einzelpreisFieldSpecified = value + Me.einzelpreisFieldSpecified = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt1() As String Get Return Me.zeilenrabatt1Field End Get Set - Me.zeilenrabatt1Field = value + Me.zeilenrabatt1Field = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt1Specified() As Boolean Get Return Me.zeilenrabatt1FieldSpecified End Get Set - Me.zeilenrabatt1FieldSpecified = value + Me.zeilenrabatt1FieldSpecified = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt2() As String Get Return Me.zeilenrabatt2Field End Get Set - Me.zeilenrabatt2Field = value + Me.zeilenrabatt2Field = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt2Specified() As Boolean Get Return Me.zeilenrabatt2FieldSpecified End Get Set - Me.zeilenrabatt2FieldSpecified = value + Me.zeilenrabatt2FieldSpecified = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt3() As String Get Return Me.zeilenrabatt3Field End Get Set - Me.zeilenrabatt3Field = value + Me.zeilenrabatt3Field = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt3Specified() As Boolean Get Return Me.zeilenrabatt3FieldSpecified End Get Set - Me.zeilenrabatt3FieldSpecified = value + Me.zeilenrabatt3FieldSpecified = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt4() As String Get Return Me.zeilenrabatt4Field End Get Set - Me.zeilenrabatt4Field = value + Me.zeilenrabatt4Field = Value End Set End Property - + ''' - _ + Public Property Zeilenrabatt4Specified() As Boolean Get Return Me.zeilenrabatt4FieldSpecified End Get Set - Me.zeilenrabatt4FieldSpecified = value + Me.zeilenrabatt4FieldSpecified = Value End Set End Property End Class diff --git a/EDIDocumentImport/Schemas/Orders/Output.vb b/ImporterShared/Schemas/Orders/Output.vb similarity index 99% rename from EDIDocumentImport/Schemas/Orders/Output.vb rename to ImporterShared/Schemas/Orders/Output.vb index b5abe18..142adf6 100644 --- a/EDIDocumentImport/Schemas/Orders/Output.vb +++ b/ImporterShared/Schemas/Orders/Output.vb @@ -16,7 +16,7 @@ Imports System.Xml.Serialization ' 'This source code was auto-generated by xsd, Version=4.8.3928.0. ' -Namespace Orders.Output +Namespace Schemas.Orders.Output ''' Public Class ReportSource diff --git a/EDIDocumentImport/Serializer.vb b/ImporterShared/Serializer.vb similarity index 98% rename from EDIDocumentImport/Serializer.vb rename to ImporterShared/Serializer.vb index 55b576d..b1caf54 100644 --- a/EDIDocumentImport/Serializer.vb +++ b/ImporterShared/Serializer.vb @@ -2,7 +2,7 @@ Imports DigitalData.Modules.Logging Public Class Serializer - Inherits Base + Inherits BaseClass Public Sub New(pLogConfig As LogConfig) MyBase.New(pLogConfig, pLogConfig.GetLogger()) End Sub diff --git a/ImporterShared/Winline/Account.vb b/ImporterShared/Winline/Account.vb new file mode 100644 index 0000000..6d0eeaf --- /dev/null +++ b/ImporterShared/Winline/Account.vb @@ -0,0 +1,10 @@ +Namespace Winline + Public Class Account + Public Property Id As String + Public Property Name As String + Public Property Mandator As String + Public Overrides Function ToString() As String + Return $"{Name} ({Id})" + End Function + End Class +End Namespace \ No newline at end of file diff --git a/ImporterShared/Winline/Data.vb b/ImporterShared/Winline/Data.vb new file mode 100644 index 0000000..5df3adf --- /dev/null +++ b/ImporterShared/Winline/Data.vb @@ -0,0 +1,261 @@ +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 V05_ACCOUNTID = "c002" + Public Const V05_ACCOUNTNAME = "c003" + 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) + Dim oSQL = $"SELECT [c002], [c003] FROM [{pMandator.Server}].[{pMandator.Database}].[dbo].[v005] WHERE c139 IS NULL" + Dim oTable = Database.GetDatatable(oSQL) + + For Each oRow As DataRow In oTable.Rows + Accounts.Add(New Account With { + .Id = oRow.Item(V05_ACCOUNTID), + .Name = oRow.Item(V05_ACCOUNTNAME), + .Mandator = pMandator.Id + }) + Next + End Sub + + Public Sub LoadMandators() + 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 + 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 TryGetAccountNumber(pGLN As String, pMandator As Mandator) As String + Try + Dim oYear As Integer = GetWinLineYear() + Dim oSQL = $" + SELECT + [c002], -- Kundennummer + [c003] -- Kundenname + FROM [{pMandator.Database}].[dbo].[v050] + WHERE [c004] = 2 -- Was für ein Konto?? + 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 oArticleNumber As String = Utils.NotNull(oRow.Item(V50_ACCOUNTNUMBER), String.Empty) + Return oArticleNumber + Catch ex As Exception + 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 diff --git a/ImporterShared/Winline/Mandator.vb b/ImporterShared/Winline/Mandator.vb new file mode 100644 index 0000000..10c1762 --- /dev/null +++ b/ImporterShared/Winline/Mandator.vb @@ -0,0 +1,15 @@ +Namespace Winline + Public Class Mandator + Public Property Id As String + Public Property Name As String + Public Property Database As String + Public Property Server As String + Public Property Regex As String + Public Property Order As Integer + Public Property IsWhitelisted As Boolean + + Public Overrides Function ToString() As String + Return $"{Name} ({Id})" + End Function + End Class +End Namespace \ No newline at end of file diff --git a/ImporterShared/Winline/WebService.vb b/ImporterShared/Winline/WebService.vb new file mode 100644 index 0000000..30cd464 --- /dev/null +++ b/ImporterShared/Winline/WebService.vb @@ -0,0 +1,100 @@ +Imports System.Xml +Imports System.Net +Imports System.Globalization +Imports AutoMapper +Imports DigitalData.Modules.Logging +Imports DigitalData.Modules.Filesystem +Imports ImporterShared.Documents + +Namespace Winline + Public Class WebService + Inherits BaseClass + + Private ReadOnly Config As Config + Private ReadOnly Serializer As Serializer + Private ReadOnly Mapper As AutoMapper.Mapper + Private ReadOnly FileEx As File + + Public Sub New(pLogConfig As LogConfig, pConfig As Config) + MyBase.New(pLogConfig, pLogConfig.GetLogger()) + FileEx = New File(pLogConfig) + Serializer = New Serializer(pLogConfig) + Config = pConfig + End Sub + + Public Function TransferDocumentToWinLine(pDocument As Document) As Boolean + If TypeOf pDocument.Data Is Schemas.Orders.Input.MESOWebService Then + TransferOrderToWinline(pDocument) + End If + + Return True + End Function + + Private Function TransferOrderToWinline(pDocument As Document) + Dim oOrderOutput = TransformOrderToOutput(pDocument.Data) + Dim oWS As Config.WebServiceConfig = Config.Webservice + Dim oFilePath = SerializeOrder(oOrderOutput) + Dim oXmlString = IO.File.ReadAllText(oFilePath) + pDocument.DataOutput = oOrderOutput + + Dim oURL As String = $"{oWS.BaseUrl}/ewlservice/import?User={oWS.Username}&Password={oWS.Password}&Company={pDocument.Mandator}&Type=30&Vorlage=EXIM-VRG_orders&ActionCode=1&Byref=0Data={oXmlString}" + Dim oRequest = WebRequest.Create(oURL) + oRequest.Method = "POST" + + Logger.Info("Creating HTTP Request to [{0}]", oWS.BaseUrl) + + ' TODO: Make better lol + + Using oResponse = oRequest.GetResponse() + Using oStream = oResponse.GetResponseStream() + Using oReader As New IO.StreamReader(oStream) + Dim oData = oReader.ReadToEnd() + + End Using + End Using + End Using + + Return True + End Function + + Private Function TransformOrderToOutput(pData As Schemas.Orders.Input.MESOWebService) As Schemas.Orders.Output.MESOWebService + Dim oData As Schemas.Orders.Input.MESOWebService = pData + Dim oResult As Schemas.Orders.Output.MESOWebService = Mapper.Map(Of Schemas.Orders.Output.MESOWebService)(oData) + + Dim oItems = oData.Items. + Select(Function(i) + If TypeOf i Is Schemas.Orders.Input.MESOWebServiceEXIMVRG_ordersT025 Then + Return Mapper.Map(Of Schemas.Orders.Output.MESOWebServiceEXIMVRG_ordersT025)(i) + Else + Return Mapper.Map(Of Schemas.Orders.Output.MESOWebServiceEXIMVRG_ordersT026)(i) + End If + End Function). + ToList() + + oResult.Items = oItems.ToArray() + Return oResult + End Function + + Private Function SerializeOrder(pData As Schemas.Orders.Output.MESOWebService) As String + Dim oSerializer = Serializer.GetSerializer(GetType(Schemas.Orders.Output.MESOWebService)) + Dim oSettings As New XmlWriterSettings With {.Indent = True} + + Dim oPath As String = IO.Path.Combine(FileEx.GetAppDataPath("Digital Data", "EDI Document Importer"), "WebService") + Dim oFileName As String = $"{Now:yyyy-MM-dd-ffff}.xml" + Dim oFilePath As String = IO.Path.Combine(oPath, oFileName) + + If IO.Directory.Exists(oPath) = False Then + IO.Directory.CreateDirectory(oPath) + End If + + Using oWriter = XmlWriter.Create(oFilePath, oSettings) + oSerializer.Serialize(oWriter, pData) + End Using + + Return oFilePath + End Function + + + End Class + +End Namespace \ No newline at end of file diff --git a/ImporterShared/packages.config b/ImporterShared/packages.config new file mode 100644 index 0000000..30c87d1 --- /dev/null +++ b/ImporterShared/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file