Compare commits
16 Commits
33937a41d3
...
84dab7f5a6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84dab7f5a6 | ||
|
|
3449b16d69 | ||
|
|
7b3dc1bf89 | ||
|
|
3d3a491744 | ||
|
|
322ca23f33 | ||
|
|
6ec458ccdf | ||
|
|
a437359114 | ||
|
|
b6b29e5de8 | ||
|
|
51c1f9f3f7 | ||
|
|
28d2e4241d | ||
|
|
edf7c37cb5 | ||
|
|
c8291116a3 | ||
|
|
7977b926f1 | ||
|
|
a46809ae24 | ||
| a66c2928f2 | |||
| dff085ced2 |
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("1.1.0.0")>
|
||||
<Assembly: AssemblyVersion("1.1.0.1")>
|
||||
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
||||
|
||||
@@ -27,11 +27,10 @@ Public Class ThreadRunner
|
||||
|
||||
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
|
||||
_logger = _logConfig.GetLogger()
|
||||
_firebird = Firebird
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig)
|
||||
_mssql = MSSQL
|
||||
|
||||
Dim args As New WorkerArgs()
|
||||
|
||||
@@ -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)
|
||||
_mssql = New MSSQLServer(_logConfig, My.Settings.MSSQL_CONNECTIONSTRING)
|
||||
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig)
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig, "")
|
||||
End Sub
|
||||
|
||||
Private Function LoadFolderConfig(args As WorkerArgs)
|
||||
@@ -164,7 +164,7 @@ Public Class Form1
|
||||
End Sub
|
||||
|
||||
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()
|
||||
|
||||
If oResult = DialogResult.OK Then
|
||||
|
||||
@@ -169,7 +169,6 @@ Public Class File
|
||||
|
||||
<DebuggerStepThrough>
|
||||
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))
|
||||
End Sub
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
Imports System.Xml
|
||||
Imports System.IO
|
||||
Imports System.Xml
|
||||
Imports System.Xml.Serialization
|
||||
Imports System.Xml.XPath
|
||||
Imports System.Xml.Xsl
|
||||
Imports DigitalData.Modules.Interfaces.Exceptions
|
||||
Imports DigitalData.Modules.Logging
|
||||
Imports GdPicture14
|
||||
|
||||
Public Class ZUGFeRDInterface
|
||||
Private _logConfig As LogConfig
|
||||
@@ -21,13 +23,23 @@ Public Class ZUGFeRDInterface
|
||||
Public ReadOnly Property FileGroup As FileGroups
|
||||
Public ReadOnly Property PropertyValues As PropertyValues
|
||||
|
||||
Public Sub New(LogConfig As LogConfig)
|
||||
Public Sub New(LogConfig As LogConfig, GDPictureKey As String)
|
||||
_logConfig = LogConfig
|
||||
_logger = _logConfig.GetLogger()
|
||||
|
||||
FileGroup = New FileGroups(_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
|
||||
|
||||
|
||||
''' <summary>
|
||||
''' Validates a ZUGFeRD File and extracts the XML Document from it
|
||||
''' </summary>
|
||||
@@ -35,7 +47,6 @@ Public Class ZUGFeRDInterface
|
||||
''' <exception cref="ZUGFeRDExecption"></exception>
|
||||
''' <returns></returns>
|
||||
Public Function ExtractZUGFeRDFile(Path As String) As CrossIndustryDocumentType
|
||||
Dim oException As New Exception
|
||||
Dim oXmlDocument = ValidateZUGFeRDFile(Path)
|
||||
|
||||
If IsNothing(oXmlDocument) Then
|
||||
@@ -45,6 +56,15 @@ Public Class ZUGFeRDInterface
|
||||
Return SerializeZUGFeRDDocument(oXmlDocument)
|
||||
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
|
||||
Dim oProcessOutput, oProcessError As String
|
||||
@@ -90,6 +110,52 @@ Public Class ZUGFeRDInterface
|
||||
Return oXmlDocument
|
||||
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
|
||||
Try
|
||||
Dim oNavigator As XPathNavigator = Document.CreateNavigator()
|
||||
|
||||
@@ -4,9 +4,9 @@ Imports DigitalData.Modules.Logging
|
||||
Imports GdPicture14
|
||||
|
||||
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 FileName As String
|
||||
@@ -17,61 +17,50 @@ Public Class PDFAttachments
|
||||
Logger = LogConfig.GetLogger
|
||||
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)
|
||||
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
|
||||
Using oGDPicturePDF As New GdPicturePDF()
|
||||
If oGDPicturePDF.LoadFromFile(FileName, False) = GdPictureStatus.OK Then
|
||||
Dim oEmbeddedFileCount As Integer = oGDPicturePDF.GetEmbeddedFileCount()
|
||||
If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then
|
||||
If oEmbeddedFileCount > 1 Then
|
||||
If oEmbeddedFileCount > 0 Then
|
||||
For index = 0 To oEmbeddedFileCount - 1
|
||||
Dim oFileName As String = oGDPicturePDF.GetEmbeddedFileName(index)
|
||||
|
||||
If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then
|
||||
Dim oExtension = New FileInfo(oFileName).Extension.ToUpper.Substring(1)
|
||||
If oFileName.ToUpper <> ZUGFERD_XML_FILENAME.ToUpper Then
|
||||
If oExtensions.Contains(oExtension) Then
|
||||
Dim FileSize As Integer = oGDPicturePDF.GetEmbeddedFileSize(index)
|
||||
If oExtensions.Contains(oExtension) Then
|
||||
Dim FileSize As Integer = oGDPicturePDF.GetEmbeddedFileSize(index)
|
||||
|
||||
If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then
|
||||
Dim oFileData As Byte() = New Byte(FileSize) {}
|
||||
Dim status As GdPictureStatus = oGDPicturePDF.ExtractEmbeddedFile(index, oFileData)
|
||||
If oGDPicturePDF.GetStat() = GdPictureStatus.OK Then
|
||||
Dim oFileData As Byte() = New Byte(FileSize) {}
|
||||
Dim status As GdPictureStatus = oGDPicturePDF.ExtractEmbeddedFile(index, oFileData)
|
||||
|
||||
If status = GdPictureStatus.OK Then
|
||||
oResults.Add(New AttachmentResult() With {
|
||||
.FileContents = oFileData,
|
||||
.FileName = oFileName
|
||||
})
|
||||
Else
|
||||
Logger.Error("The embedded file [{0}] has failed to extract. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
|
||||
Continue For
|
||||
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
|
||||
If status = GdPictureStatus.OK Then
|
||||
oResults.Add(New AttachmentResult() With {
|
||||
.FileContents = oFileData,
|
||||
.FileName = oFileName
|
||||
})
|
||||
Else
|
||||
Logger.Error("An error occurred getting the file size for [{0}]. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
|
||||
Logger.Error("The embedded file [{0}] has failed to extract. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
|
||||
Continue For
|
||||
End If
|
||||
Else
|
||||
Logger.Warn("File [{0}] was skipped because its extension [{1}] is not allowed.", oFileName, oExtension)
|
||||
Logger.Error("An error occurred getting the file size for [{0}]. Status: {1}", oFileName, oGDPicturePDF.GetStat().ToString())
|
||||
Continue For
|
||||
End If
|
||||
Else
|
||||
Logger.Debug("File [{0}] was skipped because its name indicates the invoice data file.", oFileName)
|
||||
Logger.Warn("File [{0}] was skipped because its extension [{1}] is not allowed.", oFileName, oExtension)
|
||||
Continue For
|
||||
End If
|
||||
Else
|
||||
@@ -81,12 +70,12 @@ Public Class PDFAttachments
|
||||
Next
|
||||
End If
|
||||
Else
|
||||
Logger.Error("An error occurred getting the number of embedded files. Status: {0}", oGDPicturePDF.GetStat().ToString())
|
||||
Return Nothing
|
||||
Dim oMessage = String.Format("An error occurred getting the number of embedded files. Status: {0}", oGDPicturePDF.GetStat().ToString())
|
||||
Throw New ApplicationException(oMessage)
|
||||
End If
|
||||
Else
|
||||
Logger.Error("The file [{0}] can't be loaded.", FileName)
|
||||
Return Nothing
|
||||
Dim oMessage = String.Format("The file [{0}] can't be loaded. Status: [{1}]", FileName, oGDPicturePDF.GetStat().ToString())
|
||||
Throw New ApplicationException(oMessage)
|
||||
End If
|
||||
End Using
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ Public Class PropertyValues
|
||||
|
||||
Public Class CheckPropertyValuesResult
|
||||
Public MissingProperties As New List(Of String)
|
||||
Public ValidProperties As List(Of ValidProperty)
|
||||
Public ValidProperties As New List(Of ValidProperty)
|
||||
End Class
|
||||
|
||||
Public Class ValidProperty
|
||||
@@ -36,7 +36,7 @@ Public Class PropertyValues
|
||||
|
||||
' PropertyMap items with `IsGrouped = False` are handled normally
|
||||
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,
|
||||
Function(Item) Item.Value)
|
||||
|
||||
|
||||
197
Modules.Jobs/EDMI/ZUGFeRD/EmailFunctions.vb
Normal file
197
Modules.Jobs/EDMI/ZUGFeRD/EmailFunctions.vb
Normal 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
|
||||
18
Modules.Jobs/EDMI/ZUGFeRD/EmailStrings.vb
Normal file
18
Modules.Jobs/EDMI/ZUGFeRD/EmailStrings.vb
Normal 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
|
||||
@@ -26,106 +26,47 @@ Public Class ImportZUGFeRDFiles
|
||||
Public Const ZUGFERD_ATTACHMENTS = "ZUGFeRD Attachments"
|
||||
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
|
||||
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 _logConfig As LogConfig
|
||||
Private _zugferd As ZUGFeRDInterface
|
||||
Private _firebird As Firebird
|
||||
Private _filesystem As Filesystem.File
|
||||
Private _mssql As MSSQLServer
|
||||
Private ReadOnly _logger As Logger
|
||||
Private ReadOnly _logConfig As LogConfig
|
||||
Private ReadOnly _zugferd As ZUGFeRDInterface
|
||||
Private ReadOnly _firebird As Firebird
|
||||
Private ReadOnly _filesystem As Filesystem.File
|
||||
Private ReadOnly _mssql As MSSQLServer
|
||||
Private ReadOnly _email As EmailFunctions
|
||||
|
||||
Public Sub New(LogConfig As LogConfig, Firebird As Firebird, Optional MSSQL As MSSQLServer = Nothing)
|
||||
_logConfig = LogConfig
|
||||
_logger = LogConfig.GetLogger()
|
||||
_firebird = Firebird
|
||||
_filesystem = New Filesystem.File(_logConfig)
|
||||
_zugferd = New ZUGFeRDInterface(_logConfig)
|
||||
_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
|
||||
|
||||
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
|
||||
Dim oEmailData = GetEmailDataForMessageId(MessageId)
|
||||
Dim oSource = GetOriginalEmailPath(Args.OriginalEmailDirectory, MessageId)
|
||||
Dim oEmailData = _email.GetEmailDataForMessageId(MessageId)
|
||||
Dim oSource = _email.GetOriginalEmailPath(Args.OriginalEmailDirectory, MessageId)
|
||||
Dim oDestination As String
|
||||
|
||||
' 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
|
||||
If oEmailData Is Nothing Then
|
||||
oDestination = GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, MessageId)
|
||||
oDestination = _email.GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, MessageId)
|
||||
Else
|
||||
oDestination = GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, oEmailData.Subject)
|
||||
oDestination = _email.GetEmailPathWithSubjectAsName(Args.RejectedEmailDirectory, oEmailData.Subject)
|
||||
End If
|
||||
|
||||
_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)
|
||||
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}'"
|
||||
_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
|
||||
_logger.Error(ex)
|
||||
End Try
|
||||
@@ -295,23 +110,6 @@ Public Class ImportZUGFeRDFiles
|
||||
|
||||
_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
|
||||
For Each oPath As String In oArgs.WatchDirectories
|
||||
Dim oDirInfo As New DirectoryInfo(oPath)
|
||||
@@ -398,7 +196,8 @@ Public Class ImportZUGFeRDFiles
|
||||
End Select
|
||||
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)
|
||||
If oAttachments Is Nothing Then
|
||||
_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
|
||||
oZUGFeRDCount += 1
|
||||
|
||||
#Region "Check Property Values"
|
||||
' --- BEGIN Check Property Values
|
||||
|
||||
'' PropertyMap items with `IsGrouped = False` are handled normally
|
||||
@@ -607,7 +406,7 @@ Public Class ImportZUGFeRDFiles
|
||||
'Next
|
||||
|
||||
'--- END Check Property Values
|
||||
|
||||
#End Region
|
||||
' Check the document against the configured property map and return:
|
||||
' - a List of valid 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}'"
|
||||
_firebird.ExecuteNonQuery(oSQL)
|
||||
|
||||
Dim oBody = EMAIL_MD5_ERROR
|
||||
Dim oBody = EmailStrings.EMAIL_MD5_ERROR
|
||||
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!", "")
|
||||
Catch ex As InvalidFerdException
|
||||
_logger.Error(ex)
|
||||
@@ -676,9 +475,9 @@ Public Class ImportZUGFeRDFiles
|
||||
oMoveDirectory = oArgs.ErrorDirectory
|
||||
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - ZUGFeRD yes but incorrect format' WHERE GUID = '{HISTORY_ID}'"
|
||||
_firebird.ExecuteNonQuery(oSQL)
|
||||
Dim oBody = EMAIL_INVALID_DOCUMENT
|
||||
Dim oBody = EmailStrings.EMAIL_INVALID_DOCUMENT
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException")
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "InvalidFerdException")
|
||||
AddRejectedState(oMessageId, "InvalidFerdException", "Inkorrekte Formate", "")
|
||||
Catch ex As TooMuchFerdsException
|
||||
_logger.Error(ex)
|
||||
@@ -686,9 +485,9 @@ Public Class ImportZUGFeRDFiles
|
||||
oMoveDirectory = oArgs.ErrorDirectory
|
||||
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - More than one ZUGFeRD-document in email' WHERE GUID = '{HISTORY_ID}'"
|
||||
_firebird.ExecuteNonQuery(oSQL)
|
||||
Dim oBody = EMAIL_TOO_MUCH_FERDS
|
||||
Dim oBody = EmailStrings.EMAIL_TOO_MUCH_FERDS
|
||||
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", "")
|
||||
Catch ex As NoFerdsException
|
||||
_logger.Error(ex)
|
||||
@@ -696,9 +495,9 @@ Public Class ImportZUGFeRDFiles
|
||||
oMoveDirectory = oArgs.ErrorDirectory
|
||||
Dim oSQL = $"UPDATE TBEDM_ZUGFERD_HISTORY_IN SET COMMENT = 'REJECTED - no ZUGFeRD-Document in email' WHERE GUID = '{HISTORY_ID}'"
|
||||
_firebird.ExecuteNonQuery(oSQL)
|
||||
Dim oBody = EMAIL_NO_FERDS
|
||||
Dim oBody = EmailStrings.EMAIL_NO_FERDS
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException")
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "NoFerdsException")
|
||||
AddRejectedState(oMessageId, "NoFerdsException", " Email enthielt keine ZUGFeRD-Dokumente", "")
|
||||
Catch ex As MissingValueException
|
||||
_logger.Error(ex)
|
||||
@@ -713,7 +512,7 @@ Public Class ImportZUGFeRDFiles
|
||||
|
||||
Dim oBody = CreateBodyForMissingProperties(ex.File.Name, oMissingProperties)
|
||||
Dim oEmailData = MoveAndRenameEmailToRejected(oArgs, oMessageId)
|
||||
AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException")
|
||||
_email.AddToEmailQueueMSSQL(oMessageId, oBody, oEmailData, "MissingValueException")
|
||||
AddRejectedState(oMessageId, "MissingValueException", "Es fehlten ZugferdSpezifikationen", oMessage)
|
||||
|
||||
Catch ex As Exception
|
||||
@@ -770,8 +569,11 @@ Public Class ImportZUGFeRDFiles
|
||||
End Try
|
||||
End If
|
||||
|
||||
' Filter out Attachments from `Files`
|
||||
Dim oInvoiceFiles As List(Of FileInfo) = Files.Except(AttachmentFiles).ToList()
|
||||
|
||||
' Move PDF/A Files
|
||||
For Each oFile In Files
|
||||
For Each oFile In oInvoiceFiles
|
||||
Try
|
||||
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))
|
||||
Dim oBody = String.Format(EMAIL_MISSINGPROPERTIES_1, OriginalFilename)
|
||||
Dim oBody = String.Format(EmailStrings.EMAIL_MISSINGPROPERTIES_1, OriginalFilename)
|
||||
|
||||
If MissingProperties.Count > 0 Then
|
||||
oBody &= $"{vbNewLine}{vbNewLine}"
|
||||
oBody &= EMAIL_MISSINGPROPERTIES_2
|
||||
oBody &= EmailStrings.EMAIL_MISSINGPROPERTIES_2
|
||||
oBody &= $"{vbNewLine}{vbNewLine}"
|
||||
|
||||
For Each prop In MissingProperties
|
||||
|
||||
@@ -87,6 +87,8 @@
|
||||
<Compile Include="EDMI\GraphQL\GraphQLArgs.vb" />
|
||||
<Compile Include="EDMI\GraphQL\GraphQLJob.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\WorkerArgs.vb" />
|
||||
<Compile Include="Exceptions.vb" />
|
||||
|
||||
@@ -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:
|
||||
|
||||
<Assembly: AssemblyVersion("1.1.0.0")>
|
||||
<Assembly: AssemblyVersion("1.1.0.2")>
|
||||
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
Imports System.IO
|
||||
Imports System.Reflection
|
||||
Imports NLog
|
||||
Imports NLog.Config
|
||||
Imports NLog.Targets
|
||||
@@ -14,33 +15,6 @@ Imports NLog.Targets
|
||||
''' <dependencies>
|
||||
''' NLog, >= 4.5.8
|
||||
''' </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>
|
||||
''' Imports DigitalData.Modules.Logging
|
||||
'''
|
||||
@@ -81,6 +55,7 @@ Imports NLog.Targets
|
||||
''' - NLOG_INTERNAL_LOG_FILE: ex. C:\Temp\Nlog_Internal.log
|
||||
''' </remarks>
|
||||
Public Class LogConfig
|
||||
#Region "Private Properties"
|
||||
Private Const KEEP_FILES_OPEN As Boolean = False
|
||||
' MAX_ARCHIVES_FILES works like this (in version 4.5.8):
|
||||
' 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_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 FOLDER_NAME_LOG = "Log"
|
||||
|
||||
Private ReadOnly failSafePath As String = Path.GetTempPath()
|
||||
Private ReadOnly basePath As String = failSafePath
|
||||
|
||||
Private config As LoggingConfiguration
|
||||
Private isDebug As Boolean = False
|
||||
|
||||
#End Region
|
||||
#Region "Public Properties"
|
||||
Public Enum PathType As Integer
|
||||
AppData = 0
|
||||
CurrentDirectory = 1
|
||||
@@ -173,24 +149,41 @@ Public Class LogConfig
|
||||
End Get
|
||||
End Property
|
||||
|
||||
Public ReadOnly Property NLogConfig As LoggingConfiguration
|
||||
Get
|
||||
Return config
|
||||
End Get
|
||||
End Property
|
||||
|
||||
#End Region
|
||||
|
||||
''' <summary>
|
||||
''' Initializes a new LogConfig object with a logpath and optinally a filename-suffix.
|
||||
''' </summary>
|
||||
''' <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="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)
|
||||
Dim productName As String = My.Application.Info.ProductName
|
||||
Dim companyName As String = My.Application.Info.CompanyName
|
||||
''' <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="Suffix">If set to anything other than Nothing, extends the logfile name with this suffix.</param>
|
||||
''' <param name="CompanyName">CompanyName is used to construct log-path in when LogPath is set to PathType:AppData</param>
|
||||
''' <param name="ProductName">ProductName is used to construct log-path in when LogPath is set to PathType:AppData</param>
|
||||
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)
|
||||
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)
|
||||
basePath = Path.Combine(appDataDir, CompanyName, ProductName, FOLDER_NAME_LOG)
|
||||
Else 'Custom Path
|
||||
basePath = customLogPath
|
||||
basePath = CustomLogPath
|
||||
End If
|
||||
|
||||
' 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
|
||||
Dim logFileSuffix As String = String.Empty
|
||||
|
||||
If suffix IsNot Nothing AndAlso suffix.Count > 0 Then
|
||||
logFileSuffix = $"-{suffix}"
|
||||
If Suffix IsNot Nothing AndAlso Suffix.Count > 0 Then
|
||||
logFileSuffix = $"-{Suffix}"
|
||||
End If
|
||||
|
||||
' Create config object and initalize it
|
||||
config = GetConfig(productName, logFileSuffix)
|
||||
config = GetConfig(ProductName, logFileSuffix)
|
||||
|
||||
' Save config
|
||||
LogFactory = New LogFactory With {
|
||||
@@ -236,10 +229,24 @@ Public Class LogConfig
|
||||
LogFile = GetCurrentLogFilePath()
|
||||
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>
|
||||
''' Returns the Logger for the calling class
|
||||
''' </summary>
|
||||
''' <returns>An object of Logging.Logger</returns>
|
||||
<DebuggerStepThrough()>
|
||||
Public Function GetLogger() As Logger
|
||||
Dim oClassName As String = GetClassFullName()
|
||||
Return LogFactory.GetLogger(Of Logger)(oClassName)
|
||||
@@ -250,6 +257,7 @@ Public Class LogConfig
|
||||
''' </summary>
|
||||
''' <param name="ClassName">The name of the class the logger belongs to</param>
|
||||
''' <returns>An object of Logging.Logger</returns>
|
||||
<DebuggerStepThrough()>
|
||||
Public Function GetLogger(ClassName As String) As Logger
|
||||
Return LogFactory.GetLogger(Of Logger)(ClassName)
|
||||
End Function
|
||||
@@ -268,6 +276,7 @@ Public Class LogConfig
|
||||
''' </summary>
|
||||
''' <returns>The fully qualified class name</returns>
|
||||
''' <remarks>This method is very resource-intensive!</remarks>
|
||||
<DebuggerStepThrough()>
|
||||
Public Shared Function GetClassFullName() As String
|
||||
Dim oFramesToSkip As Integer = 2
|
||||
Dim oClassName As String = String.Empty
|
||||
@@ -437,7 +446,5 @@ Public Class LogConfig
|
||||
|
||||
Return memoryLog
|
||||
End Function
|
||||
|
||||
|
||||
#End Region
|
||||
End Class
|
||||
|
||||
@@ -2,11 +2,13 @@
|
||||
|
||||
Public Class Logger
|
||||
Inherits NLog.Logger
|
||||
Implements ILogger
|
||||
|
||||
''' <summary>
|
||||
''' Prints a preformatted Block including a block identifier
|
||||
''' </summary>
|
||||
''' <param name="blockId">A unique Identifier for this block, eg. DocId, FullPath, ..</param>
|
||||
<DebuggerStepThrough()>
|
||||
Public Sub NewBlock(blockId As String)
|
||||
Dim message As String = $"-----> Start of Block {blockId}"
|
||||
Dim logEventInfo As New LogEventInfo(LogLevel.Info, Name, message)
|
||||
@@ -15,6 +17,7 @@ Public Class Logger
|
||||
Log(WrapperType, logEventInfo)
|
||||
End Sub
|
||||
|
||||
<DebuggerStepThrough()>
|
||||
Public Sub EndBlock()
|
||||
Dim message As String = $"<----- End of Block"
|
||||
Dim logEventInfo As New LogEventInfo(LogLevel.Info, Name, message)
|
||||
|
||||
@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
|
||||
' übernehmen, indem Sie "*" eingeben:
|
||||
' <Assembly: AssemblyVersion("1.0.*")>
|
||||
|
||||
<Assembly: AssemblyVersion("0.0.1.1")>
|
||||
<Assembly: AssemblyVersion("2.0.0.0")>
|
||||
<Assembly: AssemblyFileVersion("1.0.0.0")>
|
||||
|
||||
15
WEBSERVICES/ZUGFeRDRESTService/Config.cs
Normal file
15
WEBSERVICES/ZUGFeRDRESTService/Config.cs
Normal 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; }
|
||||
}
|
||||
}
|
||||
@@ -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!"
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
WEBSERVICES/ZUGFeRDRESTService/Database.cs
Normal file
64
WEBSERVICES/ZUGFeRDRESTService/Database.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
WEBSERVICES/ZUGFeRDRESTService/IDatabase.cs
Normal file
16
WEBSERVICES/ZUGFeRDRESTService/IDatabase.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
9
WEBSERVICES/ZUGFeRDRESTService/ILogging.cs
Normal file
9
WEBSERVICES/ZUGFeRDRESTService/ILogging.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using DigitalData.Modules.Logging;
|
||||
|
||||
namespace ZUGFeRDRESTService
|
||||
{
|
||||
public interface ILogging
|
||||
{
|
||||
public LogConfig LogConfig { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ZUGFeRDRESTService
|
||||
{
|
||||
public interface IZugferdValidationDataService
|
||||
{
|
||||
}
|
||||
}
|
||||
20
WEBSERVICES/ZUGFeRDRESTService/Logger.cs
Normal file
20
WEBSERVICES/ZUGFeRDRESTService/Logger.cs
Normal 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()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
WEBSERVICES/ZUGFeRDRESTService/Logging.cs
Normal file
15
WEBSERVICES/ZUGFeRDRESTService/Logging.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,14 +3,39 @@
|
||||
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>
|
||||
<span>PDF Datei:</span>
|
||||
<input type="file" name="files" />
|
||||
<label>PDF Datei:</label>
|
||||
<input type="file" name="file" required />
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<label>Benutzerkennung/Email:</label>
|
||||
<input type="email" name="user_id" required />
|
||||
</p>
|
||||
|
||||
<button type="submit">Submit</button>
|
||||
</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>
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using NLog.Web;
|
||||
using DigitalData.Modules.Logging;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ZUGFeRDRESTService
|
||||
{
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/zugferdvalidation",
|
||||
"launchUrl": "",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
|
||||
@@ -18,16 +18,29 @@ namespace ZUGFeRDRESTService
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
AppConfig = configuration.GetSection("Config");
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
private IConfigurationSection AppConfig { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
string oLogPath = AppConfig["LogPath"];
|
||||
bool.TryParse(AppConfig["LogDebug"], out bool oLogDebug);
|
||||
|
||||
services.AddControllers().AddNewtonsoftJson();
|
||||
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.
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FirebirdSql.Data.FirebirdClient" Version="7.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.1.2" />
|
||||
<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>
|
||||
|
||||
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ZUGFeRDRESTService
|
||||
{
|
||||
public class ZugferdValidationDataService: IZugferdValidationDataService
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,17 @@
|
||||
"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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user