16 Commits

Author SHA1 Message Date
Jonathan Jenne
84dab7f5a6 Merge remote-tracking branch 'origin/master' into ZugferdService-Redesign 2020-03-20 13:49:18 +01:00
Jonathan Jenne
3449b16d69 Modules.Logging: Version 2.0.0.0 2020-03-20 13:48:43 +01:00
Jonathan Jenne
7b3dc1bf89 first working version of zugferd rest service 2020-03-20 13:48:09 +01:00
Jonathan Jenne
3d3a491744 big refactor, move most zugferd processing into Modules.Interfaces 2020-03-20 13:47:36 +01:00
Jonathan Jenne
322ca23f33 clean up 2020-03-20 13:45:56 +01:00
Jonathan Jenne
6ec458ccdf Merge branch 'master' into ZugferdService-Redesign 2020-03-18 16:28:18 +01:00
Jonathan Jenne
a437359114 Jobs: Version 1.1.0.2 2020-03-18 16:24:08 +01:00
Jonathan Jenne
b6b29e5de8 fix grouping 2020-03-18 16:23:38 +01:00
Jonathan Jenne
51c1f9f3f7 Merge branch 'master' into ZugferdService-Redesign 2020-03-18 10:19:21 +01:00
Jonathan Jenne
28d2e4241d Jobs: Version 1.1.0.1 2020-03-18 10:18:49 +01:00
Jonathan Jenne
edf7c37cb5 Jobs: Version 1.1.0.1 2020-03-17 17:12:26 +01:00
Jonathan Jenne
c8291116a3 Merge branch 'master' of http://dd-vmp07-com04:3000/AppStd/Monorepo 2020-03-17 17:06:23 +01:00
Jonathan Jenne
7977b926f1 ZUGFeRD Service: Version 1.1.0.1 2020-03-17 17:06:12 +01:00
Jonathan Jenne
a46809ae24 ZUGFeRD Interface: Fix moving attachments to success folder instead of attachments 2020-03-17 17:05:41 +01:00
a66c2928f2 ms commit 2020-03-17 16:27:53 +01:00
dff085ced2 ms 2020-03-17 16:27:04 +01:00
31 changed files with 757 additions and 450 deletions

View File

@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
' übernehmen, indem Sie "*" eingeben: ' übernehmen, indem Sie "*" eingeben:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.1.0.0")> <Assembly: AssemblyVersion("1.1.0.1")>
<Assembly: AssemblyFileVersion("1.0.0.0")> <Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -27,11 +27,10 @@ Public Class ThreadRunner
Private Const TIMER_INTERVAL_MS = 10_000 Private Const TIMER_INTERVAL_MS = 10_000
Public Sub New(LogConfig As LogConfig, GDPictureKey As String, Firebird As Firebird, Optional MSSQL As MSSQLServer = Nothing) Public Sub New(LogConfig As LogConfig, Firebird As Firebird, Optional MSSQL As MSSQLServer = Nothing)
_logConfig = LogConfig _logConfig = LogConfig
_logger = _logConfig.GetLogger() _logger = _logConfig.GetLogger()
_firebird = Firebird _firebird = Firebird
_zugferd = New ZUGFeRDInterface(_logConfig)
_mssql = MSSQL _mssql = MSSQL
Dim args As New WorkerArgs() Dim args As New WorkerArgs()

View File

@@ -25,7 +25,7 @@ Public Class Form1
_firebird = New Firebird(_logConfig, My.Settings.FB_DATASOURCE, My.Settings.FB_DATABASE, My.Settings.FB_USER, My.Settings.FB_PASS) _firebird = New Firebird(_logConfig, My.Settings.FB_DATASOURCE, My.Settings.FB_DATABASE, My.Settings.FB_USER, My.Settings.FB_PASS)
_mssql = New MSSQLServer(_logConfig, My.Settings.MSSQL_CONNECTIONSTRING) _mssql = New MSSQLServer(_logConfig, My.Settings.MSSQL_CONNECTIONSTRING)
_zugferd = New ZUGFeRDInterface(_logConfig) _zugferd = New ZUGFeRDInterface(_logConfig, "")
End Sub End Sub
Private Function LoadFolderConfig(args As WorkerArgs) Private Function LoadFolderConfig(args As WorkerArgs)
@@ -164,7 +164,7 @@ Public Class Form1
End Sub End Sub
Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click Private Sub Button7_Click(sender As Object, e As EventArgs) Handles Button7.Click
Dim oExtractor = New Jobs.PDFAttachments(_logConfig) Dim oExtractor = New PDFAttachments(_logConfig)
Dim oResult = OpenFileDialog1.ShowDialog() Dim oResult = OpenFileDialog1.ShowDialog()
If oResult = DialogResult.OK Then If oResult = DialogResult.OK Then

View File

@@ -169,7 +169,6 @@ Public Class File
<DebuggerStepThrough> <DebuggerStepThrough>
Public Sub MoveTo(FilePath As String, NewFileName As String, Directory As String) Public Sub MoveTo(FilePath As String, NewFileName As String, Directory As String)
Dim oFileInfo As New FileInfo(FilePath)
IO.File.Move(FilePath, Path.Combine(Directory, NewFileName)) IO.File.Move(FilePath, Path.Combine(Directory, NewFileName))
End Sub End Sub

View File

@@ -1,9 +1,11 @@
Imports System.Xml Imports System.IO
Imports System.Xml
Imports System.Xml.Serialization Imports System.Xml.Serialization
Imports System.Xml.XPath Imports System.Xml.XPath
Imports System.Xml.Xsl Imports System.Xml.Xsl
Imports DigitalData.Modules.Interfaces.Exceptions Imports DigitalData.Modules.Interfaces.Exceptions
Imports DigitalData.Modules.Logging Imports DigitalData.Modules.Logging
Imports GdPicture14
Public Class ZUGFeRDInterface Public Class ZUGFeRDInterface
Private _logConfig As LogConfig Private _logConfig As LogConfig
@@ -21,13 +23,23 @@ Public Class ZUGFeRDInterface
Public ReadOnly Property FileGroup As FileGroups Public ReadOnly Property FileGroup As FileGroups
Public ReadOnly Property PropertyValues As PropertyValues Public ReadOnly Property PropertyValues As PropertyValues
Public Sub New(LogConfig As LogConfig) Public Sub New(LogConfig As LogConfig, GDPictureKey As String)
_logConfig = LogConfig _logConfig = LogConfig
_logger = _logConfig.GetLogger() _logger = _logConfig.GetLogger()
FileGroup = New FileGroups(_logConfig) FileGroup = New FileGroups(_logConfig)
PropertyValues = New PropertyValues(_logConfig) PropertyValues = New PropertyValues(_logConfig)
Try
Dim oLicenseManager As New LicenseManager
oLicenseManager.RegisterKEY(GDPictureKey)
Catch ex As Exception
_logger.Warn("GDPicture License could not be registered!")
_logger.Error(ex)
End Try
End Sub End Sub
''' <summary> ''' <summary>
''' Validates a ZUGFeRD File and extracts the XML Document from it ''' Validates a ZUGFeRD File and extracts the XML Document from it
''' </summary> ''' </summary>
@@ -35,7 +47,6 @@ Public Class ZUGFeRDInterface
''' <exception cref="ZUGFeRDExecption"></exception> ''' <exception cref="ZUGFeRDExecption"></exception>
''' <returns></returns> ''' <returns></returns>
Public Function ExtractZUGFeRDFile(Path As String) As CrossIndustryDocumentType Public Function ExtractZUGFeRDFile(Path As String) As CrossIndustryDocumentType
Dim oException As New Exception
Dim oXmlDocument = ValidateZUGFeRDFile(Path) Dim oXmlDocument = ValidateZUGFeRDFile(Path)
If IsNothing(oXmlDocument) Then If IsNothing(oXmlDocument) Then
@@ -45,6 +56,15 @@ Public Class ZUGFeRDInterface
Return SerializeZUGFeRDDocument(oXmlDocument) Return SerializeZUGFeRDDocument(oXmlDocument)
End Function End Function
Public Function ExtractZUGFeRDFileWithGDPicture(Path As String) As CrossIndustryDocumentType
Dim oXmlDocument = ValidateZUGFeRDFileWithGDPicture(Path)
If IsNothing(oXmlDocument) Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
End If
Return SerializeZUGFeRDDocument(oXmlDocument)
End Function
Public Function ValidateZUGFeRDFile(Path As String) As XPathDocument Public Function ValidateZUGFeRDFile(Path As String) As XPathDocument
Dim oProcessOutput, oProcessError As String Dim oProcessOutput, oProcessError As String
@@ -90,6 +110,52 @@ Public Class ZUGFeRDInterface
Return oXmlDocument Return oXmlDocument
End Function End Function
Public Function ValidateZUGFeRDFileWithGDPicture(Path As String) As XPathDocument
Dim oAttachmentExtractor = New PDFAttachments(_logConfig)
Dim oAllowedExtensions = New List(Of String) From {"xml"}
Dim oXmlDocument As XPathDocument
Try
Dim oResults = oAttachmentExtractor.Extract(Path, oAllowedExtensions)
If oResults Is Nothing Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
End If
If oResults.Count = 0 Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
End If
Dim oFound As Boolean = False
Dim oFoundResult As PDFAttachments.AttachmentResult = Nothing
For Each oResult In oResults
If oResult.FileName = PDFAttachments.ZUGFERD_XML_FILENAME Then
oFound = True
oFoundResult = oResult
End If
Next
If Not oFound Then
Throw New ZUGFeRDExecption(ErrorType.NoZugferd, "Datei ist keine ZUGFeRD Datei.")
End If
Try
Using oStream As New MemoryStream(oFoundResult.FileContents)
oXmlDocument = New XPathDocument(oStream)
End Using
Return oXmlDocument
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
Catch ex As Exception
_logger.Error(ex)
Throw ex
End Try
End Function
Public Function SerializeZUGFeRDDocument(Document As XPathDocument) As CrossIndustryDocumentType Public Function SerializeZUGFeRDDocument(Document As XPathDocument) As CrossIndustryDocumentType
Try Try
Dim oNavigator As XPathNavigator = Document.CreateNavigator() Dim oNavigator As XPathNavigator = Document.CreateNavigator()

View File

@@ -4,9 +4,9 @@ Imports DigitalData.Modules.Logging
Imports GdPicture14 Imports GdPicture14
Public Class PDFAttachments Public Class PDFAttachments
Private Logger As Logger Private ReadOnly Logger As Logger
Private Const ZUGFERD_XML_FILENAME = "ZUGFeRD-invoice.xml" Public Const ZUGFERD_XML_FILENAME = "ZUGFeRD-invoice.xml"
Public Class AttachmentResult Public Class AttachmentResult
Public FileName As String Public FileName As String
@@ -17,22 +17,28 @@ Public Class PDFAttachments
Logger = LogConfig.GetLogger Logger = LogConfig.GetLogger
End Sub End Sub
''' <summary>
''' Extracts all embedded files from a PDF file.
''' Note: This does NOT filter out `ZUGFeRD-invoice.xml` anymore to allow for a more generic use.
''' </summary>
''' <param name="FileName"></param>
''' <param name="AllowedExtensions"></param>
''' <returns></returns>
Public Function Extract(FileName As String, AllowedExtensions As List(Of String)) As List(Of AttachmentResult) Public Function Extract(FileName As String, AllowedExtensions As List(Of String)) As List(Of AttachmentResult)
Dim oResults As New List(Of AttachmentResult) Dim oResults As New List(Of AttachmentResult)
Dim oExtensions = AllowedExtensions.ConvertAll(Of String)(New Converter(Of String, String)(Function(ext) ext.ToUpper)) Dim oExtensions = AllowedExtensions.ConvertAll(New Converter(Of String, String)(Function(ext) ext.ToUpper))
Try Try
Using oGDPicturePDF As New GdPicturePDF() Using oGDPicturePDF As New GdPicturePDF()
If oGDPicturePDF.LoadFromFile(FileName, False) = GdPictureStatus.OK Then If oGDPicturePDF.LoadFromFile(FileName, False) = GdPictureStatus.OK Then
Dim oEmbeddedFileCount As Integer = oGDPicturePDF.GetEmbeddedFileCount() Dim oEmbeddedFileCount As Integer = oGDPicturePDF.GetEmbeddedFileCount()
If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then
If oEmbeddedFileCount > 1 Then If oEmbeddedFileCount > 0 Then
For index = 0 To oEmbeddedFileCount - 1 For index = 0 To oEmbeddedFileCount - 1
Dim oFileName As String = oGDPicturePDF.GetEmbeddedFileName(index) Dim oFileName As String = oGDPicturePDF.GetEmbeddedFileName(index)
If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then
Dim oExtension = New FileInfo(oFileName).Extension.ToUpper.Substring(1) Dim oExtension = New FileInfo(oFileName).Extension.ToUpper.Substring(1)
If oFileName.ToUpper <> ZUGFERD_XML_FILENAME.ToUpper Then
If oExtensions.Contains(oExtension) Then If oExtensions.Contains(oExtension) Then
Dim FileSize As Integer = oGDPicturePDF.GetEmbeddedFileSize(index) Dim FileSize As Integer = oGDPicturePDF.GetEmbeddedFileSize(index)
@@ -49,19 +55,6 @@ Public Class PDFAttachments
Logger.Error("The embedded file [{0}] has failed to extract. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString()) Logger.Error("The embedded file [{0}] has failed to extract. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
Continue For Continue For
End If End If
'If status = GdPictureStatus.OK Then
' Dim oVersionedName = Filesystem.GetVersionedFilename(oFileName)
' Dim oTempName As String = Path.Combine(Path.GetTempPath(), oVersionedName)
' Using oFileStream As New FileStream(oTempName, FileMode.OpenOrCreate)
' oFileStream.Write(oFileData, 0, oFileData.Length)
' End Using
' oResults.Add(New FileInfo(oTempName))
'Else
' Logger.Error("The embedded file [{0}] has failed to extract. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
' Continue For
'End If
Else Else
Logger.Error("An error occurred getting the file size for [{0}]. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString()) Logger.Error("An error occurred getting the file size for [{0}]. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
Continue For Continue For
@@ -70,10 +63,6 @@ Public Class PDFAttachments
Logger.Warn("File [{0}] was skipped because its extension [{1}] is not allowed.", oFileName, oExtension) Logger.Warn("File [{0}] was skipped because its extension [{1}] is not allowed.", oFileName, oExtension)
Continue For Continue For
End If End If
Else
Logger.Debug("File [{0}] was skipped because its name indicates the invoice data file.", oFileName)
Continue For
End If
Else Else
Logger.Error("An error occurred getting the file name for [{0}]. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString()) Logger.Error("An error occurred getting the file name for [{0}]. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
Continue For Continue For
@@ -81,12 +70,12 @@ Public Class PDFAttachments
Next Next
End If End If
Else Else
Logger.Error("An error occurred getting the number of embedded files. Status: {0}", oGDPicturePDF.GetStat().ToString()) Dim oMessage = String.Format("An error occurred getting the number of embedded files. Status: {0}", oGDPicturePDF.GetStat().ToString())
Return Nothing Throw New ApplicationException(oMessage)
End If End If
Else Else
Logger.Error("The file [{0}] can't be loaded.", FileName) Dim oMessage = String.Format("The file [{0}] can't be loaded. Status: [{1}]", FileName, oGDPicturePDF.GetStat().ToString())
Return Nothing Throw New ApplicationException(oMessage)
End If End If
End Using End Using

View File

@@ -16,7 +16,7 @@ Public Class PropertyValues
Public Class CheckPropertyValuesResult Public Class CheckPropertyValuesResult
Public MissingProperties As New List(Of String) Public MissingProperties As New List(Of String)
Public ValidProperties As List(Of ValidProperty) Public ValidProperties As New List(Of ValidProperty)
End Class End Class
Public Class ValidProperty Public Class ValidProperty
@@ -36,7 +36,7 @@ Public Class PropertyValues
' PropertyMap items with `IsGrouped = False` are handled normally ' PropertyMap items with `IsGrouped = False` are handled normally
Dim oDefaultProperties As Dictionary(Of String, XmlItemProperty) = PropertyMap. Dim oDefaultProperties As Dictionary(Of String, XmlItemProperty) = PropertyMap.
Where(Function(Item) Item.Value.IsGrouped = True). Where(Function(Item) Item.Value.IsGrouped = False).
ToDictionary(Function(Item) Item.Key, ToDictionary(Function(Item) Item.Key,
Function(Item) Item.Value) Function(Item) Item.Value)

View File

@@ -0,0 +1,197 @@
Imports DigitalData.Modules.Logging
Imports DigitalData.Modules.Database
Imports System.Data
Imports System.IO
Public Class EmailFunctions
Private ReadOnly _logConfig As LogConfig
Private ReadOnly _logger As Logger
Private ReadOnly _mssql As MSSQLServer
Private ReadOnly _firebird As Firebird
Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer, Firebird As Firebird)
_logConfig = LogConfig
_logger = _logConfig.GetLogger()
_mssql = MSSQL
_firebird = Firebird
End Sub
Public Sub AddToEmailQueueFB(MessageId As String, BodyText As String, EmailData As EmailData)
If EmailData Is Nothing Then
_logger.Warn("EmailData is empty. Email will not be sent!")
Exit Sub
End If
Try
Dim oJobId = RandomValue(1, 10000)
Dim oReference = MessageId
Dim oEmailTo = ""
Dim oSubject = EmailStrings.EMAIL_SUBJECT
Dim oAccountId = 1
Dim oCreatedWho = "ZUGFeRD Service"
Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT, BodyText)
Dim oEmailAddress = EmailData.From
Dim oAttachment = EmailData.Attachment
If IsNothing(oEmailAddress) OrElse String.IsNullOrWhiteSpace(oEmailAddress) Then
_logger.Warn("Could not find email-address for MessageId {0}", MessageId)
oEmailTo = String.Empty
Else
oEmailTo = oEmailAddress
End If
_logger.Debug("Generated Email:")
_logger.Debug("To: {0}", oEmailTo)
_logger.Debug("Subject: {0}", oSubject)
_logger.Debug("Body {0}", oFinalBodyText)
Dim osql = $"select * from TBEDM_EMAIL_QUEUE where REFERENCE1 = '{oReference} and EMAIL_TO = ''{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
Dim oDTResult As DataTable = _firebird.GetDatatable(osql)
If oDTResult.Rows.Count = 0 Then
Dim oSQLInsert = $"INSERT INTO TBEDM_EMAIL_QUEUE "
oSQLInsert &= "(JOB_ID, REFERENCE1, EMAIL_ACCOUNT_ID, EMAIL_TO, EMAIL_SUBJ, EMAIL_BODY, CREATEDWHO, EMAIL_ATTMT1) VALUES "
oSQLInsert &= $"({oJobId}, '{oReference}', {oAccountId}, '{oEmailTo}', '{oSubject}', '{oFinalBodyText.Replace("'", "''")}', '{oCreatedWho}', '{oAttachment}')"
_firebird.ExecuteNonQuery(oSQLInsert)
_logger.Debug("Email Queue updated for MessageId {0}.", MessageId, oEmailTo)
Else
_logger.Debug("Email has already been sent!!")
End If
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
Public Sub AddToEmailQueueMSSQL(MessageId As String, BodyText As String, pEmailData As EmailData, SourceProcedure As String)
If pEmailData Is Nothing Then
_logger.Warn("EmailData is empty. Email will not be sent!")
Exit Sub
End If
Try
Dim oJobId = RandomValue(1, 10000)
Dim oReference = MessageId
Dim oEmailTo = ""
Dim oSubject = EmailStrings.EMAIL_SUBJECT
Dim oAccountId = 1
Dim oCreatedWho = "ZUGFeRD Service"
Dim oFinalBodyText = String.Format(EmailStrings.EMAIL_WRAPPING_TEXT, BodyText)
Dim oEmailAddress = pEmailData.From
Dim oAttachment = pEmailData.Attachment
If oAttachment <> String.Empty Then
_logger.Debug($"Attachment_String [{oAttachment}]!")
If IO.File.Exists(oAttachment) = False Then
_logger.Info($"Attachment.File [{oAttachment}] is not existing!!!")
End If
End If
If IsNothing(oEmailAddress) OrElse String.IsNullOrWhiteSpace(oEmailAddress) Then
_logger.Warn("Could not find email-address for MessageId {0}", MessageId)
oEmailTo = String.Empty
Else
oEmailTo = oEmailAddress
End If
_logger.Debug("Generated Email:")
_logger.Debug("To: {0}", oEmailTo)
_logger.Debug("Subject: {0}", oSubject)
_logger.Debug("Body {0}", oFinalBodyText)
Dim osql = $"Select MAX(GUID) FROM TBEMLP_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
Dim oHistoryID = _mssql.GetScalarValue(osql)
'osql = $"select * from TBEMLP_EMAIL_OUT where REFERENCE_ID = {oHistoryID} and EMAIL_ADRESS = '{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
'Dim oDTResult As DataTable = _mssql.GetDatatable(osql)
If IsNumeric(oHistoryID) Then
Dim oInsert = $"INSERT INTO [dbo].[TBEMLP_EMAIL_OUT] (
[REMINDER_TYPE_ID]
,[SENDING_PROFILE]
,[REFERENCE_ID]
,[REFERENCE_STRING]
,[WF_ID]
,[EMAIL_ADRESS]
,[EMAIL_SUBJ]
,[EMAIL_BODY]
,[COMMENT]
,[ADDED_WHO]
,EMAIL_ATTMT1)
VALUES
(77
,{oAccountId}
,{oHistoryID}
,'{MessageId}'
,77
,'{oEmailTo}'
,'{oSubject}'
,'{oFinalBodyText}'
,'{SourceProcedure}'
,'{oCreatedWho}'
,'{oAttachment}')"
_mssql.ExecuteNonQuery(oInsert)
Else
'If oDTResult.Rows.Count = 0 Then
' _logger.Debug("Email has already been sent!!")
'Else
_logger.Warn("Could not get oHistoryID in AddToEmailQueueMSSQL!!")
' End If
End If
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
Public Function GetEmailDataForMessageId(MessageId As String) As EmailData
Dim oSQL = $"SELECT EMAIL_FROM, EMAIL_SUBJECT, EMAIL_ATTMT1 FROM TBEDM_EMAIL_PROFILER_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
Try
Dim oDatatable = _firebird.GetDatatable(oSQL)
Dim oRow As DataRow
If oDatatable.Rows.Count = 0 Then
_logger.Warn("Got no results for MessageId {0}", MessageId)
Return Nothing
ElseIf oDatatable.Rows.Count > 1 Then
_logger.Warn("Got too many results for MessageId {0}. Using last row.", MessageId)
End If
_logger.Debug("Got Email Data for FileId {0}", MessageId)
oRow = oDatatable.Rows.Item(oDatatable.Rows.Count - 1)
Return New EmailData() With {
.From = oRow.Item("EMAIL_FROM"),
.Attachment = oRow.Item("EMAIL_ATTMT1"),
.Subject = oRow.Item("EMAIL_SUBJECT")
}
Catch ex As Exception
_logger.Warn("Could not fetch Email Data for FileId {0}", MessageId)
Return Nothing
End Try
End Function
Public Function GetOriginalEmailPath(OriginalEmailDirectory As String, MessageId As String) As String
Dim oAttachmentDirectory = OriginalEmailDirectory
Dim oAttachmentFile = MessageId & ".eml"
Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile)
If IO.File.Exists(oAttachmentPath) Then
Return oAttachmentPath
Else
Return String.Empty
End If
End Function
Public Function GetEmailPathWithSubjectAsName(RejectedEmailDirectory As String, UncleanedSubject As String) As String
Dim oCleanSubject = String.Join("", UncleanedSubject.Split(Path.GetInvalidPathChars()))
Dim oAttachmentDirectory = RejectedEmailDirectory
Dim oAttachmentFile = oCleanSubject & ".eml"
Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile)
Return oAttachmentPath
End Function
Private Function RandomValue(lowerBound As Integer, upperBound As Integer) As Integer
Dim oRandomValue = CInt(Math.Floor((upperBound - lowerBound + 1) * Rnd())) + lowerBound
Return oRandomValue
End Function
End Class

View File

@@ -0,0 +1,18 @@
Public Class EmailStrings
Public Const EMAIL_WRAPPING_TEXT = "<html><body style=''font-family:""Arial"";font-size:10.0pt''>Sehr geehrte Damen und Herren,<br>
das WISAG-Portal zur Verarbeitung der Eingangsrechnungen im ZUGFeRD-Format konnte die von Ihnen gesandte Rechnung
leider nicht verarbeiten! <br><br> Grund: {0}<p>Bitte prüfen Sie die Datei und nehmen Sie bei Bedarf mit uns Kontakt auf.<p>
Vielen Dank für Ihr Verständnis.<br>Mit freundlichen Grüßen<br>Ihre IT-Abteilung</body></html>"
Public Const EMAIL_SUBJECT = "WISAG ZUGFeRD Portal: Beleg abgelehnt"
Public Const EMAIL_MISSINGPROPERTIES_1 = "<p>Die angehängte Datei entspricht nicht dem WISAG ZUGFeRD-Format: {0}</p>"
Public Const EMAIL_MISSINGPROPERTIES_2 = "<p>Die folgenden Eigenschaften wurden als ERFORDERLICH eingestuft, wurden aber nicht gefunden:<p/>"
Public Const EMAIL_MD5_ERROR = "<p>Die von Ihnen gesendete Rechnung wurde bereits von unserem System verarbeitet.</p>"
Public Const EMAIL_TOO_MUCH_FERDS = "<p>Ihre Email enthielt mehr als ein ZUGFeRD-Dokument.</p>"
Public Const EMAIL_NO_FERDS = "<p>Ihre Email enthielt keine ZUGFeRD-Dokumente.</p>"
Public Const EMAIL_INVALID_DOCUMENT = """
<p>Ihre Email enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.</p>
<p>Mögliche Gründe für ein inkorrektes Format:<ul>
<li>Betrags-Werte weisen ungültiges Format auf (25,01 anstatt 25.01)</li>
</ul></p>
"""
End Class

View File

@@ -26,106 +26,47 @@ Public Class ImportZUGFeRDFiles
Public Const ZUGFERD_ATTACHMENTS = "ZUGFeRD Attachments" Public Const ZUGFERD_ATTACHMENTS = "ZUGFeRD Attachments"
Public HISTORY_ID As Integer Public HISTORY_ID As Integer
Private Const EMAIL_WRAPPING_TEXT = "<html><body style=''font-family:""Arial"";font-size:10.0pt''>Sehr geehrte Damen und Herren,<br>
das WISAG-Portal zur Verarbeitung der Eingangsrechnungen im ZUGFeRD-Format konnte die von Ihnen gesandte Rechnung
leider nicht verarbeiten! <br><br> Grund: {0}<p>Bitte prüfen Sie die Datei und nehmen Sie bei Bedarf mit uns Kontakt auf.<p>
Vielen Dank für Ihr Verständnis.<br>Mit freundlichen Grüßen<br>Ihre IT-Abteilung</body></html>"
Private Const EMAIL_SUBJECT = "WISAG ZUGFeRD Portal: Beleg abgelehnt"
Private Const EMAIL_MISSINGPROPERTIES_1 = "<p>Die angehängte Datei entspricht nicht dem WISAG ZUGFeRD-Format: {0}</p>"
Private Const EMAIL_MISSINGPROPERTIES_2 = "<p>Die folgenden Eigenschaften wurden als ERFORDERLICH eingestuft, wurden aber nicht gefunden:<p/>"
Private Const EMAIL_MD5_ERROR = "<p>Die von Ihnen gesendete Rechnung wurde bereits von unserem System verarbeitet.</p>"
Private Const EMAIL_TOO_MUCH_FERDS = "<p>Ihre Email enthielt mehr als ein ZUGFeRD-Dokument.</p>"
Private Const EMAIL_NO_FERDS = "<p>Ihre Email enthielt keine ZUGFeRD-Dokumente.</p>"
Private Const EMAIL_INVALID_DOCUMENT = """
<p>Ihre Email enthielt ein ZUGFeRD Dokument, welches aber inkorrekt formatiert wurde.</p>
<p>Mögliche Gründe für ein inkorrektes Format:<ul>
<li>Betrags-Werte weisen ungültiges Format auf (25,01 anstatt 25.01)</li>
</ul></p>
"""
' List of allowed extensions for PDF/A Attachments ' List of allowed extensions for PDF/A Attachments
Private AllowedExtensions = New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"} Private ReadOnly AllowedExtensions As List(Of String) = New List(Of String) From {"docx", "doc", "pdf", "xls", "xlsx", "ppt", "pptx", "txt"}
Private _logger As Logger Private ReadOnly _logger As Logger
Private _logConfig As LogConfig Private ReadOnly _logConfig As LogConfig
Private _zugferd As ZUGFeRDInterface Private ReadOnly _zugferd As ZUGFeRDInterface
Private _firebird As Firebird Private ReadOnly _firebird As Firebird
Private _filesystem As Filesystem.File Private ReadOnly _filesystem As Filesystem.File
Private _mssql As MSSQLServer Private ReadOnly _mssql As MSSQLServer
Private ReadOnly _email As EmailFunctions
Public Sub New(LogConfig As LogConfig, Firebird As Firebird, Optional MSSQL As MSSQLServer = Nothing) Public Sub New(LogConfig As LogConfig, Firebird As Firebird, Optional MSSQL As MSSQLServer = Nothing)
_logConfig = LogConfig _logConfig = LogConfig
_logger = LogConfig.GetLogger() _logger = LogConfig.GetLogger()
_firebird = Firebird _firebird = Firebird
_filesystem = New Filesystem.File(_logConfig) _filesystem = New Filesystem.File(_logConfig)
_zugferd = New ZUGFeRDInterface(_logConfig)
_mssql = MSSQL _mssql = MSSQL
_email = New EmailFunctions(LogConfig, _mssql, _firebird)
_logger.Debug("Registering GDPicture License")
If _mssql IsNot Nothing Then
Dim oSQL = "SELECT LICENSE FROM TBDD_3RD_PARTY_MODULES WHERE NAME = 'GDPICTURE'"
Dim oLicenseKey As String = _mssql.GetScalarValue(oSQL)
_zugferd = New ZUGFeRDInterface(_logConfig, oLicenseKey)
Else
_logger.Warn("GDPicture License could not be registered! MSSQL is not enabled!")
Throw New ArgumentNullException("MSSQL")
End If
End Sub End Sub
Private Function RandomValue(lowerBound As Integer, upperBound As Integer) As Integer
Dim oRandomValue = CInt(Math.Floor((upperBound - lowerBound + 1) * Rnd())) + lowerBound
Return oRandomValue
End Function
Private Function GetEmailDataForMessageId(MessageId As String) As EmailData
Dim oSQL = $"SELECT EMAIL_FROM, EMAIL_SUBJECT, EMAIL_ATTMT1 FROM TBEDM_EMAIL_PROFILER_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
Try
Dim oDatatable = _firebird.GetDatatable(oSQL)
Dim oRow As DataRow
If oDatatable.Rows.Count = 0 Then
_logger.Warn("Got no results for MessageId {0}", MessageId)
Return Nothing
ElseIf oDatatable.Rows.Count > 1 Then
_logger.Warn("Got too many results for MessageId {0}. Using last row.", MessageId)
End If
_logger.Debug("Got Email Data for FileId {0}", MessageId)
oRow = oDatatable.Rows.Item(oDatatable.Rows.Count - 1)
Return New EmailData() With {
.From = oRow.Item("EMAIL_FROM"),
.Attachment = oRow.Item("EMAIL_ATTMT1"),
.Subject = oRow.Item("EMAIL_SUBJECT")
}
Catch ex As Exception
_logger.Warn("Could not fetch Email Data for FileId {0}", MessageId)
Return Nothing
End Try
End Function
Private Function GetOriginalEmailPath(OriginalEmailDirectory As String, MessageId As String) As String
Dim oAttachmentDirectory = OriginalEmailDirectory
Dim oAttachmentFile = MessageId & ".eml"
Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile)
If IO.File.Exists(oAttachmentPath) Then
Return oAttachmentPath
Else
Return String.Empty
End If
End Function
Private Function GetEmailPathWithSubjectAsName(RejectedEmailDirectory As String, UncleanedSubject As String) As String
Dim oCleanSubject = String.Join("", UncleanedSubject.Split(Path.GetInvalidPathChars()))
Dim oAttachmentDirectory = RejectedEmailDirectory
Dim oAttachmentFile = oCleanSubject & ".eml"
Dim oAttachmentPath = Path.Combine(oAttachmentDirectory, oAttachmentFile)
Return oAttachmentPath
End Function
Private Function MoveAndRenameEmailToRejected(Args As WorkerArgs, MessageId As String) As EmailData Private Function MoveAndRenameEmailToRejected(Args As WorkerArgs, MessageId As String) As EmailData
Dim oEmailData = GetEmailDataForMessageId(MessageId) Dim oEmailData = _email.GetEmailDataForMessageId(MessageId)
Dim oSource = GetOriginalEmailPath(Args.OriginalEmailDirectory, MessageId) Dim oSource = _email.GetOriginalEmailPath(Args.OriginalEmailDirectory, MessageId)
Dim oDestination As String Dim oDestination As String
' If oEmailData is Nothing, TBEDM_EMAIL_PROFILER_HISTORY for MessageId was not found. ' If oEmailData is Nothing, TBEDM_EMAIL_PROFILER_HISTORY for MessageId was not found.
' This only should happen when testing and db-tables are deleted frequently ' This only should happen when testing and db-tables are deleted frequently
If oEmailData Is Nothing Then If oEmailData Is Nothing Then
oDestination = GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, MessageId) oDestination = _email.GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, MessageId)
Else Else
oDestination = GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, oEmailData.Subject) oDestination = _email.GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, oEmailData.Subject)
End If End If
_logger.Debug("Destination for eml file is {0}", oDestination) _logger.Debug("Destination for eml file is {0}", oDestination)
@@ -154,135 +95,9 @@ Public Class ImportZUGFeRDFiles
Private Sub AddRejectedState(oMessageID As String, oTitle As String, oTitle1 As String, oComment As String) Private Sub AddRejectedState(oMessageID As String, oTitle As String, oTitle1 As String, oComment As String)
Try Try
'PRCUST_ADD_HISTORY_STATE: @MessageID VARCHAR(250), @TITLE1 VARCHAR(250), @TITLE2 VARCHAR(250)
Dim oSQL = $"EXEC PRCUST_ADD_HISTORY_STATE '{oMessageID}','{oTitle}','{oTitle1}','{oComment}'" Dim oSQL = $"EXEC PRCUST_ADD_HISTORY_STATE '{oMessageID}','{oTitle}','{oTitle1}','{oComment}'"
_mssql.NewExecutenonQuery(oSQL) _mssql.NewExecutenonQuery(oSQL)
'@MessageID VARCHAR(250), @TITLE1 VARCHAR(250), @TITLE2 VARCHAR(250)
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
Private Sub AddToEmailQueueFB(MessageId As String, BodyText As String, EmailData As EmailData)
If EmailData Is Nothing Then
_logger.Warn("EmailData is empty. Email will not be sent!")
Exit Sub
End If
Try
Dim oJobId = RandomValue(1, 10000)
Dim oReference = MessageId
Dim oEmailTo = ""
Dim oSubject = EMAIL_SUBJECT
Dim oAccountId = 1
Dim oCreatedWho = "ZUGFeRD Service"
Dim oFinalBodyText = String.Format(EMAIL_WRAPPING_TEXT, BodyText)
Dim oEmailAddress = EmailData.From
Dim oAttachment = EmailData.Attachment
If IsNothing(oEmailAddress) OrElse String.IsNullOrWhiteSpace(oEmailAddress) Then
_logger.Warn("Could not find email-address for MessageId {0}", MessageId)
oEmailTo = String.Empty
Else
oEmailTo = oEmailAddress
End If
_logger.Debug("Generated Email:")
_logger.Debug("To: {0}", oEmailTo)
_logger.Debug("Subject: {0}", oSubject)
_logger.Debug("Body {0}", oFinalBodyText)
Dim osql = $"select * from TBEDM_EMAIL_QUEUE where REFERENCE1 = '{oReference} and EMAIL_TO = ''{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
Dim oDTResult As DataTable = _firebird.GetDatatable(osql)
If oDTResult.Rows.Count = 0 Then
Dim oSQLInsert = $"INSERT INTO TBEDM_EMAIL_QUEUE "
oSQLInsert &= "(JOB_ID, REFERENCE1, EMAIL_ACCOUNT_ID, EMAIL_TO, EMAIL_SUBJ, EMAIL_BODY, CREATEDWHO, EMAIL_ATTMT1) VALUES "
oSQLInsert &= $"({oJobId}, '{oReference}', {oAccountId}, '{oEmailTo}', '{oSubject}', '{oFinalBodyText.Replace("'", "''")}', '{oCreatedWho}', '{oAttachment}')"
_firebird.ExecuteNonQuery(oSQLInsert)
_logger.Debug("Email Queue updated for MessageId {0}.", MessageId, oEmailTo)
Else
_logger.Debug("Email has already been sent!!")
End If
Catch ex As Exception
_logger.Error(ex)
End Try
End Sub
Private Sub AddToEmailQueueMSSQL(MessageId As String, BodyText As String, pEmailData As EmailData, SourceProcedure As String)
If pEmailData Is Nothing Then
_logger.Warn("EmailData is empty. Email will not be sent!")
Exit Sub
End If
Try
Dim oJobId = RandomValue(1, 10000)
Dim oReference = MessageId
Dim oEmailTo = ""
Dim oSubject = EMAIL_SUBJECT
Dim oAccountId = 1
Dim oCreatedWho = "ZUGFeRD Service"
Dim oFinalBodyText = String.Format(EMAIL_WRAPPING_TEXT, BodyText)
Dim oEmailAddress = pEmailData.From
Dim oAttachment = pEmailData.Attachment
If oAttachment <> String.Empty Then
_logger.Debug($"Attachment_String [{oAttachment}]!")
If IO.File.Exists(oAttachment) = False Then
_logger.Info($"Attachment.File [{oAttachment}] is not existing!!!")
End If
End If
If IsNothing(oEmailAddress) OrElse String.IsNullOrWhiteSpace(oEmailAddress) Then
_logger.Warn("Could not find email-address for MessageId {0}", MessageId)
oEmailTo = String.Empty
Else
oEmailTo = oEmailAddress
End If
_logger.Debug("Generated Email:")
_logger.Debug("To: {0}", oEmailTo)
_logger.Debug("Subject: {0}", oSubject)
_logger.Debug("Body {0}", oFinalBodyText)
Dim osql = $"Select MAX(GUID) FROM TBEMLP_HISTORY WHERE EMAIL_MSGID = '{MessageId}'"
Dim oHistoryID = _mssql.GetScalarValue(osql)
'osql = $"select * from TBEMLP_EMAIL_OUT where REFERENCE_ID = {oHistoryID} and EMAIL_ADRESS = '{oEmailTo}' and EMAIL_SUBJ = '{oSubject}'"
'Dim oDTResult As DataTable = _mssql.GetDatatable(osql)
If IsNumeric(oHistoryID) Then
Dim oInsert = $"INSERT INTO [dbo].[TBEMLP_EMAIL_OUT] (
[REMINDER_TYPE_ID]
,[SENDING_PROFILE]
,[REFERENCE_ID]
,[REFERENCE_STRING]
,[WF_ID]
,[EMAIL_ADRESS]
,[EMAIL_SUBJ]
,[EMAIL_BODY]
,[COMMENT]
,[ADDED_WHO]
,EMAIL_ATTMT1)
VALUES
(77
,{oAccountId}
,{oHistoryID}
,'{MessageId}'
,77
,'{oEmailTo}'
,'{oSubject}'
,'{oFinalBodyText}'
,'{SourceProcedure}'
,'{oCreatedWho}'
,'{oAttachment}')"
_mssql.ExecuteNonQuery(oInsert)
Else
'If oDTResult.Rows.Count = 0 Then
' _logger.Debug("Email has already been sent!!")
'Else
_logger.Warn("Could not get oHistoryID in AddToEmailQueueMSSQL!!")
' End If
End If
Catch ex As Exception Catch ex As Exception
_logger.Error(ex) _logger.Error(ex)
End Try End Try
@@ -295,23 +110,6 @@ Public Class ImportZUGFeRDFiles
_logger.Debug("Starting Job {0}", [GetType].Name) _logger.Debug("Starting Job {0}", [GetType].Name)
_logger.Debug("Registering GDPicture License")
If _mssql IsNot Nothing Then
Try
Dim oSQL = "SELECT LICENSE FROM TBDD_3RD_PARTY_MODULES WHERE NAME = 'GDPICTURE'"
Dim oLicenseKey As String = _mssql.GetScalarValue(oSQL)
Dim oLicenseManager As New LicenseManager
oLicenseManager.RegisterKEY(oLicenseKey)
Catch ex As Exception
_logger.Error(ex)
_logger.Warn("GDPicture License could not be retrieved! Query failed! Exiting job.")
Exit Sub
End Try
Else
_logger.Warn("GDPicture License could not be retrieved! MSSQL is not enabled! Exiting job.")
Exit Sub
End If
Try Try
For Each oPath As String In oArgs.WatchDirectories For Each oPath As String In oArgs.WatchDirectories
Dim oDirInfo As New DirectoryInfo(oPath) Dim oDirInfo As New DirectoryInfo(oPath)
@@ -398,7 +196,8 @@ Public Class ImportZUGFeRDFiles
End Select End Select
End Try End Try
' Extract all attachments other than the zugferd-invoice.xml ' Extract all attachments with the extensions specified in `AllowedExtensions`.
' If you need to extract and use embedded xml files, you need to filter out the zugferd-invoice.xml yourself.
Dim oAttachments = oAttachmentExtractor.Extract(oFile.FullName, AllowedExtensions) Dim oAttachments = oAttachmentExtractor.Extract(oFile.FullName, AllowedExtensions)
If oAttachments Is Nothing Then If oAttachments Is Nothing Then
_logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName) _logger.Warn("Attachments for file [{0}] could not be extracted", oFile.FullName)
@@ -440,7 +239,7 @@ Public Class ImportZUGFeRDFiles
' Since extraction went well, increase the amount of ZUGFeRD files ' Since extraction went well, increase the amount of ZUGFeRD files
oZUGFeRDCount += 1 oZUGFeRDCount += 1
#Region "Check Property Values"
' --- BEGIN Check Property Values ' --- BEGIN Check Property Values
'' PropertyMap items with `IsGrouped = False` are handled normally '' PropertyMap items with `IsGrouped = False` are handled normally
@@ -607,7 +406,7 @@ Public Class ImportZUGFeRDFiles
'Next 'Next
'--- END Check Property Values '--- END Check Property Values
#End Region
' Check the document against the configured property map and return: ' Check the document against the configured property map and return:
' - a List of valid properties ' - a List of valid properties
' - a List of missing properties ' - a List of missing properties
@@ -666,9 +465,9 @@ Public Class ImportZUGFeRDFiles
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - Already processed (MD5Hash)' WHERE GUID = '{HISTORY_ID}'" Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - Already processed (MD5Hash)' WHERE GUID = '{HISTORY_ID}'"
_firebird.ExecuteNonQuery(oSQL) _firebird.ExecuteNonQuery(oSQL)
Dim oBody = EMAIL_MD5_ERROR Dim oBody = EmailStrings.EMAIL_MD5_ERROR
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException") _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MD5HashException")
AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "") AddRejectedState(oMessageId, "MD5HashException", "Die gesendete Rechnung wurde bereits verarbeitet!", "")
Catch ex As InvalidFerdException Catch ex As InvalidFerdException
_logger.Error(ex) _logger.Error(ex)
@@ -676,9 +475,9 @@ Public Class ImportZUGFeRDFiles
oMoveDirectory = oArgs.ErrorDirectory oMoveDirectory = oArgs.ErrorDirectory
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - ZUGFeRD yes but incorrect format' WHERE GUID = '{HISTORY_ID}'" Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - ZUGFeRD yes but incorrect format' WHERE GUID = '{HISTORY_ID}'"
_firebird.ExecuteNonQuery(oSQL) _firebird.ExecuteNonQuery(oSQL)
Dim oBody = EMAIL_INVALID_DOCUMENT Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException") _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException")
AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "") AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "")
Catch ex As TooMuchFerdsException Catch ex As TooMuchFerdsException
_logger.Error(ex) _logger.Error(ex)
@@ -686,9 +485,9 @@ Public Class ImportZUGFeRDFiles
oMoveDirectory = oArgs.ErrorDirectory oMoveDirectory = oArgs.ErrorDirectory
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - More than one ZUGFeRD-document in email' WHERE GUID = '{HISTORY_ID}'" Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - More than one ZUGFeRD-document in email' WHERE GUID = '{HISTORY_ID}'"
_firebird.ExecuteNonQuery(oSQL) _firebird.ExecuteNonQuery(oSQL)
Dim oBody = EMAIL_TOO_MUCH_FERDS Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException") _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "TooMuchFerdsException")
AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "") AddRejectedState(oMessageId, "TooMuchFerdsException", "Email enthielt mehr als ein ZUGFeRD-Dokument", "")
Catch ex As NoFerdsException Catch ex As NoFerdsException
_logger.Error(ex) _logger.Error(ex)
@@ -696,9 +495,9 @@ Public Class ImportZUGFeRDFiles
oMoveDirectory = oArgs.ErrorDirectory oMoveDirectory = oArgs.ErrorDirectory
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - no ZUGFeRD-Document in email' WHERE GUID = '{HISTORY_ID}'" Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - no ZUGFeRD-Document in email' WHERE GUID = '{HISTORY_ID}'"
_firebird.ExecuteNonQuery(oSQL) _firebird.ExecuteNonQuery(oSQL)
Dim oBody = EMAIL_NO_FERDS Dim oBody = EmailStrings.EMAIL_NO_FERDS
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException") _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException")
AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "") AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "")
Catch ex As MissingValueException Catch ex As MissingValueException
_logger.Error(ex) _logger.Error(ex)
@@ -713,7 +512,7 @@ Public Class ImportZUGFeRDFiles
Dim oBody = CreateBodyForMissingProperties(ex.File.Name, oMissingProperties) Dim oBody = CreateBodyForMissingProperties(ex.File.Name, oMissingProperties)
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId) Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException") _email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException")
AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage) AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage)
Catch ex As Exception Catch ex As Exception
@@ -770,8 +569,11 @@ Public Class ImportZUGFeRDFiles
End Try End Try
End If End If
' Filter out Attachments from `Files`
Dim oInvoiceFiles As List(Of FileInfo) = Files.Except(AttachmentFiles).ToList()
' Move PDF/A Files ' Move PDF/A Files
For Each oFile In Files For Each oFile In oInvoiceFiles
Try Try
Dim oFileName = _filesystem.GetVersionedFilename(Path.Combine(oFinalMoveDirectory, oFile.Name)) Dim oFileName = _filesystem.GetVersionedFilename(Path.Combine(oFinalMoveDirectory, oFile.Name))
@@ -818,11 +620,11 @@ Public Class ImportZUGFeRDFiles
Private Function CreateBodyForMissingProperties(OriginalFilename As String, MissingProperties As List(Of String)) Private Function CreateBodyForMissingProperties(OriginalFilename As String, MissingProperties As List(Of String))
Dim oBody = String.Format(EMAIL_MISSINGPROPERTIES_1, OriginalFilename) Dim oBody = String.Format(EmailStrings.EMAIL_MISSINGPROPERTIES_1, OriginalFilename)
If MissingProperties.Count > 0 Then If MissingProperties.Count > 0 Then
oBody &= $"{vbNewLine}{vbNewLine}" oBody &= $"{vbNewLine}{vbNewLine}"
oBody &= EMAIL_MISSINGPROPERTIES_2 oBody &= EmailStrings.EMAIL_MISSINGPROPERTIES_2
oBody &= $"{vbNewLine}{vbNewLine}" oBody &= $"{vbNewLine}{vbNewLine}"
For Each prop In MissingProperties For Each prop In MissingProperties

View File

@@ -87,6 +87,8 @@
<Compile Include="EDMI\GraphQL\GraphQLArgs.vb" /> <Compile Include="EDMI\GraphQL\GraphQLArgs.vb" />
<Compile Include="EDMI\GraphQL\GraphQLJob.vb" /> <Compile Include="EDMI\GraphQL\GraphQLJob.vb" />
<Compile Include="EDMI\ZUGFeRD\EmailData.vb" /> <Compile Include="EDMI\ZUGFeRD\EmailData.vb" />
<Compile Include="EDMI\ZUGFeRD\EmailFunctions.vb" />
<Compile Include="EDMI\ZUGFeRD\EmailStrings.vb" />
<Compile Include="EDMI\ZUGFeRD\ImportZUGFeRDFiles.vb" /> <Compile Include="EDMI\ZUGFeRD\ImportZUGFeRDFiles.vb" />
<Compile Include="EDMI\ZUGFeRD\WorkerArgs.vb" /> <Compile Include="EDMI\ZUGFeRD\WorkerArgs.vb" />
<Compile Include="Exceptions.vb" /> <Compile Include="Exceptions.vb" />

View File

@@ -30,5 +30,5 @@ Imports System.Runtime.InteropServices
' Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern ' Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
' übernehmen, indem Sie "*" eingeben: ' übernehmen, indem Sie "*" eingeben:
<Assembly: AssemblyVersion("1.1.0.0")> <Assembly: AssemblyVersion("1.1.0.2")>
<Assembly: AssemblyFileVersion("1.0.0.0")> <Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -1,4 +1,5 @@
Imports System.IO Imports System.IO
Imports System.Reflection
Imports NLog Imports NLog
Imports NLog.Config Imports NLog.Config
Imports NLog.Targets Imports NLog.Targets
@@ -14,33 +15,6 @@ Imports NLog.Targets
''' <dependencies> ''' <dependencies>
''' NLog, >= 4.5.8 ''' NLog, >= 4.5.8
''' </dependencies> ''' </dependencies>
''' <params>
''' logPath, PathType
''' The basepath to write logs to. Can be AppData, CurrentDirectory or CustomPath.
'''
''' - AppData: writes to local application data directory
''' - CurrentDirectory: writes to `Log` directory relative to the current directory
''' - CustomPath: writes to custom path specified in `customLogPath`
'''
''' customLogPath, String (optional)
''' If `logPath` is set to custom, this defines the custom logPath.
'''
''' suffix, String (optional)
''' If set to anything other than Nothing, extends the logfile name with this suffix.
''' </params>
''' <props>
''' LogFile, String (readonly)
''' Returns the full path of the default log file.
'''
''' LogPath, String (readonly)
''' Returns the path to the log directory.
'''
''' LogFactory, NLog.LogFactory (readonly)
''' Returns the LogFactory that is used to create the Logger object
'''
''' Debug, Boolean
''' Determines if the debug log should be written.
''' </props>
''' <example> ''' <example>
''' Imports DigitalData.Modules.Logging ''' Imports DigitalData.Modules.Logging
''' '''
@@ -81,6 +55,7 @@ Imports NLog.Targets
''' - NLOG_INTERNAL_LOG_FILE: ex. C:\Temp\Nlog_Internal.log ''' - NLOG_INTERNAL_LOG_FILE: ex. C:\Temp\Nlog_Internal.log
''' </remarks> ''' </remarks>
Public Class LogConfig Public Class LogConfig
#Region "Private Properties"
Private Const KEEP_FILES_OPEN As Boolean = False Private Const KEEP_FILES_OPEN As Boolean = False
' MAX_ARCHIVES_FILES works like this (in version 4.5.8): ' MAX_ARCHIVES_FILES works like this (in version 4.5.8):
' 0 = keep ALL archives files ' 0 = keep ALL archives files
@@ -113,15 +88,16 @@ Public Class LogConfig
Private Const LOG_FORMAT_DEBUG As String = LOG_FORMAT_BASE_LONG_DATE & " >> ${message}" Private Const LOG_FORMAT_DEBUG As String = LOG_FORMAT_BASE_LONG_DATE & " >> ${message}"
Private Const LOG_FORMAT_MEMORY As String = LOG_FORMAT_BASE_LONG_DATE & " >> ${message}${newline}${exception:format=Message}${newline}${exception:format=StackTrace}" Private Const LOG_FORMAT_MEMORY As String = LOG_FORMAT_BASE_LONG_DATE & " >> ${message}${newline}${exception:format=Message}${newline}${exception:format=StackTrace}"
Private Const FOLDER_NAME_LOG = "Log"
Private Const FILE_NAME_ACCESS_TEST = "accessTest.txt" Private Const FILE_NAME_ACCESS_TEST = "accessTest.txt"
Private Const FOLDER_NAME_LOG = "Log"
Private ReadOnly failSafePath As String = Path.GetTempPath() Private ReadOnly failSafePath As String = Path.GetTempPath()
Private ReadOnly basePath As String = failSafePath Private ReadOnly basePath As String = failSafePath
Private config As LoggingConfiguration Private config As LoggingConfiguration
Private isDebug As Boolean = False Private isDebug As Boolean = False
#End Region
#Region "Public Properties"
Public Enum PathType As Integer Public Enum PathType As Integer
AppData = 0 AppData = 0
CurrentDirectory = 1 CurrentDirectory = 1
@@ -173,24 +149,41 @@ Public Class LogConfig
End Get End Get
End Property End Property
Public ReadOnly Property NLogConfig As LoggingConfiguration
Get
Return config
End Get
End Property
#End Region
''' <summary> ''' <summary>
''' Initializes a new LogConfig object with a logpath and optinally a filename-suffix. ''' Initializes a new LogConfig object with a logpath and optinally a filename-suffix.
''' </summary> ''' </summary>
''' <param name="logPath">The basepath to write logs to. Can be AppData, CurrentDirectory or CustomPath.</param> ''' <param name="LogPath">The basepath to write logs to. Can be AppData, CurrentDirectory or CustomPath.</param>
''' <param name="customLogPath">If `logPath` is set to custom, this defines the custom logPath.</param> ''' <param name="CustomLogPath">If `logPath` is set to custom, this defines the custom logPath.</param>
''' <param name="suffix">If set to anything other than Nothing, extends the logfile name with this suffix.</param> ''' <param name="Suffix">If set to anything other than Nothing, extends the logfile name with this suffix.</param>
Public Sub New(logPath As PathType, Optional customLogPath As String = Nothing, Optional suffix As String = Nothing) ''' <param name="CompanyName">CompanyName is used to construct log-path in when LogPath is set to PathType:AppData</param>
Dim productName As String = My.Application.Info.ProductName ''' <param name="ProductName">ProductName is used to construct log-path in when LogPath is set to PathType:AppData</param>
Dim companyName As String = My.Application.Info.CompanyName Public Sub New(LogPath As PathType,
Optional CustomLogPath As String = Nothing,
Optional Suffix As String = Nothing,
Optional CompanyName As String = Nothing,
Optional ProductName As String = Nothing)
If logPath = PathType.AppData Then If LogPath = PathType.AppData And (ProductName Is Nothing Or CompanyName Is Nothing) Then
Throw New ArgumentException("Modules.Logging: PathType is AppData and either CompanyName or ProductName was not supplied!")
End If
If LogPath = PathType.CurrentDirectory Then
Throw New ArgumentException("Modules.Logging: LogPath.CurrentDirectory is deprecated. Please use LogPath.CustomPath!")
End If
If LogPath = PathType.AppData Then
Dim appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) Dim appDataDir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
basePath = Path.Combine(appDataDir, companyName, productName, FOLDER_NAME_LOG) basePath = Path.Combine(appDataDir, CompanyName, ProductName, FOLDER_NAME_LOG)
ElseIf logPath = PathType.CurrentDirectory Then
Dim currentDirectory As String = My.Application.Info.DirectoryPath
basePath = Path.Combine(currentDirectory, FOLDER_NAME_LOG)
Else 'Custom Path Else 'Custom Path
basePath = customLogPath basePath = CustomLogPath
End If End If
' If directory does not exist, try to create it! ' If directory does not exist, try to create it!
@@ -219,12 +212,12 @@ Public Class LogConfig
' Set the suffix to the given string if it exists ' Set the suffix to the given string if it exists
Dim logFileSuffix As String = String.Empty Dim logFileSuffix As String = String.Empty
If suffix IsNot Nothing AndAlso suffix.Count > 0 Then If Suffix IsNot Nothing AndAlso Suffix.Count > 0 Then
logFileSuffix = $"-{suffix}" logFileSuffix = $"-{Suffix}"
End If End If
' Create config object and initalize it ' Create config object and initalize it
config = GetConfig(productName, logFileSuffix) config = GetConfig(ProductName, logFileSuffix)
' Save config ' Save config
LogFactory = New LogFactory With { LogFactory = New LogFactory With {
@@ -236,10 +229,24 @@ Public Class LogConfig
LogFile = GetCurrentLogFilePath() LogFile = GetCurrentLogFilePath()
End Sub End Sub
Private Sub CheckMyApplication()
Dim oAssembly = Assembly.GetEntryAssembly()
Dim oMyApp = Nothing
For Each oType As Type In oAssembly.DefinedTypes
If oType.Name = "MyApplication" Then
oMyApp = oType
Exit For
End If
Next
oMyApp.GetType().GetProperty("")
End Sub
''' <summary> ''' <summary>
''' Returns the Logger for the calling class ''' Returns the Logger for the calling class
''' </summary> ''' </summary>
''' <returns>An object of Logging.Logger</returns> ''' <returns>An object of Logging.Logger</returns>
<DebuggerStepThrough()>
Public Function GetLogger() As Logger Public Function GetLogger() As Logger
Dim oClassName As String = GetClassFullName() Dim oClassName As String = GetClassFullName()
Return LogFactory.GetLogger(Of Logger)(oClassName) Return LogFactory.GetLogger(Of Logger)(oClassName)
@@ -250,6 +257,7 @@ Public Class LogConfig
''' </summary> ''' </summary>
''' <param name="ClassName">The name of the class the logger belongs to</param> ''' <param name="ClassName">The name of the class the logger belongs to</param>
''' <returns>An object of Logging.Logger</returns> ''' <returns>An object of Logging.Logger</returns>
<DebuggerStepThrough()>
Public Function GetLogger(ClassName As String) As Logger Public Function GetLogger(ClassName As String) As Logger
Return LogFactory.GetLogger(Of Logger)(ClassName) Return LogFactory.GetLogger(Of Logger)(ClassName)
End Function End Function
@@ -268,6 +276,7 @@ Public Class LogConfig
''' </summary> ''' </summary>
''' <returns>The fully qualified class name</returns> ''' <returns>The fully qualified class name</returns>
''' <remarks>This method is very resource-intensive!</remarks> ''' <remarks>This method is very resource-intensive!</remarks>
<DebuggerStepThrough()>
Public Shared Function GetClassFullName() As String Public Shared Function GetClassFullName() As String
Dim oFramesToSkip As Integer = 2 Dim oFramesToSkip As Integer = 2
Dim oClassName As String = String.Empty Dim oClassName As String = String.Empty
@@ -437,7 +446,5 @@ Public Class LogConfig
Return memoryLog Return memoryLog
End Function End Function
#End Region #End Region
End Class End Class

View File

@@ -2,11 +2,13 @@
Public Class Logger Public Class Logger
Inherits NLog.Logger Inherits NLog.Logger
Implements ILogger
''' <summary> ''' <summary>
''' Prints a preformatted Block including a block identifier ''' Prints a preformatted Block including a block identifier
''' </summary> ''' </summary>
''' <param name="blockId">A unique Identifier for this block, eg. DocId, FullPath, ..</param> ''' <param name="blockId">A unique Identifier for this block, eg. DocId, FullPath, ..</param>
<DebuggerStepThrough()>
Public Sub NewBlock(blockId As String) Public Sub NewBlock(blockId As String)
Dim message As String = $"-----> Start of Block {blockId}" Dim message As String = $"-----> Start of Block {blockId}"
Dim logEventInfo As New LogEventInfo(LogLevel.Info, Name, message) Dim logEventInfo As New LogEventInfo(LogLevel.Info, Name, message)
@@ -15,6 +17,7 @@ Public Class Logger
Log(WrapperType, logEventInfo) Log(WrapperType, logEventInfo)
End Sub End Sub
<DebuggerStepThrough()>
Public Sub EndBlock() Public Sub EndBlock()
Dim message As String = $"<----- End of Block" Dim message As String = $"<----- End of Block"
Dim logEventInfo As New LogEventInfo(LogLevel.Info, Name, message) Dim logEventInfo As New LogEventInfo(LogLevel.Info, Name, message)

View File

@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
' übernehmen, indem Sie "*" eingeben: ' übernehmen, indem Sie "*" eingeben:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("0.0.1.1")> <Assembly: AssemblyVersion("2.0.0.0")>
<Assembly: AssemblyFileVersion("1.0.0.0")> <Assembly: AssemblyFileVersion("1.0.0.0")>

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ZUGFeRDRESTService
{
public class Config
{
public string Name { get; set; }
public string LogPath { get; set; }
public string MSSQLConnectionString { get; set; }
}
}

View File

@@ -0,0 +1,126 @@
using System;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using DigitalData.Modules.Interfaces;
using DigitalData.Modules.Logging;
namespace ZUGFeRDRESTService.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ValidationController : ControllerBase
{
public static string RESPONSE_OK = "OK";
public static string RESPONSE_ERROR = "ERROR";
private readonly ZUGFeRDInterface _zugferd;
private readonly IDatabase _database;
private readonly DigitalData.Modules.Logging.LogConfig _logConfig;
private readonly DigitalData.Modules.Logging.Logger _logger;
private readonly PropertyValues _props;
private readonly Dictionary<String, XmlItemProperty> _propertyMap;
public class ValidationResponse
{
public string status;
public string message;
public List<string> errors;
public ValidationResponse()
{
status = RESPONSE_OK;
message = String.Empty;
errors = new List<string>();
}
}
public ValidationController(ILogging logging, IDatabase database)
{
_logConfig = logging.LogConfig;
_logger = _logConfig.GetLogger();
_logger.Debug("Validation Controller initializing");
_database = database;
var oGDPictureKey = database.GetGDPictureKey();
var oPropertyMap = database.GetPropertyMap();
_propertyMap = oPropertyMap;
_zugferd = new ZUGFeRDInterface(_logConfig, oGDPictureKey);
_props = new PropertyValues(_logConfig);
_logger.Debug("Validation Controller initialized!");
}
/// <summary>
/// POST: api/Validation
/// </summary>
/// <param name="files">This parameter's name needs to correspond to the html form's file-input name</param>
[HttpPost]
public async Task<ValidationResponse> Post(IFormFile file, string user_id)
{
string oFilePath;
string oFileName;
oFilePath = Path.Combine(Path.GetTempPath(), file.FileName);
oFileName = file.FileName;
using FileStream oStream = new FileStream(oFilePath, FileMode.Create);
await file.CopyToAsync(oStream);
CrossIndustryDocumentType oDocument;
try
{
oDocument = _zugferd.ExtractZUGFeRDFileWithGDPicture(oFilePath);
}
catch (Exception ex)
{
_logger.Error(ex);
return new ValidationResponse()
{
status = RESPONSE_ERROR,
message = "The uploaded file is not a valid ZUGFeRD Invoice!"
};
}
try
{
PropertyValues.CheckPropertyValuesResult oResult = _props.CheckPropertyValues(oDocument, _propertyMap, "MESSAGEID");
if (oResult.MissingProperties.Count > 0)
{
return new ValidationResponse()
{
status = RESPONSE_ERROR,
message = "The uploaded file is a valid ZUGFeRD Invoice but missing some properties!",
errors = oResult.MissingProperties
};
}
}
catch (Exception ex)
{
_logger.Error(ex);
return new ValidationResponse()
{
status = RESPONSE_ERROR,
message = "The uploaded file is not a valid ZUGFeRD Invoice!"
};
}
return new ValidationResponse()
{
status = RESPONSE_OK,
message = "The uploaded files is a valid ZUGFeRD Invoice!"
};
}
}
}

View File

@@ -1,81 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ZUGFeRDRESTService.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ZugferdValidationController : ControllerBase
{
public static string RESPONSE_OK = "OK";
public static string RESPONSE_ERROR = "ERROR";
private readonly IZugferdValidationDataService _dataService;
public class ZugferdValidationResponse
{
public string status;
public string message;
public List<string> errors;
public ZugferdValidationResponse()
{
status = RESPONSE_OK;
message = String.Empty;
errors = new List<string>();
}
}
public ZugferdValidationController(IZugferdValidationDataService dataService)
{
_dataService = dataService;
}
/// <summary>
/// POST: api/ZugferdValidation
/// </summary>
/// <param name="files">This parameter's name needs to correspond to the html form's file-input name</param>
[HttpPost]
public async Task<ZugferdValidationResponse> Post(List<IFormFile> files)
{
var oFilePaths = new List<String>();
var oFileNames = new List<String>();
if (files.Count == 0) {
return new ZugferdValidationResponse()
{
status = RESPONSE_ERROR,
message = "No File received!"
};
}
foreach (var formFile in files)
{
var oFilePath = Path.GetTempFileName();
oFilePaths.Add(oFilePath);
oFileNames.Add(formFile.FileName);
using (var oStream = new FileStream(oFilePath, FileMode.Create))
{
await formFile.CopyToAsync(oStream);
}
}
var oResponse = new ZugferdValidationResponse
{
message = "You uploaded the following file: " + oFileNames.First()
};
return oResponse;
}
}
}

View File

@@ -0,0 +1,64 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using DigitalData.Modules.Database;
using DigitalData.Modules.Interfaces;
using Microsoft.Extensions.Configuration;
namespace ZUGFeRDRESTService
{
public class Database: IDatabase
{
private string _gdPictureKey = null;
private Dictionary<String, XmlItemProperty> _propertyMap = null;
private const string QUERY_GET_GDPICTURE_KEY = "SELECT LICENSE FROM TBDD_3RD_PARTY_MODULES WHERE NAME = 'GDPICTURE'";
private const string QUERY_GET_PROPERTY_MAP = "SELECT * FROM TBEDM_XML_ITEMS WHERE SPECIFICATION = '{0}' AND ACTIVE = True ORDER BY XML_PATH";
public MSSQLServer MSSQL { get; set; }
public Firebird Firebird { get; set; }
public Database(ILogging Logging, IConfiguration Config)
{
var LogConfig = Logging.LogConfig;
var AppConfig = Config.GetSection("Config");
var FBConfig = AppConfig.GetSection("Firebird");
MSSQL = new MSSQLServer(LogConfig, AppConfig["MSSQLConnectionString"]);
Firebird = new Firebird(LogConfig, FBConfig["Datasource"], FBConfig["Database"], FBConfig["Username"], FBConfig["Password"]);
}
public string GetGDPictureKey()
{
if (_gdPictureKey == null)
_gdPictureKey = MSSQL.GetScalarValue(QUERY_GET_GDPICTURE_KEY).ToString();
return _gdPictureKey;
}
public Dictionary<String, XmlItemProperty> GetPropertyMap()
{
if (_propertyMap == null)
{
_propertyMap = new Dictionary<string, XmlItemProperty>();
var oDatatable = Firebird.GetDatatable(string.Format(QUERY_GET_PROPERTY_MAP, "DEFAULT"));
foreach (DataRow oRow in oDatatable.Rows)
{
_propertyMap.Add(oRow["XML_PATH"].ToString(), new XmlItemProperty()
{
Description = oRow["DESCRIPTION"].ToString(),
TableName = oRow["TABLE_NAME"].ToString(),
GroupScope = oRow["GROUP_SCOPE"].ToString(),
IsRequired = (bool)oRow["IS_REQUIRED"],
IsGrouped = (bool)oRow["IS_GROUPED"]
});
}
}
return _propertyMap;
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using DigitalData.Modules.Database;
using DigitalData.Modules.Interfaces;
namespace ZUGFeRDRESTService
{
public interface IDatabase
{
public MSSQLServer MSSQL { get; set; }
public Firebird Firebird { get; set; }
public string GetGDPictureKey();
public Dictionary<String, XmlItemProperty> GetPropertyMap();
}
}

View File

@@ -0,0 +1,9 @@
using DigitalData.Modules.Logging;
namespace ZUGFeRDRESTService
{
public interface ILogging
{
public LogConfig LogConfig { get; set; }
}
}

View File

@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ZUGFeRDRESTService
{
public interface IZugferdValidationDataService
{
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ZUGFeRDRESTService
{
public sealed class Logger
{
private static readonly Lazy<Logger> lazy = new Lazy<Logger>(() => new Logger());
public static Logger Instance { get { return lazy.Value; } }
private Logger()
{
}
}
}

View File

@@ -0,0 +1,15 @@
using DigitalData.Modules.Logging;
namespace ZUGFeRDRESTService
{
internal class Logging : ILogging
{
public LogConfig LogConfig { get; set; }
public Logging(string LogPath, bool Debug)
{
LogConfig = new LogConfig(LogConfig.PathType.CustomPath, LogPath, null, "Digital Data", "ZUGFeRD-REST-API");
LogConfig.Debug = Debug;
}
}
}

View File

@@ -3,14 +3,39 @@
ViewData["Title"] = "UploadTest"; ViewData["Title"] = "UploadTest";
} }
<h1>UploadTest</h1> <h1>ZUGFeRD Validation</h1>
<form method="post" action="/api/zugferdvalidation" enctype="multipart/form-data" > <form method="post" action="/api/validation" enctype="multipart/form-data" >
<p> <p>
<span>PDF Datei:</span> <label>PDF Datei:</label>
<input type="file" name="files" /> <input type="file" name="file" required />
</p>
<p>
<label>Benutzerkennung/Email:</label>
<input type="email" name="user_id" required />
</p> </p>
<button type="submit">Submit</button> <button type="submit">Submit</button>
</form> </form>
<style>
form {}
form p {
border-bottom: 1px solid grey;
padding-bottom: 1rem;
}
form label {
display: block;
width: 20rem;
margin-bottom: 1rem;
}
form input {
display: block;
width: 20rem;
}
</style>

View File

@@ -6,6 +6,9 @@ using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using NLog.Web;
using DigitalData.Modules.Logging;
using System.Reflection;
namespace ZUGFeRDRESTService namespace ZUGFeRDRESTService
{ {

View File

@@ -12,7 +12,7 @@
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "api/zugferdvalidation", "launchUrl": "",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }

View File

@@ -18,16 +18,29 @@ namespace ZUGFeRDRESTService
public Startup(IConfiguration configuration) public Startup(IConfiguration configuration)
{ {
Configuration = configuration; Configuration = configuration;
AppConfig = configuration.GetSection("Config");
} }
public IConfiguration Configuration { get; } public IConfiguration Configuration { get; }
private IConfigurationSection AppConfig { get; }
// This method gets called by the runtime. Use this method to add services to the container. // This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) public void ConfigureServices(IServiceCollection services)
{ {
string oLogPath = AppConfig["LogPath"];
bool.TryParse(AppConfig["LogDebug"], out bool oLogDebug);
services.AddControllers().AddNewtonsoftJson(); services.AddControllers().AddNewtonsoftJson();
services.AddRazorPages(); services.AddRazorPages();
services.AddTransient<IZugferdValidationDataService, ZugferdValidationDataService>(); services.Configure<Config>(Configuration.GetSection("Config"));
services.AddSingleton<ILogging>(sp => new Logging(oLogPath, oLogDebug));
services.AddSingleton((Func<IServiceProvider, IDatabase>)(sp => {
var logging = sp.GetService<ILogging>();
var config = sp.GetService<IConfiguration>();
return new Database(logging, config);
}));
} }
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline. // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.

View File

@@ -1,12 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk.Web"> <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FirebirdSql.Data.FirebirdClient" Version="7.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" /> <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.1" />
<PackageReference Include="NLog" Version="4.6.8" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" />
<PackageReference Include="System.Data.SqlClient" Version="4.8.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Modules.Database\Database.vbproj" />
<ProjectReference Include="..\..\Modules.Interfaces\Interfaces.vbproj" />
<ProjectReference Include="..\..\Modules.Logging\Logging.vbproj" />
</ItemGroup> </ItemGroup>

View File

@@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ZUGFeRDRESTService
{
public class ZugferdValidationDataService: IZugferdValidationDataService
{
}
}

View File

@@ -6,5 +6,17 @@
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
"Config": {
"LogPath": "E:\\ZUGFeRDRESTService",
"LogDebug": true,
"Name": "ZUGFeRD REST API",
"MSSQLConnectionString": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM_TEST;User Id=sa;Password=dd;",
"Firebird": {
"Datasource": "172.24.12.41",
"Database": "172.24.12.41:E:\\DB\\Firebird\\Databases\\EDMI_TEMPLATE\\EDMI_MASTER.FDB",
"Username": "SYSDBA",
"Password": "dd"
}
}
} }