From e30bc21cf2e2992ed9adb1ae507b5707fc0c1214 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 14 Dec 2018 16:18:12 +0100 Subject: [PATCH] jj: oh my god /o\ --- DDMonorepo.sln | 7 ++ DDZUGFeRDService/DDZUGFeRDService.vbproj | 4 + DDZUGFeRDService/ThreadRunner.vb | 59 +++++---- DDZUGFeRDService/ZUGFeRDService.vb | 4 +- Filesystem/File.vb | 5 + Jobs/App.config | 6 + Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb | 99 +++++++++++++++ Jobs/EDMI/ZUGFeRD/PropertyValues.vb | 68 +++++++++++ Jobs/IJob.vb | 3 + Jobs/Jobs.vbproj | 101 ++++++++++++++++ Jobs/My Project/AssemblyInfo.vb | 34 ++++++ Jobs/packages.config | 4 + Modules.Database/Firebird.vb | 10 ++ ...eRD1p0.vb => CrossIndustryDocumentType.vb} | 0 Modules.Interfaces/Interfaces.vbproj | 2 +- Modules.Interfaces/ZUGFeRDInterface.vb | 53 ++++---- ZUGFeRDTest/App.config | 28 +++++ ZUGFeRDTest/Form1.vb | 82 +++++++++++-- ZUGFeRDTest/My Project/Settings.Designer.vb | 114 ++++++++++++------ ZUGFeRDTest/My Project/Settings.settings | 23 +++- ZUGFeRDTest/ZUGFeRDTest.vbproj | 18 +++ ZUGFeRDTest/packages.config | 4 + 22 files changed, 623 insertions(+), 105 deletions(-) create mode 100644 Jobs/App.config create mode 100644 Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb create mode 100644 Jobs/EDMI/ZUGFeRD/PropertyValues.vb create mode 100644 Jobs/IJob.vb create mode 100644 Jobs/Jobs.vbproj create mode 100644 Jobs/My Project/AssemblyInfo.vb create mode 100644 Jobs/packages.config rename Modules.Interfaces/{ZUGFeRD1p0.vb => CrossIndustryDocumentType.vb} (100%) create mode 100644 ZUGFeRDTest/packages.config diff --git a/DDMonorepo.sln b/DDMonorepo.sln index 1901fe72..f966aadb 100644 --- a/DDMonorepo.sln +++ b/DDMonorepo.sln @@ -51,6 +51,8 @@ Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Interfaces", "Modules.Inter EndProject Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "ZUGFeRDTest", "ZUGFeRDTest\ZUGFeRDTest.vbproj", "{16156434-E471-43F1-8030-76A0DA17CD5A}" EndProject +Project("{F184B08F-C81C-45F6-A57F-5ABD9991F28F}") = "Jobs", "Jobs\Jobs.vbproj", "{39EC839A-3C30-4922-A41E-6B09D1DDE5C3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -117,6 +119,10 @@ Global {16156434-E471-43F1-8030-76A0DA17CD5A}.Debug|Any CPU.Build.0 = Debug|Any CPU {16156434-E471-43F1-8030-76A0DA17CD5A}.Release|Any CPU.ActiveCfg = Release|Any CPU {16156434-E471-43F1-8030-76A0DA17CD5A}.Release|Any CPU.Build.0 = Release|Any CPU + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -137,6 +143,7 @@ Global {7DEEC36E-EA5F-4711-AD1E-FD8894F4AD77} = {7AF3F9C2-C939-4A08-95C1-0453207E298A} {AB6F09BF-E794-4F6A-94BB-C97C0BA84D64} = {3E2008C8-27B1-41DD-9B1A-0C4029F6AECC} {16156434-E471-43F1-8030-76A0DA17CD5A} = {8FFE925E-8B84-45F1-93CB-32B1C96F41EB} + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3} = {3E2008C8-27B1-41DD-9B1A-0C4029F6AECC} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C1BE4090-A0FD-48AF-86CB-39099D14B286} diff --git a/DDZUGFeRDService/DDZUGFeRDService.vbproj b/DDZUGFeRDService/DDZUGFeRDService.vbproj index bb82b9f2..443886ad 100644 --- a/DDZUGFeRDService/DDZUGFeRDService.vbproj +++ b/DDZUGFeRDService/DDZUGFeRDService.vbproj @@ -127,6 +127,10 @@ + + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3} + Jobs + {eaf0ea75-5fa7-485d-89c7-b2d843b03a96} Database diff --git a/DDZUGFeRDService/ThreadRunner.vb b/DDZUGFeRDService/ThreadRunner.vb index 958f7bbf..2fb3c65a 100644 --- a/DDZUGFeRDService/ThreadRunner.vb +++ b/DDZUGFeRDService/ThreadRunner.vb @@ -1,7 +1,11 @@ Imports System.ComponentModel Imports System.IO Imports System.Timers +Imports System.Xml.XPath +Imports DigitalData.Modules.Database Imports DigitalData.Modules.Interfaces +Imports DigitalData.Modules.Jobs +Imports DigitalData.Modules.Jobs.ImportZUGFeRDFiles Imports DigitalData.Modules.Logging Public Class ThreadRunner @@ -11,14 +15,35 @@ Public Class ThreadRunner Private _logConfig As LogConfig Private _logger As Logger - Private _directories As List(Of String) + Private _firebird As Firebird + Private _watchDirectories As List(Of String) + Private _successDirectory As String + Private _errorDirectory As String + Private _zugferd As ZUGFeRDInterface Private Const TIMER_INTERVAL = 60_000 - Public Sub New(LogConfig As LogConfig, Directories As List(Of String)) + Public Sub New(LogConfig As LogConfig, WatchDirectories As List(Of String), SuccessDirectory As String, ErrorDirectory As String) _logConfig = LogConfig _logger = _logConfig.GetLogger() - _directories = Directories + _watchDirectories = WatchDirectories + _successDirectory = SuccessDirectory + _errorDirectory = ErrorDirectory + _zugferd = New ZUGFeRDInterface(_logConfig) + + If Not Directory.Exists(SuccessDirectory) Then + Throw New DirectoryNotFoundException("SuccessDirectory: " & SuccessDirectory) + End If + + If Not Directory.Exists(ErrorDirectory) Then + Throw New DirectoryNotFoundException("ErrorDirectory: " & ErrorDirectory) + End If + + For Each oDirectory In WatchDirectories + If Not Directory.Exists(oDirectory) Then + Throw New DirectoryNotFoundException("WatchDirectory: " & oDirectory) + End If + Next _workerThread = New BackgroundWorker() With { .WorkerReportsProgress = True, @@ -46,33 +71,21 @@ Public Class ThreadRunner Private Sub TimerElapsed(sender As Object, e As ElapsedEventArgs) Handles _workerTimer.Elapsed If Not _workerThread.IsBusy Then - _workerThread.RunWorkerAsync(_directories) + _workerThread.RunWorkerAsync(New WorkerArgs() With { + .WatchDirectories = _watchDirectories, + .SuccessDirectory = _successDirectory, + .ErrorDirectory = _errorDirectory + }) Else _logger.Warn("Worker is busy") End If End Sub Private Sub DoWork(sender As Object, e As DoWorkEventArgs) Handles _workerThread.DoWork - Dim oDirectories As List(Of String) = e.Argument + Dim args As WorkerArgs = e.Argument - For Each oPath As String In oDirectories - Dim oDirInfo As New DirectoryInfo(oPath) - - _logger.Info($"Processing directory {oDirInfo.FullName}..") - - If oDirInfo.Exists Then - Dim oFiles As List(Of FileInfo) = oDirInfo.GetFiles().ToList() - Dim oFileCount = oFiles.Count - Dim oCurrentFileCount = 0 - - For Each oFile In oFiles - oCurrentFileCount += 1 - _logger.Info($"Processing file {oFile.FullName} (${oCurrentFileCount}/{oFileCount})") - - ZUGFeRDInterface.ExtractXMLFile(oFile.FullName) - Next - End If - Next + Dim job As New ImportZUGFeRDFiles(_logConfig, _firebird) + job.Start(args) End Sub Private Sub WorkProgress(sender As Object, e As ProgressChangedEventArgs) Handles _workerThread.ProgressChanged Throw New NotImplementedException() diff --git a/DDZUGFeRDService/ZUGFeRDService.vb b/DDZUGFeRDService/ZUGFeRDService.vb index 2b3c0b7e..55c5115f 100644 --- a/DDZUGFeRDService/ZUGFeRDService.vb +++ b/DDZUGFeRDService/ZUGFeRDService.vb @@ -18,11 +18,11 @@ Public Class ZUGFeRDService Dim oDatabase As String = "" Dim oUser As String = "" Dim oPassword As String = "" - Dim directories As New List(Of String) From {"E:\ZUGFeRD_Import"} + Dim watchDirectories As New List(Of String) From {"E:\ZUGFeRD_Import"} _firebird = New Firebird(_logConfig, oDataSource, oDatabase, oUser, oPassword) - _threadRunner = New ThreadRunner(_logConfig, directories) + _threadRunner = New ThreadRunner(_logConfig, watchDirectories) _threadRunner.Start() End Sub diff --git a/Filesystem/File.vb b/Filesystem/File.vb index 38ba28d6..4d02582f 100644 --- a/Filesystem/File.vb +++ b/Filesystem/File.vb @@ -89,6 +89,11 @@ Public Class File Return True End Function + Public Sub MoveTo(FilePath As String, Directory As String) + Dim oFileInfo As New FileInfo(FilePath) + IO.File.Move(FilePath, Path.Combine(Directory, oFileInfo.Name)) + End Sub + Private Function TestPathIsDirectory(Path As String) As Boolean Dim oIsDirectory As Boolean = (System.IO.File.GetAttributes(Path) And FileAttributes.Directory) = FileAttributes.Directory Return oIsDirectory diff --git a/Jobs/App.config b/Jobs/App.config new file mode 100644 index 00000000..731f6de6 --- /dev/null +++ b/Jobs/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb b/Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb new file mode 100644 index 00000000..848178b0 --- /dev/null +++ b/Jobs/EDMI/ZUGFeRD/ImportZUGFeRDFiles.vb @@ -0,0 +1,99 @@ +Imports System.Collections.Generic +Imports System.IO +Imports System.Linq +Imports DigitalData.Modules.Database +Imports DigitalData.Modules.Interfaces +Imports DigitalData.Modules.Logging +Imports DigitalData.Modules.Filesystem + +Public Class ImportZUGFeRDFiles + Implements IJob + + Private _logger As Logger + Private _logConfig As LogConfig + Private _zugferd As ZUGFeRDInterface + Private _firebird As Firebird + Private _filesystem As Filesystem.File + + Public Class WorkerArgs + Public WatchDirectories As List(Of String) + Public SuccessDirectory As String + Public ErrorDirectory As String + Public PropertyMap As Dictionary(Of String, String) + + Public Sub New() + WatchDirectories = New List(Of String) + SuccessDirectory = Nothing + ErrorDirectory = Nothing + PropertyMap = New Dictionary(Of String, String) + End Sub + End Class + + Public Sub New(LogConfig As LogConfig, Firebird As Firebird) + _logConfig = LogConfig + _logger = LogConfig.GetLogger() + _firebird = Firebird + _filesystem = New Filesystem.File(_logConfig) + _zugferd = New ZUGFeRDInterface(_logConfig) + End Sub + + Public Sub Start(Arguments As Object) Implements IJob.Start + Dim args As WorkerArgs = Arguments + + _logger.Info("Starting Job {0}", Me.GetType.Name) + For Each oPath As String In args.WatchDirectories + Dim oDirInfo As New DirectoryInfo(oPath) + + _logger.Info($"Start processing directory {oDirInfo.FullName}") + + If oDirInfo.Exists Then + Dim oFiles As List(Of FileInfo) = oDirInfo.GetFiles().ToList() + Dim oFileCount = oFiles.Count + Dim oCurrentFileCount = 0 + + _logger.Info("Found {0} files", oFileCount) + + For Each oFile In oFiles + oCurrentFileCount += 1 + _logger.Info($"({oCurrentFileCount}/{oFileCount}) Start processing file {oFile.Name}") + + Dim oMoveDirectory As String = args.SuccessDirectory + Dim oDocument As CrossIndustryDocumentType + Dim oValues As New Dictionary(Of String, String) + Dim oGuid As String = Path.GetFileNameWithoutExtension(oFile.FullName) + + Try + oDocument = _zugferd.ExtractZUGFeRDFile(oFile.FullName) + + For Each mapping In args.PropertyMap + Dim propertyValue As String = PropertyValues.GetPropValue(oDocument, mapping.Value) + _logger.Info("Mapping Property {0} to value {1}. Will be inserted into column {2}", mapping.Value, propertyValue, mapping.Key) + + ' TODO: Check for missing values + If String.IsNullOrEmpty(propertyValue) Then + Throw New Exception($"Property {mapping.Value} not found or empty.") + End If + + oValues.Add(mapping.Key, propertyValue) + Next + + ' TODO: Insert into scheise + + Catch ex As Exception + oMoveDirectory = args.ErrorDirectory + _logger.Error(ex) + Finally + _filesystem.MoveTo(oFile.FullName, oMoveDirectory) + _logger.Info("Finished processing file {0}", oFile.Name) + End Try + Next + End If + + _logger.Info("Finished processing directory {0}", oPath) + Next + End Sub + + + + +End Class diff --git a/Jobs/EDMI/ZUGFeRD/PropertyValues.vb b/Jobs/EDMI/ZUGFeRD/PropertyValues.vb new file mode 100644 index 00000000..b0bce3ea --- /dev/null +++ b/Jobs/EDMI/ZUGFeRD/PropertyValues.vb @@ -0,0 +1,68 @@ +Imports System.Reflection +Imports System.Text.RegularExpressions + +Public Class PropertyValues + Private Shared _indexPattern = "\((\d+)\)" + Private Shared _indexRegex As Regex = New Regex(_indexPattern) + + Public Shared Function GetPropValue(Obj As Object, PropertyName As String) + Dim oNameParts As String() = PropertyName.Split("."c) + Dim oIndexReplaceRegex = "\(\d+\)" + + If IsNothing(Obj) Then + Return Nothing + End If + + If oNameParts.Length = 1 Then + Return Obj.GetType().GetProperty(PropertyName).GetValue(Obj, Nothing) + End If + + For Each oPart As String In oNameParts + Dim oType As Type = Obj.GetType() + Dim oPartName = oPart + Dim oIndex As Integer = Nothing + Dim oHasIndex As Boolean = HasIndex(oPartName) + + If oHasIndex Then + oPartName = StripIndex(oPart) + oIndex = GetIndex(oPart) + End If + + Dim oInfo As PropertyInfo = oType.GetProperty(oPartName) + + If IsNothing(oInfo) Then + Return Nothing + End If + + Obj = oInfo.GetValue(Obj, Nothing) + + If oHasIndex Then + Obj = Obj(0) + End If + Next + + Return Obj + End Function + + Private Shared Function GetIndex(Prop As String) As Integer + If Regex.IsMatch(Prop, _indexPattern) Then + Dim oMatch = _indexRegex.Match(Prop) + Dim oGroup = oMatch.Groups.Item(1) + Dim oValue = oGroup.Value + + Return Integer.Parse(oValue) + End If + + Return Nothing + End Function + + Private Shared Function StripIndex(Prop As String) As String + Return Regex.Replace(Prop, _indexPattern, "") + End Function + + Private Shared Function HasIndex(Prop As String) As Boolean + Return Regex.IsMatch(Prop, _indexPattern) + End Function + + +End Class diff --git a/Jobs/IJob.vb b/Jobs/IJob.vb new file mode 100644 index 00000000..cb1aab71 --- /dev/null +++ b/Jobs/IJob.vb @@ -0,0 +1,3 @@ +Public Interface IJob + Sub Start(Arguments As Object) +End Interface diff --git a/Jobs/Jobs.vbproj b/Jobs/Jobs.vbproj new file mode 100644 index 00000000..d0ad6d0c --- /dev/null +++ b/Jobs/Jobs.vbproj @@ -0,0 +1,101 @@ + + + + + Debug + AnyCPU + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3} + Library + DigitalData.Modules.Jobs + DigitalData.Modules.Jobs + 512 + Empty + v4.6.1 + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + true + + + AnyCPU + true + full + true + true + bin\Debug\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + AnyCPU + pdbonly + false + true + true + bin\Release\ + + + 42016,41999,42017,42018,42019,42032,42036,42020,42021,42022 + + + On + + + Binary + + + Off + + + On + + + + + + + + + + + + + + + {991d0231-4623-496d-8bd0-9ca906029cbc} + Filesystem + + + {EAF0EA75-5FA7-485D-89C7-B2D843B03A96} + Database + + + {AB6F09BF-E794-4F6A-94BB-C97C0BA84D64} + Interfaces + + + {903B2D7D-3B80-4BE9-8713-7447B704E1B0} + Logging + + + + + + + + + + + + ..\packages\NLog.4.5.11\lib\net45\NLog.dll + + + + + + + + + + + + \ No newline at end of file diff --git a/Jobs/My Project/AssemblyInfo.vb b/Jobs/My Project/AssemblyInfo.vb new file mode 100644 index 00000000..228bfeee --- /dev/null +++ b/Jobs/My Project/AssemblyInfo.vb @@ -0,0 +1,34 @@ +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 bestimmt die ID der Typbibliothek, 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 die standardmäßigen Build- und Revisionsnummern +' übernehmen, indem Sie "*" eingeben: + + + diff --git a/Jobs/packages.config b/Jobs/packages.config new file mode 100644 index 00000000..f89fa324 --- /dev/null +++ b/Jobs/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Modules.Database/Firebird.vb b/Modules.Database/Firebird.vb index 3dd2cbed..db0fefba 100644 --- a/Modules.Database/Firebird.vb +++ b/Modules.Database/Firebird.vb @@ -94,6 +94,8 @@ Public Class Firebird _connectionPassword = Password _connectionString = oConnectionString + _logger.Debug("Connecting to database..") + ' Test the connection Dim oConnection = GetConnection() ' If initial connection was successfully, close it @@ -102,6 +104,8 @@ Public Class Firebird If oConnection Is Nothing Then Throw New Exceptions.DatabaseException() End If + + _logger.Debug("Connection sucessfully established!") End Sub Public Function GetConnection() As FbConnection @@ -165,6 +169,8 @@ Public Class Firebird ''' The Firebird connection to use ''' True, if command was executed sucessfully. Otherwise false. Public Function ExecuteNonQueryWithConnection(SqlCommand As String, Connection As FbConnection) As Boolean + _logger.Debug("Executing Non-Query: {0}", SqlCommand) + If Connection Is Nothing Then Return Nothing End If @@ -208,6 +214,8 @@ Public Class Firebird ''' The Firebird connection to use ''' The scalar value if the command was executed successfully. Nothing otherwise. Public Function GetScalarValueWithConnection(SqlQuery As String, Connection As FbConnection) As Object + _logger.Debug("Fetching Scalar-Value: {0}", SqlQuery) + If Connection Is Nothing Then Return Nothing End If @@ -252,6 +260,8 @@ Public Class Firebird ''' The Firebird connection to use ''' A datatable containing the results if the command was executed successfully. Nothing otherwise. Public Function GetDatatableWithConnection(SqlQuery As String, Connection As FbConnection, Optional TransactionMode As TransactionMode = TransactionMode.NoTransaction) As DataTable + _logger.Debug("Fetching Datatable: {0}", SqlQuery) + If Connection Is Nothing Then Return Nothing End If diff --git a/Modules.Interfaces/ZUGFeRD1p0.vb b/Modules.Interfaces/CrossIndustryDocumentType.vb similarity index 100% rename from Modules.Interfaces/ZUGFeRD1p0.vb rename to Modules.Interfaces/CrossIndustryDocumentType.vb diff --git a/Modules.Interfaces/Interfaces.vbproj b/Modules.Interfaces/Interfaces.vbproj index 9118bed5..e3996de3 100644 --- a/Modules.Interfaces/Interfaces.vbproj +++ b/Modules.Interfaces/Interfaces.vbproj @@ -88,7 +88,7 @@ Settings.settings True - + diff --git a/Modules.Interfaces/ZUGFeRDInterface.vb b/Modules.Interfaces/ZUGFeRDInterface.vb index 8dd60e8c..b5dd1685 100644 --- a/Modules.Interfaces/ZUGFeRDInterface.vb +++ b/Modules.Interfaces/ZUGFeRDInterface.vb @@ -28,31 +28,31 @@ Public Class ZUGFeRDInterface ''' ''' ''' - Public Function ExtractXMLFile(Path As String) As XPathDocument + Public Function ExtractZUGFeRDFile(Path As String) As CrossIndustryDocumentType Dim oException As New Exception - Dim oXmlDocument = ExtractZugferd(Path) + Dim oXmlDocument = ValidateZUGFeRDFile(Path) If IsNothing(oXmlDocument) Then Throw New ZUGFeRDExecption(ErrorType.ExtractionFailed, "Datei ist kein gültiges ZUGFeRD Format.") End If - Return oXmlDocument + Return SerializeZUGFeRDDocument(oXmlDocument) End Function - Public Function ExtractZugferd(Path As String) As XPathDocument - Dim oProcessOutput, oProcessError, oFileContent As String + + Public Function ValidateZUGFeRDFile(Path As String) As XPathDocument + Dim oProcessOutput, oProcessError As String Dim oXmlDocument As XPathDocument - Dim oTempFile = System.IO.Path.GetTempFileName() - - Dim oProcessStartInfo As New ProcessStartInfo() With { - .FileName = ZUGFERD_CONVERTER_EXE, - .RedirectStandardError = True, - .RedirectStandardOutput = True, - .UseShellExecute = False, - .Arguments = $"-i ""{Path}"" -o ""{oTempFile}""" - } + Dim oTempFile = IO.Path.GetTempFileName() + Dim oProcess As New Process() With { - .StartInfo = oProcessStartInfo + .StartInfo = New ProcessStartInfo() With { + .FileName = ZUGFERD_CONVERTER_EXE, + .RedirectStandardError = True, + .RedirectStandardOutput = True, + .UseShellExecute = False, + .Arguments = $"-i ""{Path}"" -o ""{oTempFile}""" + } } Try @@ -62,30 +62,35 @@ Public Class ZUGFeRDInterface oProcess.WaitForExit() Catch ex As Exception _logger.Error(ex) - Return Nothing + Throw ex End Try If Not oProcessOutput.Contains(ZUGFERD_CONVERTER_SUCCESS_MESSAGE) Then _logger.Warn("File {0} is not a valid ZUGFeRD File!", Path) - Return Nothing + Throw New ZUGFeRDExecption(ErrorType.NoValidFile, "Datei ist kein gültiges ZUGFeRD Format.") End If Try - oXmlDocument = New XPath.XPathDocument(oTempFile) + oXmlDocument = New XPathDocument(oTempFile) Catch ex As Exception _logger.Error(ex) - Return Nothing + Throw ex End Try Return oXmlDocument End Function - Public Function ParseXMLDocument(doc As XPathDocument) - Dim nav As XPathNavigator = doc.CreateNavigator() - Dim reader = nav.ReadSubtree() + Public Function SerializeZUGFeRDDocument(Document As XPathDocument) As CrossIndustryDocumentType + Try + Dim oNavigator As XPathNavigator = Document.CreateNavigator() + Dim oReader = oNavigator.ReadSubtree() + Dim oSerializer As New XmlSerializer(GetType(CrossIndustryDocumentType)) - Dim serializer As New XmlSerializer(GetType(CrossIndustryDocumentType)) - Dim cross As CrossIndustryDocumentType = serializer.Deserialize(reader) + Return oSerializer.Deserialize(oReader) + Catch ex As Exception + _logger.Error(ex) + Throw ex + End Try End Function End Class diff --git a/ZUGFeRDTest/App.config b/ZUGFeRDTest/App.config index 5534e287..203b80fb 100644 --- a/ZUGFeRDTest/App.config +++ b/ZUGFeRDTest/App.config @@ -1,6 +1,34 @@  + + +
+ + +
+ + + + + + 172.24.12.41:E:\DB\Firebird\Databases\EDMI_TEMPLATE\EDMI_MASTER.FDB + + + 172.24.12.41 + + + + + + + sysdba + + + dd + + + \ No newline at end of file diff --git a/ZUGFeRDTest/Form1.vb b/ZUGFeRDTest/Form1.vb index bb004c6a..bb109ec2 100644 --- a/ZUGFeRDTest/Form1.vb +++ b/ZUGFeRDTest/Form1.vb @@ -1,25 +1,81 @@ -Imports System.Xml +Imports System.IO +Imports System.Reflection +Imports System.Text.RegularExpressions +Imports System.Xml +Imports DigitalData.Modules +Imports DigitalData.Modules.Database Imports DigitalData.Modules.Interfaces +Imports DigitalData.Modules.Jobs.ImportZUGFeRDFiles Imports DigitalData.Modules.Logging Public Class Form1 - Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click - Dim logConfig As New LogConfig(LogConfig.PathType.CurrentDirectory) - Dim logger = logConfig.GetLogger() - OpenFileDialog1.Filter = "pdf Dateien|*.pdf" - OpenFileDialog1.Multiselect = False + Public Const ZUGFERD_IN = "ZUGFeRD in" + Public Const ZUGFERD_ERROR = "ZUGFeRD Error" + Public Const ZUGFERD_SUCCESS = "ZUGFeRD Success" + + Private _logConfig As LogConfig + Private _firebird As Firebird + + Private PropertyMap As New Dictionary(Of String, String) + + Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load + _logConfig = New LogConfig(LogConfig.PathType.CurrentDirectory) + _logConfig.Debug = True + _firebird = New Firebird(_logConfig, My.Settings.FB_DATASOURCE, My.Settings.FB_DATABASE, My.Settings.FB_USER, My.Settings.FB_PASS) + + PropertyMap.Add("TBEDM_INVOICE_HEAD.INVOICE_NR", "HeaderExchangedDocument.ID.Value") + PropertyMap.Add("TBEDM_INVOICE_HEAD.DOC_TYPE", "HeaderExchangedDocument.Name(0).Value") + PropertyMap.Add("TBEDM_INVOICE_HEAD.INVOICE_DATE", "HeaderExchangedDocument.IssueDateTime.Item.Value") + PropertyMap.Add("TBEDM_INVOICE_HEAD.INVOICE_DATE_FORMAT", "HeaderExchangedDocument.IssueDateTime.Item.format") + PropertyMap.Add("TBEDM_INVOICE_HEAD.NOTE", "HeaderExchangedDocument.IncludedNote(0).Content(0).Value") + End Sub + + Private Function LoadFolderConfig(args As WorkerArgs) + Dim oSQL As String = "SELECT T1.FOLDER_TYPE, T.FOLDER_PATH FROM TBEDM_FOLDER T, TBEDM_FOLDER_TYPE T1 WHERE T.FOLDER_TYPE_ID = T1.GUID AND T1.""ACTIVE"" = True AND T.""ACTIVE"" = True" + Dim oResult As DataTable = _firebird.GetDatatable(oSQL) + + For Each row As DataRow In oResult.Rows + Dim oFolderType = row.Item("FOLDER_TYPE") - Dim oFDialogResult As DialogResult = OpenFileDialog1.ShowDialog() - Dim zugferd As ZUGFeRDInterface = New ZUGFeRDInterface(logConfig) + Select Case oFolderType + Case ZUGFERD_IN + args.WatchDirectories.Add(row.Item("FOLDER_PATH")) - If oFDialogResult = DialogResult.OK Then - Dim xml As XPath.XPathDocument = zugferd.ExtractXMLFile(OpenFileDialog1.FileName) + Case ZUGFERD_SUCCESS + args.SuccessDirectory = row.Item("FOLDER_PATH") - zugferd.ParseXMLDocument(xml) + Case ZUGFERD_ERROR + args.ErrorDirectory = row.Item("FOLDER_PATH") + + End Select + Next + + Return args + End Function + + Private Function LoadPropertyMapFor(args As WorkerArgs, specification As String) + Dim oSQL As String = $"SELECT * FROM TBEDM_XML_ITEMS WHERE SPECIFICATION = '{specification}' AND ACTIVE = True" + Dim oResult As DataTable = _firebird.GetDatatable(oSQL) + + For Each row As DataRow In oResult.Rows + Dim xmlPath = row.Item("XML_PATH") + Dim tableName = row.Item("TABLE_NAME") + Dim tableColumn = row.Item("TABLE_COLUMN") + + args.PropertyMap.Add($"{tableName}.{tableColumn}", xmlPath) + Next + + Return args + End Function + + Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click + Dim args As New WorkerArgs() + args = LoadFolderConfig(args) + args = LoadPropertyMapFor(args, "ZUGFeRD-Invoice") - MsgBox("YAY!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") - End If + Dim job As New Jobs.ImportZUGFeRDFiles(_logConfig, _firebird) + job.Start(args) End Sub End Class diff --git a/ZUGFeRDTest/My Project/Settings.Designer.vb b/ZUGFeRDTest/My Project/Settings.Designer.vb index 8f7ff546..a170e231 100644 --- a/ZUGFeRDTest/My Project/Settings.Designer.vb +++ b/ZUGFeRDTest/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,57 +13,99 @@ 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 End Property + + _ + Public ReadOnly Property FB_DATABASE() As String + Get + Return CType(Me("FB_DATABASE"),String) + End Get + End Property + + _ + Public ReadOnly Property FB_DATASOURCE() As String + Get + Return CType(Me("FB_DATASOURCE"),String) + End Get + End Property + + _ + Public Property FB_USER() As String + Get + Return CType(Me("FB_USER"),String) + End Get + Set + Me("FB_USER") = value + End Set + End Property + + _ + Public Property FB_PASS() As String + Get + Return CType(Me("FB_PASS"),String) + End Get + Set + Me("FB_PASS") = value + End Set + End Property End Class End Namespace Namespace My - - _ + + _ Friend Module MySettingsProperty - - _ + + _ Friend ReadOnly Property Settings() As Global.ZUGFeRDTest.My.MySettings Get Return Global.ZUGFeRDTest.My.MySettings.Default diff --git a/ZUGFeRDTest/My Project/Settings.settings b/ZUGFeRDTest/My Project/Settings.settings index 85b890b3..61758f88 100644 --- a/ZUGFeRDTest/My Project/Settings.settings +++ b/ZUGFeRDTest/My Project/Settings.settings @@ -1,7 +1,18 @@  - - - - - - + + + + + 172.24.12.41:E:\DB\Firebird\Databases\EDMI_TEMPLATE\EDMI_MASTER.FDB + + + 172.24.12.41 + + + sysdba + + + dd + + + \ No newline at end of file diff --git a/ZUGFeRDTest/ZUGFeRDTest.vbproj b/ZUGFeRDTest/ZUGFeRDTest.vbproj index 5ffa10c6..c1d84664 100644 --- a/ZUGFeRDTest/ZUGFeRDTest.vbproj +++ b/ZUGFeRDTest/ZUGFeRDTest.vbproj @@ -47,10 +47,19 @@ On + + + ..\packages\NLog.4.5.11\lib\net45\NLog.dll + + + + + + @@ -117,8 +126,17 @@ Settings.Designer.vb + + + {39EC839A-3C30-4922-A41E-6B09D1DDE5C3} + Jobs + + + {EAF0EA75-5FA7-485D-89C7-B2D843B03A96} + Database + {ab6f09bf-e794-4f6a-94bb-c97c0ba84d64} Interfaces diff --git a/ZUGFeRDTest/packages.config b/ZUGFeRDTest/packages.config new file mode 100644 index 00000000..f89fa324 --- /dev/null +++ b/ZUGFeRDTest/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file