MS Sichtbeleg

This commit is contained in:
Developer01 2025-02-07 14:42:54 +01:00
parent 6a051f7a92
commit 6515e1811b
6 changed files with 315 additions and 13 deletions

View File

@ -14,6 +14,8 @@
<NoWarn>42016,41999,42017,42018,42019,42032,42036,42020,42021,42022</NoWarn>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
@ -116,12 +118,16 @@
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
<Compile Include="ZUGFeRD\XRechnungStrings.vb" />
<Compile Include="ZUGFeRD\XRechnungViewDocument.vb" />
</ItemGroup>
<ItemGroup>
<Reference Include="FirebirdSql.Data.FirebirdClient, Version=7.5.0.0, Culture=neutral, PublicKeyToken=3750abcc3150b00c, processorArchitecture=MSIL">
<HintPath>..\packages\FirebirdSql.Data.FirebirdClient.7.5.0\lib\net452\FirebirdSql.Data.FirebirdClient.dll</HintPath>
</Reference>
<Reference Include="GdPicture.NET.14, Version=14.2.90.0, Culture=neutral, PublicKeyToken=f52a2e60ad468dbb, processorArchitecture=MSIL">
<HintPath>..\packages\GdPicture.14.2.90\lib\net462\GdPicture.NET.14.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
@ -143,4 +149,11 @@
<PropertyGroup>
<PostBuildEvent>powershell.exe -command "&amp; { &amp;'$(SolutionDir)copy-binary.ps1' '$(TargetPath)' '$(TargetFileName)' '$(ConfigurationName)' '$(ProjectName)' }"</PostBuildEvent>
</PropertyGroup>
<Import Project="..\packages\GdPicture.runtimes.windows.14.2.90\build\net462\GdPicture.runtimes.windows.targets" Condition="Exists('..\packages\GdPicture.runtimes.windows.14.2.90\build\net462\GdPicture.runtimes.windows.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\GdPicture.runtimes.windows.14.2.90\build\net462\GdPicture.runtimes.windows.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GdPicture.runtimes.windows.14.2.90\build\net462\GdPicture.runtimes.windows.targets'))" />
</Target>
</Project>

View File

@ -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("2.6.3.0")>
<Assembly: AssemblyFileVersion("2.6.3.0")>
<Assembly: AssemblyVersion("2.6.4.0")>
<Assembly: AssemblyFileVersion("2.6.4.0")>

View File

@ -40,11 +40,15 @@ Public Class ImportZUGFeRDFiles
Private ReadOnly _hash As HashFunctions
Private ReadOnly _embeds As PDFEmbeds
Private ReadOnly _gdpictureLicenseKey As String
Private SQL_xRechnung_ItemTemplate As String = ""
Private ReadOnly _gdpictureLicenseKey As String
Private _xRechnungCreator As XRechnungViewDocument
Private _zugferd As ZUGFeRDInterface
Private _EmailOutAccountId As Integer
Private MyTemplateValues_xInvDT As DataTable
Private Class ProcessFileResult
Public ZugferdFileFound As Boolean = False
@ -70,7 +74,7 @@ Public Class ImportZUGFeRDFiles
_history = New ZUGFeRD.HistoryFunctions(LogConfig, _mssql)
_embeds = New PDFEmbeds(LogConfig)
_hash = New HashFunctions(_logConfig, _mssql)
_xRechnungCreator = New XRechnungViewDocument(_logConfig, _mssql, _gdpictureLicenseKey)
_logger.Debug("Registering GDPicture License")
If _mssql IsNot Nothing Then
_gdpictureLicenseKey = ConfigDbFunct.GetProductLicense("GDPICTURE", "11.2024", _logConfig, _mssql.CurrentConnectionString)
@ -92,6 +96,11 @@ Public Class ImportZUGFeRDFiles
})
_logger.Debug("Starting Job {0}", [GetType].Name)
If oArgs.AllowXRechnung Then
Dim oSQL = "Select SQL_COMMAND from TBDD_SQL_COMMANDS WHERE TITLE = 'VWDD_ZUGFERD_VIEW_RECEIPT_TEMPLATE_ITEMS'"
SQL_xRechnung_ItemTemplate = _mssql.GetScalarValue(oSQL)
End If
Try
'For Each oPath As String In oArgs.WatchDirectory
@ -123,12 +132,23 @@ Public Class ImportZUGFeRDFiles
_logger.Info("Found {0} file groups", oGrouped.Count)
' Process each file group together
'Process each file group together
'oGrouped equals one e-invoice
For Each oFileGroup In oGrouped
' Start a new transaction for each file group.
' This way we can rollback database changes for the whole filegroup in case something goes wrong.
Dim oSQLConnection As SqlConnection = _mssql.GetConnection()
If oArgs.AllowXRechnung Then
'but before we need to get all Data we need
MyTemplateValues_xInvDT = Nothing
Dim oSQL_MsgIDReplacec = SQL_xRechnung_ItemTemplate
oSQL_MsgIDReplacec = oSQL_MsgIDReplacec.Replace("@MSG_ID", oFileGroup.Key)
MyTemplateValues_xInvDT = _mssql.GetDatatable(oSQL_MsgIDReplacec)
End If
Dim oSQLTransaction As SqlTransaction = oSQLConnection?.BeginTransaction()
Dim oConnections As New DatabaseConnections() With {
@ -151,7 +171,7 @@ Public Class ImportZUGFeRDFiles
Dim oExpectedError As Boolean = True
' Create file lists
Dim oFileGroupFiles As List(Of FileInfo) = oFileGroup.Value
Dim oEInvoiceFileGroup As List(Of FileInfo) = oFileGroup.Value
Dim oEmailAttachmentFiles As New List(Of FileInfo)
Dim oEmbeddedAttachmentFiles As New List(Of PDFEmbeds.EmbeddedFile)
@ -160,7 +180,7 @@ Public Class ImportZUGFeRDFiles
_logger.Info("START processing file group {0}", oMessageId)
If _file.CheckFileAge(oFileGroupFiles, oArgs.MinFileAgeInMinutes) Then
If _file.CheckFileAge(oEInvoiceFileGroup, oArgs.MinFileAgeInMinutes) Then
_logger.Info("At least one file was created less than [{0}] minutes ago. Skipping file group.", oArgs.MinFileAgeInMinutes)
Continue For
End If
@ -169,7 +189,8 @@ Public Class ImportZUGFeRDFiles
Dim oFileCounter As Integer = 0
Try
For Each oFile In oFileGroupFiles
For Each oFile In oEInvoiceFileGroup
oFileCounter += 1
Dim oResult As ProcessFileResult
@ -395,15 +416,28 @@ Public Class ImportZUGFeRDFiles
Finally
Try
Dim oxRechnungHandle As Boolean = False
Dim oRegularMove As Boolean = False
' If an application error occurred, dont move files so they will be processed again later
If oMoveDirectory = DIRECTORY_DONT_MOVE Then
_logger.Info("Application Error occurred. Files for message Id {0} will not be moved.", oMessageId)
ElseIf (1 = 0) Then
ElseIf oArgs.AllowXRechnung And oIsSuccess And oEInvoiceFileGroup.Item(0).Extension = ".xml" Then
oxRechnungHandle = True
' Hier das neue PDF erzeugen
If Not IsNothing(MyTemplateValues_xInvDT) Then
Dim oViewReceiptFileInfo As FileInfo = _xRechnungCreator.Create_PDFfromXML(oEInvoiceFileGroup.Item(0), MyTemplateValues_xInvDT)
If Not IsNothing(oViewReceiptFileInfo) Then
oEInvoiceFileGroup.Item(0) = oViewReceiptFileInfo
oRegularMove = True
End If
End If
Else
oRegularMove = True
End If
If oRegularMove Then
' Move all files of the current group
_file.MoveFiles(oArgs, oMessageId, oFileGroupFiles, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
_file.MoveFiles(oArgs, oMessageId, oEInvoiceFileGroup, oEmailAttachmentFiles, oEmbeddedAttachmentFiles, oMoveDirectory, oIsSuccess)
End If
_logger.Info("END processing file group {0}", oMessageId)
Catch ex As Exception

View File

@ -0,0 +1,7 @@
Public Class XRechnungStrings
Public Const CommentSichtbeleg_DE_Row1 = "Achtung: dies ist ein technisch erstelltes Abbild einer digitalen Rechnung."
Public Const CommentSichtbeleg_DE_Row2 = "Die Darstellung basiert auf den Inhalten der xml-Datei, welche als Anhang in diese PDF integriert wurde!"
Public Const CommentSichtbeleg_EN_Row1 = "Please note: this is a technically created image of a digital invoice."
Public Const CommentSichtbeleg_EN_Row2 = "The representation is based on the contents of the xml file, which has been integrated into this PDF as an attachment!"
Public Const Seperator_Line = "-------------------------------------------------------------------------"
End Class

View File

@ -1,3 +1,249 @@
Public Class XRechnungViewDocument
Imports System.Data
Imports System.Data.SqlClient
Imports System.IO
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Database
Imports DigitalData.Modules.Logging
Imports FirebirdSql.Data
Imports GdPicture14
Public Class XRechnungViewDocument
Private ReadOnly _logger As Logger
Private ReadOnly _logConfig As LogConfig
Private ReadOnly _filesystem As FilesystemEx
'Private ReadOnly _mssql As MSSQLServer
Private ReadOnly _file As ZUGFeRD.FileFunctions
Private ReadOnly _gdpictureLicenseKey As String
Public Sub New(LogConfig As LogConfig, MSSQL As MSSQLServer, GDPictureLicenseKey As String)
_logConfig = LogConfig
_logger = LogConfig.GetLogger()
_filesystem = New FilesystemEx(_logConfig)
_file = New ZUGFeRD.FileFunctions(LogConfig, MSSQL)
_gdpictureLicenseKey = GDPictureLicenseKey
End Sub
Public Function Create_PDFfromXML(oxmlFile As FileInfo, pDTItemValues As DataTable) As FileInfo
Try
Dim oXRechnungFile = oxmlFile.FullName
Dim oNewFileinfo As FileInfo
Dim oxmlFilePath = oxmlFile.FullName
Dim oViewRecieptFilename = oxmlFile.Name
Dim oTempFilePath = Path.GetDirectoryName(oxmlFilePath) + "\Temp"
If Not Directory.Exists(oTempFilePath) Then
Directory.CreateDirectory(oTempFilePath)
End If
oTempFilePath = oTempFilePath + "\xrechnung.xml"
If File.Exists(oTempFilePath) Then
File.Delete(oTempFilePath)
End If
File.Move(oxmlFilePath, oTempFilePath)
oxmlFile = New FileInfo(oTempFilePath)
oViewRecieptFilename = oViewRecieptFilename.Replace("xml", "pdf")
Dim oOutputPath = Path.GetDirectoryName(oxmlFilePath) + "\" + oViewRecieptFilename
If File.Exists(oOutputPath) Then
File.Delete(oOutputPath)
End If
Dim gdpicturePDF As GdPicturePDF = New GdPicturePDF()
gdpicturePDF.NewPDF(PdfConformance.PDF_A_2a)
Dim ostatus As GdPictureStatus = gdpicturePDF.NewPDF()
If ostatus <> GdPictureStatus.OK Then
_logger.Warn($"Error initializing PDF: {ostatus}")
Return Nothing
End If
gdpicturePDF.SetOrigin(PdfOrigin.PdfOriginTopLeft)
gdpicturePDF.SetMeasurementUnit(PdfMeasurementUnit.PdfMeasurementUnitMillimeter)
gdpicturePDF.SetLineWidth(1)
Dim fontResName = gdpicturePDF.AddStandardFont(PdfStandardFont.PdfStandardFontHelvetica)
Dim fontResNameBold = gdpicturePDF.AddStandardFont(PdfStandardFont.PdfStandardFontHelveticaBold)
Dim fontResNameItalic = gdpicturePDF.AddStandardFont(PdfStandardFont.PdfStandardFontHelveticaBoldOblique)
gdpicturePDF.SetTitle("xInvoice VisualReceipt")
gdpicturePDF.SetAuthor("Digital Data GmbH, Heuchelheim")
'Create a New page
gdpicturePDF.NewPage(PdfPageSizes.PdfPageSizeA4)
'Draw content on the PDF
Dim yPosition As Integer = 20
gdpicturePDF.SetTextSize(18)
gdpicturePDF.DrawText(fontResName, 10, yPosition, "xRechnung Sichtbeleg - xInvoice Visual Receipt")
yPosition += 10
gdpicturePDF.SetTextSize(10)
gdpicturePDF.DrawText(fontResNameItalic, 10, yPosition, XRechnungStrings.CommentSichtbeleg_DE_Row1)
yPosition += 5
gdpicturePDF.DrawText(fontResNameItalic, 10, yPosition, XRechnungStrings.CommentSichtbeleg_DE_Row2)
yPosition += 5
gdpicturePDF.DrawText(fontResNameItalic, 10, yPosition, XRechnungStrings.CommentSichtbeleg_EN_Row1)
yPosition += 5
gdpicturePDF.DrawText(fontResNameItalic, 10, yPosition, XRechnungStrings.CommentSichtbeleg_EN_Row2)
Dim oArea As String = ""
Dim oIsPosition As Boolean = False
Dim oPosCount = 0
Dim oPosTerm As String = ""
Dim oCurrencySymbol = ""
yPosition += 5
Dim oIndex As Integer = 0
For Each oRow As DataRow In pDTItemValues.Rows
Dim Y_eq_lastrow As Boolean = CBool(oRow.Item("Y_eq_lastrow"))
Dim oRowCaption As String = oRow.Item("Row_Caption")
Dim oItemSPECNAME As String = oRow.Item("SPEC_NAME")
Dim oItemValue As String = oRow.Item("ITEM_VALUE")
Dim oDisplay As Boolean = oRow.Item("Display")
Dim oRowGUID As String = oRow.Item("GUID")
Dim oAreaSwitch As Boolean = False
_logger.Debug($"Working on SPEC_NAME: {oItemSPECNAME}")
If oArea <> oRow.Item("Area") Then
'########## AREA WECHSEL ###########
oAreaSwitch = True
oArea = oRow.Item("Area")
Dim oAREACaption As String
If oArea = "TYPE" Then
oAREACaption = $"{Return_InvType(oItemValue)} [{oItemValue}]"
ElseIf oArea = "SELLER" Then
oAREACaption = "Verkäufer / Seller:"
ElseIf oArea = "BUYER" Then
oAREACaption = "Käufer / Buyer:"
ElseIf oArea = "POSITION" Then
oAREACaption = "Positionen / Positions:"
oIsPosition = True
ElseIf oArea = "AMOUNT" Then
oAREACaption = "Steuern / Taxes:"
ElseIf oArea = "PAYMENT" Then
oAREACaption = "Zahlungsinformationen / Payment details:"
Else
oAREACaption = String.Empty
End If
If Not oAREACaption = String.Empty Then
'erste Area-Linie
yPosition += 8
gdpicturePDF.DrawLine(10, yPosition, 125, yPosition)
'gdpicturePDF.DrawText(fontResName, 10, yPosition, XRechnungStrings.Seperator_Line)
yPosition += 5
'Area caption
gdpicturePDF.DrawText(fontResNameBold, 10, yPosition, oAREACaption)
yPosition += 5
If oArea = "TYPE" Then
gdpicturePDF.DrawLine(10, yPosition, 125, yPosition)
' gdpicturePDF.DrawText(fontResName, 10, yPosition, XRechnungStrings.Seperator_Line)
yPosition += 5
End If
End If
If oArea = "TYPE" Then
If oItemSPECNAME = "INVOICE_CURRENCY" Then
If oItemValue <> "EUR" Then
oCurrencySymbol = oItemValue
End If
End If
End If
If oArea = "POSITION" Then
oIsPosition = True
If oItemSPECNAME = "INVOICE_POSITION_AMOUNT" Then
oPosCount += 1
oPosTerm = $"{oPosCount}. {oItemValue} * "
End If
End If
Else
'INDIVIDUELLES VERHALTEN BEI Folge-ITEMS
If oArea = "POSITION" Then
oIsPosition = True
If oItemSPECNAME = "INVOICE_POSITION_AMOUNT" Then
oPosCount += 1
oPosTerm = $"{oPosCount}. {oItemValue} * "
ElseIf oItemSPECNAME = "INVOICE_POSITION_ARTICLE" Then
oPosTerm += $" {oItemValue}"
ElseIf oItemSPECNAME = "INVOICE_TAXPOS_TAX_RATE" Or oItemSPECNAME = "INVOICE_TAXPOS_RATE" Then
oPosTerm += $" - ({oItemValue} %)"
End If
oItemValue = oPosTerm
If oPosCount >= 9 Then
oDisplay = False
End If
ElseIf oArea = "AMOUNT" Then
If oItemSPECNAME = "INVOICE_TOTAL_NET" Or oItemSPECNAME = "INVOICE_TOTAL_TAX" Then
oItemValue += $" {oCurrencySymbol}"
End If
ElseIf oArea = "HEAD" Then
If oItemSPECNAME = "INVOICE_DATE" Or oItemSPECNAME = "INVOICE_SERVICE_DATE" Then
Dim oDateString As String = oItemValue
Dim oParsedDate As DateTime = DateTime.ParseExact(oDateString, "yyyyMMdd", System.Globalization.CultureInfo.InvariantCulture)
oItemValue = oParsedDate.ToString("dd.MM.yyyy")
End If
End If
End If
If oDisplay = True Then
If Y_eq_lastrow = False And oAreaSwitch = False Then
yPosition += 5
End If
If oRowCaption <> String.Empty Then
gdpicturePDF.DrawText(fontResName, 10, yPosition, oRowCaption)
gdpicturePDF.DrawText(fontResName, 70, yPosition, oItemValue)
Else
If Y_eq_lastrow = True Then
If oIsPosition = True And oPosCount = 9 Then
gdpicturePDF.DrawText(fontResName, 10, yPosition, "...es gibt noch mehr Positionen, diese werden aber aus Layoutgründen nicht dargestellt.")
gdpicturePDF.DrawText(fontResName, 10, yPosition, "...There are more positions, but these are not shown for layout reasons.")
Else
gdpicturePDF.DrawText(fontResName, oRow.Item("xPosition"), yPosition, oItemValue)
End If
Else
gdpicturePDF.DrawText(fontResName, 10, yPosition, oItemValue)
End If
End If
End If
oIndex += 1
Next
Dim oCreated = Now.ToString
gdpicturePDF.DrawLine(10, 280, 200, 280)
'gdpicturePDF.DrawText(fontResName, 10, 285, XRechnungStrings.Seperator_Line)
Dim oCreatedString = $"Maschinell erstellt durch/Automatically created by Digital Data E-Rechnung Parser: {oCreated}"
gdpicturePDF.DrawText(fontResName, 10, 285, oCreatedString)
Dim oeinv_Format As PdfInvoiceDataFormat = PdfInvoiceDataFormat.ZUGFeRD_2_0
gdpicturePDF.EmbedFile(oTempFilePath, "Rechnungsdaten im ZUGFeRD-XML-Format")
'Finalize And save the PDF
ostatus = gdpicturePDF.SaveToFile(oOutputPath)
If ostatus = GdPictureStatus.OK Then
_logger.Info("PDF VisualReceipt generated successfully!")
Else
_logger.Warn($"Error generating PDF VisualReceipt: {ostatus}")
End If
'Release resources
gdpicturePDF.CloseDocument()
If ostatus = GdPictureStatus.OK Then
File.Delete(oXRechnungFile)
oNewFileinfo = New FileInfo(oOutputPath)
Return oNewFileinfo
Else
Return Nothing
End If
Catch ex As Exception
_logger.Error(ex)
Return Nothing
End Try
End Function
Private Function Return_InvType(pType As String) As String
Dim oReturn As String = "Rechnung/invoice"
If pType = "380" Then
oReturn = "Handelsrechnung/Commercial invoice"
ElseIf pType = "381" Then
oReturn = "Gutschriftanzeige/Credit advice"
ElseIf pType = "384" Then
oReturn = "Rechnungskorrektur/Invoice correction"
ElseIf pType = "386" Then
oReturn = "Vorauszahlungsrechnung/Prepayment invoice"
ElseIf pType = "326" Then
oReturn = "Teilrechnung/Partial invoice"
ElseIf pType = "84" Then
oReturn = "Gutschrift/Credit note"
ElseIf pType = "389" Then
oReturn = "Gutschriftsverfahren/Credit note procedure"
End If
Return oReturn
End Function
End Class

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FirebirdSql.Data.FirebirdClient" version="7.5.0" targetFramework="net461" />
<package id="GdPicture" version="14.2.90" targetFramework="net462" />
<package id="GdPicture.runtimes.windows" version="14.2.90" targetFramework="net462" />
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net461" />
<package id="NLog" version="5.0.5" targetFramework="net461" />
</packages>