From 3883c0dad7fdec7840e7dce0e1e094b3cbcbd4b5 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Wed, 30 Nov 2022 09:34:26 +0100 Subject: [PATCH 01/26] Messaging: Add general WCF code --- Messaging/Messaging.vbproj | 3 ++ Messaging/My Project/AssemblyInfo.vb | 6 +-- Messaging/WCF/Channel.vb | 69 ++++++++++++++++++++++++++++ Messaging/WCF/Constants.vb | 20 ++++++++ Messaging/WCF/ServerAddress.vb | 7 +++ 5 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 Messaging/WCF/Channel.vb create mode 100644 Messaging/WCF/Constants.vb create mode 100644 Messaging/WCF/ServerAddress.vb diff --git a/Messaging/Messaging.vbproj b/Messaging/Messaging.vbproj index 41388910..9ce49a60 100644 --- a/Messaging/Messaging.vbproj +++ b/Messaging/Messaging.vbproj @@ -96,6 +96,9 @@ True + + + diff --git a/Messaging/My Project/AssemblyInfo.vb b/Messaging/My Project/AssemblyInfo.vb index fea7fb5c..1c0d3e79 100644 --- a/Messaging/My Project/AssemblyInfo.vb +++ b/Messaging/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + diff --git a/Messaging/WCF/Channel.vb b/Messaging/WCF/Channel.vb new file mode 100644 index 00000000..71a45348 --- /dev/null +++ b/Messaging/WCF/Channel.vb @@ -0,0 +1,69 @@ +Imports System.ServiceModel +Imports System.Xml +Imports DigitalData.Modules.Base +Imports DigitalData.Modules.Logging + +Namespace WCF + Public Class Channel(Of TChannel As IClientChannel) + Inherits BaseClass + + Private ReadOnly ChannelFactory As ChannelFactory(Of TChannel) + + Public Event Reconnect As EventHandler + + Public Sub New(pLogConfig As LogConfig, pServerAddress As ServerAddress) + MyBase.New(pLogConfig) + ChannelFactory = GetChannelFactory(pServerAddress) + End Sub + + ''' + ''' Creates a channel and adds a Faulted-Handler + ''' + ''' A channel object + Public Function GetChannel() As TChannel + Try + Logger.Debug("Creating channel.") + Dim oChannel = ChannelFactory.CreateChannel() + + AddHandler oChannel.Faulted, Sub() RaiseEvent Reconnect(Me, Nothing) + + Return oChannel + Catch ex As Exception + Logger.Error(ex) + Throw ex + End Try + End Function + + ''' + ''' Creates and returns a channel factory with the supplied name and address + ''' + ''' The service name, will be: net.tcp://ip:port/DigitalData/Services/[name] + ''' The service address, in the form of ip address and port + ''' + Private Function GetChannelFactory(pAddress As ServerAddress, Optional pName As String = "Main") As ChannelFactory(Of TChannel) + Dim oBinding = GetBinding() + Dim oAddress = New EndpointAddress($"net.tcp://{pAddress.Host}:{pAddress.Port}/DigitalData/Services/{pName}") + Dim oFactory = New ChannelFactory(Of TChannel)(oBinding, oAddress) + Return oFactory + End Function + + Public Shared Function GetBinding(Optional AuthenticationMode As TcpClientCredentialType = TcpClientCredentialType.Windows) As NetTcpBinding + Return New NetTcpBinding() With { + .MaxReceivedMessageSize = Constants.ChannelSettings.MAX_RECEIVED_MESSAGE_SIZE, + .MaxBufferSize = Constants.ChannelSettings.MAX_BUFFER_SIZE, + .MaxBufferPoolSize = Constants.ChannelSettings.MAX_BUFFER_POOL_SIZE, + .TransferMode = TransferMode.Streamed, + .Security = New NetTcpSecurity() With { + .Mode = SecurityMode.Transport, + .Transport = New TcpTransportSecurity() With { + .ClientCredentialType = AuthenticationMode + } + }, + .ReaderQuotas = New XmlDictionaryReaderQuotas() With { + .MaxArrayLength = Constants.ChannelSettings.MAX_ARRAY_LENGTH, + .MaxStringContentLength = Constants.ChannelSettings.MAX_STRING_CONTENT_LENGTH + } + } + End Function + End Class +End Namespace diff --git a/Messaging/WCF/Constants.vb b/Messaging/WCF/Constants.vb new file mode 100644 index 00000000..3f34b90f --- /dev/null +++ b/Messaging/WCF/Constants.vb @@ -0,0 +1,20 @@ +Namespace WCF + Public Class Constants + Public Const DEFAULT_SERVICE_PORT = 9000 + + ''' + ''' Infos about MaxBufferSize and MaxBufferPoolSize + ''' https://social.msdn.microsoft.com/Forums/vstudio/en-US/d6e234d3-942f-4e9d-8470-32618d3f3212/maxbufferpoolsize-vs-maxbuffersize?forum=wcf + ''' + Public Class ChannelSettings + Public Const MAX_RECEIVED_MESSAGE_SIZE = 2147483647 ' 1GB + Public Const MAX_BUFFER_SIZE = 104857600 ' 100MB + Public Const MAX_BUFFER_POOL_SIZE = 1048576 ' 1MB + + Public Const MAX_CONNECTIONS = 500 + Public Const MAX_ARRAY_LENGTH = 2147483647 + Public Const MAX_STRING_CONTENT_LENGTH = 2147483647 + End Class + End Class + +End Namespace diff --git a/Messaging/WCF/ServerAddress.vb b/Messaging/WCF/ServerAddress.vb new file mode 100644 index 00000000..aa63cac7 --- /dev/null +++ b/Messaging/WCF/ServerAddress.vb @@ -0,0 +1,7 @@ +Namespace WCF + Public Structure ServerAddress + Public Host As String + Public Port As Integer + End Structure + +End Namespace \ No newline at end of file From bd6d4838672babc773c791b12c9047cd15a26806 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 9 Dec 2022 13:31:01 +0100 Subject: [PATCH 02/26] Windream: Fix NewFolder --- Windream/Windream.vb | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Windream/Windream.vb b/Windream/Windream.vb index bb6de4bf..2e71d39c 100644 --- a/Windream/Windream.vb +++ b/Windream/Windream.vb @@ -638,6 +638,7 @@ Public Class Windream Return False End Try End Function + ''' ''' Archives windream object immediately ''' @@ -654,7 +655,7 @@ Public Class Windream End Try End Function - Public Function NewFolder(Path As String, pExtension As String) As Boolean + Public Function NewFolder(Path As String) As Boolean If Not TestSessionLoggedIn() Then Return False End If @@ -665,13 +666,11 @@ Public Class Windream Dim oFolderObject As WMObject Dim oCurrentPath As String = String.Empty - For Each oFolder In oFolders - If oFolder.ToString.EndsWith(pExtension) Then - Exit For - ElseIf oFolder = String.Empty Then + If oFolder = String.Empty Then Continue For End If + oCurrentPath = Combine(oCurrentPath, oFolder) If TestFolderExists(oCurrentPath) = False Then @@ -706,13 +705,13 @@ Public Class Windream Public Function NewFileStream(ByVal FilenameSource As String, ByVal FilenameTarget As String) As Boolean NewDocumentID = 0 - Dim oExtension As String = Path.GetExtension(FilenameSource) If Not TestSessionLoggedIn() Then Return False End If Dim oTargetDrive As String = Path.GetDirectoryName(FilenameTarget) + FilenameTarget = GetNormalizedPath(FilenameTarget, True) _logger.Debug($"Preparing to stream file from {FilenameSource} to {FilenameTarget}") @@ -721,7 +720,7 @@ Public Class Windream Dim oFileIO As WMFileIO Dim oWMStream As WMStream - NewFolder(FilenameTarget, oExtension) + NewFolder(oTargetDrive) 'Indexierungsdialog der Session unterdrücken Session.SwitchEvents(Constants.COM_EVENT_SESSION_NEED_INDEX, False) @@ -816,10 +815,12 @@ Public Class Windream Public Function GetNormalizedPath(Path As String, pCleanPath As Boolean) As String _logger.Debug("Normalizing Path: [{0}]", Path) Dim oNormalizedPath As String = Path + If pCleanPath = True Then oNormalizedPath = Language.Utils.RemoveInvalidCharacters(Path) - _logger.Debug("path after RemoveInvalidCharacters: [{0}]", oNormalizedPath) + _logger.Debug("Path after RemoveInvalidCharacters: [{0}]", oNormalizedPath) End If + Try ' Convert any forward slashes / and double slashes \\ into backslashes \ ' See: https://stackoverflow.com/questions/3144492/how-do-i-get-nets-path-combine-to-convert-forward-slashes-to-backslashes @@ -830,7 +831,7 @@ Public Class Windream ' Remove Driveletter, eg. W:\ If oNormalizedPath.StartsWith($"{ClientDriveLetter}:\") Then oNormalizedPath = oNormalizedPath.Substring(ClientDriveLetter.Length + 2) - _logger.Debug($"path after replaced ClientDriveLetter: [{oNormalizedPath}]") + _logger.Debug($"Path after replaced ClientDriveLetter: [{oNormalizedPath}]") End If ' Remove Windream Base Path, eg. \\windream\objects\ @@ -845,14 +846,16 @@ Public Class Windream _logger.Warn($"Check Your config ClientDriveLetter [{ClientDriveLetter}] // ClientBasePath [{ClientBasePath}]") oNormalizedPath = oNormalizedPath.Substring(3) End If + If oNormalizedPath.StartsWith("\") = False Then oNormalizedPath = $"\{oNormalizedPath}" End If - _logger.Debug($"oNormalizedPath: [{oNormalizedPath}]") + + _logger.Debug($"NormalizedPath: [{oNormalizedPath}]") Return oNormalizedPath Catch ex As Exception - _logger.Warn($"Unexpected error in GetNormalizedPath - oNormalizedPath [{oNormalizedPath}] - Error: [{ex.Message}]") + _logger.Warn($"Unexpected error in GetNormalizedPath - NormalizedPath [{oNormalizedPath}] - Error: [{ex.Message}]") Return "" End Try End Function From 1ea73d92341ef686db14754f11cb94a635abe06c Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 9 Dec 2022 13:40:10 +0100 Subject: [PATCH 03/26] Windream: improve logging --- Windream/Windream.vb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Windream/Windream.vb b/Windream/Windream.vb index 0348820d..7f302e54 100644 --- a/Windream/Windream.vb +++ b/Windream/Windream.vb @@ -777,7 +777,6 @@ Public Class Windream oWMStream.Close() _logger.Debug("Saving new object") - oWMObject.aObjectType = GetObjectByName(WMObjecttypeName, WMEntityObjectType) oWMObject.Save() @@ -847,7 +846,7 @@ Public Class Windream ' Handle misconfigured drive-letter If oNormalizedPath.Contains(":") Then - _logger.Warn($"oNormalizedPath still contains a drive name!!") + _logger.Warn($"NormalizedPath [{oNormalizedPath}] still contains a drive name!!") _logger.Warn($"Check Your config ClientDriveLetter [{ClientDriveLetter}] // ClientBasePath [{ClientBasePath}]") oNormalizedPath = oNormalizedPath.Substring(3) End If From f5107a3d21d90be03d3c89b07a252408c5e1010b Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:33:09 +0100 Subject: [PATCH 04/26] Windream: Fix normalized paths --- Windream/Windream.vb | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/Windream/Windream.vb b/Windream/Windream.vb index 7f302e54..ddf8d434 100644 --- a/Windream/Windream.vb +++ b/Windream/Windream.vb @@ -816,22 +816,16 @@ Public Class Windream End Try End Function - Public Function GetNormalizedPath(Path As String, pCleanPath As Boolean) As String - _logger.Debug("Normalizing Path: [{0}]", Path) - Dim oNormalizedPath As String = Path + Public Function GetNormalizedPath(pPath As String, pCleanPath As Boolean) As String + _logger.Debug("Normalizing Path: [{0}]", pPath) + Dim oNormalizedPath As String = pPath If pCleanPath = True Then - oNormalizedPath = Language.Utils.RemoveInvalidCharacters(Path) + oNormalizedPath = Utils.RemoveInvalidCharacters(pPath) _logger.Debug("Path after RemoveInvalidCharacters: [{0}]", oNormalizedPath) End If Try - ' Convert any forward slashes / and double slashes \\ into backslashes \ - ' See: https://stackoverflow.com/questions/3144492/how-do-i-get-nets-path-combine-to-convert-forward-slashes-to-backslashes - If IsPathRooted(oNormalizedPath) Then - oNormalizedPath = GetFullPath(oNormalizedPath) - End If - ' Remove Driveletter, eg. W:\ If oNormalizedPath.StartsWith($"{ClientDriveLetter}:\") Then oNormalizedPath = oNormalizedPath.Substring(ClientDriveLetter.Length + 2) @@ -851,6 +845,18 @@ Public Class Windream oNormalizedPath = oNormalizedPath.Substring(3) End If + ' Convert any forward slashes / and double slashes \\ into backslashes \ + ' See: https://stackoverflow.com/questions/3144492/how-do-i-get-nets-path-combine-to-convert-forward-slashes-to-backslashes + If IsPathRooted(oNormalizedPath) Then + ' This breaks because it converts the path "\SomeFolder" into "C:\SomeFolder" LOL + 'oNormalizedPath = GetFullPath(oNormalizedPath) + ' Lets just be pragmatic here + oNormalizedPath = oNormalizedPath.Replace("\\", "\") + oNormalizedPath = oNormalizedPath.Replace("/", "\") + + _logger.Debug("Path after converting slashes: [{0}]", oNormalizedPath) + End If + If oNormalizedPath.StartsWith("\") = False Then oNormalizedPath = $"\{oNormalizedPath}" End If @@ -864,6 +870,11 @@ Public Class Windream End Try End Function + Public Function GetAbsolutePath(pPath As String) As String + Dim oNormalizedPath = GetNormalizedPath(pPath, False) + Return $"\\windream\objects{oNormalizedPath}" + End Function + ''' ''' Returns the result of a search file ''' From b927e07141c5432b826a9144e76162602f22c4e6 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:33:39 +0100 Subject: [PATCH 05/26] Windream: Version 1.7.1 --- Windream/My Project/AssemblyInfo.vb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Windream/My Project/AssemblyInfo.vb b/Windream/My Project/AssemblyInfo.vb index 3c846cac..de54f711 100644 --- a/Windream/My Project/AssemblyInfo.vb +++ b/Windream/My Project/AssemblyInfo.vb @@ -12,8 +12,8 @@ Imports System.Runtime.InteropServices - - + + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From 2816b644da38e500a25e0051166fea432b2197a1 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:34:19 +0100 Subject: [PATCH 06/26] Database: Log all command parameters --- Database/Adapters/MSSQLServer.vb | 16 ++++++++++++++-- Database/Database.vbproj | 1 - Database/Helpers.vb | 10 ---------- 3 files changed, 14 insertions(+), 13 deletions(-) delete mode 100644 Database/Helpers.vb diff --git a/Database/Adapters/MSSQLServer.vb b/Database/Adapters/MSSQLServer.vb index c6695542..d3e4d02f 100644 --- a/Database/Adapters/MSSQLServer.vb +++ b/Database/Adapters/MSSQLServer.vb @@ -340,7 +340,7 @@ Public Class MSSQLServer pSqlCommandObject.CommandTimeout = pTimeout Using oAdapter As New SqlDataAdapter(pSqlCommandObject) - Logger.Debug("GetDatatableWithConnectionObject: Running Query [{0}]", pSqlCommandObject.CommandText) + Logger.Debug("GetDatatableWithConnectionObject: Running Query [{0}] and Parameters [{1}]", pSqlCommandObject.CommandText, GetParameterListAsString(pSqlCommandObject)) oAdapter.Fill(oTable) End Using @@ -427,7 +427,7 @@ Public Class MSSQLServer Dim oTransaction As SqlTransaction = MaybeGetTransaction(pSqlConnection, pTransactionMode, pTransaction) Try - Logger.Debug("ExecuteNonQueryWithConnectionObject: Running Command [{0}]", pSqlCommandObject.CommandText) + Logger.Debug("ExecuteNonQueryWithConnectionObject: Running Command [{0}] and Parameters [{1}]", pSqlCommandObject.CommandText, GetParameterListAsString(pSqlCommandObject)) pSqlCommandObject.Connection = pSqlConnection pSqlCommandObject.Transaction = oTransaction @@ -517,6 +517,9 @@ Public Class MSSQLServer Dim oResult As Object = Nothing Try + + Logger.Debug("GetScalarValueWithConnectionObject: Running Query [{0}] with Parameters [{1}]", pSqlCommandObject, GetParameterListAsString(pSqlCommandObject)) + pSqlCommandObject.Connection = pSqlConnection pSqlCommandObject.CommandTimeout = pTimeout pSqlCommandObject.Transaction = oTransaction @@ -601,4 +604,13 @@ Public Class MSSQLServer Dim res = command.EndExecuteNonQuery(result) Logger.Info("Finished executing Async database operation: {0}", command.CommandText) End Sub + + Private Function GetParameterListAsString(pSQLCommand As SqlCommand) As String + Dim oList = pSQLCommand.Parameters. + Cast(Of SqlParameter). + Select(Function(p) $"({p.ParameterName}={p.Value})"). + ToList() + + Return String.Join(",", oList) + End Function End Class diff --git a/Database/Database.vbproj b/Database/Database.vbproj index 74ade489..3327e3ea 100644 --- a/Database/Database.vbproj +++ b/Database/Database.vbproj @@ -99,7 +99,6 @@ - diff --git a/Database/Helpers.vb b/Database/Helpers.vb deleted file mode 100644 index 4d09d04b..00000000 --- a/Database/Helpers.vb +++ /dev/null @@ -1,10 +0,0 @@ -Public Class Helpers - - Public Shared Function MaybeEscapeSQLCommand(pSQLCommand As String) As String - - - - End Function - - -End Class From d74e0f304a7e377f133c9c852eb0dd611b20789d Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:34:33 +0100 Subject: [PATCH 07/26] Database: Version 2.3.1.0 --- Database/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Database/My Project/AssemblyInfo.vb b/Database/My Project/AssemblyInfo.vb index 9e1ccdd2..2c7ff65c 100644 --- a/Database/My Project/AssemblyInfo.vb +++ b/Database/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From eae009e82d3da76fe1df90b23f2f1ce08c2c0999 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:35:06 +0100 Subject: [PATCH 08/26] Filesystem: Add new method GetVersionedFilenameWithFileCheck --- Filesystem/File.vb | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/Filesystem/File.vb b/Filesystem/File.vb index 60379f2b..3a20856d 100644 --- a/Filesystem/File.vb +++ b/Filesystem/File.vb @@ -109,11 +109,21 @@ Public Class File ''' ''' Adds file version string to given filename `Destination` if that file already exists. ''' - ''' - ''' - Public Function GetVersionedFilename(Destination As String) As String + ''' Filepath to check + ''' Versioned string + Public Function GetVersionedFilename(pFilePath As String) As String + Return GetVersionedFilenameWithFilecheck(pFilePath, Function(pPath As String) IO.File.Exists(pFilePath)) + End Function + + ''' + ''' Adds file version string to given filename `Destination` if that file already exists. + ''' + ''' Filepath to check + ''' Custom action to check for file existence + ''' Versioned string + Public Function GetVersionedFilenameWithFilecheck(pFilePath As String, pFileExistsAction As Func(Of String, Boolean)) As String Try - Dim oFileName As String = Destination + Dim oFileName As String = pFilePath Dim oFinalFileName = oFileName Dim oDestinationDir = Path.GetDirectoryName(oFileName) @@ -131,7 +141,7 @@ Public Class File ' Shorten the filename (only filename, without extension or version) ' by cutting the length in half. This should work no matter how long the path and/or filename are. ' The initial check operates on the full path to catch all scenarios. - If Destination.Length > MAX_FILE_PATH_LENGTH Then + If pFilePath.Length > MAX_FILE_PATH_LENGTH Then _Logger.Info("Filename is too long. Filename will be cut to prevent further errors.") _Logger.Info("Original Filename is: {0}", oFileNameWithoutExtension) Dim oNewLength As Integer = Math.Round(oFileNameWithoutExtension.Length / 2) @@ -147,15 +157,15 @@ Public Class File _Logger.Debug("Intermediate Filename is {0}", oFinalFileName) _Logger.Debug("File version: {0}", oFileVersion) oFileVersion += 1 - Loop While (IO.File.Exists(oFinalFileName)) + Loop While pFileExistsAction(oFinalFileName) = True _Logger.Debug("Final Filename is {0}", oFinalFileName) Return oFinalFileName Catch ex As Exception - _Logger.Warn("Filename {0} could not be versioned. Original filename will be returned!", Destination) + _Logger.Warn("Filename {0} could not be versioned. Original filename will be returned!", pFilePath) _Logger.Error(ex) - Return Destination + Return pFilePath End Try End Function @@ -195,6 +205,8 @@ Public Class File oStringVersion = 1 End If + _Logger.Debug("Versioned: String [{0}], Version [{1}]", pString, oStringVersion) + Return New Tuple(Of String, Integer)(pString, oStringVersion) End Function From e717dffa5405309fd3939d5cedc9c4ef6e92a6f7 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:35:37 +0100 Subject: [PATCH 09/26] Filesystem: Version 1.4.1.0 --- Filesystem/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Filesystem/My Project/AssemblyInfo.vb b/Filesystem/My Project/AssemblyInfo.vb index f1519343..dffefb47 100644 --- a/Filesystem/My Project/AssemblyInfo.vb +++ b/Filesystem/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From d5e98c5de4495f6fe9298a7e1d1fe0affd49b4b2 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:36:56 +0100 Subject: [PATCH 10/26] Interfaces: Prepare language attribute in ADUser --- Interfaces/ActiveDirectoryInterface.vb | 2 ++ Interfaces/ActiveDirectoryInterface/ActiveDirectoryUser.vb | 1 + 2 files changed, 3 insertions(+) diff --git a/Interfaces/ActiveDirectoryInterface.vb b/Interfaces/ActiveDirectoryInterface.vb index d3617f4e..5da2f55a 100644 --- a/Interfaces/ActiveDirectoryInterface.vb +++ b/Interfaces/ActiveDirectoryInterface.vb @@ -193,6 +193,8 @@ Public Class ActiveDirectoryInterface .FirebirdSyskey = oMap.FirebirdSyskey, .MSSQLColumn = oMap.MSSQLColumn }) + Else + _logger.Debug("Attribute [{0}] is empty.", oMap.AttributeName) End If Next Else diff --git a/Interfaces/ActiveDirectoryInterface/ActiveDirectoryUser.vb b/Interfaces/ActiveDirectoryInterface/ActiveDirectoryUser.vb index ee7504f6..0a0558b3 100644 --- a/Interfaces/ActiveDirectoryInterface/ActiveDirectoryUser.vb +++ b/Interfaces/ActiveDirectoryInterface/ActiveDirectoryUser.vb @@ -8,6 +8,7 @@ Public Class ADUser Public Property GivenName As String Public Property Middlename As String Public Property Email As String + Public Property Language As String Public CustomAttributes As List(Of CustomAttribute) From db1d3fb19706290466df1e1fec6720db6b37d3b7 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 08:37:29 +0100 Subject: [PATCH 11/26] Interfaces: Version 1.9.1.0 --- Interfaces/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Interfaces/My Project/AssemblyInfo.vb b/Interfaces/My Project/AssemblyInfo.vb index d792ad58..a6182373 100644 --- a/Interfaces/My Project/AssemblyInfo.vb +++ b/Interfaces/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From a00ad5a9c0ec34c2d343c03ae3c57cce4b2ec264 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 09:03:21 +0100 Subject: [PATCH 12/26] Logging: WIP Json logging --- Logging/LogConfig.vb | 89 +++++++++++++++++++++++++++++--------------- 1 file changed, 59 insertions(+), 30 deletions(-) diff --git a/Logging/LogConfig.vb b/Logging/LogConfig.vb index 8a9d1458..091a7b33 100644 --- a/Logging/LogConfig.vb +++ b/Logging/LogConfig.vb @@ -81,6 +81,7 @@ Public Class LogConfig Private Const TARGET_ERROR As String = "errorTarget" Private Const TARGET_DEBUG As String = "debugTarget" Private Const TARGET_TRACE As String = "traceTarget" + Private Const TARGET_JSON As String = "jsonTarget" 'Private Const TARGET_MEMORY As String = "memoryTarget" Private Const LOG_FORMAT_BASE As String = "${time}|${logger:shortName=True}|${level:uppercase=true}" @@ -101,8 +102,9 @@ Public Class LogConfig Private ReadOnly _basePath As String = _failSafePath Private _config As LoggingConfiguration - Private _isDebug As Boolean = False - Private _isTrace As Boolean = False + Private _EnableDebugLogging As Boolean = False + Private _EnableTraceLogging As Boolean = False + Private _EnableJsonLogging As Boolean = False #End Region #Region "Public Properties" @@ -137,21 +139,31 @@ Public Class LogConfig ''' True, if debug log will be written. False otherwise. Public Property Debug As Boolean Get - Return _isDebug + Return _EnableDebugLogging End Get - Set(isDebug As Boolean) - _isDebug = isDebug - ReloadConfig(isDebug, _isTrace) + Set(value As Boolean) + _EnableDebugLogging = value + ReloadConfig() End Set End Property Public Property Trace As Boolean Get - Return _isTrace + Return _EnableTraceLogging End Get - Set(isTrace As Boolean) - _isTrace = isTrace - ReloadConfig(_isDebug, isTrace) + Set(value As Boolean) + _EnableTraceLogging = value + ReloadConfig() + End Set + End Property + + Public Property EnableJsonLog As Boolean + Get + Return _EnableJsonLogging + End Get + Set(value As Boolean) + _EnableJsonLogging = value + ReloadConfig() End Set End Property @@ -478,9 +490,7 @@ Public Class LogConfig ''' ''' Reconfigures and re-adds all loggers, optionally adding the debug rule. ''' - ''' Adds the Debug rule if true. - ''' Adds the Trace rule if true. - Private Sub ReloadConfig(Optional Debug As Boolean = False, Optional Trace As Boolean = False) + Private Sub ReloadConfig() Dim oLogger = GetLogger() ' Clear Logging Rules @@ -489,15 +499,22 @@ Public Class LogConfig ' Add default rules AddDefaultRules(_config) + ' Add json rule, if configured + If _EnableJsonLogging = True Then + oLogger.Info("JSON Logging is now Enabled.") + _config.AddRule(LogLevel.Debug, LogLevel.Error, TARGET_JSON) + End If + ' Add debug rule, if configured - If Debug = True Then + If _EnableDebugLogging = True Then _config.AddRule(LogLevel.Debug, LogLevel.Error, TARGET_DEBUG) oLogger.Info("DEBUG Logging is now Enabled.") Else oLogger.Debug("DEBUG Logging is now Disabled.") End If - If Trace = True Then + ' Add trace rule, if configured + If _EnableTraceLogging = True Then _config.AddRule(LogLevel.Trace, LogLevel.Error, TARGET_TRACE) End If @@ -506,11 +523,34 @@ Public Class LogConfig End Sub #Region "Log Targets" + Private Function GetJsonLogTarget(basePath As String) As FileTarget + Dim defaultLog As New FileTarget() With { + .FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT), + .Name = TARGET_JSON, + .Layout = LOG_FORMAT_DEFAULT, + .MaxArchiveFiles = MAX_ARCHIVE_FILES_DEFAULT, + .ArchiveEvery = ARCHIVE_EVERY, + .KeepFileOpen = KEEP_FILES_OPEN, + .Encoding = Text.Encoding.Unicode + } + + Return defaultLog + End Function + Private Function GetDefaultLogTarget(basePath As String) As FileTarget + Dim oJsonLayout = New Layouts.JsonLayout + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("level", "${level}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("message", "${message}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("date", "${shortdate}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("product", "${var:product}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("suffix", "${var:suffix}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("module", "${event-properties:item=ModuleName}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("exception", "${exception:format=Message,StackTrace:innerFormat=Message:maxInnerExceptionLevel=3}")) + Dim defaultLog As New FileTarget() With { .FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT), .Name = TARGET_DEFAULT, - .Layout = LOG_FORMAT_DEFAULT, + .Layout = oJsonLayout, .MaxArchiveFiles = MAX_ARCHIVE_FILES_DEFAULT, .ArchiveEvery = ARCHIVE_EVERY, .KeepFileOpen = KEEP_FILES_OPEN, @@ -565,9 +605,9 @@ Public Class LogConfig End Function Private Function GetTraceLogTarget(basePath As String) As FileTarget - Dim debugLog As New FileTarget() With { + Dim traceLog As New FileTarget() With { .FileName = Path.Combine(basePath, FILE_NAME_FORMAT_TRACE), - .Name = TARGET_DEBUG, + .Name = TARGET_TRACE, .Layout = LOG_FORMAT_DEBUG, .MaxArchiveFiles = MAX_ARCHIVE_FILES_DEBUG_DETAIL, .ArchiveEvery = ARCHIVE_EVERY, @@ -578,18 +618,7 @@ Public Class LogConfig .Encoding = Text.Encoding.Unicode } - Return debugLog + Return traceLog End Function - - 'Private Function GetMemoryDebugTarget() As MemoryTarget - ' Dim memoryLog As New MemoryTarget() With { - ' .Layout = LOG_FORMAT_DEBUG, - ' .Name = TARGET_MEMORY, - ' .OptimizeBufferReuse = True, - ' .MaxLogsCount = MAX_MEMORY_LOG_COUNT - ' } - - ' Return memoryLog - 'End Function #End Region End Class From 33a95ba46dc7866d564fd26be115a8e94011f5b0 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 09:03:41 +0100 Subject: [PATCH 13/26] Version 2.6.1.0 --- Logging/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Logging/My Project/AssemblyInfo.vb b/Logging/My Project/AssemblyInfo.vb index 196b58c3..b0a1cecb 100644 --- a/Logging/My Project/AssemblyInfo.vb +++ b/Logging/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From c082222c800ad38fc531834bb5e1783f776fa382 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 09:04:14 +0100 Subject: [PATCH 14/26] Messaging: Add binding class --- Messaging/Messaging.vbproj | 1 + Messaging/WCF/Binding.vb | 31 +++++++++++++++++++++++++++++++ Messaging/WCF/Channel.vb | 29 ++++++----------------------- 3 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 Messaging/WCF/Binding.vb diff --git a/Messaging/Messaging.vbproj b/Messaging/Messaging.vbproj index 9ce49a60..d0a2b3b2 100644 --- a/Messaging/Messaging.vbproj +++ b/Messaging/Messaging.vbproj @@ -96,6 +96,7 @@ True + diff --git a/Messaging/WCF/Binding.vb b/Messaging/WCF/Binding.vb new file mode 100644 index 00000000..7ff1cf49 --- /dev/null +++ b/Messaging/WCF/Binding.vb @@ -0,0 +1,31 @@ +Imports System.Net +Imports System.ServiceModel +Imports System.Xml + +Namespace WCF + Public Class Binding + Public Shared Function GetBinding(Optional AuthenticationMode As TcpClientCredentialType = TcpClientCredentialType.Windows) As NetTcpBinding + Return New NetTcpBinding() With { + .MaxReceivedMessageSize = Constants.ChannelSettings.MAX_RECEIVED_MESSAGE_SIZE, + .MaxBufferSize = Constants.ChannelSettings.MAX_BUFFER_SIZE, + .MaxBufferPoolSize = Constants.ChannelSettings.MAX_BUFFER_POOL_SIZE, + .TransferMode = TransferMode.Streamed, + .Security = New NetTcpSecurity() With { + .Mode = SecurityMode.Transport, + .Transport = New TcpTransportSecurity() With { + .ClientCredentialType = AuthenticationMode + } + }, + .ReaderQuotas = New XmlDictionaryReaderQuotas() With { + .MaxArrayLength = Constants.ChannelSettings.MAX_ARRAY_LENGTH, + .MaxStringContentLength = Constants.ChannelSettings.MAX_STRING_CONTENT_LENGTH + } + } + End Function + + Public Shared Function GetAddress(pHost As String, pPort As Integer, pName As String) As Uri + Return New Uri($"net.tcp://{pHost}:{pPort}/DigitalData/Services/{pName}") + End Function + End Class + +End Namespace \ No newline at end of file diff --git a/Messaging/WCF/Channel.vb b/Messaging/WCF/Channel.vb index 71a45348..5d05e590 100644 --- a/Messaging/WCF/Channel.vb +++ b/Messaging/WCF/Channel.vb @@ -11,9 +11,9 @@ Namespace WCF Public Event Reconnect As EventHandler - Public Sub New(pLogConfig As LogConfig, pServerAddress As ServerAddress) + Public Sub New(pLogConfig As LogConfig, pServerAddress As ServerAddress, Optional pName As String = "Main") MyBase.New(pLogConfig) - ChannelFactory = GetChannelFactory(pServerAddress) + ChannelFactory = GetChannelFactory(pServerAddress, pName) End Sub ''' @@ -40,30 +40,13 @@ Namespace WCF ''' The service name, will be: net.tcp://ip:port/DigitalData/Services/[name] ''' The service address, in the form of ip address and port ''' - Private Function GetChannelFactory(pAddress As ServerAddress, Optional pName As String = "Main") As ChannelFactory(Of TChannel) - Dim oBinding = GetBinding() - Dim oAddress = New EndpointAddress($"net.tcp://{pAddress.Host}:{pAddress.Port}/DigitalData/Services/{pName}") + Private Function GetChannelFactory(pAddress As ServerAddress, pName As String) As ChannelFactory(Of TChannel) + Dim oBinding = Binding.GetBinding() + Dim oAddress = New EndpointAddress(Binding.GetAddress(pAddress.Host, pAddress.Port, pName)) Dim oFactory = New ChannelFactory(Of TChannel)(oBinding, oAddress) Return oFactory End Function - Public Shared Function GetBinding(Optional AuthenticationMode As TcpClientCredentialType = TcpClientCredentialType.Windows) As NetTcpBinding - Return New NetTcpBinding() With { - .MaxReceivedMessageSize = Constants.ChannelSettings.MAX_RECEIVED_MESSAGE_SIZE, - .MaxBufferSize = Constants.ChannelSettings.MAX_BUFFER_SIZE, - .MaxBufferPoolSize = Constants.ChannelSettings.MAX_BUFFER_POOL_SIZE, - .TransferMode = TransferMode.Streamed, - .Security = New NetTcpSecurity() With { - .Mode = SecurityMode.Transport, - .Transport = New TcpTransportSecurity() With { - .ClientCredentialType = AuthenticationMode - } - }, - .ReaderQuotas = New XmlDictionaryReaderQuotas() With { - .MaxArrayLength = Constants.ChannelSettings.MAX_ARRAY_LENGTH, - .MaxStringContentLength = Constants.ChannelSettings.MAX_STRING_CONTENT_LENGTH - } - } - End Function + End Class End Namespace From 3df54fa62cbc1f762b0ebebc1c1ef04bee6282d5 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 09:29:34 +0100 Subject: [PATCH 15/26] Jobs/Interfaces: add options for enabling / disabling zugferd schemas --- Interfaces/ZUGFeRDInterface.vb | 26 ++++++++++++++++++-------- Jobs/ZUGFeRD/WorkerArgs.vb | 2 ++ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/Interfaces/ZUGFeRDInterface.vb b/Interfaces/ZUGFeRDInterface.vb index 344d4f01..190f11b9 100644 --- a/Interfaces/ZUGFeRDInterface.vb +++ b/Interfaces/ZUGFeRDInterface.vb @@ -35,6 +35,8 @@ Public Class ZUGFeRDInterface Public Class ZugferdOptions Public Property AllowFacturX_Filename As Boolean = True Public Property AllowXRechnung_Filename As Boolean = True + Public Property AllowZugferd_1_0_Schema As Boolean = True + Public Property AllowZugferd_2_x_Schema As Boolean = True End Class ''' @@ -220,14 +222,21 @@ Public Class ZUGFeRDInterface Dim oReader As XmlReader Dim oResult = Nothing - Dim oTypes As New List(Of Type) From { - GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType), - GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType), - GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType), - GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType) - } + Dim oAllowedTypes As New List(Of Type) - For Each oType In oTypes + If _Options.AllowZugferd_1_0_Schema Then + oAllowedTypes.Add(GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType)) + End If + + If _Options.AllowZugferd_2_x_Schema Then + oAllowedTypes.AddRange(New List(Of Type) From { + GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType), + GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType), + GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType) + }) + End If + + For Each oType In oAllowedTypes _logger.Debug("Trying Type [{0}]", oType.FullName) Dim oSerializer As New XmlSerializer(oType) @@ -251,7 +260,8 @@ Public Class ZUGFeRDInterface Catch ex As Exception _logger.Error(ex) - Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, "Datei ist eine ungültige ZUGFeRD Datei.") + Dim oMessage = "Datei ist eine ungültige ZUGFeRD Datei oder das Format wird nicht unterstüzt, oder das Format ist deaktiviert." + Throw New ZUGFeRDExecption(ErrorType.NoValidZugferd, oMessage) End Try End Function diff --git a/Jobs/ZUGFeRD/WorkerArgs.vb b/Jobs/ZUGFeRD/WorkerArgs.vb index a34a90b0..ba9ac70d 100644 --- a/Jobs/ZUGFeRD/WorkerArgs.vb +++ b/Jobs/ZUGFeRD/WorkerArgs.vb @@ -26,4 +26,6 @@ Public Class WorkerArgs Public AllowFacturX As Boolean = True Public AllowXRechnung As Boolean = True + Public AllowZugferd10 As Boolean = True + Public AllowZugferd2x As Boolean = True End Class \ No newline at end of file From 36dd27b26cdaff968e910c76ba21eb79b7a2228d Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 09:30:10 +0100 Subject: [PATCH 16/26] Jobs: Version 1.12.0.0 --- Jobs/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jobs/My Project/AssemblyInfo.vb b/Jobs/My Project/AssemblyInfo.vb index 9dac9b52..15d87553 100644 --- a/Jobs/My Project/AssemblyInfo.vb +++ b/Jobs/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -30,5 +30,5 @@ Imports System.Runtime.InteropServices ' Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern ' übernehmen, indem Sie "*" eingeben: - - + + From 0ed5a164e815217a9356ff5055ed79a54625f5e6 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 09:30:52 +0100 Subject: [PATCH 17/26] Interfaces: Version 1.10.0.0 --- Interfaces/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Interfaces/My Project/AssemblyInfo.vb b/Interfaces/My Project/AssemblyInfo.vb index a6182373..955d1b45 100644 --- a/Interfaces/My Project/AssemblyInfo.vb +++ b/Interfaces/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From 19f33dbb2c554404bc8d117c023c1d339fe42296 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 13:52:33 +0100 Subject: [PATCH 18/26] Fix json target --- Logging/LogConfig.vb | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/Logging/LogConfig.vb b/Logging/LogConfig.vb index 091a7b33..77450f51 100644 --- a/Logging/LogConfig.vb +++ b/Logging/LogConfig.vb @@ -75,6 +75,7 @@ Public Class LogConfig Private Const FILE_NAME_FORMAT_DEBUG As String = "${shortdate}-${var:product}${var:suffix}${event-properties:item=ModuleName}-Debug.log" Private Const FILE_NAME_FORMAT_TRACE As String = "${shortdate}-${var:product}${var:suffix}${event-properties:item=ModuleName}-Trace.log" Private Const FILE_NAME_FORMAT_ERROR As String = "${shortdate}-${var:product}${var:suffix}${event-properties:item=ModuleName}-Error.log" + Private Const FILE_NAME_FORMAT_JSON As String = "${shortdate}-${var:product}${var:suffix}${event-properties:item=ModuleName}.log.json" Private Const TARGET_DEFAULT As String = "defaultTarget" Private Const TARGET_ERROR_EX As String = "errorExceptionTarget" @@ -455,6 +456,7 @@ Public Class LogConfig _config.AddTarget(TARGET_DEFAULT, GetDefaultLogTarget(_basePath)) _config.AddTarget(TARGET_DEBUG, GetDebugLogTarget(_basePath)) _config.AddTarget(TARGET_TRACE, GetTraceLogTarget(_basePath)) + _config.AddTarget(TARGET_JSON, GetJsonLogTarget(_basePath)) '_config.AddTarget(TARGET_MEMORY, GetMemoryDebugTarget()) ' Add default rules @@ -524,33 +526,33 @@ Public Class LogConfig #Region "Log Targets" Private Function GetJsonLogTarget(basePath As String) As FileTarget - Dim defaultLog As New FileTarget() With { - .FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT), + Dim oJsonLayout = New Layouts.JsonLayout + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("level", "${level}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("message", "${message}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("date", "${shortdate}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("product", "${var:product}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("suffix", "${var:suffix}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("module", "${event-properties:item=ModuleName}")) + oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("exception", "${exception:format=Message,StackTrace:innerFormat=Message:maxInnerExceptionLevel=3}")) + + Dim jsonLog As New FileTarget() With { + .FileName = Path.Combine(basePath, FILE_NAME_FORMAT_JSON), .Name = TARGET_JSON, - .Layout = LOG_FORMAT_DEFAULT, + .Layout = oJsonLayout, .MaxArchiveFiles = MAX_ARCHIVE_FILES_DEFAULT, .ArchiveEvery = ARCHIVE_EVERY, .KeepFileOpen = KEEP_FILES_OPEN, .Encoding = Text.Encoding.Unicode } - Return defaultLog + Return jsonLog End Function Private Function GetDefaultLogTarget(basePath As String) As FileTarget - Dim oJsonLayout = New Layouts.JsonLayout - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("level", "${level}")) - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("message", "${message}")) - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("date", "${shortdate}")) - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("product", "${var:product}")) - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("suffix", "${var:suffix}")) - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("module", "${event-properties:item=ModuleName}")) - oJsonLayout.Attributes.Add(New Layouts.JsonAttribute("exception", "${exception:format=Message,StackTrace:innerFormat=Message:maxInnerExceptionLevel=3}")) - Dim defaultLog As New FileTarget() With { .FileName = Path.Combine(basePath, FILE_NAME_FORMAT_DEFAULT), .Name = TARGET_DEFAULT, - .Layout = oJsonLayout, + .Layout = LOG_FORMAT_DEFAULT, .MaxArchiveFiles = MAX_ARCHIVE_FILES_DEFAULT, .ArchiveEvery = ARCHIVE_EVERY, .KeepFileOpen = KEEP_FILES_OPEN, From 0d207a25a5b5dfe7eda6ff4fe2dfd7aeffd1fd12 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 16 Dec 2022 13:52:43 +0100 Subject: [PATCH 19/26] Logging: Version 2.6.2.0 --- Logging/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Logging/My Project/AssemblyInfo.vb b/Logging/My Project/AssemblyInfo.vb index b0a1cecb..b416a8b8 100644 --- a/Logging/My Project/AssemblyInfo.vb +++ b/Logging/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices ' übernehmen, indem Sie "*" eingeben: ' - - + + From a9567a9d180999296b0516f98b776dec2e6719b5 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Wed, 21 Dec 2022 10:14:19 +0100 Subject: [PATCH 20/26] Jobs/zugferd: Include subject in rejection messages --- Jobs/ZUGFeRD/EmailStrings.vb | 8 ++++---- Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb | 8 ++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Jobs/ZUGFeRD/EmailStrings.vb b/Jobs/ZUGFeRD/EmailStrings.vb index ed3b1639..42fbff03 100644 --- a/Jobs/ZUGFeRD/EmailStrings.vb +++ b/Jobs/ZUGFeRD/EmailStrings.vb @@ -20,9 +20,9 @@ Public Const EMAIL_MD5_ERROR = "

Die von Ihnen gesendete Rechnung wurde bereits von unserem System verarbeitet.

" - Public Const EMAIL_TOO_MUCH_FERDS = "

Ihre Email enthielt mehr als ein ZUGFeRD-Dokument.

" + Public Const EMAIL_TOO_MUCH_FERDS = "

In Ihrer Email ({0}) sind mehr als ein ZUGFeRD Dokument enthalten. Bitte prüfen Sie Rechnung an Anhänge. Nur eine Rechnung darf das ZUGFeRD-Format enthalten

" - Public Const EMAIL_NO_FERDS = "

Ihre Email enthielt keine ZUGFeRD-Dokumente.

" + Public Const EMAIL_NO_FERDS = "

Ihre Email ({0}) enthielt keine ZUGFeRD-Dokumente.

" Public Const EMAIL_FILE_SIZE_REACHED = "

Die von Ihnen gesendete Rechnung oder einer der Rechnungs-Anhänge überschreitet die erlaubte Größe von {0} MB.

@@ -32,13 +32,13 @@ " Public Const EMAIL_INVALID_DOCUMENT = " -

Ihre Email enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.

+

Ihre Email ({0}) enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.

Mögliche Gründe für ein inkorrektes Format:

  • Betrags-Werte weisen ungültiges Format auf (25,01 anstatt 25.01)

" Public Const EMAIL_UNSUPPORTED_DOCUMENT = " -

Ihre Email enthielt ein ZUGFeRD Dokument ({0}), welches zur Zeit noch nicht unsterstützt wird.

+

Ihre Email ({0}) enthielt ein ZUGFeRD Dokument ({1}), welches zur Zeit noch nicht freigeschaltet ist.

" End Class diff --git a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb index 226ada45..5c61659e 100644 --- a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb +++ b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb @@ -400,6 +400,8 @@ Public Class ImportZUGFeRDFiles Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, ex.XmlFile) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) + Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, oEmailData.Subject, ex.XmlFile) + _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "UnsupportedFerdException", _EmailOutAccountId, oArgs.NamePortal) AddRejectedState(oMessageId, "UnsupportedFerdException", "Nicht unterstütztes Datenformat", "", oSQLTransaction) @@ -412,6 +414,8 @@ Public Class ImportZUGFeRDFiles Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) + Dim oBody = String.Format(EmailStrings.EMAIL_INVALID_DOCUMENT, oEmailData.Subject) + _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException", _EmailOutAccountId, oArgs.NamePortal) AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "", oSQLTransaction) @@ -422,6 +426,8 @@ Public Class ImportZUGFeRDFiles Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) + Dim oBody = String.Format(EmailStrings.EMAIL_TOO_MUCH_FERDS, oEmailData.Subject) + _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException", _EmailOutAccountId, oArgs.NamePortal) AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "", oSQLTransaction) @@ -432,6 +438,8 @@ Public Class ImportZUGFeRDFiles Dim oBody = EmailStrings.EMAIL_NO_FERDS Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) + Dim oBody = String.Format(EmailStrings.EMAIL_NO_FERDS, oEmailData.Subject) + _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException", _EmailOutAccountId, oArgs.NamePortal) AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "", oSQLTransaction) From 79cad24b3f244e7073bcb550131e2b7289a7e7d4 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Wed, 21 Dec 2022 10:16:50 +0100 Subject: [PATCH 21/26] Interfaces/zugferd: fix parameter error which leads to falsely allowing mails with two zugferd invoices --- Interfaces/ZUGFeRDInterface.vb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Interfaces/ZUGFeRDInterface.vb b/Interfaces/ZUGFeRDInterface.vb index 190f11b9..0c04fed8 100644 --- a/Interfaces/ZUGFeRDInterface.vb +++ b/Interfaces/ZUGFeRDInterface.vb @@ -220,7 +220,7 @@ Public Class ZUGFeRDInterface Try Dim oNavigator As XPathNavigator = pDocument.Item2.CreateNavigator() Dim oReader As XmlReader - Dim oResult = Nothing + Dim oObject As Object = Nothing Dim oAllowedTypes As New List(Of Type) @@ -242,7 +242,7 @@ Public Class ZUGFeRDInterface Try oReader = oNavigator.ReadSubtree() - oResult = oSerializer.Deserialize(oReader) + oObject = oSerializer.Deserialize(oReader) _logger.Debug("Serializing with type [{0}] succeeded", oType.FullName) Exit For Catch ex As Exception @@ -252,11 +252,11 @@ Public Class ZUGFeRDInterface End Try Next - If oResult Is Nothing Then + If oObject Is Nothing Then Throw New ApplicationException("No Types matched the given document. Document could not be serialized.") End If - Return oResult + Return New Tuple(Of String, Object)(pDocument.Item1, oObject) Catch ex As Exception _logger.Error(ex) From 902c835c37f3fbac7d08adece18961842663ab8b Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Wed, 21 Dec 2022 10:17:31 +0100 Subject: [PATCH 22/26] Jobs/zugferd: add fallback for missing values in GetEmailDataForMessageId --- Jobs/ZUGFeRD/EmailFunctions.vb | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Jobs/ZUGFeRD/EmailFunctions.vb b/Jobs/ZUGFeRD/EmailFunctions.vb index 9dd4c1ae..010de5b1 100644 --- a/Jobs/ZUGFeRD/EmailFunctions.vb +++ b/Jobs/ZUGFeRD/EmailFunctions.vb @@ -1,5 +1,6 @@ Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Database +Imports DigitalData.Modules.Language Imports System.Data Imports System.IO Imports System.Data.SqlClient @@ -164,10 +165,19 @@ Public Class EmailFunctions _logger.Debug("Got Email Data for FileId {0}", MessageId) oRow = oDatatable.Rows.Item(oDatatable.Rows.Count - 1) + Dim oFromDefault = String.Format("No Sender found for ({0})", MessageId) + Dim oFrom = oRow.ItemEx("EMAIL_FROM", oFromDefault) + + Dim oAttachmentDefault = String.Format("No Attachment found for ({0})", MessageId) + Dim oAttachment = oRow.ItemEx("EMAIL_ATTMT1", oAttachmentDefault) + + Dim oSubjectDefault = String.Format("No Subject found for ({0})", MessageId) + Dim oSubject = oRow.ItemEx("EMAIL_SUBJECT", oSubjectDefault) + Return New EmailData() With { - .From = oRow.Item("EMAIL_FROM"), - .Attachment = oRow.Item("EMAIL_ATTMT1"), - .Subject = oRow.Item("EMAIL_SUBJECT") + .From = oFrom, + .Attachment = oAttachment, + .Subject = oSubject } Catch ex As Exception _logger.Warn("Could not fetch Email Data for FileId {0}", MessageId) From 65d58a227417226d74bc3a673737ce1929b6941c Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Wed, 21 Dec 2022 14:02:44 +0100 Subject: [PATCH 23/26] Zugferd: prepare loading different specs per document schema version --- Interfaces/ZUGFeRDInterface.vb | 76 ++++++++++++------- .../ZUGFeRDInterface/XmlItemProperty.vb | 10 ++- Jobs/Jobs.vbproj | 4 +- Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb | 31 ++++++-- 4 files changed, 85 insertions(+), 36 deletions(-) diff --git a/Interfaces/ZUGFeRDInterface.vb b/Interfaces/ZUGFeRDInterface.vb index 0c04fed8..4c10aa50 100644 --- a/Interfaces/ZUGFeRDInterface.vb +++ b/Interfaces/ZUGFeRDInterface.vb @@ -12,6 +12,13 @@ Public Class ZUGFeRDInterface Private ReadOnly _logger As Logger Private ReadOnly _Options As ZugferdOptions + ' These constants define the specification markers for the different + ' zugferd document schema versions. These markers need to be used to + ' define the property map in the database (column SPECIFICATION). + Public Const ZUGFERD_SPEC_DEFAULT = "DEFAULT" + Public Const ZUGFERD_SPEC_10 = "ZUGFERD_10" + Public Const ZUGFERD_SPEC_2x = "ZUGFERD_2x" + Private ReadOnly ValidFilenames As New List(Of String) From { PDFEmbeds.ZUGFERD_XML_FILENAME.ToUpper, PDFEmbeds.FACTUR_X_XML_FILENAME_DE.ToUpper, @@ -39,6 +46,13 @@ Public Class ZUGFeRDInterface Public Property AllowZugferd_2_x_Schema As Boolean = True End Class + Public Class ZugferdResult + Public Property DataFileName As String + Public Property XPathObject As XPathDocument + Public Property SchemaObject As Object + Public Property Specification As String + End Class + ''' ''' Create a new instance of ZUGFeRDInterface ''' @@ -91,14 +105,14 @@ Public Class ZUGFeRDInterface '''
''' ''' - Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As Tuple(Of String, Object) - Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path) + Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As ZugferdResult + Dim oResult = ValidateZUGFeRDFileWithGDPicture(Path) - If IsNothing(oXmlDocument.Item2) Then + If IsNothing(oResult.SchemaObject) Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.") End If - Return SerializeZUGFeRDDocument(oXmlDocument) + Return SerializeZUGFeRDDocument(oResult) End Function ''' @@ -106,14 +120,14 @@ Public Class ZUGFeRDInterface ''' ''' ''' - Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As Tuple(Of String, Object) - Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Stream) + Public Function ExtractZUGFeRDFileWithGDPicture(Stream As Stream) As ZugferdResult + Dim oResult = ValidateZUGFeRDFileWithGDPicture(Stream) - If IsNothing(oXmlDocument.Item2) Then + If IsNothing(oResult.SchemaObject) Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.") End If - Return SerializeZUGFeRDDocument(oXmlDocument) + Return SerializeZUGFeRDDocument(oResult) End Function ''' @@ -122,7 +136,7 @@ Public Class ZUGFeRDInterface ''' ''' ''' The embedded xml data as an XPath document - Public Function ValidateZUGFeRDFileWithGDPicture(pStream As Stream) As Tuple(Of String, XPathDocument) + Public Function ValidateZUGFeRDFileWithGDPicture(pStream As Stream) As ZugferdResult Dim oEmbedExtractor = New PDFEmbeds(_logConfig) Try @@ -150,7 +164,7 @@ Public Class ZUGFeRDInterface ''' ''' ''' The embedded xml data as an XPath document - Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As Tuple(Of String, XPathDocument) + Public Function ValidateZUGFeRDFileWithGDPicture(pPath As String) As ZugferdResult Dim oEmbedExtractor = New PDFEmbeds(_logConfig) Try @@ -172,7 +186,7 @@ Public Class ZUGFeRDInterface End Try End Function - Private Function HandleEmbeddedFiles(pResults As List(Of PDFEmbeds.EmbeddedFile)) As Tuple(Of String, XPathDocument) + Private Function HandleEmbeddedFiles(pResults As List(Of PDFEmbeds.EmbeddedFile)) As ZugferdResult If pResults Is Nothing Then Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei, weil die Attachments nicht gelesen werden konnten.") End If @@ -202,7 +216,10 @@ Public Class ZUGFeRDInterface Try Using oStream As New MemoryStream(oAllowedResult.FileContents) - Return New Tuple(Of String, XPathDocument)(oAllowedResult.FileName, New XPathDocument(oStream)) + Return New ZugferdResult With { + .DataFileName = oAllowedResult.FileName, + .XPathObject = New XPathDocument(oStream) + } End Using Catch ex As ZUGFeRDExecption @@ -216,37 +233,41 @@ Public Class ZUGFeRDInterface End Try End Function - Public Function SerializeZUGFeRDDocument(pDocument As Tuple(Of String, XPathDocument)) As Tuple(Of String, Object) + Public Function SerializeZUGFeRDDocument(pResult As ZugferdResult) As ZugferdResult Try - Dim oNavigator As XPathNavigator = pDocument.Item2.CreateNavigator() + Dim oNavigator As XPathNavigator = pResult.XPathObject.CreateNavigator() Dim oReader As XmlReader + Dim oObject As Object = Nothing + Dim oSpecification As String = Nothing - Dim oAllowedTypes As New List(Of Type) + Dim oAllowedTypes As New Dictionary(Of String, Type) If _Options.AllowZugferd_1_0_Schema Then - oAllowedTypes.Add(GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType)) + oAllowedTypes.Add(ZUGFERD_SPEC_10, GetType(ZUGFeRD.Version1_0.CrossIndustryDocumentType)) End If If _Options.AllowZugferd_2_x_Schema Then - oAllowedTypes.AddRange(New List(Of Type) From { - GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType), - GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType), - GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType) - }) + oAllowedTypes.Add(ZUGFERD_SPEC_2x, GetType(ZUGFeRD.Version2_0.CrossIndustryInvoiceType)) + oAllowedTypes.Add(ZUGFERD_SPEC_2x, GetType(ZUGFeRD.Version2_1_1.CrossIndustryInvoiceType)) + oAllowedTypes.Add(ZUGFERD_SPEC_2x, GetType(ZUGFeRD.Version2_2_FacturX.CrossIndustryInvoiceType)) End If For Each oType In oAllowedTypes - _logger.Debug("Trying Type [{0}]", oType.FullName) - Dim oSerializer As New XmlSerializer(oType) + Dim oTypeName As String = oType.Value.FullName + Dim oSerializer As New XmlSerializer(oType.Value) + _logger.Debug("Trying Type [{0}]", oTypeName) Try oReader = oNavigator.ReadSubtree() + oObject = oSerializer.Deserialize(oReader) - _logger.Debug("Serializing with type [{0}] succeeded", oType.FullName) + oSpecification = oType.Key + + _logger.Debug("Serializing with type [{0}] succeeded", oTypeName) Exit For Catch ex As Exception - _logger.Debug("Serializing with type [{0}] failed", oType.FullName) + _logger.Debug("Serializing with type [{0}] failed", oTypeName) _logger.Debug(ex.Message) _logger.Error(ex.InnerException?.Message) End Try @@ -256,7 +277,10 @@ Public Class ZUGFeRDInterface Throw New ApplicationException("No Types matched the given document. Document could not be serialized.") End If - Return New Tuple(Of String, Object)(pDocument.Item1, oObject) + pResult.Specification = oSpecification + pResult.SchemaObject = oObject + + Return pResult Catch ex As Exception _logger.Error(ex) diff --git a/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb b/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb index a14c456e..672dcce0 100644 --- a/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb +++ b/Interfaces/ZUGFeRDInterface/XmlItemProperty.vb @@ -1,8 +1,14 @@ Public Class XmlItemProperty + Public IsRequired As Boolean + Public IsGrouped As Boolean + Public TableName As String Public TableColumn As String Public Description As String - Public IsRequired As Boolean - Public IsGrouped As Boolean Public GroupScope As String + + ''' + ''' Document version, eg. ZUGFeRD Schema version + ''' + Public Specification As String End Class \ No newline at end of file diff --git a/Jobs/Jobs.vbproj b/Jobs/Jobs.vbproj index eb622bad..aa97236c 100644 --- a/Jobs/Jobs.vbproj +++ b/Jobs/Jobs.vbproj @@ -116,9 +116,9 @@ - + False - ..\Interfaces\bin\Debug\DigitalData.Modules.Language.dll + ..\Language\bin\Debug\DigitalData.Modules.Language.dll ..\packages\FirebirdSql.Data.FirebirdClient.7.5.0\lib\net452\FirebirdSql.Data.FirebirdClient.dll diff --git a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb index 5c61659e..f8a0171b 100644 --- a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb +++ b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb @@ -206,7 +206,9 @@ Public Class ImportZUGFeRDFiles ' different versions of ZUGFeRD and the type is unknown at compile-time. ' 17.11.2022: oDocument is now a Tuple of (String, Object), to be able to return the filename ' of the extracted xml file. - Dim oDocument As Tuple(Of String, Object) + ' 21.12.2022: oDocument is now an object of type ZugferdResult to be able to save + ' the new meta data, ie. the type of schema (zugferd version) + Dim oDocument As ZUGFeRDInterface.ZugferdResult ' Start a global group counter for each file Dim oGlobalGroupCounter = 0 @@ -283,7 +285,8 @@ Public Class ImportZUGFeRDFiles ' Check the document against the configured property map and return: ' - a List of valid properties ' - a List of missing properties - Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument, oArgs.PropertyMap, oMessageId) + Dim oPropertyMap = GetPropertyMapFor(oArgs, oDocument) + Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument.SchemaObject, oPropertyMap, oMessageId) _logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count) @@ -398,7 +401,6 @@ Public Class ImportZUGFeRDFiles ' That 's why we set it to String.Empty here. Create_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but unsupported format", oFBTransaction) - Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, ex.XmlFile) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oBody As String = String.Format(EmailStrings.EMAIL_UNSUPPORTED_DOCUMENT, oEmailData.Subject, ex.XmlFile) @@ -412,7 +414,6 @@ Public Class ImportZUGFeRDFiles ' That 's why we set it to String.Empty here. Create_HistoryEntry(oMessageId, String.Empty, "REJECTED - ZUGFeRD yes but incorrect format", oFBTransaction) - Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oBody = String.Format(EmailStrings.EMAIL_INVALID_DOCUMENT, oEmailData.Subject) @@ -424,7 +425,6 @@ Public Class ImportZUGFeRDFiles Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - More than one ZUGFeRD-document in email", oFBTransaction) - Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oBody = String.Format(EmailStrings.EMAIL_TOO_MUCH_FERDS, oEmailData.Subject) @@ -436,7 +436,6 @@ Public Class ImportZUGFeRDFiles Create_HistoryEntry(oMessageId, oMD5CheckSum, "REJECTED - no ZUGFeRD-Document in email", oFBTransaction) - Dim oBody = EmailStrings.EMAIL_NO_FERDS Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oBody = String.Format(EmailStrings.EMAIL_NO_FERDS, oEmailData.Subject) @@ -584,6 +583,26 @@ Public Class ImportZUGFeRDFiles End Try End Sub + Private Function GetPropertyMapFor(pWorkerArgs As WorkerArgs, pSpecification As String) As Dictionary(Of String, XmlItemProperty) + Dim oPropertyMap = DoGetPropertyMapFor(pWorkerArgs, pSpecification) + + _logger.Debug("Found [{0}] Properties for Specification [{1}].", oPropertyMap.Count, pSpecification) + + ' If no properties were found, fall back to the default specification before giving up + If oPropertyMap.Count = 0 Then + _logger.Warn("No Properties found for Specification [{0}]. Loading default property map!", pSpecification) + Return DoGetPropertyMapFor(pWorkerArgs, ZUGFeRDInterface.ZUGFERD_SPEC_DEFAULT) + End If + + Return oPropertyMap + End Function + + Private Function DoGetPropertyMapFor(pWorkerArgs As WorkerArgs, pSpecification As String) As Dictionary(Of String, XmlItemProperty) + Return pWorkerArgs.PropertyMap. + Where(Function(kv) kv.Value.Specification = pSpecification). + ToDictionary(Function(kv) kv.Key, Function(kv) kv.Value) + End Function + Private Sub MoveFiles( Args As WorkerArgs, MessageId As String, From 4dfe32ba335818835657f862971cf9ce70970e85 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 23 Dec 2022 13:28:41 +0100 Subject: [PATCH 24/26] Jobs: Fix typo in EmailStrings --- Jobs/ZUGFeRD/EmailStrings.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jobs/ZUGFeRD/EmailStrings.vb b/Jobs/ZUGFeRD/EmailStrings.vb index 42fbff03..fbecd5bb 100644 --- a/Jobs/ZUGFeRD/EmailStrings.vb +++ b/Jobs/ZUGFeRD/EmailStrings.vb @@ -39,6 +39,6 @@ " Public Const EMAIL_UNSUPPORTED_DOCUMENT = " -

Ihre Email ({0}) enthielt ein ZUGFeRD Dokument ({1}), welches zur Zeit noch nicht freigeschaltet ist.

+

Ihre Email ({0}) enthielt ein ZUGFeRD Format ({1}), welches zur Zeit noch nicht freigeschaltet ist.

" End Class From e5ec777d616473b4015ba5e8029e69130063dde4 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 23 Dec 2022 13:29:01 +0100 Subject: [PATCH 25/26] Jobs: Fix typo in importzugferdfiles --- Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb index f8a0171b..88b98b26 100644 --- a/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb +++ b/Jobs/ZUGFeRD/ImportZUGFeRDFiles.vb @@ -285,7 +285,7 @@ Public Class ImportZUGFeRDFiles ' Check the document against the configured property map and return: ' - a List of valid properties ' - a List of missing properties - Dim oPropertyMap = GetPropertyMapFor(oArgs, oDocument) + Dim oPropertyMap = GetPropertyMapFor(oArgs, oDocument.Specification) Dim oCheckResult = _zugferd.PropertyValues.CheckPropertyValues(oDocument.SchemaObject, oPropertyMap, oMessageId) _logger.Info("Properties checked: [{0}] missing properties / [{1}] valid properties found.", oCheckResult.MissingProperties.Count, oCheckResult.ValidProperties.Count) From baa661cb141f65d2783bf4c3c8384f2000461f01 Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Fri, 23 Dec 2022 13:29:46 +0100 Subject: [PATCH 26/26] Jobs: Version 1.12.0.1 --- Jobs/My Project/AssemblyInfo.vb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Jobs/My Project/AssemblyInfo.vb b/Jobs/My Project/AssemblyInfo.vb index 15d87553..4625e99b 100644 --- a/Jobs/My Project/AssemblyInfo.vb +++ b/Jobs/My Project/AssemblyInfo.vb @@ -13,7 +13,7 @@ Imports System.Runtime.InteropServices - + @@ -30,5 +30,5 @@ Imports System.Runtime.InteropServices ' Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern ' übernehmen, indem Sie "*" eingeben: - - + +