diff --git a/.gitignore b/.gitignore index b9d6bd9..4cd339b 100644 --- a/.gitignore +++ b/.gitignore @@ -130,7 +130,7 @@ publish/ # NuGet Packages Directory ## TODO: If you have NuGet Package Restore enabled, uncomment the next line -#packages/ +packages/ # Windows Azure Build Output csx @@ -213,3 +213,6 @@ pip-log.txt #Mr Developer .mr.developer.cfg + + +.vs/ \ No newline at end of file diff --git a/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj b/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj index af4c473..2b5ed86 100644 --- a/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj +++ b/Ghostscript.NET.DisplayTest/Ghostscript.NET.DisplayTest.csproj @@ -1,133 +1,30 @@ - - + - Debug + net6.0-windows x86 - 8.0.30703 - 2.0 - {3509F0F7-A7AD-4FEE-B388-AA817F3413E9} WinExe - Properties - Ghostscript.NET.DisplayTest - Ghostscript.NET.DisplayTest - v4.0 - - - 512 - - - - - - - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + + + + + false + true + true - true bin\x64\Debug\ - DEBUG;TRACE - full - AnyCPU - prompt true true bin\x64\Release\ - TRACE - true - pdbonly - AnyCPU - prompt true true - - - - - - - - - - Form - - - FMain.cs - - - Form - - - FPreview.cs - - - - - FMain.cs - - - FPreview.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - {8BDBDEEC-CAB1-4C0B-86C2-7B0D0D3FE363} - Ghostscript.NET - + - - - \ No newline at end of file diff --git a/Ghostscript.NET.DisplayTest/Properties/AssemblyInfo.cs b/Ghostscript.NET.DisplayTest/Properties/AssemblyInfo.cs deleted file mode 100644 index bb7f9a4..0000000 --- a/Ghostscript.NET.DisplayTest/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Ghostscript.NET.DisplayTest")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Habjan")] -[assembly: AssemblyProduct("Ghostscript.NET.DisplayTest")] -[assembly: AssemblyCopyright("Copyright © 2013-2021 Josip Habjan (habjan@gmail.com)")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("6655d0b4-fdcb-4dd2-869f-82ed57d92951")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.3")] -[assembly: AssemblyFileVersion("1.2.3")] diff --git a/Ghostscript.NET.DisplayTest/Properties/Resources.Designer.cs b/Ghostscript.NET.DisplayTest/Properties/Resources.Designer.cs index 6339ff3..fcf8bfd 100644 --- a/Ghostscript.NET.DisplayTest/Properties/Resources.Designer.cs +++ b/Ghostscript.NET.DisplayTest/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -13,13 +13,13 @@ namespace Ghostscript.NET.DisplayTest.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,7 +33,7 @@ internal Resources() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ internal Resources() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ internal Resources() { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap ghostscript_dotnet { get { diff --git a/Ghostscript.NET.DisplayTest/Properties/Settings.Designer.cs b/Ghostscript.NET.DisplayTest/Properties/Settings.Designer.cs index 27ef5da..67c2c32 100644 --- a/Ghostscript.NET.DisplayTest/Properties/Settings.Designer.cs +++ b/Ghostscript.NET.DisplayTest/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace Ghostscript.NET.DisplayTest.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/Ghostscript.NET.DisplayTest/app.config b/Ghostscript.NET.DisplayTest/app.config index fcd0c93..f9833da 100644 --- a/Ghostscript.NET.DisplayTest/app.config +++ b/Ghostscript.NET.DisplayTest/app.config @@ -1,3 +1,12 @@ - + - + + + + + + + + + + diff --git a/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj b/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj index 953e0dd..33842bb 100644 --- a/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj +++ b/Ghostscript.NET.Samples/Ghostscript.NET.Samples.csproj @@ -1,111 +1,49 @@ - - + - Debug + net6.0 x86 - 8.0.30703 - 2.0 - {4C7B5A1E-2172-48A8-8139-5CB7A3D6065F} Exe - Properties - Ghostscript.NET.Samples - Ghostscript.NET.Samples - v4.0 - - - 512 - - - - - - - - + + + + + false + Ghostscript.NET.Samples + Habjan + Ghostscript.NET.Samples + Copyright © 2013-2021 Josip Habjan %28habjan%40gmail.com%29 + 1.2.3 + 1.2.3 x64 - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - true bin\x64\Debug\ - DEBUG;TRACE - full - AnyCPU - prompt true true - false bin\x64\Release\ - TRACE - true - pdbonly - AnyCPU - prompt true true - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {8BDBDEEC-CAB1-4C0B-86C2-7B0D0D3FE363} - Ghostscript.NET - + - + + + + + + + + + + + + + - - \ No newline at end of file diff --git a/Ghostscript.NET.Samples/Program.cs b/Ghostscript.NET.Samples/Program.cs index b78352e..ce2dbe7 100644 --- a/Ghostscript.NET.Samples/Program.cs +++ b/Ghostscript.NET.Samples/Program.cs @@ -26,40 +26,37 @@ using System; using System.Collections.Generic; -using Ghostscript.NET.Viewer; +using Ghostscript.NET; +using Ghostscript.NET.Samples; -namespace Ghostscript.NET.Samples -{ - class Program - { - static void Main(string[] args) - { - Console.WriteLine("Ghostscript.NET Samples"); - - if (!GhostscriptVersionInfo.IsGhostscriptInstalled) - { - throw new Exception("You don't have Ghostscript installed on this machine!"); - } +Console.WriteLine("Ghostscript.NET Samples"); - ISample sample; - - //sample = new GetInkCoverageSample(); - //sample = new ProcessorSample1(); - //sample = new ProcessorSample2(); - //sample = new FindInstalledGhostscriptVersionsSample(); - //sample = new RunMultipleInstancesSample(); - //sample = new ViewerSample(); - sample = new RasterizerSample1(); - //sample = new RasterizerSample2(); - //sample = new AddWatermarkSample(); - //sample = new DeviceUsageSample(); - //sample = new PipedOutputSample(); - //sample = new SendToPrinterSample(); - //sample = new RasterizerCropSample(); +if (!GhostscriptVersionInfo.IsGhostscriptInstalled) +{ + throw new Exception("You don't have Ghostscript installed on this machine!"); +} - sample.Start(); +List samples = new() +{ + //new GetInkCoverageSample(), + //new ProcessorSample1(), + //new ProcessorSample2(), + //new FindInstalledGhostscriptVersionsSample(), + //new RunMultipleInstancesSample(), + //new ViewerSample(), + //new RasterizerSample1(), + //new RasterizerSample2(), + //new AddWatermarkSample(), + //new DeviceUsageSample(), + //new PipedOutputSample(), + //new SendToPrinterSample(), + new FacturXWriteSample() +}; - Console.ReadLine(); - } - } +foreach (ISample sample in samples) +{ + sample.Start(); + Console.WriteLine($"Sample '{sample.GetType().Name}' run successful!"); } + +Console.ReadLine(); diff --git a/Ghostscript.NET.Samples/Properties/AssemblyInfo.cs b/Ghostscript.NET.Samples/Properties/AssemblyInfo.cs index 4a5c532..02fd22f 100644 --- a/Ghostscript.NET.Samples/Properties/AssemblyInfo.cs +++ b/Ghostscript.NET.Samples/Properties/AssemblyInfo.cs @@ -1,16 +1,6 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Ghostscript.NET.Samples")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Habjan")] -[assembly: AssemblyProduct("Ghostscript.NET.Samples")] -[assembly: AssemblyCopyright("Copyright © 2013-2021 Josip Habjan (habjan@gmail.com)")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -21,16 +11,3 @@ // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("a9c22027-b799-4221-b8e0-58a94add72a6")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.3")] -[assembly: AssemblyFileVersion("1.2.3")] diff --git a/Ghostscript.NET.Samples/Samples/FacturXWriteSample.cs b/Ghostscript.NET.Samples/Samples/FacturXWriteSample.cs new file mode 100644 index 0000000..44adbdd --- /dev/null +++ b/Ghostscript.NET.Samples/Samples/FacturXWriteSample.cs @@ -0,0 +1,59 @@ +// +// AddWatermarkSample.cs +// This file is part of Ghostscript.NET.Samples project +// +// Author: Josip Habjan (habjan@gmail.com, http://www.linkedin.com/in/habjan) +// Copyright (c) 2013-2016 by Josip Habjan. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using Ghostscript.NET; +using Ghostscript.NET.Processor; +using System.IO; +using java.math; +using Ghostscript.NET.FacturX.ZUGFeRD; + + +namespace Ghostscript.NET.Samples +{ + public class FacturXWriteSample : ISample + { + + + public void Start() + { + + Invoice i = (new Invoice()).setDueDate(DateTime.Now).setIssueDate(DateTime.Now).setDeliveryDate(DateTime.Now).setSender((new TradeParty("Test company", "teststr", "55232", "teststadt", "DE")).addTaxID("DE4711").addVATID("DE0815").setContact(new Contact("Hans Test", "+49123456789", "test@example.org")).addBankDetails(new BankDetails("DE12500105170648489890", "COBADEFXXX"))).setRecipient(new TradeParty("Franz Müller", "teststr.12", "55232", "Entenhausen", "DE")).setReferenceNumber("991-01484-64").setNumber("123"). + addItem(new Item(new Product("Testprodukt", "", "C62", new BigDecimal(19)), new BigDecimal("1.0"), new BigDecimal("1.0"))); + + ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider(); + zf2p.setProfile(Profiles.getByName("XRechnung")); + zf2p.generateXML(i); + System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); + + string outfilename = "xrechnung.xml"; + File.WriteAllBytes(outfilename, zf2p.getXML()); + } + + } +} diff --git a/Ghostscript.NET.Samples/app.config b/Ghostscript.NET.Samples/app.config index fcd0c93..75c9e95 100644 --- a/Ghostscript.NET.Samples/app.config +++ b/Ghostscript.NET.Samples/app.config @@ -1,3 +1,16 @@ - + - + + + + + + + + + + + + + + diff --git a/Ghostscript.NET.VS2019.sln b/Ghostscript.NET.VS2019.sln index 85564f9..14369e8 100644 --- a/Ghostscript.NET.VS2019.sln +++ b/Ghostscript.NET.VS2019.sln @@ -1,15 +1,15 @@ - + Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.30907.101 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghostscript.NET", "Ghostscript.NET\Ghostscript.NET.csproj", "{8BDBDEEC-CAB1-4C0B-86C2-7B0D0D3FE363}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET", "Ghostscript.NET\Ghostscript.NET.csproj", "{8BDBDEEC-CAB1-4C0B-86C2-7B0D0D3FE363}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghostscript.NET.Samples", "Ghostscript.NET.Samples\Ghostscript.NET.Samples.csproj", "{4C7B5A1E-2172-48A8-8139-5CB7A3D6065F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET.Samples", "Ghostscript.NET.Samples\Ghostscript.NET.Samples.csproj", "{4C7B5A1E-2172-48A8-8139-5CB7A3D6065F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghostscript.NET.DisplayTest", "Ghostscript.NET.DisplayTest\Ghostscript.NET.DisplayTest.csproj", "{3509F0F7-A7AD-4FEE-B388-AA817F3413E9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET.DisplayTest", "Ghostscript.NET.DisplayTest\Ghostscript.NET.DisplayTest.csproj", "{3509F0F7-A7AD-4FEE-B388-AA817F3413E9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ghostscript.NET.Viewer", "Ghostscript.NET.Viewer\Ghostscript.NET.Viewer.csproj", "{C099EB3A-B4D7-4379-AFAB-4FCD4DF4F003}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET.Viewer", "Ghostscript.NET.Viewer\Ghostscript.NET.Viewer.csproj", "{C099EB3A-B4D7-4379-AFAB-4FCD4DF4F003}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{3AA07E8A-8E52-4E60-A6BB-A5991B5F829F}" ProjectSection(SolutionItems) = preProject diff --git a/Ghostscript.NET.VS2022.sln b/Ghostscript.NET.VS2022.sln new file mode 100644 index 0000000..e4ae929 --- /dev/null +++ b/Ghostscript.NET.VS2022.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34928.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET", "Ghostscript.NET\Ghostscript.NET.csproj", "{C3553CA6-33AF-4137-A5C2-73D57A8DAF43}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET.DisplayTest", "Ghostscript.NET.DisplayTest\Ghostscript.NET.DisplayTest.csproj", "{FDB623A5-8362-47BA-9145-781B574962DA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET.Samples", "Ghostscript.NET.Samples\Ghostscript.NET.Samples.csproj", "{749F1BE2-A1BE-4C89-B94B-A2F1E38E03EB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ghostscript.NET.Viewer", "Ghostscript.NET.Viewer\Ghostscript.NET.Viewer.csproj", "{194189A8-3558-4D92-9573-01BCAF85912F}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C3553CA6-33AF-4137-A5C2-73D57A8DAF43}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3553CA6-33AF-4137-A5C2-73D57A8DAF43}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3553CA6-33AF-4137-A5C2-73D57A8DAF43}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3553CA6-33AF-4137-A5C2-73D57A8DAF43}.Release|Any CPU.Build.0 = Release|Any CPU + {FDB623A5-8362-47BA-9145-781B574962DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDB623A5-8362-47BA-9145-781B574962DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDB623A5-8362-47BA-9145-781B574962DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDB623A5-8362-47BA-9145-781B574962DA}.Release|Any CPU.Build.0 = Release|Any CPU + {749F1BE2-A1BE-4C89-B94B-A2F1E38E03EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {749F1BE2-A1BE-4C89-B94B-A2F1E38E03EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {749F1BE2-A1BE-4C89-B94B-A2F1E38E03EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {749F1BE2-A1BE-4C89-B94B-A2F1E38E03EB}.Release|Any CPU.Build.0 = Release|Any CPU + {194189A8-3558-4D92-9573-01BCAF85912F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {194189A8-3558-4D92-9573-01BCAF85912F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {194189A8-3558-4D92-9573-01BCAF85912F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {194189A8-3558-4D92-9573-01BCAF85912F}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {51B9DE2F-D521-41F2-9AC0-DB8F8587A599} + EndGlobalSection +EndGlobal diff --git a/Ghostscript.NET.Viewer/Ghostscript.NET.Viewer.csproj b/Ghostscript.NET.Viewer/Ghostscript.NET.Viewer.csproj index ff849d0..a170316 100644 --- a/Ghostscript.NET.Viewer/Ghostscript.NET.Viewer.csproj +++ b/Ghostscript.NET.Viewer/Ghostscript.NET.Viewer.csproj @@ -1,101 +1,19 @@ - - + - Debug + net6.0-windows x86 - 8.0.30703 - 2.0 - {C099EB3A-B4D7-4379-AFAB-4FCD4DF4F003} WinExe - Properties - Ghostscript.NET.Viewer - Ghostscript.NET.Viewer - v4.0 - - - 512 - - - - - - - - - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + + + + + false + true + true _res\Ghostscript.NET.Viewer.Icon.ico - - - - - - - - - - - Form - - - FDebug.cs - - - Form - - - FMain.cs - - - - - - FDebug.cs - - - FMain.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - @@ -108,17 +26,6 @@ - - {8BDBDEEC-CAB1-4C0B-86C2-7B0D0D3FE363} - Ghostscript.NET - + - - \ No newline at end of file diff --git a/Ghostscript.NET.Viewer/Properties/AssemblyInfo.cs b/Ghostscript.NET.Viewer/Properties/AssemblyInfo.cs deleted file mode 100644 index cf8bbe0..0000000 --- a/Ghostscript.NET.Viewer/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Ghostscript.NET.Viewer")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Habjan")] -[assembly: AssemblyProduct("Ghostscript.NET.Viewer")] -[assembly: AssemblyCopyright("Copyright © 2013-2021 Josip Habjan (habjan@gmail.com)")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("49a5f948-aef2-46cf-a79e-e7c68e5f114b")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.2.3")] -[assembly: AssemblyFileVersion("1.2.3")] diff --git a/Ghostscript.NET.Viewer/Properties/Resources.Designer.cs b/Ghostscript.NET.Viewer/Properties/Resources.Designer.cs index d8e3c1e..8bfcc9a 100644 --- a/Ghostscript.NET.Viewer/Properties/Resources.Designer.cs +++ b/Ghostscript.NET.Viewer/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -13,13 +13,13 @@ namespace Ghostscript.NET.Viewer.Properties { /// - /// A strongly-typed resource class, for looking up localized strings, etc. + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,7 +33,7 @@ internal Resources() { } /// - /// Returns the cached ResourceManager instance used by this class. + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ internal Resources() { } /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -61,7 +61,7 @@ internal Resources() { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap ghostscript_dotnet { get { @@ -71,7 +71,7 @@ internal static System.Drawing.Bitmap ghostscript_dotnet { } /// - /// Looks up a localized resource of type System.Drawing.Icon similar to (Icon). + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol). /// internal static System.Drawing.Icon Ghostscript_NET_Viewer_Icon { get { @@ -81,7 +81,7 @@ internal static System.Drawing.Icon Ghostscript_NET_Viewer_Icon { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tb_first { get { @@ -91,7 +91,7 @@ internal static System.Drawing.Bitmap tb_first { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tb_last { get { @@ -101,7 +101,7 @@ internal static System.Drawing.Bitmap tb_last { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tb_next { get { @@ -111,7 +111,7 @@ internal static System.Drawing.Bitmap tb_next { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tb_previous { get { @@ -121,7 +121,7 @@ internal static System.Drawing.Bitmap tb_previous { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tb_zoom_in { get { @@ -131,7 +131,7 @@ internal static System.Drawing.Bitmap tb_zoom_in { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tb_zoom_out { get { @@ -141,7 +141,7 @@ internal static System.Drawing.Bitmap tb_zoom_out { } /// - /// Looks up a localized resource of type System.Drawing.Bitmap. + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. /// internal static System.Drawing.Bitmap tool_background { get { diff --git a/Ghostscript.NET.Viewer/Properties/Settings.Designer.cs b/Ghostscript.NET.Viewer/Properties/Settings.Designer.cs index 778bc27..b802c2f 100644 --- a/Ghostscript.NET.Viewer/Properties/Settings.Designer.cs +++ b/Ghostscript.NET.Viewer/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.18408 +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace Ghostscript.NET.Viewer.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "12.0.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.9.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/Ghostscript.NET.Viewer/app.config b/Ghostscript.NET.Viewer/app.config index fcd0c93..f9833da 100644 --- a/Ghostscript.NET.Viewer/app.config +++ b/Ghostscript.NET.Viewer/app.config @@ -1,3 +1,12 @@ - + - + + + + + + + + + + diff --git a/Ghostscript.NET/FacturX/PDFConverter.cs b/Ghostscript.NET/FacturX/PDFConverter.cs new file mode 100644 index 0000000..571072e --- /dev/null +++ b/Ghostscript.NET/FacturX/PDFConverter.cs @@ -0,0 +1,509 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Security; +using System.Text; +using System.Threading.Tasks; +using Microsoft.VisualBasic; +using Ghostscript.NET; +using Ghostscript.NET.Processor; +using Microsoft.Extensions.FileProviders.Embedded; +using Microsoft.Extensions.FileProviders; + +using Ghostscript.NET.FacturX.ZUGFeRD; +/// + +/// ''' Klasse um per Ghostscript.net/Ghostscript beliebige PDFs in PDF/A-3 Dateien zu konvertieren + +/// ''' + +/// ''' +namespace Ghostscript.NET.FacturX +{ + public class PDFConverter + { + private string? file_GSDLL_DLL = null; + private readonly string? file_AdobeRGB1998_ICC = null; + private readonly string? file_BIGSCRIPT_PS = null; + + private readonly string resourceDir = Path.GetTempPath(); + private GhostscriptVersionInfo? gsVersion = null; + + protected string mPDFInFile = ""; // 08.06.20 + protected string mPDFOutFile = ""; + protected string? mXMLOutFile = null; + protected string FXVersion = "1.0"; + protected Profile usedProfile = Profiles.getByName("EN16931"); + + + /// + /// ''' Konstruktor mit Angabe Datenbankdatei, intern-nummer, KlassenID (und Gruppenpositionen) wenn ZUGFeRD geschrieben werden soll + /// ''' + /// ''' PDF-Eingabedatei + /// ''' PDF-A/3 Ausgabedatei + public PDFConverter(string pPDFInFile, string pPDFOutFile) + { + file_AdobeRGB1998_ICC = this.resourceDir + "\\AdobeCompat-v2.icc"; + file_BIGSCRIPT_PS = this.resourceDir + "\\pdfconvert.ps"; + + mPDFInFile = pPDFInFile; + mPDFOutFile = pPDFOutFile; + } + public PDFConverter setFXVersion(string pZFVersion) { + FXVersion = pZFVersion; + + return this; + } + public PDFConverter setFXProfile(Profile p) { + usedProfile = p; + + return this; + } + + + /// + /// ''' Erlaubt die Angabe einer einzubettenden XML-Datei. Die Ausgabe wird dann inkl. RDF-Metadaten und PDF/A-Schema Extension zur ZUGFeRD-Datei in der in + /// ''' pZFVersion angegebenen Version (2p0 fr 2.0, 2.0.1 sowie 2.1, 2.1.1) + /// ''' + /// ''' + /// ''' + public void EmbedXMLForZF(string pXMLOutFile, string pZFVersion) + { + mXMLOutFile = pXMLOutFile; + } + + + + public void prepareICC() + { + var embeddedProvider = new EmbeddedFileProvider(Assembly.GetExecutingAssembly()); + using (var reader = embeddedProvider.GetFileInfo("assets\\AdobeRGB1998.icc").CreateReadStream()) + { + byte[] data = new BinaryReader(reader).ReadBytes((int)reader.Length); + string tempfilename = Path.GetTempPath() + "AdobeRGB1998.icc"; + File.WriteAllBytes(tempfilename, data); + } + } + + + /// + /// ''' Schreibt eine Postscript-, genauer gesagt PDFMark-Datei die von Ghostscript interpretiert werden kann und mindestens in eine PDF-A/3 umwandelt + /// ''' + /// ''' + /// ''' ICC-Farbprofildatei bspw von https://www.adobe.com/support/downloads/iccprofiles/iccprofiles_win.html + /// ''' + protected void WritePDFMark(string pEmbeddedAdobeRGB1998ICCFile) + { + string EscapedEmbeddedXMLFile = ""; + + if (mXMLOutFile != null) + { + if (!File.Exists(mXMLOutFile)) + { + throw new Exception("Datei " + mXMLOutFile + " existiert nicht"); + } + EscapedEmbeddedXMLFile = mXMLOutFile.Replace(@"\", @"\\"); // in PDFMark werden \ zu \\ gequoted + } + + + + if (!File.Exists(pEmbeddedAdobeRGB1998ICCFile)) + { + throw new Exception("Datei " + file_AdobeRGB1998_ICC + " existiert nicht"); + } + /* if (!pEmbeddedAdobeRGB1998ICCFile.Contains(Directory.GetCurrentDirectory())) + { + throw new Exception("Datei " + file_AdobeRGB1998_ICC + " muss unterhalb des absolut angegebenen Applikationspfades " + Directory.GetCurrentDirectory() + " liegen."); + } + */ + string EscapedEmbeddedICCFile = file_AdobeRGB1998_ICC.Replace(Directory.GetCurrentDirectory(), @".\").Replace(@"\", @"\\"); + + if (mPDFInFile == mPDFOutFile) + { + throw new Exception("Eingabedatei darf nicht Ausgabedatei sein"); + } + + string pdfMarkA3 = @"%! + +%Title + +[ /Title (Mustangproject.org .net) + /DOCINFO pdfmark + +% Define entries in the document Info dictionary : +/ICCProfile (" + EscapedEmbeddedICCFile + @") % Customise +def + +% Define an ICC profile : + +[/_objdef {icc_PDFA} /type /stream /OBJ pdfmark +[{icc_PDFA} +<< + /N currentpagedevice /ProcessColorModel known { + currentpagedevice /ProcessColorModel get dup /DeviceGray eq + {pop 1} { + /DeviceRGB eq + {3}{4} ifelse + } ifelse + } { + (ERROR, unable to determine ProcessColorModel) == flush + } ifelse +>> /PUT pdfmark + +[{icc_PDFA} ICCProfile (r) file /PUT pdfmark + +% Define the output intent dictionary : + +[/_objdef {OutputIntent_PDFA} /type /dict /OBJ pdfmark +[{OutputIntent_PDFA} << + /Type /OutputIntent % Must be so (the standard requires). + /S /GTS_PDFA1 % Must be so (the standard requires). + /DestOutputProfile {icc_PDFA} % Must be so (see above). + /OutputConditionIdentifier (sRGB) % Customize +>> /PUT pdfmark + +[{Catalog} <> /PUT pdfmark +"; + + string PDFmark = pdfMarkA3; + if (mXMLOutFile != null) + { + // Dim myFile As New FileInfo(mXMLOutFile) + // Dim sizeInBytes As Long = myFile.Length + FileInfo fi = new FileInfo(mXMLOutFile); + long sizeInBytes = fi.Length; + + string rdfFXProfile = "EN 16931"; + + string pfdMarkZugferd = @" + +% istring SimpleUTF16BE ostring +/SimpleUTF16BE +{ + dup length + 1 add + 2 mul + string + + % istring ostring + dup 0 16#FE put + dup 1 16#FF put + 2 + 3 -1 roll + + % ostring index istring + { + % ostring index ichar + 3 1 roll + % ichar ostring index + 2 copy 16#00 put + 1 add + 2 copy + 5 -1 roll + % ostring index ostring index ichar + put + 1 add + % ostring index + } + forall + + % ostring index + pop +} +bind def + +/XmlFileName (factur-x.xml) def +/XmlFileDesc (invoice) def +/XmlFileDate (D:" + DateTime.Now.ToString("yyyyMMddHHmmssK").Replace(":", "'") + @"') def +/XmlFileData (" + EscapedEmbeddedXMLFile + @") (r) file def + + + + % Object {ContentStream} anlegen und befllen + [ + /_objdef {ContentStream} + /type /stream + /OBJ pdfmark + + [ + {ContentStream} << + /Type /EmbeddedFile + /Subtype (text/xml) cvn + /Params << + /ModDate XmlFileDate + /Size " + sizeInBytes + @" + >> + >> + /PUT pdfmark + + [ + {ContentStream} XmlFileData + /PUT pdfmark + + [ + {ContentStream} + /CLOSE pdfmark + + % Object {FSDict} fr File Specification anlegen und befllen + [ + /_objdef {FSDict} + /type /dict + /OBJ pdfmark + + [ + {FSDict} << + /Type /FileSpec + /F XmlFileName + /UF XmlFileName SimpleUTF16BE + /Desc XmlFileDesc + /AFRelationship /Alternative + /EF << + /F {ContentStream} + /UF {ContentStream} + >> + >> + /PUT pdfmark + + % Object {AFArray} fr Associated Files anlegen und befllen + [ + /_objdef {AFArray} + /type /array + /OBJ pdfmark + + [ + {AFArray} {FSDict} + /APPEND pdfmark + + + + % Associated Files im Object {Catalog} eintragen + [ + {Catalog} << + /AF {AFArray} + >> + /PUT pdfmark + + + + % File Specification unter Names/Embedded Files/Names im Object {Catalog} eintragen + [ + /Name XmlFileName + /FS {FSDict} + /EMBED pdfmark + + % Metadata im Object {Catalog} eintragen + [ + /XML ( + + + + + Factur-x PDFA Extension Schema + urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0# + fx + + + + DocumentFileName + Text + external + Name of the embedded XML invoice file + + + DocumentType + Text + external + INVOICE + + + Version + Text + external + The actual version of the ZUGFeRD data + + + ConformanceLevel + Text + external + The conformance level of the ZUGFeRD data + + + + + + + + + + + INVOICE + factur-x.xml + " + FXVersion + @" + " + usedProfile.getXMPName() + @" + + + ) + /Ext_Metadata pdfmark"; + PDFmark += pfdMarkZugferd; + } + + + + UTF8Encoding utf8 = new UTF8Encoding(false); // kein BOM verwenden, s. https://docs.microsoft.com/de-de/dotnet/api/system.text.utf8encoding?view=netcore-3.1 + File.WriteAllBytes(file_BIGSCRIPT_PS, utf8.GetBytes(PDFmark)); + + } + + // + // Prft ob die Ausgabedatei beschrieben werden kann + // + public bool IsFileLocked(FileInfo file) + { + FileStream stream = (FileStream)null; + try + { + stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None); + } + catch (IOException generatedExceptionName) + { + // handle the exception your way + return true; + } + finally + { + if (stream != null) + stream.Close(); + } + return false; + } + + + /// + /// ''' Wandelt eine PDF-Datei (Dateiname in inputfile) in eine PDF A/3 (Outputfilename) um und hngt die aktuelle E-rechnung an + /// ''' + /// ''' True wenn die Konvertierung funktioniert hat + public bool ConvertToPDFA3(String gsdll) + { + + file_GSDLL_DLL = gsdll; + gsVersion = new GhostscriptVersionInfo(file_GSDLL_DLL); + + this.prepareICC(); + + // based on https://github.com/jhabjan/Ghostscript.NET/blob/master/Ghostscript.NET.Samples/Samples/ProcessorSample1.cs + if (!File.Exists(file_GSDLL_DLL)) + { + throw new Exception("Ghostscript DLL " + file_GSDLL_DLL + " bitte ins Verzeichnis " + Directory.GetCurrentDirectory() + " kopieren"); + + } + + if (!File.Exists(file_AdobeRGB1998_ICC)) + { + throw new Exception("Farbpprofile " + file_AdobeRGB1998_ICC + " bitte ins Verzeichnis " + Directory.GetCurrentDirectory() + " kopieren"); + + } + if (!File.Exists(mPDFInFile)) + { + throw new Exception("Eingabedatei " + mPDFInFile + " existiert nicht"); + + } + if (File.Exists(mPDFOutFile)) + { + if (FileSystem.GetAttr(mPDFOutFile) == Constants.vbReadOnly) + { + throw new Exception("Ausgabedatei " + mPDFOutFile + " keine Schreibrechte"); + + + } + FileInfo fi = new FileInfo(mPDFOutFile); + if (IsFileLocked(fi)) + { + throw new Exception("Ausgabedatei " + mPDFOutFile + " nicht beschreibbar (noch geffnet?)"); + + } + } + + // Info: braucht folgende DLLs: + // BouncyCastle.Crypto.dll, Common.Logging.Core.dll, Common.Logging.dll + // und: etliche, weitere der iText*.dll -> vorsichtshalber alle 9 kopiert + /* PdfDocument doc = new PdfDocument(new PdfReader(mPDFInFile)); + PdfAConformanceLevel comLev = doc.GetReader().GetPdfAConformanceLevel(); + if (comLev != null) + { + } + + */ + + + + WritePDFMark(file_AdobeRGB1998_ICC); + + // MsgBox(gsVersion.ToString) + GhostscriptLibrary gsL = null/* TODO Change to default(_) if this is not a reference type */; + // Dim gsL As GhostscriptLibrary = New GhostscriptLibrary(File.ReadAllBytes(ClsCommon.JS.StartupDir & ClsEDocs_Base.FixedValues.FILENAME_ZF_GSDLL32)) + gsL = new GhostscriptLibrary(gsVersion); + GhostscriptPipedOutput gsPipedOutput = new GhostscriptPipedOutput(); + + List switches = new List(); + // works : "C:\Program Files (x86)\gs\gs9.52\bin\gswin32c.exe" -dPDFA=1 -dNOOUTERSAVE -sProcessColorModel=DeviceRGB -sDEVICE=pdfwrite -o RG_10690-pdfa.pdf -dPDFACompatibilityPolicy=1 "C:\Program Files (x86)\gs\gs9.52\lib\PDFA_def.ps" RG_10690.pdf + // "C:\Program Files (x86)\gs\gs9.52\bin\gswin64c.exe" -dPDFA=1 -dNOOUTERSAVE -sProcessColorModel=DeviceRGB -sDEVICE=pdfwrite -o RG_10690-pdfa.pdf -dPDFACompatibilityPolicy=1 "C:\Program Files (x86)\gs\gs9.52\lib\PDFA_def.ps" RG_10690.pdf + switches.Add(""); // ' Der allererste Parameter wird mitunter ignoriert weil EXEs da ihren eigenen Namen bergeben bekommen + switches.Add("-P"); // Zugriff auf Ressourcen unterhalb des aktuellen Verzeichnisses erlauben + switches.Add("-dPDFA=3"); // 'in A/3 umwandeln Teil 1 von 3 + // switches.Add("-dCompressStreams=false") ''hatten mal Probleme weil scheinbar auch die XMP Metadaten von ZUGFeRD komprimiert wurden, das hat sich mittlerweile erledigt + switches.Add("-sColorConversionStrategy=RGB"); // ' muss fr PDF/A angegeben werden + switches.Add("-sDEVICE=pdfwrite"); // ' ein Device muss frs Rastern angegeben werden + switches.Add("-o" + mPDFOutFile); // ' Ausgabedatei + switches.Add("-dPDFACompatibilityPolicy=1"); // 'in A/3 umwandeln Teil 2 von 3 + switches.Add("-dRenderIntent=3"); // 'in A/3 umwandeln Teil 3 von 3 + switches.Add("-sGenericResourceDir=\"" + resourceDir + "/\""); // ' hier kann ein zustzliches Verzeichnis angegeben werden in dem Ressourcen wie die icc-Datei liegen drfen + switches.Add(file_BIGSCRIPT_PS); // ' die PDFMark-Programmdatei die interpretiert werden soll. Anders als die ICC und ggf. einzubettende XML-Datei ist das keine Ressourcendatei und die kann liegen wo sie will. + // siehe https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/pdfmark_reference.pdf + // und https://gitlab.com/crossref/pdfmark + switches.Add(mPDFInFile); // ' PDF-Eingabedatei + + bool success = false; + using (GhostscriptProcessor gsProcessor = new GhostscriptProcessor(gsL)) + { + VerboseMsgBoxOutput stdio = new VerboseMsgBoxOutput(); + // gsProcessor.StartProcessing(switches.ToArray(), stdio) + gsProcessor.StartProcessing(switches.ToArray(), null/* TODO Change to default(_) if this is not a reference type */); + + // (erfolglose) Versuche, das Hngen zu vermeiden... + gsProcessor.Dispose(); + } + success = true; + return success; + } + + // + // Zum Debuggen von Ghostscript ist es manchmal hilfreich, die Ausgabe in MsgBoxes umleiten zu knnen + // Bekannte Fehlercodes -100: Datei nicht gefunden oder nicht beschreibbar + // + public class VerboseMsgBoxOutput : GhostscriptStdIO + { + public VerboseMsgBoxOutput() : base(true, true, true) + { + } + + public override void StdOut(string output) + { + Console.Write("Out:" + output); + } + + public override void StdError(string error) + { + Console.Write("Error:" + error); + } + + public override void StdIn(out string input, int count) + { + input = "debug input"; + } + } + } } diff --git a/Ghostscript.NET/FacturX/XMLTools.cs b/Ghostscript.NET/FacturX/XMLTools.cs new file mode 100644 index 0000000..576f8d8 --- /dev/null +++ b/Ghostscript.NET/FacturX/XMLTools.cs @@ -0,0 +1,107 @@ +using System; +using System.Text; +using java.math; +using System.Security; + +namespace Ghostscript.NET.FacturX +{ + + + + public class XMLTools + { + public virtual string escapeAttributeEntities(string s) + { +// return base.escapeAttributeEntities(s); + return s; + } + + public virtual string escapeElementEntities(string s) + { +// return base.escapeElementEntities(s); + return s; + + } + + + public static string nDigitFormat(BigDecimal value, int scale) + { + /* + * I needed 123,45, locale independent.I tried + * NumberFormat.getCurrencyInstance().format( 12345.6789 ); but that is locale + * specific.I also tried DecimalFormat df = new DecimalFormat( "0,00" ); + * df.setDecimalSeparatorAlwaysShown(true); df.setGroupingUsed(false); + * DecimalFormatSymbols symbols = new DecimalFormatSymbols(); + * symbols.setDecimalSeparator(','); symbols.setGroupingSeparator(' '); + * df.setDecimalFormatSymbols(symbols); + * + * but that would not switch off grouping. Although I liked very much the + * (incomplete) "BNF diagram" in + * http://docs.oracle.com/javase/tutorial/i18n/format/decimalFormat.html in the + * end I decided to calculate myself and take eur+sparator+cents + * + */ + return value.setScale(scale, RoundingMode.HALF_UP).toPlainString(); + + } + + + public static string encodeXML(String s) + { + return SecurityElement.Escape(s); + } + + + /// + /// Returns the Byte Order Mark size and thus allows to skips over a BOM + /// at the beginning of the given ByteArrayInputStream, if one exists. + /// + /// the ByteArrayInputStream used + /// if can not be read from is + /// Autodetection of Character Encodings" + /// + /// public static int guessBOMSize(ByteArrayInputStream is) throws IOException { + /// byte[] pad = new byte[4]; + /// is.read(pad); + /// is.reset(); + /// int test2 = ((pad[0] & 0xFF) << 8) | (pad[1] & 0xFF); + /// int test3 = ((test2 & 0xFFFF) << 8) | (pad[2] & 0xFF); + /// int test4 = ((test3 & 0xFFFFFF) << 8) | (pad[3] & 0xFF); + /// // + /// if (test4 == 0x0000FEFF || test4 == 0xFFFE0000 || test4 == 0x0000FFFE || test4 == 0xFEFF0000) { + /// // UCS-4: BOM takes 4 bytes + /// return 4; + /// } else if (test3 == 0xEFBBFF) { + /// // UTF-8: BOM takes 3 bytes + /// return 3; + /// } else if (test2 == 0xFEFF || test2 == 0xFFFE) { + /// // UTF-16: BOM takes 2 bytes + /// return 2; + /// } + /// return 0; + /// }/> + + /// + ///* + /// removes utf8 byte order marks from byte arrays, in case one is there + /// the CII XML + /// the byte array without bom + public static byte[] removeBOM(byte[] zugferdRaw) + { + byte[] zugferdData; + if ((zugferdRaw[0] == unchecked((byte) 0xEF)) && (zugferdRaw[1] == unchecked((byte) 0xBB)) && (zugferdRaw[2] == unchecked((byte) 0xBF))) + { + // I don't like BOMs, lets remove it + zugferdData = new byte[zugferdRaw.Length - 3]; + Array.Copy(zugferdRaw, 3, zugferdData, 0, zugferdRaw.Length - 3); + } + else + { + zugferdData = zugferdRaw; + } + return zugferdData; + } + + + } +} diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/BankDetails.cs b/Ghostscript.NET/FacturX/ZUGFeRD/BankDetails.cs new file mode 100644 index 0000000..5e276cb --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/BankDetails.cs @@ -0,0 +1,102 @@ +using System; + +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + /// + /// provides e.g. the IBAN to transfer money to :-) + /// + public class BankDetails : IZUGFeRDTradeSettlementPayment + { + protected internal string IBAN, BIC, accountName = null; + + public BankDetails(string IBAN, string BIC) + { + this.IBAN = IBAN; + this.BIC = BIC; + } + + public virtual string getIBAN() + { + return IBAN; + } + + /// + /// Sets the IBAN "ID", which means that it only needs to be a way to uniquely + /// identify the IBAN. Of course you will specify your own IBAN in full length but + /// if you deduct from a customer's account you may e.g. leave out the first or last + /// digits so that nobody spying on the invoice gets to know the complete number + /// the "IBAN ID", i.e. the IBAN or parts of it + /// fluent setter + public virtual BankDetails setIBAN(string IBAN) + { + this.IBAN = IBAN; + return this; + } + + public virtual string getBIC() + { + return BIC; + } + + /// + ///* + /// The bank identifier. Bank name is no longer neccessary in SEPA. + /// the bic code + /// fluent setter + public virtual BankDetails setBIC(string BIC) + { + this.BIC = BIC; + return this; + } + + /// + ///* + /// getOwn... methods will be removed in the future in favor of Tradeparty (e.g. Sender) class + /// + /// + [Obsolete] + public string getOwnBIC() + { + return getBIC(); + } + + [Obsolete] + public string getOwnIBAN() + { + return getIBAN(); + } + + + /// + /// set Holder + /// account name (usually account holder if != sender) + /// fluent setter + public virtual BankDetails setAccountName(string name) + { + accountName = name; + return this; + } + + public string getAccountName() + { + return accountName; + } + public string getSettlementXML() + { + string accountNameStr = ""; + if (getAccountName() != null) + { + accountNameStr = "" + XMLTools.encodeXML(getAccountName()) + "\n"; + + } + + string xml = " \n" + " 58\n" + " SEPA credit transfer\n" + " \n" + " " + XMLTools.encodeXML(getOwnIBAN()) + "\n"; + xml += accountNameStr; + xml += " \n" + " \n" + " " + XMLTools.encodeXML(getOwnBIC()) + "\n" + " \n" + " \n"; + return xml; + } + + + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/Contact.cs b/Ghostscript.NET/FacturX/ZUGFeRD/Contact.cs new file mode 100644 index 0000000..8dfb3f8 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/Contact.cs @@ -0,0 +1,259 @@ +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + using Node = org.w3c.dom.Node; + using NodeList = org.w3c.dom.NodeList; + + /// + ///* + /// a named contact person in an organisation + /// for the organisation/company itsel please + /// + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: @JsonIgnoreProperties(ignoreUnknown = true) public class Contact implements org.mustangproject.ZUGFeRD.IZUGFeRDExportableContact + public class Contact : IZUGFeRDExportableContact + { + + protected internal string name, phone, email, zip, street, location, country; + protected internal string fax = null; + + /// + ///* + /// default constructor. + /// Name, phone and email of sender contact person are e.g. required by XRechnung + /// full name of the contact + /// full phone number + /// email address of the contact + public Contact(string name, string phone, string email) + { + this.name = name; + this.phone = phone; + this.email = email; + } + + /// + ///* + /// empty constructor. + /// as always, not recommended, for jackson... + /// + public Contact() + { + } + + /// + ///* + /// complete specification of a named contact with a different address + /// full name + /// full phone number + /// full email + /// street+number + /// postcode + /// city + /// two-letter iso code + public Contact(string name, string phone, string email, string street, string zip, string location, string country) + { + this.name = name; + this.phone = phone; + this.email = email; + this.street = street; + this.zip = zip; + this.location = location; + this.country = country; + + } + + /// + ///* + /// XML parsing constructor + /// the nodelist returned e.g. from xpath + public Contact(NodeList nodes) + { + if (nodes.getLength() > 0) + { + + /* + will parse sth like + + Name + + 069 100-0 + + + test@example.com + + + */ + for (int nodeIndex = 0; nodeIndex < nodes.getLength(); nodeIndex++) + { + //nodes.item(i).getTextContent())) { + Node currentItemNode = nodes.item(nodeIndex); + if (currentItemNode.getLocalName() != null) + { + + if (currentItemNode.getLocalName().Equals("PersonName")) + { + setName(currentItemNode.getFirstChild().getNodeValue()); + } + if (currentItemNode.getLocalName().Equals("TelephoneUniversalCommunication")) + { + NodeList tel = currentItemNode.getChildNodes(); + for (int telChildIndex = 0; telChildIndex < tel.getLength(); telChildIndex++) + { + if (tel.item(telChildIndex).getLocalName() != null) + { + if (tel.item(telChildIndex).getLocalName().Equals("CompleteNumber")) + { + setPhone(tel.item(telChildIndex).getTextContent()); + } + } + } + } + if (currentItemNode.getLocalName().Equals("EmailURIUniversalCommunication")) + { + NodeList email = currentItemNode.getChildNodes(); + for (int emailChildIndex = 0; emailChildIndex < email.getLength(); emailChildIndex++) + { + if (email.item(emailChildIndex).getLocalName() != null) + { + if (email.item(emailChildIndex).getLocalName().Equals("URIID")) + { + setEMail(email.item(emailChildIndex).getTextContent()); + } + } + } + } + } + } + } + } + + + public string? getName() + { + return name; + } + + /// + /// the first and last name of the contact + /// + /// first and last name + /// fluent setter + public virtual Contact setName(string name) + { + this.name = name; + return this; + } + + public string getPhone() + { + return phone; + } + + /// + ///* + /// complete phone number of the contact + /// the complete phone number + /// fluent setter + public virtual Contact setPhone(string phone) + { + this.phone = phone; + return this; + } + + public string getFax() + { + return fax; + } + + /// + ///* + /// (optional) complete fax number + /// complete fax number of the contact + /// fluent setter + public virtual Contact setFax(string fax) + { + this.fax = fax; + return this; + } + + public virtual string getEMail() + { + return email; + } + + /// + ///* + /// personal email address of the contact person + /// the email address of the contact + /// fluent setter + public virtual Contact setEMail(string email) + { + this.email = email; + return this; + } + + public virtual string getZIP() + { + return zip; + } + + /// + ///* + /// the postcode, if the address is different to the organisation + /// the postcode of the contact + /// fluent setter + public virtual Contact setZIP(string zip) + { + this.zip = zip; + return this; + } + + public string getStreet() + { + return street; + } + + /// + /// street and number, if the address is different to the organisation + /// + /// street and number of the contact + /// fluent setter + public virtual Contact setStreet(string street) + { + this.street = street; + return this; + } + public string getLocation() + { + return location; + } + + /// + ///* + /// city of the contact person, if different from organisation + /// city + /// fluent setter + public virtual Contact setLocation(string location) + { + this.location = location; + return this; + } + + public string getCountry() + { + return country; + } + + /// + ///* + /// two-letter ISO country code of the contact, if different from organisation + /// two-letter iso code + /// fluent setter + public virtual Contact setCountry(string country) + { + this.country = country; + return this; + } + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IExportableTransaction.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IExportableTransaction.cs new file mode 100644 index 0000000..4cec3ff --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IExportableTransaction.cs @@ -0,0 +1,422 @@ +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + public interface IExportableTransaction + { + /** + * appears in /rsm:CrossIndustryDocument/rsm:HeaderExchangedDocument/ram:Name + * + * @return Name of document + */ + String getDocumentName() + { + return "RECHNUNG"; + } + + + /** + * + * + * @return Code number of Document type, e.g. "380" for invoiceF + * String getDocumentCode() { + return DocumentCodeTypeConstants.INVOICE; + }*/ + + + /** + * Number, typically invoice number of the invoice + * + * @return invoice number + */ + String getNumber() + { + return null; + } + + + /** + * the date when the invoice was created + * + * @return when the invoice was created + */ + DateTime? getIssueDate() + { + return null; + } + + + + + /** + * when the invoice is to be paid + * + * @return when the invoice is to be paid + */ + DateTime? getDueDate() + { + return null; + } + + String getContractReferencedDocument() + { + return null; + } + + + /** + * the sender of the invoice + * + * @return the contact person at the supplier side + */ + IZUGFeRDExportableTradeParty getSender() + { + return null; + } + + + /** + * subject of the document e.g. invoice and order + * number as human readable text + * + * @return string with document subject + */ + String getSubjectNote() + { + return null; + } + + /* + IZUGFeRDAllowanceCharge[] getZFAllowances() { + return null; + } + + + IZUGFeRDAllowanceCharge[] getZFCharges() { + return null; + } + + + IZUGFeRDAllowanceCharge[] getZFLogisticsServiceCharges() { + return null; + } + */ + + IZUGFeRDExportableItem[] getZFItems(); + + + /** + * the recipient + * + * @return the recipient of the invoice + */ + IZUGFeRDExportableTradeParty getRecipient(); + + + /** + * the creditors payment informations + * @deprecated use getTradeSettlement + * @return an array of IZUGFeRDTradeSettlementPayment + */ + IZUGFeRDTradeSettlementPayment[]? getTradeSettlementPayment() + { + return null; + } + /** + * the payment information for any payment means + * + * @return an array of IZUGFeRDTradeSettlement + */ + IZUGFeRDTradeSettlement[]? getTradeSettlement() + { + return null; + } + + + /** + * Tax ID (not VAT ID) of the sender + * + * @return Tax ID (not VAT ID) of the sender + */ + String getOwnTaxID() + { + if (getSender() != null) + { + return getSender().getTaxID(); + } + else + { + return null; + } + } + + + /** + * VAT ID (Umsatzsteueridentifikationsnummer) of the sender + * + * @return VAT ID (Umsatzsteueridentifikationsnummer) of the sender + */ + String getOwnVATID() + { + if (getSender() != null) + { + return getSender().getVATID(); + } + else + { + return null; + } + } + + + /** + * supplier identification assigned by the costumer + * + * @return the sender's identification + */ + String getOwnForeignOrganisationID() + { + return null; + } + + + + + /** + * get delivery date + * + * @return the day the goods have been delivered + */ + DateTime? getDeliveryDate(); + + + /** + * get main invoice currency used on the invoice + * + * @return three character currency of this invoice + */ + String getCurrency() + { + return "EUR"; + } + + + /** + * get payment term descriptional text e.g. Bis zum 22.10.2015 ohne Abzug + * + * @return get payment terms + */ + String getPaymentTermDescription() + { + return null; + } + + /** + * get payment terms. if set, getPaymentTermDescription() and getDueDate() are + * ignored + * + * @return the IZUGFeRDPaymentTerms of the invoice + **/ + IZUGFeRDPaymentTerms getPaymentTerms() + { + return null; + } + + /** + * returns if a rebate agreements exists + * + * @return true if a agreement exists + */ + bool rebateAgreementExists() + { + return false; + } + + /** + * get reference document number typically used for Invoice Corrections Will be added as IncludedNote in comfort profile + * + * @return the ID of the document this document refers to + */ + String getReferenceNumber() + { + return null; + } + + + /** + * consignee identification (identification of the organisation the goods are shipped to [assigned by the costumer]) + * + * @return the sender's identification + */ + String getShipToOrganisationID() + { + return null; + } + + + /** + * consignee name (name of the organisation the goods are shipped to) + * + * @return the consignee's organisation name + */ + String getShipToOrganisationName() + { + return null; + } + + + /** + * consignee street address (street of the organisation the goods are shipped to) + * + * @return consignee street address + */ + String getShipToStreet() + { + return null; + } + + + /** + * consignee street postal code (postal code of the organisation the goods are shipped to) + * + * @return consignee postal code + */ + String getShipToZIP() + { + return null; + } + + + /** + * consignee city (city of the organisation the goods are shipped to) + * + * @return the consignee's city + */ + String getShipToLocation() + { + return null; + } + + + /** + * consignee two digit country code (country code of the organisation the goods are shipped to) + * + * @return the consignee's two character country iso code + */ + String getShipToCountry() + { + return null; + } + + + /** + * get the ID of the SellerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement/ApplicableHeaderTradeAgreement + * + * @return the ID of the document + */ + String getSellerOrderReferencedDocumentID() + { + return null; + } + /** + * get the ID of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement + * + * @return the ID of the document + */ + String getBuyerOrderReferencedDocumentID() + { + return null; + } + + /** + * get the ID of the preceding invoice, which is e.g. to be corrected if this is a correction + * + * @return the ID of the document + */ + String getInvoiceReferencedDocumentID() + { + return null; + } + + DateTime? getInvoiceReferencedIssueDate() { return null; } + /** + * get the issue timestamp of the BuyerOrderReferencedDocument, which sits in the ApplicableSupplyChainTradeAgreement + * + * @return the IssueDateTime in format CCYY-MM-DDTHH:MM:SS + */ + String getBuyerOrderReferencedDocumentIssueDateTime() + { + return null; + } + + + /** + * get the TotalPrepaidAmount located in SpecifiedTradeSettlementMonetarySummation (v1) or SpecifiedTradeSettlementHeaderMonetarySummation (v2) + * + * @return the total sum (incl. VAT) of prepayments, i.e. the difference between GrandTotalAmount and DuePayableAmount + */ + BigDecimal getTotalPrepaidAmount() + { + return BigDecimal.ZERO; + } + + + /*** + * delivery address, i.e. ram:ShipToTradeParty (only supported for zf2) + * @return the IZUGFeRDExportableTradeParty delivery address + */ + + IZUGFeRDExportableTradeParty getDeliveryAddress() + { + return null; + } + + + /*** + * specifies the document level delivery period, will be included in a BillingSpecifiedPeriod element + * @return the beginning of the delivery period + */ + DateTime? getDetailedDeliveryPeriodFrom() + { + return null; + } + + /*** + * specifies the document level delivery period, will be included in a BillingSpecifiedPeriod element + * @return the end of the delivery period + */ + DateTime? getDetailedDeliveryPeriodTo() + { + return null; + } + + /** + * get additional referenced documents acccording to BG-24 XRechnung (Rechnungsbegruendende Unterlagen), + * i.e. ram:ApplicableHeaderTradeAgreement/ram:AdditionalReferencedDocument + * + * @return a array of objects from class FileAttachment + + FileAttachment[] getAdditionalReferencedDocuments() { + return null; + } +*/ + + /*** + * additional text description + * @return an array of strings of document wide "includedNotes" (descriptive text values) + */ + String[] getNotes() + { + return null; + } + + String getSpecifiedProcuringProjectName() + { + return null; + } + + String getSpecifiedProcuringProjectID() + { + return null; + } + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableContact.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableContact.cs new file mode 100644 index 0000000..f057cf0 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableContact.cs @@ -0,0 +1,101 @@ +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public interface IZUGFeRDExportableContact + { + + /// + /// customer identification assigned by the seller + /// + /// customer identification + string getID() + { + return null; + } + + + /// + /// First and last name of the recipient + /// + /// First and last name of the recipient + string? getName() + { + return null; + } + + string getPhone() + { + return null; + } + + string getEMail() + { + return null; + } + + string getFax() + { + return null; + } + + + /// + /// Postal code of the recipient + /// + /// Postal code of the recipient + string getZIP() + { + return null; + } + + + /// + /// VAT ID (Umsatzsteueridentifikationsnummer) of the contact + /// + /// VAT ID (Umsatzsteueridentifikationsnummer) of the contact + string getVATID() + { + return null; + } + + + /// + /// two-letter country code of the contact + /// + /// two-letter iso country code of the contact + string getCountry() + { + return null; + } + + + /// + /// Returns the city of the contact + /// + /// Returns the city of the recipient + string getLocation() + { + return null; + } + + + /// + /// Returns the street address (street+number) of the contact + /// + /// street address (street+number) of the contact + string getStreet() + { + return null; + } + + /// + /// returns additional address information which is display in xml tag "LineTwo" + /// + /// additional address information + string getAdditionalAddress() + { + return null; + } + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableItem.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableItem.cs new file mode 100644 index 0000000..a68a8db --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableItem.cs @@ -0,0 +1,124 @@ +using System; +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + public interface IZUGFeRDExportableItem + { + IZUGFeRDExportableProduct getProduct(); + + /// + /// item level discounts + /// array of the discounts on a single item + /// + /// IZUGFeRDAllowanceCharge[] getItemAllowances() { + /// return null; + /// } + /// + /// ** + /// item level price additions + /// array of the additional charges on the item + /// + /// IZUGFeRDAllowanceCharge[] getItemCharges() { + /// return null; + /// } + /// + /// + ///* + /// BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247) + /// @return + /// + string getBuyerOrderReferencedDocumentLineID() + { + + return null; + + } + + + /// + /// The price of one item excl. taxes + /// + /// The price of one item excl. taxes + BigDecimal getPrice(); + + BigDecimal getValue() + { + + return getPrice(); + + } + /// + /// how many get billed + /// + /// the quantity of the item + BigDecimal getQuantity(); + + /// + /// how many items units per price + /// + /// item units per price + BigDecimal getBasisQuantity() + { + return BigDecimal.ONE.setScale(4); + } + + /// + ///* + /// the ID of an additionally referenced document for this item + /// the id as string + string getAdditionalReferencedDocumentID() + { + return null; + } + + + /// + ///* + /// allows to specify multiple(!) referenced documents along with e.g. their typecodes + /// @return + /// + /*IReferencedDocument[] ReferencedDocuments + { + get + { + return null; + } + }*/ + /// + ///* + /// descriptive texts + /// an array of strings of item specific "includedNotes", text values + string[] getNotes() + { + + return null; + + } + + + + /// + ///* + /// specifies the item level delivery period (there is also one on document level), + /// this will be included in a BillingSpecifiedPeriod element + /// the beginning of the delivery period + DateTime? getDetailedDeliveryPeriodFrom() + { + + return null; + + } + + /// + ///* + /// specifies the item level delivery period (there is also one on document level), + /// this will be included in a BillingSpecifiedPeriod element + /// the end of the delivery period + DateTime? getDetailedDeliveryPeriodTo() + { + return null; + + } + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableProduct.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableProduct.cs new file mode 100644 index 0000000..6a025f5 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableProduct.cs @@ -0,0 +1,114 @@ +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + public interface IZUGFeRDExportableProduct + { + + /// + /// + /// HUR hour + /// KGM kilogram + /// KTM kilometre + /// KWH kilowatt hour + /// LS lump sum + /// LTR litre + /// MIN minute + /// MMK square millimetre + /// MMT millimetre + /// MTK square metre + /// MTQ cubic metre + /// MTR metre + /// NAR number of articles + /// NPR number of pairs + /// P1 percent + /// SET set + /// TNE tonne (metric ton) + /// WEE week + /// + /// a UN/ECE rec 20 unit code see https://www.unece.org/fileadmin/DAM/cefact/recommendations/rec20/rec20_rev3_Annex2e.pdf + string getUnit(); + + /// + /// Short name of the product + /// + /// Short name of the product + string getName(); + + /// + /// long description of the product + /// + /// long description of the product + string getDescription(); + + /// + /// Get the ID that had been assigned by the seller to + /// identify the product + /// + /// seller assigned product ID + string getSellerAssignedID() + { + return null; + } + + /// + /// Get the ID that had been assigned by the buyer to + /// identify the product + /// + /// buyer assigned product ID + string getBuyerAssignedID() + { + return null; + } + + /// + /// VAT percent of the product (e.g. 19, or 5.1 if you like) + /// + /// VAT percent of the product + BigDecimal getVATPercent(); + + bool getIntraCommunitySupply() + { + return false; + } + + bool getReverseCharge() + { + return false; + } + + string getTaxCategoryCode() + { + /* if (isIntraCommunitySupply()) + { + return "K"; // "K"; // within europe + } + else if (isReverseCharge()) + { + return "AE"; // "AE"; // to out of europe... + } + else if (getVATPercent().compareTo(BigDecimal.ZERO) == 0) + { + return "Z"; // "Z"; // zero rated goods + } + else + {*/ + return "S"; // "S"; // one of the "standard" rates (not + // neccessarily a rate, even a deducted VAT + // is standard calculation) + //} + } + + string getTaxExemptionReason() + { + /* if (isIntraCommunitySupply()) + { + return "Intra-community supply"; + } + else if (isReverseCharge()) + { + return "Reverse Charge"; + }*/ + return null; + } + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableTradeParty.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableTradeParty.cs new file mode 100644 index 0000000..6a3122d --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDExportableTradeParty.cs @@ -0,0 +1,100 @@ + using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public interface IZUGFeRDExportableTradeParty + { + + /// + /// customer identification assigned by the seller + /// + /// customer identification + string getID() + { + return null; + } + + /// + /// customer global identification assigned by the seller + /// + /// customer identification + string getGlobalID() + { + return null; + } + + /// + ///* + /// gets the official representation + /// the interface with the attributes of the legal organisation + /* IZUGFeRDLegalOrganisation getLegalOrganisation() + { + return null; + } + */ + /// + /// customer global identification scheme + /// + /// customer identification + string getGlobalIDScheme() + { + return null; + } + + + IZUGFeRDExportableContact getContact() + { + return null; + } + + /// + /// First and last name of the recipient + /// + /// First and last name of the recipient + string getName(); + /// + /// Postal code of the recipient + /// + /// Postal code of the recipient + string getZIP(); + /// + /// VAT ID (Umsatzsteueridentifikationsnummer) of the contact + /// + /// VAT ID (Umsatzsteueridentifikationsnummer) of the contact + string getVATID() + { + return null; + } + /// + /// two-letter country code of the contact + /// + /// two-letter iso country code of the contact + string getCountry(); + /// + /// Returns the city of the contact + /// + /// Returns the city of the recipient + string getLocation(); + /// + /// Returns the street address (street+number) of the contact + /// + /// street address (street+number) of the contact + string getStreet(); + /// + /// returns additional address information which is display in xml tag "LineTwo" + /// + /// additional address information + string getAdditionalAddress() + { + return null; + } + /// + ///* + /// obligatory for sender but not for recipient + /// the tax id as string + string getTaxID() + { + return null; + } + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDPaymentTerms.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDPaymentTerms.cs new file mode 100644 index 0000000..aa5299d --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDPaymentTerms.cs @@ -0,0 +1,16 @@ +using System; + +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + + public interface IZUGFeRDPaymentTerms + { + + string getDescription(); + + DateTime getDueDate(); + + // IZUGFeRDPaymentDiscountTerms getDiscountTerms(); + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDTradeSettlement.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDTradeSettlement.cs new file mode 100644 index 0000000..c682858 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDTradeSettlement.cs @@ -0,0 +1,25 @@ +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + public interface IZUGFeRDTradeSettlement + { + + /// + ///* + /// + /// zf2 xml for applicableHeaderTradeSettlement + string getSettlementXML(); + + + /// + ///* + /// + /// zf2 xml for applicableHeaderTradePayment + string getPaymentXML() + { + return null; + } + + + + } +} diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDTradeSettlementPayment.cs b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDTradeSettlementPayment.cs new file mode 100644 index 0000000..9b6a0bd --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/IZUGFeRDTradeSettlementPayment.cs @@ -0,0 +1,91 @@ +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + /// + /// ********************************************************************** + /// + /// Copyright 2019 by ak on 12.04.19. + /// + /// Use is subject to license terms. + /// + /// Licensed under the Apache License, Version 2.0 (the "License"); you may not + /// use this file except in compliance with the License. You may obtain a copy + /// of the License at http://www.apache.org/licenses/LICENSE-2.0. + /// + /// Unless required by applicable law or agreed to in writing, software + /// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + /// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + /// + /// See the License for the specific language governing permissions and + /// limitations under the License. + /// + /// *********************************************************************** + /// + + + public interface IZUGFeRDTradeSettlementPayment : IZUGFeRDTradeSettlement + { + + /// + /// get payment information text. e.g. Bank transfer + /// + /// payment information text + string getOwnPaymentInfoText() + { + return null; + } + + /// + /// BIC of the sender + /// + /// the BIC code of the recipient sender's bank + string getOwnBIC() + { + return null; + } + + + /// + /// IBAN of the sender + /// + /// the IBAN of the invoice sender's bank account + string getOwnIBAN() + { + return null; + } + + /// + ///* + /// Account name + /// + /// the name of the account holder (if not identical to sender) + string getAccountName() + { + return null; + } + + + public string getSettlementXML() + { + string accountNameStr = ""; + if (getAccountName() != null) + { + accountNameStr = "" + XMLTools.encodeXML(getAccountName()) + "\n"; + + } + + string xml = " \n" + " 58\n" + " SEPA credit transfer\n" + " \n" + " " + XMLTools.encodeXML(getOwnIBAN()) + "\n"; + xml += accountNameStr; + xml += " \n" + " \n" + " " + XMLTools.encodeXML(getOwnBIC()) + "\n" + " \n" + " \n"; + return xml; + } + + + /* I'd love to implement getPaymentXML() and put there because this is where it belongs + * unfortunately, the due date is part of the transaction which is not accessible here :-( + */ + + + } + +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/Invoice.cs b/Ghostscript.NET/FacturX/ZUGFeRD/Invoice.cs new file mode 100644 index 0000000..109973d --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/Invoice.cs @@ -0,0 +1,805 @@ +/** + * ********************************************************************* + *

+ * Copyright 2018 Jochen Staerk + *

+ * Use is subject to license terms. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy + * of the License at http://www.apache.org/licenses/LICENSE-2.0. + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + *

+ * See the License for the specific language governing permissions and + * limitations under the License. + *

+ * ********************************************************************** + */ + using System; +using System.Collections.Generic; +using java.math; + +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + ///

+ ///* + /// An invoice, with fluent setters + /// + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: @JsonIgnoreProperties(ignoreUnknown = true) public class Invoice implements IExportableTransaction + public class Invoice : IExportableTransaction + { + + protected internal string documentName = null, documentCode = null, number = null, ownOrganisationFullPlaintextInfo = null, referenceNumber = null, shipToOrganisationID = null, shipToOrganisationName = null, shipToStreet = null, shipToZIP = null, shipToLocation = null, shipToCountry = null, buyerOrderReferencedDocumentID = null, invoiceReferencedDocumentID = null, buyerOrderReferencedDocumentIssueDateTime = null, ownForeignOrganisationID = null, ownOrganisationName = null, currency = null, paymentTermDescription = null; + protected internal DateTime? issueDate = null, dueDate = null; + protected DateTime? deliveryDate = null; + protected internal BigDecimal totalPrepaidAmount = null; + protected internal TradeParty sender = null, recipient = null, deliveryAddress = null; +//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: +//ORIGINAL LINE: @JsonDeserialize(contentAs=Item.class) protected java.util.ArrayList ZFItems = null; + protected internal List ZFItems = null; + protected internal List notes = null; + protected internal string sellerOrderReferencedDocumentID; + protected internal string contractReferencedDocument = null; + //protected internal List xmlEmbeddedFiles = null; + + protected internal DateTime? detailedDeliveryDateStart = null; + protected internal DateTime? detailedDeliveryPeriodEnd = null; + + //protected internal List Allowances = new List(), Charges = new List(), LogisticsServiceCharges = new List(); + protected internal IZUGFeRDPaymentTerms paymentTerms = null; + protected internal DateTime invoiceReferencedIssueDate; + protected internal string specifiedProcuringProjectID = null; + protected internal string specifiedProcuringProjectName = null; + + public Invoice() + { + ZFItems = new List(); + setCurrency("EUR"); + } + + + + +public string getDocumentName() +{ + return documentName; +} + + public string getContractReferencedDocument() + { + return contractReferencedDocument; + } + + public virtual Invoice setDocumentName(string documentName) + { + this.documentName = documentName; + return this; + } + + public string DocumentCode() + { + return documentCode; + } + + public virtual Invoice setDocumentCode(string documentCode) + { + this.documentCode = documentCode; + return this; + } +/* + public virtual Invoice embedFileInXML(FileAttachment fa) + { + if (xmlEmbeddedFiles == null) + { + xmlEmbeddedFiles = new List<>(); + } + xmlEmbeddedFiles.add(fa); + return this; + } + + public override FileAttachment[] getAdditionalReferencedDocuments() + { + + if (xmlEmbeddedFiles == null) + { + return null; + } + return xmlEmbeddedFiles.toArray(new FileAttachment[0]); + + + } + */ + public IZUGFeRDExportableTradeParty getRecipient() + { + return recipient; + } + + /// + /// required. + /// sets the invoice receiving institution = invoicee + /// the invoicee organisation + /// fluent setter + public virtual Invoice setRecipient(TradeParty recipient) + { + this.recipient = recipient; + return this; + } + + + public string getNumber() + { + return number; + } + + public virtual Invoice setNumber(string number) + { + this.number = number; + return this; + } + + + /*** + * switch type to invoice correction and refer to document number. + * Please note that the quantities need to be negative, if you + * e.g. delivered 100 and take 50 back the quantity should be -50 in the + * corrected invoice, which will result in negative VAT and a negative payment amount + * @param number the invoice number to be corrected + * @return this object (fluent setter) + */ +public virtual Invoice setCorrection(string number) +{ + setInvoiceReferencedDocumentID(number); + documentCode = "384"; + return this; +} + public virtual Invoice setCreditNote() + { + documentCode = "381"; + return this; + } + + public string getOwnOrganisationFullPlaintextInfo() + { + return ownOrganisationFullPlaintextInfo; + } + + public virtual Invoice setOwnOrganisationFullPlaintextInfo(string ownOrganisationFullPlaintextInfo) + { + this.ownOrganisationFullPlaintextInfo = ownOrganisationFullPlaintextInfo; + return this; + } + + public string getReferenceNumber() + { + return referenceNumber; + } + + public virtual Invoice setReferenceNumber(string referenceNumber) + { + this.referenceNumber = referenceNumber; + return this; + } + + public string getShipToOrganisationID() + { + return shipToOrganisationID; + + } + + public virtual Invoice setShipToOrganisationID(string shipToOrganisationID) + { + this.shipToOrganisationID = shipToOrganisationID; + return this; + } + + public string ShipToOrganisationName() + { + + return shipToOrganisationName; + + } + + public virtual Invoice setShipToOrganisationName(string shipToOrganisationName) + { + this.shipToOrganisationName = shipToOrganisationName; + return this; + } + + public string getShipToStreet() + { + + return shipToStreet; + + } + + + public virtual Invoice setShipToStreet(string shipToStreet) + { + this.shipToStreet = shipToStreet; + return this; + } + + public string getShipToZIP() + { + + return shipToZIP; + + } + + public virtual Invoice setShipToZIP(string shipToZIP) + { + this.shipToZIP = shipToZIP; + return this; + } + + public string ShipToLocation() + { + + return shipToLocation; + + } + + public virtual Invoice setShipToLocation(string shipToLocation) + { + this.shipToLocation = shipToLocation; + return this; + } + + public string ShipToCountry() + { + + return shipToCountry; + + } + + public virtual Invoice setShipToCountry(string shipToCountry) + { + this.shipToCountry = shipToCountry; + return this; + } + + public string BuyerOrderReferencedDocumentID() + { + + return buyerOrderReferencedDocumentID; + + } + public string SellerOrderReferencedDocumentID() + { + + return sellerOrderReferencedDocumentID; + + } + + + + +public virtual Invoice setSellerOrderReferencedDocumentID(string sellerOrderReferencedDocumentID) +{ + this.sellerOrderReferencedDocumentID = sellerOrderReferencedDocumentID; + return this; +} + /// + ///* + /// usually the order number + /// string with number + /// fluent setter + public virtual Invoice setBuyerOrderReferencedDocumentID(string buyerOrderReferencedDocumentID) + { + this.buyerOrderReferencedDocumentID = buyerOrderReferencedDocumentID; + return this; + } + + /// + ///* + /// usually in case of a correction the original invoice number + /// string with number + /// fluent setter + public virtual Invoice setInvoiceReferencedDocumentID(string invoiceReferencedDocumentID) + { + this.invoiceReferencedDocumentID = invoiceReferencedDocumentID; + return this; + } + public string getInvoiceReferencedDocumentID() + { + + return invoiceReferencedDocumentID; + + } + + public DateTime getInvoiceReferencedIssueDate() + { + + return invoiceReferencedIssueDate; + + } + + public virtual Invoice setInvoiceReferencedIssueDate(DateTime issueDate) + { + this.invoiceReferencedIssueDate = issueDate; + return this; + } + + public string getBuyerOrderReferencedDocumentIssueDateTime() + { + + return buyerOrderReferencedDocumentIssueDateTime; + + } + + /// + ///* + /// when the order (or whatever reference in BuyerOrderReferencedDocumentID) was issued (@todo switch to date?) + /// IssueDateTime in format CCYY-MM-DDTHH:MM:SS + /// fluent setter + public virtual Invoice setBuyerOrderReferencedDocumentIssueDateTime(string buyerOrderReferencedDocumentIssueDateTime) + { + this.buyerOrderReferencedDocumentIssueDateTime = buyerOrderReferencedDocumentIssueDateTime; + return this; + } + public IZUGFeRDExportableTradeParty getSender() { + return sender; + } + public string getOwnTaxID() + { + return getSender().getTaxID(); + } + + +[Obsolete] +public virtual Invoice setOwnTaxID(string ownTaxID) +{ + sender.addTaxID(ownTaxID); + return this; +} + + public string getOwnVATID() + { + + return getSender().getVATID(); + + } + + [Obsolete] + public virtual Invoice setOwnVATID(string ownVATID) + { + sender.addVATID(ownVATID); + return this; + } + + public string getOwnForeignOrganisationID() + { + + return ownForeignOrganisationID; + + } + + + + + public virtual void setZFItems(List ims) + { + ZFItems = ims; + } + + [Obsolete] + public virtual Invoice setOwnForeignOrganisationID(string ownForeignOrganisationID) + { + this.ownForeignOrganisationID = ownForeignOrganisationID; + return this; + } + + public string getOwnOrganisationName() + { + + return ownOrganisationName; + + } + + + [Obsolete] + public virtual Invoice setOwnOrganisationName(string ownOrganisationName) + { + this.ownOrganisationName = ownOrganisationName; + return this; + } + + public string getOwnStreet() + { + + return sender.getStreet(); + + } + + + public string getOwnZIP() + { + + return sender.getZIP(); + + } + + + public string getOwnLocation() + { + + return sender.getLocation(); + + } + + + public string getOwnCountry() + { + + return sender.getCountry(); + + } + + + public string[] getNotes() + { + + if (notes == null) + { + return null; + } + return notes.ToArray(); + + } + + public string getCurrency() + { + + return currency; + + } + + + public virtual Invoice setCurrency(string currency) + { + this.currency = currency; + return this; + } + + public string getPaymentTermDescription() + { + + return paymentTermDescription; + + } + + public virtual Invoice setPaymentTermDescription(string paymentTermDescription) + { + this.paymentTermDescription = paymentTermDescription; + return this; + } + + public DateTime? getIssueDate() + { + + return issueDate; + + } + + public virtual Invoice setIssueDate(DateTime issueDate) + { + this.issueDate = issueDate; + return this; + } + + public DateTime? getDueDate() + { + + return dueDate; + + } + + public virtual Invoice setDueDate(DateTime dueDate) + { + this.dueDate = dueDate; + return this; + } + + public DateTime? getDeliveryDate() + { + + return deliveryDate; + + } + + public virtual Invoice setDeliveryDate(DateTime deliveryDate) + { + this.deliveryDate = deliveryDate; + return this; + } + + public BigDecimal getTotalPrepaidAmount() + { + + return totalPrepaidAmount; + + } + + public virtual Invoice setTotalPrepaidAmount(BigDecimal totalPrepaidAmount) + { + this.totalPrepaidAmount = totalPrepaidAmount; + return this; + } + + + /// + ///* + /// sets a named sender contact + /// @deprecated use setSender + /// + /// the sender contact + /// fluent setter + public virtual Invoice setOwnContact(Contact ownContact) + { + this.sender.setContact(ownContact); + return this; + } + + /// + /// required. + /// sets the invoicing institution = invoicer + /// the invoicer + /// fluent setter + public virtual Invoice setSender(TradeParty sender) + { + this.sender = sender; +/* if ((sender.getBankDetails() != null) && (sender.getBankDetails().size() > 0)) + { + // convert bankdetails + + }*/ + return this; + } +/* + public IZUGFeRDAllowanceCharge[] getZFAllowances() + { + + if (Allowances.isEmpty()) + { + return null; + } + else + { + return Allowances.toArray(new IZUGFeRDAllowanceCharge[0]); + } + + } + + + public IZUGFeRDAllowanceCharge[] getZFCharges() + { + + if (Charges.isEmpty()) + { + return null; + } + else + { + return Charges.toArray(new IZUGFeRDAllowanceCharge[0]); + } + + } + + + public IZUGFeRDAllowanceCharge[] getZFLogisticsServiceCharges() + { + + if (LogisticsServiceCharges.isEmpty()) + { + return null; + } + else + { + return LogisticsServiceCharges.toArray(new IZUGFeRDAllowanceCharge[0]); + } + + } + +*/ + public IZUGFeRDTradeSettlement[]? getTradeSettlement() + { + + + if (getSender() == null) + { + return null; + } + + return ((TradeParty) getSender()).getAsTradeSettlement(); + + + } + + + public IZUGFeRDPaymentTerms getPaymentTerms() + { + + return paymentTerms; + + } + + public virtual Invoice setPaymentTerms(IZUGFeRDPaymentTerms paymentTerms) + { + this.paymentTerms = paymentTerms; + return this; + } + + public TradeParty getDeliveryAddress() + { + + return deliveryAddress; + + } + + /// + ///* + /// if the delivery address is not the recipient address, it can be specified here + /// the goods receiving organisation + /// fluent setter + public virtual Invoice setDeliveryAddress(TradeParty deliveryAddress) + { + this.deliveryAddress = deliveryAddress; + return this; + } + + public IZUGFeRDExportableItem[] getZFItems() + { + return ZFItems.ToArray(); + + } + + + /// + /// required + /// adds invoice "lines" :-) + /// + /// the invoice line + /// fluent setter + public virtual Invoice addItem(IZUGFeRDExportableItem item) + { + ZFItems.Add(item); + return this; + } + + + /// + ///* + /// checks if all required items are set in order to be able to export it + /// true if all required items are set + public virtual bool Valid + { + get + { + return (dueDate != null) && (sender != null) && (sender.getTaxID() != null) && (sender.getVATID() != null) && (recipient != null); + //contact + // this.phone = phone; + // this.email = email; + // this.street = street; + // this.zip = zip; + // this.location = location; + // this.country = country; + } + } + + +/// +///* +/// adds a document level addition to the price +/// +/// the charge to be applied +/// fluent setter +/* + public virtual Invoice addCharge(IZUGFeRDAllowanceCharge izac) + { + Charges.add(izac); + return this; + } +*/ + /// + ///* + /// adds a document level rebate + /// + /// the allowance to be applied + /// fluent setter +/* + public virtual Invoice addAllowance(IZUGFeRDAllowanceCharge izac) + { + Allowances.add(izac); + return this; + } +*/ + /// + ///* + /// adds the ID of a contract referenced in the invoice + /// the contract number + /// fluent setter + public virtual Invoice setContractReferencedDocument(string s) + { + contractReferencedDocument = s; + return this; + } + + + /// + ///* + /// sets a document level delivery period, + /// which is optional additional to the mandatory deliverydate + /// and which will become a BillingSpecifiedPeriod-Element + /// the date of first delivery + /// the date of last delivery + /// fluent setter + public virtual Invoice setDetailedDeliveryPeriod(DateTime start, DateTime end) + { + detailedDeliveryDateStart = start; + detailedDeliveryPeriodEnd = end; + + return this; + } + + + public DateTime? getDetailedDeliveryPeriodFrom() + { + + return detailedDeliveryDateStart; + + } + + public DateTime? getDetailedDeliveryPeriodTo() + { + + return detailedDeliveryPeriodEnd; + + } + + + /// + /* + /// adds a free text paragraph, which will become a includedNote element + /// freeform UTF8 plain text + /// fluent setter + public virtual Invoice addNote(string text) + { + if (notes == null) + { + notes = new List<>(); + } + notes.add(text); + return this; + }*/ + + public string getSpecifiedProcuringProjectID() + { + + return specifiedProcuringProjectID; + + } + + public virtual Invoice setSpecifiedProcuringProjectID(string specifiedProcuringProjectID) + { + this.specifiedProcuringProjectID = specifiedProcuringProjectID; + return this; + } + + public string getSpecifiedProcuringProjectName() +{ + + return specifiedProcuringProjectName; + +} + + public virtual Invoice setSpecifiedProcuringProjectName(string specifiedProcuringProjectName) + { + this.specifiedProcuringProjectName = specifiedProcuringProjectName; + return this; + } +} +} diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/Item.cs b/Ghostscript.NET/FacturX/ZUGFeRD/Item.cs new file mode 100644 index 0000000..aaaa80f --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/Item.cs @@ -0,0 +1,293 @@ +using System; +using System.Collections.Generic; +using java.math; + +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + + /// + ///* + /// describes any invoice line + /// + + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: @JsonIgnoreProperties(ignoreUnknown = true) public class Item implements org.mustangproject.ZUGFeRD.IZUGFeRDExportableItem + public class Item : IZUGFeRDExportableItem + { + protected internal BigDecimal price, quantity, tax, grossPrice, lineTotalAmount; + protected internal DateTime? detailedDeliveryPeriodFrom = null, detailedDeliveryPeriodTo = null; + protected internal string id; + protected internal string referencedLineID = null; + protected internal Product product; + protected internal List notes = null; + //protected internal List referencedDocuments = null; +// protected internal List Allowances = new List(), Charges = new List(); + + /// + ///* + /// default constructor + /// contains the products name, tax rate, and unit + /// the base price of one item the product + /// the number, dimensions or the weight of the delivered product or good in this context + public Item(Product product, BigDecimal price, BigDecimal quantity) + { + this.price = price; + this.quantity = quantity; + this.product = product; + } + + + /// + ///* + /// empty constructor + /// do not use, but might be used e.g. by jackson + /// + /// + public Item() + { + } + + public virtual Item addReferencedLineID(string s) + { + referencedLineID = s; + return this; + } + + /// + ///* + /// BT 132 (issue https://github.com/ZUGFeRD/mustangproject/issues/247) + /// @return + /// + public string getBuyerOrderReferencedDocumentLineID() + { + return referencedLineID; + } + + public virtual BigDecimal getLineTotalAmount() + { + return lineTotalAmount; + } + + /// + /// should only be set by calculator classes or maybe when reading from XML + /// price*quantity of this line + /// fluent setter + public virtual Item setLineTotalAmount(BigDecimal lineTotalAmount) + { + this.lineTotalAmount = lineTotalAmount; + return this; + } + + public virtual BigDecimal getGrossPrice() + { + return grossPrice; + } + + + /// + ///* + /// the list price without VAT (sic!), refer to EN16931-1 for definition + /// the list price without VAT + /// fluent setter + public virtual Item setGrossPrice(BigDecimal grossPrice) + { + this.grossPrice = grossPrice; + return this; + } + + + public virtual BigDecimal getTax() + { + return tax; + } + + public virtual Item setTax(BigDecimal tax) + { + this.tax = tax; + return this; + } + + public virtual Item setId(string id) + { + this.id = id; + return this; + } + + public virtual string getId() + { + return id; + } + + public BigDecimal getPrice() + { + return price; + } + + public virtual Item setPrice(BigDecimal price) + { + this.price = price; + return this; + } + + + + public BigDecimal getQuantity() + { + return quantity; + } + + public virtual Item setQuantity(BigDecimal quantity) + { + this.quantity = quantity; + return this; + } + + public IZUGFeRDExportableProduct getProduct() + { + return product; + } + +/* public override IZUGFeRDAllowanceCharge[] getItemAllowances() + { + if (Allowances.Count == 0) + { + return null; + } + else + { + return Allowances.ToArray(); + } + } + + public override IZUGFeRDAllowanceCharge[] getItemCharges() + { + if (Charges.Count == 0) + { + return null; + } + else + { + return Charges.ToArray(); + } + } + +*/ + + public string[] getNotes() + { + if (notes == null) + { + return null; + } + return notes.ToArray(); + } + + public virtual Item setProduct(Product product) + { + this.product = product; + return this; + } + + + /// + ///* + /// Adds a item level addition to the price (will be multiplied by quantity) + /// + /// a relative or absolute charge + /// fluent setter +/* public virtual Item addCharge(IZUGFeRDAllowanceCharge izac) + { + Charges.Add(izac); + return this; + } + + /// + ///* + /// Adds a item level reduction the price (will be multiplied by quantity) + /// + /// a relative or absolute allowance + /// fluent setter + public virtual Item addAllowance(IZUGFeRDAllowanceCharge izac) + { + Allowances.Add(izac); + return this; + } +*/ + /// + ///* + /// adds item level freetext fields (includednote) + /// UTF8 plain text + /// fluent setter + public virtual Item addNote(string text) + { + if (notes == null) + { + notes = new List(); + } + notes.Add(text); + return this; + } + + /// + ///* + /// adds item level Referenced documents along with their typecodes and issuerassignedIDs + /// the ReferencedDocument to add + /// fluent setter + /* + public virtual Item addReferencedDocument(ReferencedDocument doc) + { + if (referencedDocuments == null) + { + referencedDocuments = new List(); + } + referencedDocuments.Add(doc); + return this; + } + + public override IReferencedDocument[] getReferencedDocuments() + { + if (referencedDocuments == null) + { + return null; + } + return referencedDocuments.ToArray(); + }*/ + /// + ///* + /// specify a item level delivery period + /// (apart from the document level delivery period, and the document level + /// delivery day, which is probably anyway required) + /// + /// start date + /// end date + /// fluent setter + public virtual Item setDetailedDeliveryPeriod(DateTime from, DateTime to) + { + detailedDeliveryPeriodFrom = from; + detailedDeliveryPeriodTo = to; + return this; + } + + /// + ///* + /// specifies the item level delivery period (there is also one on document level), + /// this will be included in a BillingSpecifiedPeriod element + /// the beginning of the delivery period + public virtual DateTime? getDetailedDeliveryPeriodFrom() + { + return detailedDeliveryPeriodFrom; + } + + /// + ///* + /// specifies the item level delivery period (there is also one on document level), + /// this will be included in a BillingSpecifiedPeriod element + /// the end of the delivery period + public virtual DateTime? getDetailedDeliveryPeriodTo() + { + return detailedDeliveryPeriodTo; + } + + } +} diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/LineCalculator.cs b/Ghostscript.NET/FacturX/ZUGFeRD/LineCalculator.cs new file mode 100644 index 0000000..d27a7e6 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/LineCalculator.cs @@ -0,0 +1,91 @@ + +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class LineCalculator + { + private BigDecimal price; + private BigDecimal priceGross; + private BigDecimal itemTotalNetAmount; + private BigDecimal itemTotalVATAmount; + private BigDecimal allowance = BigDecimal.ZERO; + private BigDecimal charge = BigDecimal.ZERO; + + //JAVA TO C# CONVERTER WARNING: The following constructor is declared outside of its associated class: + //ORIGINAL LINE: public LineCalculator(IZUGFeRDExportableItem currentItem) + public LineCalculator(IZUGFeRDExportableItem currentItem) + { + /* + if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) + { + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: foreach(IZUGFeRDAllowanceCharge allowance @in currentItem.getItemAllowances()) + + { + addAllowance(allowance.getTotalAmount(currentItem)); + } + } + if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) + { + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: foreach(IZUGFeRDAllowanceCharge charge @in currentItem.getItemCharges()) + + { + addCharge(charge.getTotalAmount(currentItem)); + } + } + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: @decimal multiplicator = currentItem.getProduct().getVATPercent().divide(100); + */ + BigDecimal multiplicator = currentItem.getProduct().getVATPercent().divide(new BigDecimal(100)); + priceGross = currentItem.getPrice(); // see https://github.com/ZUGFeRD/mustangproject/issues/159 + price = priceGross.subtract(allowance).add(charge); + itemTotalNetAmount = currentItem.getQuantity().multiply(price).divide(currentItem.getBasisQuantity()).setScale(2, BigDecimal.ROUND_HALF_UP); + itemTotalVATAmount = itemTotalNetAmount.multiply(multiplicator); + + } + + + public virtual BigDecimal getPrice() + { + + return price; + + } + + public virtual BigDecimal getItemTotalNetAmount() + { + + return itemTotalNetAmount; + + } + + public virtual BigDecimal getItemTotalVATAmount() + { + return itemTotalVATAmount; + } + + public virtual BigDecimal getItemTotalGrossAmount() + { + return itemTotalNetAmount; + } + + public virtual BigDecimal getPriceGross() + { + return priceGross; + } + + public virtual void addAllowance(BigDecimal b) + { + allowance = allowance.add(b); + } + + public virtual void addCharge(BigDecimal b) + { + charge = charge.add(b); + } + + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/Product.cs b/Ghostscript.NET/FacturX/ZUGFeRD/Product.cs new file mode 100644 index 0000000..bde863c --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/Product.cs @@ -0,0 +1,174 @@ +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + /// + ///* + /// describes a product, good or service used in an invoice item line + /// +//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: +//ORIGINAL LINE: @JsonIgnoreProperties(ignoreUnknown = true) public class Product implements org.mustangproject.ZUGFeRD.IZUGFeRDExportableProduct + public class Product : IZUGFeRDExportableProduct + { + protected internal string unit, name, description, sellerAssignedID, buyerAssignedID; + protected internal BigDecimal VATPercent; +//JAVA TO C# CONVERTER NOTE: Fields cannot have the same name as methods of the current type: + protected internal bool isReverseCharge_Conflict = false; +//JAVA TO C# CONVERTER NOTE: Fields cannot have the same name as methods of the current type: + protected internal bool isIntraCommunitySupply_Conflict = false; + + /// + ///* + /// default constructor + /// product short name + /// product long name + /// a two/three letter UN/ECE rec 20 unit code, e.g. "C62" for piece + /// product vat rate + public Product(string name, string description, string unit, BigDecimal VATPercent) + { + this.unit = unit; + this.name = name; + this.description = description; + this.VATPercent = VATPercent; + } + + + /// + ///* + /// empty constructor + /// just for jackson etc + /// + public Product() + { + + } + + + public virtual string getSellerAssignedID() + { + return sellerAssignedID; + } + + /// + ///* + /// how the seller identifies this type of product + /// a unique String + /// fluent setter + public virtual Product setSellerAssignedID(string sellerAssignedID) + { + this.sellerAssignedID = sellerAssignedID; + return this; + } + + public virtual string getBuyerAssignedID() + { + return buyerAssignedID; + } + + /// + ///* + /// if the buyer provided an ID how he refers to this product + /// a string the buyer provided + /// fluent setter + public virtual Product setBuyerAssignedID(string buyerAssignedID) + { + this.buyerAssignedID = buyerAssignedID; + return this; + } + + public bool isReverseCharge() + { + return isReverseCharge_Conflict; + } + + public bool isIntraCommunitySupply() + { + return isIntraCommunitySupply_Conflict; + } + + /// + ///* + /// sets reverse charge(=delivery to outside EU) + /// fluent setter + public virtual Product setReverseCharge() + { + isReverseCharge_Conflict = true; + setVATPercent(BigDecimal.ZERO); + return this; + } + + + /// + ///* + /// sets intra community supply(=delivery outside the country inside the EU) + /// fluent setter + public virtual Product setIntraCommunitySupply() + { + isIntraCommunitySupply_Conflict = true; + setVATPercent(BigDecimal.ZERO); + return this; + } + + public string getUnit() + { + return unit; + } + + /// + ///* + /// sets a UN/ECE rec 20 or 21 code which unit the product ships in, e.g. C62=piece + /// 2-3 letter UN/ECE rec 20 or 21 + /// fluent setter + public virtual Product setUnit(string unit) + { + this.unit = unit; + return this; + } + + public string getName() + { + return name; + } + + /// + /// name of the product + /// short name + /// fluent setter + public virtual Product setName(string name) + { + this.name = name; + return this; + } + + public string getDescription() + { + return description; + } + + /// + /// description of the product (required) + /// long name + /// fluent setter + public virtual Product setDescription(string description) + { + this.description = description; + return this; + } + + public BigDecimal getVATPercent() + { + return VATPercent; + } + + /// + ///** + /// VAT rate of the product + /// vat rate of the product + /// fluent setter + public virtual Product setVATPercent(BigDecimal VATPercent) + { + this.VATPercent = VATPercent; + return this; + } + } +} diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/Profile.cs b/Ghostscript.NET/FacturX/ZUGFeRD/Profile.cs new file mode 100644 index 0000000..8528d3e --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/Profile.cs @@ -0,0 +1,57 @@ +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class Profile + { + protected internal string name, id; + + /// + ///* + /// Contruct + /// human readable name of the profile, also used as basis to detemine the XMP Name + /// XML Guideline ID + public Profile(string name, string ID) + { + this.name = name; + this.id = ID; + } + + /// + ///* + /// gets the name + /// the name of the profile + public virtual string getName() + { + return name; + } + + /// + ///* + /// get guideline id + /// the XML Guideline ID of the profile + public virtual string getID() + { + return id; + } + + /// + ///* + /// if the profile is embedded in PDF we need RDF metadata + /// the XMP name string of the profile + public virtual string getXMPName() + { + if (name.Equals("BASICWL")) + { + return "BASIC WL"; + } + else if (name.Equals("EN16931")) + { + return "EN 16931"; + } + else + { + return name; + } + } + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/Profiles.cs b/Ghostscript.NET/FacturX/ZUGFeRD/Profiles.cs new file mode 100644 index 0000000..a34ff32 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/Profiles.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class Profiles + { + private static readonly Dictionary zf2Map = new Dictionary + { + {"MINIMUM", new Profile("MINIMUM", "urn:factur-x.eu:1p0:minimum")}, + {"BASICWL", new Profile("BASICWL", "urn:factur-x.eu:1p0:basicwl")}, + {"BASIC", new Profile("BASIC", "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic")}, + {"EN16931", new Profile("EN16931", "urn:cen.eu:en16931:2017")}, + {"EXTENDED", new Profile("EXTENDED", "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended")}, + {"XRECHNUNG", new Profile("XRECHNUNG", "urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.1")} + }; + + private static readonly Dictionary zf1Map = new Dictionary + { + + {"BASIC", new Profile("BASIC", "urn:ferd:CrossIndustryDocument:invoice:1p0:basic")}, + {"COMFORT", new Profile("COMFORT", "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort")}, + {"EXTENDED", new Profile("EXTENDED", "urn:ferd:CrossIndustryDocument:invoice:1p0:extended")} + }; + + + public static Profile getByName(string name, int version) + { + Profile result = null; + if (version == 1) + { + result = zf1Map[name.ToUpper()]; + } + else + { + result = zf2Map[name.ToUpper()]; + } + if (result == null) + { + throw new Exception("Profile not found"); + } + return result; + } + public static Profile getByName(string name) + { + return getByName(name, 2); + } + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/TradeParty.cs b/Ghostscript.NET/FacturX/ZUGFeRD/TradeParty.cs new file mode 100644 index 0000000..66be459 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/TradeParty.cs @@ -0,0 +1,288 @@ +using System.Collections.Generic; + +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + /// + ///* + /// A organisation, i.e. usually a company + /// + //JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: + //ORIGINAL LINE: @JsonIgnoreProperties(ignoreUnknown = true) public class TradeParty implements IZUGFeRDExportableTradeParty + public class TradeParty : IZUGFeRDExportableTradeParty + { + + protected internal string name, zip, street, location, country; + protected internal string taxID = null, vatID = null; + protected internal string ID = null; + protected internal string additionalAddress = null; + protected internal IList bankDetails = new List(); + //protected internal IList debitDetails = new List(); + protected internal Contact contact = null; + // protected internal LegalOrganisation legalOrg = null; + + /// + /// Default constructor. + /// Probably a bad idea but might be needed by jackson or similar + /// + public TradeParty() + { + + } + + + /// + /// + /// of the company + /// street and number (use setAdditionalAddress for more parts) + /// postcode of the company + /// city of the company + /// two letter ISO code + public TradeParty(string name, string street, string zip, string location, string country) + { + this.name = name; + this.street = street; + this.zip = zip; + this.location = location; + this.country = country; + + } + /// + /// XML parsing constructor + /// the nodelist returned e.g. from xpath + //JAVA TO C# CONVERTER WARNING: The following constructor is declared outside of its associated class: + //ORIGINAL LINE: public TradeParty(NodeList nodes) + + public string getID() + { + return ID; + } + + /// + /// if it's a customer, this can e.g. be the customer ID + /// + /// customer/seller number + /// fluent setter + public virtual TradeParty setID(string ID) + { + this.ID = ID; + return this; + } + + /// + ///* + /// (optional) a named contact person + /// + /// the named contact person + /// fluent setter + public virtual TradeParty setContact(Contact c) + { + this.contact = c; + return this; + } + + /// + ///* + /// required (for senders, if payment is not debit): the BIC and IBAN + /// bank credentials + /// fluent setter + public virtual TradeParty addBankDetails(BankDetails s) + { + bankDetails.Add(s); + return this; + } + + /// + /// (optional) + /// + /// + /// fluent setter + /*public virtual TradeParty addDebitDetails(IZUGFeRDTradeSettlementDebit debitDetail) + { + debitDetails.add(debitDetail); + return this; + }*/ + /* + public override IZUGFeRDLegalOrganisation getLegalOrganisation() + { + return legalOrg; + } + + public virtual TradeParty setLegalOrganisation(LegalOrganisation legalOrganisation) + { + legalOrg = legalOrganisation; + return this; + } + */ + public virtual IList getBankDetails() + { + return bankDetails; + } + + /// + ///* + /// a general tax ID + /// tax number of the organisation + /// fluent setter + public virtual TradeParty addTaxID(string taxID) + { + this.taxID = taxID; + return this; + } + + /// + ///* + /// the USt-ID + /// Ust-ID + /// fluent setter + public virtual TradeParty addVATID(string vatID) + { + this.vatID = vatID; + return this; + } + + public string getVATID() + { + return vatID; + } + + public virtual TradeParty setVATID(string VATid) + { + this.vatID = VATid; + return this; + } + + public string getTaxID() + { + return taxID; + } + + public virtual TradeParty setTaxID(string tax) + { + this.taxID = tax; + return this; + } + + public virtual string getName() + { + return name; + } + + /// + ///* + /// required, usually done in the constructor: the complete name of the organisation + /// complete legal name + /// fluent setter + public virtual TradeParty setName(string name) + { + this.name = name; + return this; + } + + + public virtual string getZIP() + { + return zip; + } + + /// + ///* + /// usually set in the constructor, required for recipients in german invoices: postcode + /// postcode + /// fluent setter + public virtual TradeParty setZIP(string zip) + { + this.zip = zip; + return this; + } + + public string getStreet() + { + return street; + } + + /// + ///* + /// usually set in constructor, required in germany, street and house number + /// street name and number + /// fluent setter + public virtual TradeParty setStreet(string street) + { + this.street = street; + return this; + } + + public string getLocation() + { + return location; + } + + /// + ///* + /// usually set in constructor, usually required in germany, the city of the organisation + /// city + /// fluent setter + public virtual TradeParty setLocation(string location) + { + this.location = location; + return this; + } + + public string getCountry() + { + return country; + } + + /// + ///* + /// two-letter ISO code of the country + /// two-letter-code + /// fluent setter + public virtual TradeParty setCountry(string country) + { + this.country = country; + return this; + } + + + public virtual string getVatID() + { + return vatID; + } + + public IZUGFeRDExportableContact getContact() + { + return contact; + } + + public virtual IZUGFeRDTradeSettlement[]? getAsTradeSettlement() + { + if (bankDetails.Count == 0) + { + return null; + } + return bankDetails.ToArray(); + } + + + public string getAdditionalAddress() + { + return additionalAddress; + } + + + /// + ///* + /// additional parts of the address, e.g. which floor. + /// Street address will become "lineOne", this will become "lineTwo" + /// additional address description + /// fluent setter + public virtual TradeParty setAdditionalAddress(string additionalAddress) + { + this.additionalAddress = additionalAddress; + return this; + } + + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/TransactionCalculator.cs b/Ghostscript.NET/FacturX/ZUGFeRD/TransactionCalculator.cs new file mode 100644 index 0000000..f299525 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/TransactionCalculator.cs @@ -0,0 +1,251 @@ +using System.Collections.Generic; + +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class TransactionCalculator + { + protected internal IExportableTransaction trans; + + /// + ///* + /// + /// the invoice (or IExportableTransaction) to be calculated + public TransactionCalculator(IExportableTransaction trans) + { + this.trans = trans; + } + + /// + ///* + /// if something had already been paid in advance, this will get it from the transaction + /// prepaid amount + protected internal virtual BigDecimal getTotalPrepaid() + { + if (trans.getTotalPrepaidAmount() == null) + { + return BigDecimal.ZERO; + } + else + { + return trans.getTotalPrepaidAmount().setScale(2, RoundingMode.HALF_UP); + } + } + + /// + ///* + /// the invoice total with VAT, corrected by prepaid amount, allowances and charges + /// the invoice total including taxes + public virtual BigDecimal getGrandTotal() + { + + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + BigDecimal res = getTaxBasis(); + Dictionary VATPercentAmountMap = getVATPercentAmountMap(); + foreach (BigDecimal currentTaxPercent in VATPercentAmountMap.Keys) + { + VATAmount amount = VATPercentAmountMap[currentTaxPercent]; + res = res.add(amount.getCalculated()); + } + return res.setScale(2, RoundingMode.HALF_UP); + + } + + /// + ///* + /// returns total of charges for this tax rate + /// a specific rate, or null for any rate + /// the total amount + + /* + protected internal virtual BigDecimal getChargesForPercent(decimal percent) + { + IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); + return sumAllowanceCharge(percent, charges); + } + + private BigDecimal sumAllowanceCharge(BigDecimal percent, IZUGFeRDAllowanceCharge[] charges) + { + BigDecimal res = BigDecimal.ZERO; + if ((charges != null) && (charges.Length > 0)) + { + foreach (IZUGFeRDAllowanceCharge currentCharge in charges) + { + if ((percent == null) || (currentCharge.getTaxPercent().compareTo(percent) == 0)) + { + res = res + currentCharge.getTotalAmount(this); + } + } + } + return res; + } + + /// + ///* + /// returns a (potentially concatenated) string of charge reasons, or "Charges" if none are defined + /// a specific rate, or null for any rate + /// the space separated String + protected internal virtual string getChargeReasonForPercent(BigDecimal percent) + { + IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); + string res = getAllowanceChargeReasonForPercent(percent, charges); + if ("".Equals(res)) + { + res = "Charges"; + } + return res; + } + + private string getAllowanceChargeReasonForPercent(BigDecimal percent, IZUGFeRDAllowanceCharge[] charges) + { + string res = " "; + if ((charges != null) && (charges.Length > 0)) + { + foreach (IZUGFeRDAllowanceCharge currentCharge in charges) + { + if ((percent == null) || (currentCharge.getTaxPercent().compareTo(percent) == 0) && currentCharge.getReason() != null) + { + res += currentCharge.getReason() + " "; + } + } + } + res = res.Substring(0, res.Length - 1); + return res; + } + + /// + ///* + /// returns a (potentially concatenated) string of allowance reasons, or "Allowances", if none are defined + /// a specific rate, or null for any rate + /// the space separated String + protected internal virtual string getAllowanceReasonForPercent(BigDecimal percent) + { + IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); + string res = getAllowanceChargeReasonForPercent(percent, allowances); + if ("".Equals(res)) + { + res = "Allowances"; + } + return res; + } + + + /// + ///* + /// returns total of allowances for this tax rate + /// a specific rate, or null for any rate + /// the total amount + protected internal virtual BigDecimal getAllowancesForPercent(BigDecimal percent) + { + IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); + return sumAllowanceCharge(percent, allowances); + } + */ + + /// + ///* + /// returns the total net value of all items, without document level charges/allowances + /// item sum + protected internal virtual BigDecimal getTotal() + { + //JAVA TO C# CONVERTER TODO TASK: Method reference constructor syntax is not converted by Java to C# Converter: + + BigDecimal res = BigDecimal.ZERO; + foreach (IZUGFeRDExportableItem currentItem in trans.getZFItems()) + { + LineCalculator lc = new LineCalculator(currentItem); + res = res.add(lc.getItemTotalGrossAmount()); + } + return res; + + + + } + + /// + ///* + /// returns the total net value of the invoice, including charges/allowances on document + /// level + /// item sum +- charges/allowances + protected internal virtual BigDecimal getTaxBasis() + { + return getTotal() /*+ (getChargesForPercent(null).setScale(2, RoundingMode.HALF_UP)).subtract(getAllowancesForPercent(null).setScale(2, RoundingMode.HALF_UP)).setScale(2, RoundingMode.HALF_UP)*/; + } + + /// + /// which taxes have been used with which amounts in this transaction, empty for + /// no taxes, or e.g. 19:190 and 7:14 if 1000 Eur were applicable to 19% VAT + /// (=190 EUR VAT) and 200 EUR were applicable to 7% (=14 EUR VAT) 190 Eur + /// + /// which taxes have been used with which amounts in this invoice + protected internal virtual Dictionary getVATPercentAmountMap() + { + Dictionary hm = new Dictionary(); + + foreach (IZUGFeRDExportableItem currentItem in trans.getZFItems()) + { + BigDecimal percent = currentItem.getProduct().getVATPercent(); + + LineCalculator lc = new LineCalculator(currentItem); + VATAmount itemVATAmount = new VATAmount(lc.getItemTotalNetAmount(), lc.getItemTotalVATAmount(), currentItem.getProduct().getTaxCategoryCode()); + + + if (!hm.ContainsKey(percent.stripTrailingZeros())) + { + hm[percent.stripTrailingZeros()] = itemVATAmount; + } + else + { + VATAmount current = hm[percent.stripTrailingZeros()]; + hm[percent.stripTrailingZeros()] = current.add(itemVATAmount); + } + } + + /* + IZUGFeRDAllowanceCharge[] charges = trans.getZFCharges(); + if ((charges != null) && (charges.Length > 0)) + { + foreach (IZUGFeRDAllowanceCharge currentCharge in charges) + { + VATAmount theAmount = hm[currentCharge.getTaxPercent().stripTrailingZeros()]; + if (theAmount == null) + { + theAmount = new VATAmount(decimal.Zero, decimal.Zero, currentCharge.getCategoryCode() != null ? currentCharge.getCategoryCode() : "S"); + } + theAmount.setBasis(theAmount.getBasis().add(currentCharge.getTotalAmount(this))); + decimal factor = currentCharge.getTaxPercent().divide(new decimal(100)); + theAmount.setCalculated(theAmount.getBasis().multiply(factor)); + hm[currentCharge.getTaxPercent().stripTrailingZeros()] = theAmount; + } + } + IZUGFeRDAllowanceCharge[] allowances = trans.getZFAllowances(); + if ((allowances != null) && (allowances.Length > 0)) + { + foreach (IZUGFeRDAllowanceCharge currentAllowance in allowances) + { + VATAmount theAmount = hm[currentAllowance.getTaxPercent().stripTrailingZeros()]; + if (theAmount == null) + { + theAmount = new VATAmount(BigDecimal.ZERO, BigDecimal.ZERO, currentAllowance.getCategoryCode() != null ? currentAllowance.getCategoryCode() : "S"); + } + theAmount.setBasis(theAmount.getBasis().subtract(currentAllowance.getTotalAmount(this))); + decimal factor = currentAllowance.getTaxPercent().divide(new BigDecimal(100)); + theAmount.setCalculated(theAmount.getBasis().multiply(factor)); + + hm[currentAllowance.getTaxPercent().stripTrailingZeros()] = theAmount; + } + }*/ + + return hm; + + } + + + public BigDecimal getValue() + { + return getTotal(); + } + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/VATAmount.cs b/Ghostscript.NET/FacturX/ZUGFeRD/VATAmount.cs new file mode 100644 index 0000000..bd15d6f --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/VATAmount.cs @@ -0,0 +1,103 @@ +using System; + +using java.math; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class VATAmount + { + + public VATAmount(BigDecimal basis, BigDecimal calculated, string categoryCode) : base() + { + this.basis = basis; + this.calculated = calculated; + this.categoryCode = categoryCode; + } + + internal BigDecimal basis, calculated, applicablePercent; + + internal string categoryCode; + + public virtual BigDecimal getApplicablePercent() + { + + return applicablePercent; + } + public virtual VATAmount setApplicablePercent(BigDecimal value) + { + this.applicablePercent = value; + return this; + } + + + public virtual BigDecimal getBasis() + { + + return basis; + } + public virtual VATAmount setBasis(BigDecimal value) + { + this.basis = value.setScale(2, RoundingMode.HALF_UP); + return this; + + } + + + + + + public virtual BigDecimal getCalculated() { + return calculated; + } + + + public virtual VATAmount setCalculated(BigDecimal value) { + + this.calculated = value; + return this; + } + + + /// + /// @deprecated Use + /// String with category code + [Obsolete("Use ")] + public virtual string getDocumentCode() + { + + return categoryCode; + } + public virtual VATAmount setDocumentCode(string value) + + { + this.categoryCode = value; + return this; + } + + + + public virtual string getCategoryCode() + { + + return categoryCode; + } + public virtual VATAmount setCategoryCode(String value) + { + this.categoryCode = value; + return this; + } + + + + public virtual VATAmount add(VATAmount v) + { + return new VATAmount(basis.add(v.getBasis()), calculated.add(v.getCalculated()), this.categoryCode); + } + + public virtual VATAmount subtract(VATAmount v) + { + return new VATAmount(basis.subtract(v.getBasis()), calculated.subtract(v.getCalculated()), this.categoryCode); + } + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRD2PullProvider.cs b/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRD2PullProvider.cs new file mode 100644 index 0000000..832cea0 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRD2PullProvider.cs @@ -0,0 +1,527 @@ +using System; +using System.Collections.Generic; +using System.Text; +using java.math; +using System.Text.RegularExpressions; + + +using System.Reflection; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class ZUGFeRD2PullProvider + { + + //// MAIN CLASS + protected internal String zugferdDateFormatting = "yyyyMMdd"; + protected internal byte[] zugferdData; + protected internal IExportableTransaction trans; + protected internal TransactionCalculator calc; + private string paymentTermsDescription; + protected internal Profile profile = Profiles.getByName("EN16931"); + + + /// + /// enables the flag to indicate a test invoice in the XML structure + /// + public void setTest() + { + } + + private string vatFormat(BigDecimal value) + { + return XMLTools.nDigitFormat(value, 2); + } + + private string currencyFormat(BigDecimal value) + { + return XMLTools.nDigitFormat(value, 2); + } + + private string priceFormat(BigDecimal value) + { + return XMLTools.nDigitFormat(value, 4); + } + + private string quantityFormat(BigDecimal value) + { + return XMLTools.nDigitFormat(value, 4); + } + + public byte[] getXML() + { + return zugferdData; + } + + + public Profile getProfile() + { + return profile; + } + + // @todo check if the two boolean args can be refactored + + /// + ///* + /// returns the UN/CEFACT CII XML for companies(tradeparties), which is actually + /// the same for ZF1 (v 2013b) and ZF2 (v 2016b) + /// + /// some attributes are allowed only for senders in certain profiles + /// some attributes are allowed only for senders or recipients + /// @return + protected internal virtual string getTradePartyAsXML(IZUGFeRDExportableTradeParty party, bool isSender, bool isShipToTradeParty) + { + string xml = ""; + // According EN16931 either GlobalID or seller assigned ID might be present for BuyerTradeParty + // and ShipToTradeParty, but not both. Prefer seller assigned ID for now. + if (party.getID() != null) + { + xml += " " + XMLTools.encodeXML(party.getID()) + "\n"; + } + else if ((party.getGlobalIDScheme() != null) && (party.getGlobalID() != null)) + { + xml = xml + " " + XMLTools.encodeXML(party.getGlobalID()) + "\n"; + } + xml += " " + XMLTools.encodeXML(party.getName()) + "\n"; //$NON-NLS-2$ + + if ((party.getContact() != null) && (isSender || profile == Profiles.getByName("Extended"))) + { + xml = xml + "\n" + " " + XMLTools.encodeXML(party.getContact().getName()) + "\n"; + if (party.getContact().getPhone() != null) + { + + xml = xml + " \n" + " " + XMLTools.encodeXML(party.getContact().getPhone()) + "\n" + " \n"; + } + + if ((party.getContact().getFax() != null) && (profile == Profiles.getByName("Extended"))) + { + xml = xml + " \n" + " " + XMLTools.encodeXML(party.getContact().getFax()) + "\n" + " \n"; + } + if (party.getContact().getEMail() != null) + { + + xml = xml + " \n" + " " + XMLTools.encodeXML(party.getContact().getEMail()) + "\n" + " \n"; + } + + xml = xml + " "; + + } + xml += " \n" + " " + XMLTools.encodeXML(party.getZIP()) + "\n" + " " + XMLTools.encodeXML(party.getStreet()) + "\n"; + if (party.getAdditionalAddress() != null) + { + xml += " " + XMLTools.encodeXML(party.getAdditionalAddress()) + "\n"; + } + xml += " " + XMLTools.encodeXML(party.getLocation()) + "\n" + " " + XMLTools.encodeXML(party.getCountry()) + "\n" + " \n"; + if ((party.getVATID() != null) && (!isShipToTradeParty)) + { + xml += " \n" + " " + XMLTools.encodeXML(party.getVATID()) + "\n" + " \n"; + } + if ((party.getTaxID() != null) && (!isShipToTradeParty)) + { + xml += " \n" + " " + XMLTools.encodeXML(party.getTaxID()) + "\n" + " \n"; + + } + return xml; + + } + + + /// + ///* + /// returns the XML for a charge or allowance on item level + /// + /// + /// @return + /* protected internal virtual string getAllowanceChargeStr(IZUGFeRDAllowanceCharge allowance, IAbsoluteValueProvider item) + { + string percentage = ""; + string chargeIndicator = "false"; + if ((allowance.getPercent() != null) && (profile == Profiles.getByName("Extended"))) + { + percentage = "" + vatFormat(allowance.getPercent()) + ""; + percentage += "" + item.getValue() + ""; + } + if (allowance.isCharge()) + { + chargeIndicator = "true"; + } + + string reason = ""; + if ((allowance.getReason() != null) && (profile == Profiles.getByName("Extended"))) + { + // only in extended profile + reason = "" + XMLTools.encodeXML(allowance.getReason()) + ""; + } + string allowanceChargeStr = "" + chargeIndicator + "" + percentage + "" + priceFormat(allowance.getTotalAmount(item)) + "" + reason + ""; + return allowanceChargeStr; + }*/ + + public void generateXML(IExportableTransaction trans) + { + this.trans = trans; + this.calc = new TransactionCalculator(trans); + + bool hasDueDate = false; + String germanDateFormatting = "dd.MM.yyyy"; + + string exemptionReason = ""; + + if (trans.getPaymentTermDescription() != null) + { + paymentTermsDescription = trans.getPaymentTermDescription(); + } + + if ((string.ReferenceEquals(paymentTermsDescription, null)) /*&& (trans.getDocumentCode() != org.mustangproject.ZUGFeRD.model.DocumentCodeTypeConstants.CORRECTEDINVOICE)*/) + { + paymentTermsDescription = "Zahlbar ohne Abzug bis " + ((DateTime)trans.getDueDate()).ToString(germanDateFormatting); + + } + + string senderReg = ""; + /* if (trans.getOwnOrganisationFullPlaintextInfo() != null) + { + senderReg = "" + "\n" + " \n" + XMLTools.encodeXML(trans.getOwnOrganisationFullPlaintextInfo()) + " \n" + "REG\n" + "\n"; + + } + */ + string rebateAgreement = ""; + if (trans.rebateAgreementExists()) + { + rebateAgreement = "\n" + " " + "Es bestehen Rabatt- und Bonusvereinbarungen.\n" + "AAK\n" + "\n"; + } + + string subjectNote = ""; + if (trans.getSubjectNote() != null) + { + subjectNote = "\n" + " " + XMLTools.encodeXML(trans.getSubjectNote()) + "\n" + "\n"; + } + + string typecode = "380"; + /* if (trans.getDocumentCode() != null) + { + typecode = trans.getDocumentCode(); + }*/ + string notes = ""; + if (trans.getNotes() != null) + { + foreach (string currentNote in trans.getNotes()) + { + notes = notes + "" + XMLTools.encodeXML(currentNote) + ""; + + } + } + string xml = "\n" + "\n" + " \n" + " \n" + " " + getProfile().getID() + "\n" + " \n" + " \n" + " \n" + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" + " " + typecode + "\n" + " " + ((DateTime)trans.getIssueDate()).ToString(zugferdDateFormatting) + "\n" + notes + subjectNote + rebateAgreement + senderReg + " \n" + " \n"; + int lineID = 0; + foreach (IZUGFeRDExportableItem currentItem in trans.getZFItems()) + { + lineID++; + if (currentItem.getProduct().getTaxExemptionReason() != null) + { + exemptionReason = "" + XMLTools.encodeXML(currentItem.getProduct().getTaxExemptionReason()) + ""; + } + notes = ""; + if (currentItem.getNotes() != null) + { + foreach (string currentNote in currentItem.getNotes()) + { + notes = notes + "" + XMLTools.encodeXML(currentNote) + ""; + + } + } + LineCalculator lc = new LineCalculator(currentItem); + xml = xml + " \n" + " \n" + " " + lineID + "\n" + notes + " \n" + " \n"; + // + " 4012345001235\n" + if (currentItem.getProduct().getSellerAssignedID() != null) + { + xml = xml + " " + XMLTools.encodeXML(currentItem.getProduct().getSellerAssignedID()) + "\n"; + } + if (currentItem.getProduct().getBuyerAssignedID() != null) + { + xml = xml + " " + XMLTools.encodeXML(currentItem.getProduct().getBuyerAssignedID()) + "\n"; + } + string allowanceChargeStr = ""; + /* if (currentItem.getItemAllowances() != null && currentItem.getItemAllowances().length > 0) + { + foreach (IZUGFeRDAllowanceCharge allowance in currentItem.getItemAllowances()) + { + allowanceChargeStr += getAllowanceChargeStr(allowance, currentItem); + } + } + if (currentItem.getItemCharges() != null && currentItem.getItemCharges().length > 0) + { + foreach (IZUGFeRDAllowanceCharge charge in currentItem.getItemCharges()) + { + allowanceChargeStr += getAllowanceChargeStr(charge, currentItem); + + } + } + */ + + xml = xml + " " + XMLTools.encodeXML(currentItem.getProduct().getName()) + "\n" + " " + XMLTools.encodeXML(currentItem.getProduct().getDescription()) + "\n" + " \n" + " \n" + " \n" + " " + priceFormat(lc.getPriceGross()) + "\n" + "" + quantityFormat(currentItem.getBasisQuantity()) + "\n" + allowanceChargeStr + " \n" + " \n" + " " + priceFormat(lc.getPrice()) + "\n" + " " + quantityFormat(currentItem.getBasisQuantity()) + "\n" + " \n" + " \n" + " \n" + " " + quantityFormat(currentItem.getQuantity()) + "\n" + " \n" + " \n" + " \n" + " VAT\n" + exemptionReason + " " + currentItem.getProduct().getTaxCategoryCode() + "\n" + " " + vatFormat(currentItem.getProduct().getVATPercent()) + "\n" + " \n"; + if ((currentItem.getDetailedDeliveryPeriodFrom() != null) || (currentItem.getDetailedDeliveryPeriodTo() != null)) + { + xml = xml + ""; + if (currentItem.getDetailedDeliveryPeriodFrom() != null) + { + xml = xml + "" + ((DateTime)currentItem.getDetailedDeliveryPeriodFrom()).ToString(zugferdDateFormatting) + ""; + } + if (currentItem.getDetailedDeliveryPeriodTo() != null) + { + xml = xml + "" + ((DateTime)currentItem.getDetailedDeliveryPeriodTo()).ToString(zugferdDateFormatting) + ""; + } + xml = xml + ""; + + } + + xml = xml + " \n" + " " + currencyFormat(lc.getItemTotalNetAmount()) + "\n" + " \n"; + if (currentItem.getAdditionalReferencedDocumentID() != null) + { + xml = xml + " " + currentItem.getAdditionalReferencedDocumentID() + "130\n"; + + } + xml = xml + " \n" + " \n"; + + } + + xml = xml + " \n"; + if (trans.getReferenceNumber() != null) + { + xml = xml + " " + XMLTools.encodeXML(trans.getReferenceNumber()) + "\n"; + + } + xml = xml + " \n" + getTradePartyAsXML(trans.getSender(), true, false) + " \n" + " \n"; + // + " GE2020211\n" + // + " 4000001987658\n" + + xml += getTradePartyAsXML(trans.getRecipient(), false, false); + xml += " \n"; + + if (trans.getBuyerOrderReferencedDocumentID() != null) + { + xml = xml + " \n" + " " + XMLTools.encodeXML(trans.getBuyerOrderReferencedDocumentID()) + "\n" + " \n"; + } + if (trans.getContractReferencedDocument() != null) + { + xml = xml + " \n" + " " + XMLTools.encodeXML(trans.getContractReferencedDocument()) + "\n" + " \n"; + } + + // Additional Documents of XRechnung (Rechnungsbegruendende Unterlagen - BG-24 XRechnung) + /* if (trans.getAdditionalReferencedDocuments() != null) + { + foreach (FileAttachment f in trans.getAdditionalReferencedDocuments()) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final String documentContent = new String(Base64.getEncoder().encodeToString(f.getData())); + string documentContent = new string(Convert.ToBase64String(f.getData())); + xml = xml + " \n" + " " + f.getFilename() + "\n" + " 916\n" + " " + f.getDescription() + "\n" + " " + documentContent + "\n" + " \n"; + } + } + */ + xml = xml + " \n" + " \n"; + if (this.trans.getDeliveryAddress() != null) + { + xml += "" + getTradePartyAsXML(this.trans.getDeliveryAddress(), false, true) + ""; + } + + xml += " \n" + " "; + + if (trans.getDeliveryDate() != null) + { + xml += "" + ((DateTime)trans.getDeliveryDate()).ToString(zugferdDateFormatting) + ""; + } + else + { + throw new System.InvalidOperationException("No delivery date provided"); + } + xml += "\n"; + xml += " \n" + " \n" + " \n" + " " + XMLTools.encodeXML(trans.getNumber()) + "\n" + " " + trans.getCurrency() + "\n"; + + if (trans.getTradeSettlementPayment() != null) + { + foreach (IZUGFeRDTradeSettlementPayment payment in trans.getTradeSettlementPayment()) + { + if (payment != null) + { + hasDueDate = true; + xml += payment.getSettlementXML(); + } + } + } + if (trans.getTradeSettlement() != null) + { + foreach (IZUGFeRDTradeSettlement payment in trans.getTradeSettlement()) + { + if (payment != null) + { + if (payment is IZUGFeRDTradeSettlementPayment) + { + hasDueDate = true; + } + xml += payment.getSettlementXML(); + } + } + } + /* if (trans.getDocumentCode() == DocumentCodeTypeConstants.CORRECTEDINVOICE) + { + hasDueDate = false; + } + */ + Dictionary VATPercentAmountMap = calc.getVATPercentAmountMap(); + foreach (BigDecimal currentTaxPercent in VATPercentAmountMap.Keys) + { + VATAmount amount = VATPercentAmountMap[currentTaxPercent]; + if (amount != null) + { + xml += " \n" + " " + currencyFormat(amount.getCalculated()) + "\n" + " VAT\n" + exemptionReason + " " + currencyFormat(amount.getBasis()) + "\n" + " " + amount.getCategoryCode() + "\n" + " " + vatFormat(currentTaxPercent) + "\n" + " \n"; //$NON-NLS-2$ + + } + } + if ((trans.getDetailedDeliveryPeriodFrom() != null) || (trans.getDetailedDeliveryPeriodTo() != null)) + { + xml = xml + ""; + if (trans.getDetailedDeliveryPeriodFrom() != null) + { + xml = xml + "" + ((DateTime)trans.getDetailedDeliveryPeriodFrom()).ToString(zugferdDateFormatting) + ""; + } + if (trans.getDetailedDeliveryPeriodTo() != null) + { + xml = xml + "" + ((DateTime)trans.getDetailedDeliveryPeriodTo()).ToString(zugferdDateFormatting) + ""; + } + xml = xml + ""; + + + } + /* + if ((trans.getZFCharges() != null) && (trans.getZFCharges().length > 0)) + { + + foreach (BigDecimal currentTaxPercent in VATPercentAmountMap.Keys) + { + if (calc.getChargesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) + { + + + xml = xml + " \n" + " \n" + " true\n" + " \n" + " " + currencyFormat(calc.getChargesForPercent(currentTaxPercent)) + "\n" + " " + XMLTools.encodeXML(calc.getChargeReasonForPercent(currentTaxPercent)) + "\n" + " \n" + " VAT\n" + " " + VATPercentAmountMap[currentTaxPercent].getCategoryCode() + "\n" + " " + vatFormat(currentTaxPercent) + "\n" + " \n" + " \n"; + + } + } + + } + + if ((trans.getZFAllowances() != null) && (trans.getZFAllowances().length > 0)) + { + foreach (BigDecimal currentTaxPercent in VATPercentAmountMap.Keys) + { + if (calc.getAllowancesForPercent(currentTaxPercent).compareTo(BigDecimal.ZERO) != 0) + { + xml = xml + " \n" + " \n" + " false\n" + " \n" + " " + currencyFormat(calc.getAllowancesForPercent(currentTaxPercent)) + "\n" + " " + XMLTools.encodeXML(calc.getAllowanceReasonForPercent(currentTaxPercent)) + "\n" + " \n" + " VAT\n" + " " + VATPercentAmountMap[currentTaxPercent].getCategoryCode() + "\n" + " " + vatFormat(currentTaxPercent) + "\n" + " \n" + " \n"; + } + } + } + */ + + if (trans.getPaymentTerms() == null) + { + xml = xml + " \n" + " " + paymentTermsDescription + "\n"; + + /* if (trans.getTradeSettlement() != null) + { + foreach (IZUGFeRDTradeSettlement payment in trans.getTradeSettlement()) + { + if ((payment != null) && (payment is IZUGFeRDTradeSettlementDebit)) + { + xml += payment.getPaymentXML(); + } + } + } + */ + if (hasDueDate && (trans.getDueDate() != null)) + { + xml = xml + " " + ((DateTime)trans.getDueDate()).ToString(zugferdDateFormatting) + "\n"; // 20130704 + + } + xml = xml + " \n"; + } + else + { + xml = xml + buildPaymentTermsXml(); + } + + + //string allowanceTotalLine = "" + currencyFormat(calc.getAllowancesForPercent(null)) + ""; + + //string chargesTotalLine = "" + currencyFormat(calc.getChargesForPercent(null)) + ""; + string chargesTotalLine = ""; + string allowanceTotalLine = ""; + xml = xml + "\n" + "" + currencyFormat(calc.getTotal()) + "\n" + chargesTotalLine + allowanceTotalLine + "" + currencyFormat(calc.getTaxBasis()) + "\n" + " " + currencyFormat(calc.getGrandTotal().subtract(calc.getTaxBasis())) + "\n" + " " + currencyFormat(calc.getGrandTotal()) + "\n" + " " + currencyFormat(calc.getTotalPrepaid()) + "\n" + " " + currencyFormat(calc.getGrandTotal().subtract(calc.getTotalPrepaid())) + "\n" + " \n" + " \n"; + // + " \n" + // + " \n" + // + " \n" + // + " Wir erlauben uns Ihnen folgende Positionen aus der Lieferung Nr. + // 2013-51112 in Rechnung zu stellen:\n" + // + " \n" + // + " \n" + // + " \n"; + + xml = xml + " \n" + ""; + + System.Text.UTF8Encoding encoding = new + System.Text.UTF8Encoding(); + + byte[] zugferdRaw; + zugferdRaw = encoding.GetBytes(xml); ; + + zugferdData = XMLTools.removeBOM(zugferdRaw); + } + + public void setProfile(Profile p) + { + profile = p; + } + private string buildPaymentTermsXml() + { + string paymentTermsXml = ""; + + IZUGFeRDPaymentTerms paymentTerms = trans.getPaymentTerms(); + //IZUGFeRDPaymentDiscountTerms discountTerms = paymentTerms.getDiscountTerms(); + DateTime dueDate = paymentTerms.getDueDate(); + if (dueDate != null /*&& discountTerms != null && discountTerms.getBaseDate() != null*/) + { + throw new System.InvalidOperationException("if paymentTerms.dueDate is specified, paymentTerms.discountTerms.baseDate has not to be specified"); + } + paymentTermsXml += "" + paymentTerms.getDescription() + ""; + if (dueDate != null) + { + paymentTermsXml += ""; + paymentTermsXml += "" + dueDate.ToString(zugferdDateFormatting) + ""; + paymentTermsXml += ""; + } + /* + if (discountTerms != null) + { + paymentTermsXml += ""; + string currency = trans.getCurrency(); + string basisAmount = currencyFormat(calc.getGrandTotal()); + paymentTermsXml += "" + basisAmount + ""; + paymentTermsXml += "" + discountTerms.getCalculationPercentage().ToString() + ""; + + if (discountTerms.getBaseDate() != null) + { + DateTime baseDate = discountTerms.getBaseDate(); + paymentTermsXml += ""; + paymentTermsXml += "" + zugferdDateFormat.format(baseDate) + ""; + paymentTermsXml += ""; + + paymentTermsXml += "" + discountTerms.getBasePeriodMeasure() + ""; + } + + paymentTermsXml += ""; + } + */ + paymentTermsXml += ""; + return paymentTermsXml; + } + + + } +} \ No newline at end of file diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRDExporter.cs b/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRDExporter.cs new file mode 100644 index 0000000..274e5d7 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRDExporter.cs @@ -0,0 +1,77 @@ +using System; +using System.Collections.Generic; +using System.IO; +using iText.Kernel.Pdf; +using System.Xml; +using Microsoft.Extensions.Logging; +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + public class ZUGFeRDExporter + { + protected String? gsDLL = null; + protected String? sourcePDF = null; + protected bool noSourceCopy = false; + protected String profile = "EN16931"; + protected int version = 2; + protected IExportableTransaction? trans = null; + + public ZUGFeRDExporter(String gsDLL) + { + this.gsDLL = gsDLL; + } + public ZUGFeRDExporter load(String PDFfilename) + { + String basename=Path.GetFileName(PDFfilename); + this.sourcePDF = Path.GetTempPath() + basename; + String d1=Path.GetDirectoryName(PDFfilename)+Path.DirectorySeparatorChar; + String d2=Path.GetTempPath(); + if (d1.Equals(Path.GetTempPath())) { + noSourceCopy=true; + } else { + File.Copy(PDFfilename, sourcePDF); + } + return this; + } + public ZUGFeRDExporter setTransaction(IExportableTransaction trans) + { + this.trans = trans; + return this; + } + + public ZUGFeRDExporter setZUGFeRDVersion(int version) + { + this.version = version; + return this; + } + + public ZUGFeRDExporter setProfile(String profile) + { + this.profile = profile; + return this; + } + + + public void export(String targetFilename) + { + + PDFConverter pc = new PDFConverter(sourcePDF, targetFilename); + + ZUGFeRD2PullProvider zf2p = new ZUGFeRD2PullProvider(); + zf2p.setProfile(Profiles.getByName(profile)); + zf2p.generateXML(trans); + System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); + + string tempfilename = Path.GetTempPath() + "\\factur-x.xml"; + File.WriteAllBytes(tempfilename, zf2p.getXML()); + + pc.EmbedXMLForZF(tempfilename, Convert.ToString(version)); + pc.ConvertToPDFA3(gsDLL); + File.Delete(Path.GetTempPath() + "\\factur-x.xml"); + if (!noSourceCopy) { + File.Delete(sourcePDF); + } + + } + } +} diff --git a/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRDImporter.cs b/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRDImporter.cs new file mode 100644 index 0000000..d7d7958 --- /dev/null +++ b/Ghostscript.NET/FacturX/ZUGFeRD/ZUGFeRDImporter.cs @@ -0,0 +1,1342 @@ +using System; +using System.Collections.Generic; +using System.IO; +using iText.Kernel.Pdf; +using System.Xml; +using Microsoft.Extensions.Logging; + +/// +/// ********************************************************************** Copyright 2018 Jochen Staerk Use is subject to license terms. Licensed under the +/// Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at +/// http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed +/// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions +/// and limitations under the License. +/// +namespace Ghostscript.NET.FacturX.ZUGFeRD +{ + + /// + /// Mustangproject's ZUGFeRD implementation ZUGFeRD importer Licensed under the APLv2 + /// + /// @date 2014-07-07 + /// @version 1.1.0 + /// @author jstaerk + /// + + + + using Item = Ghostscript.NET.FacturX.ZUGFeRD.Item; + using Product = Ghostscript.NET.FacturX.ZUGFeRD.Product; + using Document = org.w3c.dom.Document; + using Node = org.w3c.dom.Node; + using NodeList = org.w3c.dom.NodeList; + using SAXException = org.xml.sax.SAXException; + + public class ZUGFeRDImporter + { + + /// + /// if metadata has been found + /// + //JAVA TO C# CONVERTER NOTE: Fields cannot have the same name as methods of the current type: + protected internal bool containsMeta_Conflict = false; + protected System.Xml.XmlDocument xmlDoc; + /// + /// map filenames of additional XML files to their contents + /// + private Dictionary additionalXMLs = new Dictionary(); + /// + /// Raw XML form of the extracted data - may be directly obtained. + /// + private byte[] rawXML = null; + /// + /// XMP metadata + /// + private string xmpString = null; // XMP metadata + /// + /// parsed Document + /// + private Document document; + + private readonly ILogger _logger; + + + protected internal ZUGFeRDImporter() + { + //constructor for extending classes + } + + public ZUGFeRDImporter(string pdfFilename) + { + using var loggerFactory = LoggerFactory.Create(builder => + { + builder + .AddFilter("Microsoft", LogLevel.Warning) + .AddFilter("System", LogLevel.Warning) + .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug); + }); + + if (!File.Exists(pdfFilename)) { + throw new Exception("File not found"); + } + + _logger = loggerFactory.CreateLogger(); + _logger.LogInformation("Example log message"); + FromPDF(pdfFilename); + //FileStream fs = File.OpenRead(pdfFilename); + // extractLowLevel(fs); + } + + + public ZUGFeRDImporter(Stream pdfStream) + { + try + { + extractLowLevel(pdfStream); + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final java.io.IOException e) + catch (IOException e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + // _logger.LogError(e.Message); + // throw new ZUGFeRDExportException(e); + } + } + + + /// + /// Extracts a ZUGFeRD invoice from a PDF document represented by an input stream. Errors are reported via exception handling. + /// + /// a inputstream of a pdf file + //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: + //ORIGINAL LINE: private void extractLowLevel(java.io.InputStream pdfStream) throws java.io.IOException + private void extractLowLevel(Stream pdfStream) + { + + } + + /// + + /// ''' Liest eine PDF-Datei, füllt mPDFInfo und liefert im Erfolgsfall (es ist eine ZF-Datei) den Stream zurück um die XML-Daten auszulesen. + + /// ''' Normal und vor dem schreiben kann die Check-Methode aufgerufen werden, importCheck ist eine autarke Methode die zurückliefert ob ein Leseversuch + + /// ''' (in dem Fall einer ZUGFeRD-Datei) überhaupt Aussicht auf Erfolg brächte + + /// ''' + + /// ''' + + /// ''' + protected PdfStream GetStreamFromPDF(string pPDFFile) + { + PdfReader reader = null/* TODO Change to default(_) if this is not a reference type */; + try + { + reader = new PdfReader(pPDFFile); + } + catch (Exception ex) + { + return null/* TODO Change to default(_) if this is not a reference type */; + }// No valid PDF file + //mPDFFileInfo.isPDF = true; + + PdfDocument doc = new PdfDocument(reader); + + PdfAConformanceLevel PDFConfLevel = doc.GetReader().GetPdfAConformanceLevel(); + if (PDFConfLevel == null) + return null/* TODO Change to default(_) if this is not a reference type */;// kein PDF/A + //mPDFFileInfo.isPDFA = true; + + //mPDFFileInfo.levelConf = PDFConfLevel.GetConformance(); + //mPDFFileInfo.levelPart = PDFConfLevel.GetPart(); + //mPDFFileInfo.isPDFA3 = System.Convert.ToBoolean(mPDFFileInfo.levelPart == "3"); // True + + if ((PDFConfLevel.GetPart() != "3") && (PDFConfLevel.GetPart() != "4")) + return null/* TODO Change to default(_) if this is not a reference type */;// kein PDF/A-3 + + + PdfDictionary root = doc.GetCatalog().GetPdfObject(); + PdfDictionary names = root.GetAsDictionary(PdfName.Names); + PdfDictionary embeddedFiles; // = names.GetAsDictionary(PdfName.EmbeddedFiles) + if (names == null) + return null/* TODO Change to default(_) if this is not a reference type */;// keine eingebetteten dateien + embeddedFiles = names.GetAsDictionary(PdfName.EmbeddedFiles); + PdfArray namesArray = embeddedFiles.GetAsArray(PdfName.Names); + int currentNameIndex = 0; + PdfDictionary filespec; + PdfStream stream = null/* TODO Change to default(_) if this is not a reference type */; + + if (namesArray == null) + { + // Es gibt in PDF/A-3 zwei Möglichkeiten Dateien einzubetten: Flat arrays und "normal" + // hier Flat Arrays + PdfArray kidsArray = (PdfArray)embeddedFiles.Get(PdfName.Kids); + filespec = kidsArray.GetAsDictionary(0); + PdfObject pdfNamesArrayObject = filespec.Get(PdfName.Names); + if (pdfNamesArrayObject.IsArray()) + { + PdfArray pdfNamesArray = (PdfArray)pdfNamesArrayObject; + + //mPDFFileInfo.ctrAttachments = pdfNamesArray.Size; + for (int j = 0; j <= pdfNamesArray.Size() - 1; j++) + { + PdfObject pdfNamesArrayItemObject = pdfNamesArray.Get(j); + if (pdfNamesArrayItemObject.IsString()) + { + PdfString filename = (PdfString)pdfNamesArrayItemObject; + + } + else if (pdfNamesArrayItemObject.IsDictionary()) + { + PdfDictionary pdfNamesArrayDictionary = (PdfDictionary)pdfNamesArrayItemObject; + PdfDictionary pdfEFdict = (PdfDictionary)pdfNamesArrayDictionary.Get(PdfName.EF); + stream = (PdfStream)pdfEFdict.Get(PdfName.F); + } + } + } + } + else + { + //mPDFFileInfo.ctrAttachments = namesArray.Size; + // Hier werden normal eingebettete Dateien ausgelesen + while (currentNameIndex < namesArray.Size()) + { + namesArray.GetAsName(currentNameIndex); + currentNameIndex += 1; + filespec = namesArray.GetAsDictionary(currentNameIndex); + currentNameIndex += 1; + PdfDictionary refs = filespec.GetAsDictionary(PdfName.EF); + foreach (PdfName key in refs.KeySet()) + { + string filename = filespec.GetAsString(key).ToString(); + + if (filename.ToLower() == "factur-x.xml" | filename.ToLower() == "zugferd-invoice.xml" | filename.ToLower() == "xrechnung.xml" | filename.ToLower() == "order-x.xml" | filename.ToLower() == "deliver-x.xml") + stream = refs.GetAsStream(key); + } + } + } + //if (stream != null) + // mPDFFileInfo.hasZFAttachment = true; + + + return stream; + } + + /// + /// ''' Lesen der ZUGFeRD-XML-Struktur aus einer PDF-Datei in eine Zieldatei + /// ''' + /// ''' + /// ''' false, falls nicht gelesen werden kann. Probleme können in dem Fall mPDFInfo entnommen werden, dort muss alles auf True bzw. 1 stehen + public bool FromPDF(string pPDFFile) + { + PdfStream stream = GetStreamFromPDF(pPDFFile); + if (stream == null) + return false; // details in mPDFInfo + else + { + xmlDoc = new System.Xml.XmlDocument(); + // Dim encoding As New System.Text.UTF8Encoding(True) ' The boolean parameter controls BOM + // Dim reader As New System.IO.StreamReader("your file path", encoding) + + + // Dim xm As XmlReader = XmlReader.Create(New StringReader(Text.Encoding.UTF8.GetString(stream.GetBytes))) + // + System.Text.UTF8Encoding enc = new System.Text.UTF8Encoding(false); + // Dim xm As XmlReader = XmlReader.Create(enc.GetString(stream.GetBytes)) + // Dim encoding As New System.Text.UTF8Encoding(False) ' The boolean parameter controls BOM + + // Dim readerx As New System.IO.StreamReader("C:\Users\jstaerk\test.xml", encoding) + byte[] xmlBytes = stream.GetBytes(); + string xml = enc.GetString(xmlBytes); + + if (xmlBytes.Length > 3 & xmlBytes[0] == 239 & xmlBytes[1] == 187 & xmlBytes[2] == 191) + // has a UTF8 BOM of three bytes, which is converted to ONE single unicode character in the String + xml = xml.Substring(1); + + + xmlDoc.LoadXml(xml); + + rawXML = xmlBytes; + // FromXML(xmlDoc); + + return true; + } + } + + + + /// + /// Returns the raw XML data as extracted from the ZUGFeRD PDF file. + /// + /// the raw ZUGFeRD XML data + public virtual byte[] getRawXML() + { + return rawXML; + } + /* + protected internal virtual Document getDocument() + { + return document; + } + + + private void setDocument() + { + DocumentBuilderFactory xmlFact = DocumentBuilderFactory.newInstance(); + xmlFact.setNamespaceAware(true); + DocumentBuilder builder = xmlFact.newDocumentBuilder(); + MemoryStream @is = new MemoryStream(rawXML); + /// is.skip(guessBOMSize(is)); + document = builder.parse(@is); + } + + + public virtual void setRawXML(sbyte[] rawXML) + { + this.rawXML = rawXML; + try + { + setDocument(); + } + catch (Exception e) when (e is ParserConfigurationException || e is SAXException) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + throw new ZUGFeRDExportException(e); + } + } + + + + */ + protected internal virtual string extractString(string xpathStr) + { + XmlNode resultNode = xmlDoc.SelectSingleNode(xpathStr); + + + + + /* string result = extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']/*[local-name() = 'DuePayableAmount']"); + if (string.ReferenceEquals(result, null) || result.Length == 0) + { + + // fx/zf would be SpecifiedTradeSettlementMonetarySummation + // but ox is SpecifiedTradeSettlementHeaderMonetarySummation... + result = extractString("//*[local-name() = 'GrandTotalAmount']"); + + + } + */ + if (resultNode.InnerText == null) { return ""; } + return resultNode.InnerText; + + } + /// the reference (purpose) the sender specified for this invoice + public virtual string getForeignReference() + { + string result = extractString("//*[local-name() = 'ApplicableHeaderTradeSettlement']/*[local-name() = 'PaymentReference']"); + if (string.ReferenceEquals(result, null) || result.Length == 0) + { + result = extractString("//*[local-name() = 'ApplicableSupplyChainTradeSettlement']/*[local-name() = 'PaymentReference']"); + } + return result; + } + + /// the ZUGFeRD Profile + public virtual string getZUGFeRDProfil() + { + switch (extractString("//*[local-name() = 'GuidelineSpecifiedDocumentContextParameter']//*[local-name() = 'ID']")) + { + case "urn:cen.eu:en16931:2017": + case "urn:ferd:CrossIndustryDocument:invoice:1p0:comfort": + return "COMFORT"; + case "urn:cen.eu:en16931:2017#compliant#urn:factur-x.eu:1p0:basic": + case "urn:ferd:CrossIndustryDocument:invoice:1p0:basic": + return "BASIC"; + case "urn:factur-x.eu:1p0:basicwl": + return "BASIC WL"; + case "urn:factur-x.eu:1p0:minimum": + return "MINIMUM"; + case "urn:ferd:CrossIndustryDocument:invoice:1p0:extended": + case "urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended": + return "EXTENDED"; + } + return ""; + } + + /// the Invoice Currency Code + public virtual string getInvoiceCurrencyCode() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'ApplicableSupplyChainTradeSettlement']//*[local-name() = 'InvoiceCurrencyCode']"); + } + else + { + return extractString("//*[local-name() = 'ApplicableHeaderTradeSettlement']//*[local-name() = 'InvoiceCurrencyCode']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + + return ""; + } + } + + /// the IssuerAssigned ID + public virtual string getIssuerAssignedID() + { + return extractIssuerAssignedID("BuyerOrderReferencedDocument"); + } + + /// the SellerOrderReferencedDocument IssuerAssigned ID + public virtual string getSellerOrderReferencedDocumentIssuerAssignedID() + { + return extractIssuerAssignedID("SellerOrderReferencedDocument"); + } + + /// the IssuerAssigned ID + public virtual string getContractOrderReferencedDocumentIssuerAssignedID() + { + return extractIssuerAssignedID("ContractReferencedDocument"); + } + + private string extractIssuerAssignedID(string propertyName) + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'BuyerOrderReferencedDocument']//*[local-name() = 'ID']"); + } + else + { + return extractString("//*[local-name() = 'BuyerOrderReferencedDocument']//*[local-name() = 'IssuerAssignedID']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the BuyerTradeParty ID + public virtual string getBuyerTradePartyID() + { + return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'ID']"); + } + + /// the Issue Date() + public virtual string getIssueDate() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'HeaderExchangedDocument']//*[local-name() = 'IssueDateTime']//*[local-name() = 'DateTimeString']"); + } + else + { + return extractString("//*[local-name() = 'ExchangedDocument']//*[local-name() = 'IssueDateTime']//*[local-name() = 'DateTimeString']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the TaxBasisTotalAmount + public virtual string getTaxBasisTotalAmount() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementMonetarySummation']//*[local-name() = 'TaxBasisTotalAmount']"); + } + else + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'TaxBasisTotalAmount']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the TaxTotalAmount + public virtual string getTaxTotalAmount() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementMonetarySummation']//*[local-name() = 'TaxTotalAmount']"); + } + else + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'TaxTotalAmount']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the RoundingAmount + public virtual string getRoundingAmount() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementMonetarySummation']//*[local-name() = 'RoundingAmount']"); + } + else + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'RoundingAmount']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the TotalPrepaidAmount + public virtual string getPaidAmount() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementMonetarySummation']//*[local-name() = 'TotalPrepaidAmount']"); + } + else + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'TotalPrepaidAmount']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// SellerTradeParty GlobalID + public virtual string getSellerTradePartyGlobalID() + { + return extractString("//*[local-name() = 'SellerTradeParty']//*[local-name() = 'GlobalID']"); + } + + /// the BuyerTradeParty GlobalID + public virtual string getBuyerTradePartyGlobalID() + { + return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'GlobalID']"); + } + + /// the BuyerTradeParty SpecifiedTaxRegistration ID + public virtual string getBuyertradePartySpecifiedTaxRegistrationID() + { + return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'SpecifiedTaxRegistration']//*[local-name() = 'ID']"); + } + + + /// the IncludedNote + public virtual string getIncludedNote() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'HeaderExchangedDocument']//*[local-name() = 'IncludedNote']"); + } + else + { + return extractString("//*[local-name() = 'ExchangedDocument']//*[local-name() = 'IncludedNote']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the BuyerTradeParty Name + public virtual string getBuyerTradePartyName() + { + return extractString("//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'Name']"); + } + + + + /// the line Total Amount + public virtual string getLineTotalAmount() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementMonetarySummation']//*[local-name() = 'LineTotalAmount']"); + } + else + { + return extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']//*[local-name() = 'LineTotalAmount']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the Payment Terms + public virtual string getPaymentTerms() + { + return extractString("//*[local-name() = 'SpecifiedTradePaymentTerms']//*[local-name() = 'Description']"); + } + + /// the Taxpoint Date + public virtual string getTaxPointDate() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'ActualDeliverySupplyChainEvent']//*[local-name() = 'OccurrenceDateTime']//*[local-name() = 'DateTimeString']"); + } + else + { + return extractString("//*[local-name() = 'ActualDeliverySupplyChainEvent']//*[local-name() = 'OccurrenceDateTime']//*[local-name() = 'DateTimeString']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + /// the Invoice ID + public virtual string getInvoiceID() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'HeaderExchangedDocument']//*[local-name() = 'ID']"); + } + else + { + return extractString("//*[local-name() = 'ExchangedDocument']//*[local-name() = 'ID']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + + + /// the document code + public virtual string getDocumentCode() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'HeaderExchangedDocument']/*[local-name() = 'TypeCode']"); + } + else + { + return extractString("//*[local-name() = 'ExchangedDocument']/*[local-name() = 'TypeCode']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + + /// the referred document + public virtual string getReference() + { + try + { + if (getVersion() == 1) + { + return extractString("//*[local-name() = 'ApplicableSupplyChainTradeAgreement']/*[local-name() = 'BuyerReference']"); + } + else + { + return extractString("//*[local-name() = 'ApplicableHeaderTradeAgreement']/*[local-name() = 'BuyerReference']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return ""; + } + } + + + /// the sender's bank's BIC code + public virtual string getBIC() + { + return extractString("//*[local-name() = 'PayeeSpecifiedCreditorFinancialInstitution']/*[local-name() = 'BICID']"); + } + + + /// the sender's bank name + public virtual string getBankName() + { + return extractString("//*[local-name() = 'PayeeSpecifiedCreditorFinancialInstitution']/*[local-name() = 'Name']"); + } + + + /// the sender's account IBAN code + public virtual string getIBAN() + { + return extractString("//*[local-name() = 'PayeePartyCreditorFinancialAccount']/*[local-name() = 'IBANID']"); + } + + + public virtual string getHolder() + { + return extractString("//*[local-name() = 'SellerTradeParty']/*[local-name() = 'Name']"); + } + + + /// the total payable amount + public virtual string getAmount() + { + + // xmlDoc property is a XmlDocument + // + XmlNode amountNode = xmlDoc.SelectSingleNode("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']/*[local-name() = 'DuePayableAmount']"); + + + + /* string result = extractString("//*[local-name() = 'SpecifiedTradeSettlementHeaderMonetarySummation']/*[local-name() = 'DuePayableAmount']"); + if (string.ReferenceEquals(result, null) || result.Length == 0) + { + + // fx/zf would be SpecifiedTradeSettlementMonetarySummation + // but ox is SpecifiedTradeSettlementHeaderMonetarySummation... + result = extractString("//*[local-name() = 'GrandTotalAmount']"); + + + } + */ + if (amountNode.InnerText == null) { return ""; } + return amountNode.InnerText; + } + + + /// when the payment is due + public virtual string getDueDate() + { + return extractString("//*[local-name() = 'SpecifiedTradePaymentTerms']/*[local-name() = 'DueDateDateTime']/*[local-name() = 'DateTimeString']"); + } + public virtual int getVersion() + { + if (!containsMeta_Conflict) + { + throw new Exception("Not yet parsed"); + } + if (getUTF8().Contains(" getAdditionalData() + { + return additionalXMLs; + } + + + /// + /// get xmp metadata of the PDF, null if not available + /// + /// string + public virtual string getXMP() + { + return xmpString; + } + + + /// if export found parseable ZUGFeRD data + public virtual bool containsMeta() + { + return containsMeta_Conflict; + } + + + /// raw XML to be set + /// if raw can not be set + //JAVA TO C# CONVERTER WARNING: Method 'throws' clauses are not available in C#: + //ORIGINAL LINE: public void setMeta(String meta) throws java.io.IOException + public virtual void setMeta(string meta) + { + setRawXML(meta.GetBytes()); + } + + + /// raw XML of the invoice + public virtual string getMeta() + { + if (rawXML == null) + { + return null; + } + + return StringHelper.NewString(rawXML); + } + + + + + /// return UTF8 XML (without BOM) of the invoice + + + + + + /// + /// will return true if the metadata (just extract-ed or set with setMeta) contains ZUGFeRD XML + /// + /// true if the invoice contains ZUGFeRD XML + public virtual bool canParse() + { + + // SpecifiedExchangedDocumentContext is in the schema, so a relatively good + // indication if zugferd is present - better than just invoice + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final String meta = getMeta(); + string meta = getMeta(); + return (!string.ReferenceEquals(meta, null)) && (meta.Length > 0) && ((meta.Contains("SpecifiedExchangedDocumentContext") || meta.Contains("ExchangedDocumentContext"))); + } + + + internal static string convertStreamToString(Stream @is) + { + // source https://stackoverflow.com/questions/309424/how-do-i-read-convert-an-inputstream-into-a-string-in-java referring to + // https://community.oracle.com/blogs/pat/2004/10/23/stupid-scanner-tricks + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final java.util.Scanner s = new java.util.Scanner(is, "UTF-8").useDelimiter("\\A"); + Scanner s = (new Scanner(@is, "UTF-8")).useDelimiter("\\A"); + return s.hasNext() ? s.next() : ""; + } + + /// + /// returns an instance of PostalTradeAddress for SellerTradeParty section + /// an instance of PostalTradeAddress + public virtual PostalTradeAddress getBuyerTradePartyAddress() + { + + NodeList nl = null; + + try + { + if (getVersion() == 1) + { + nl = getNodeListByPath("//*[local-name() = 'CrossIndustryDocument']//*[local-name() = 'SpecifiedSupplyChainTradeTransaction']/*[local-name() = 'ApplicableSupplyChainTradeAgreement']//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'PostalTradeAddress']"); + } + else + { + nl = getNodeListByPath("//*[local-name() = 'CrossIndustryInvoice']//*[local-name() = 'SupplyChainTradeTransaction']//*[local-name() = 'ApplicableHeaderTradeAgreement']//*[local-name() = 'BuyerTradeParty']//*[local-name() = 'PostalTradeAddress']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return null; + } + + return getAddressFromNodeList(nl); + } + + /// + /// returns an instance of PostalTradeAddress for SellerTradeParty section + /// an instance of PostalTradeAddress + public virtual PostalTradeAddress getSellerTradePartyAddress() + { + + NodeList nl = null; + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final PostalTradeAddress address = new PostalTradeAddress(); + PostalTradeAddress address = new PostalTradeAddress(); + + try + { + if (getVersion() == 1) + { + nl = getNodeListByPath("//*[local-name() = 'CrossIndustryDocument']//*[local-name() = 'SpecifiedSupplyChainTradeTransaction']//*[local-name() = 'ApplicableSupplyChainTradeAgreement']//*[local-name() = 'SellerTradeParty']//*[local-name() = 'PostalTradeAddress']"); + } + else + { + nl = getNodeListByPath("//*[local-name() = 'CrossIndustryInvoice']//*[local-name() = 'SupplyChainTradeTransaction']//*[local-name() = 'ApplicableHeaderTradeAgreement']//*[local-name() = 'SellerTradeParty']//*[local-name() = 'PostalTradeAddress']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return null; + } + + return getAddressFromNodeList(nl); + } + + private PostalTradeAddress getAddressFromNodeList(NodeList nl) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final PostalTradeAddress address = new PostalTradeAddress(); + PostalTradeAddress address = new PostalTradeAddress(); + + if (nl != null) + { + for (int i = 0; i < nl.getLength(); i++) + { + Node n = nl.item(i); + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.NodeList nodes = n.getChildNodes(); + NodeList nodes = n.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) + { + n = nodes.item(j); + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final short nodeType = n.getNodeType(); + short nodeType = n.getNodeType(); + if ((nodeType == Node.ELEMENT_NODE) && (n.getLocalName() != null)) + { + switch (n.getLocalName()) + { + case "PostcodeCode": + address.setPostCodeCode(""); + if (n.getFirstChild() != null) + { + address.setPostCodeCode(n.getFirstChild().getNodeValue()); + } + break; + case "LineOne": + address.setLineOne(""); + if (n.getFirstChild() != null) + { + address.setLineOne(n.getFirstChild().getNodeValue()); + } + break; + case "LineTwo": + address.setLineTwo(""); + if (n.getFirstChild() != null) + { + address.setLineTwo(n.getFirstChild().getNodeValue()); + } + break; + case "LineThree": + address.setLineThree(""); + if (n.getFirstChild() != null) + { + address.setLineThree(n.getFirstChild().getNodeValue()); + } + break; + case "CityName": + address.setCityName(""); + if (n.getFirstChild() != null) + { + address.setCityName(n.getFirstChild().getNodeValue()); + } + break; + case "CountryID": + address.setCountryID(""); + if (n.getFirstChild() != null) + { + address.setCountryID(n.getFirstChild().getNodeValue()); + } + break; + case "CountrySubDivisionName": + address.setCountrySubDivisionName(""); + if (n.getFirstChild() != null) + { + address.setCountrySubDivisionName(n.getFirstChild().getNodeValue()); + } + break; + } + } + } + } + } + return address; + } + + /// + /// returns a list of LineItems + /// a List of LineItem instances + public virtual IList getLineItemList() + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final java.util.List nodeList = getLineItemNodes(); + IList nodeList = getLineItemNodes(); + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final java.util.List lineItemList = new java.util.ArrayList<>(); + IList lineItemList = new List(); + + foreach (Node n in nodeList) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.mustangproject.Item lineItem = new org.mustangproject.Item(null, null, null); + Item lineItem = new Item(null, null, null); + lineItem.setProduct(new Product(null,null,null,null)); + + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.NodeList nl = n.getChildNodes(); + NodeList nl = n.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.Node nn = nl.item(i); + Node nn = nl.item(i); + Node node = null; + if (nn.getLocalName() != null) + { + switch (nn.getLocalName()) + { + case "SpecifiedLineTradeAgreement": + case "SpecifiedSupplyChainTradeAgreement": + + node = getNodeByName(nn.getChildNodes(), "NetPriceProductTradePrice"); + if (node != null) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.NodeList tradeAgreementChildren = node.getChildNodes(); + NodeList tradeAgreementChildren = node.getChildNodes(); + node = getNodeByName(tradeAgreementChildren, "ChargeAmount"); + lineItem.setPrice(tryBigDecimal(getNodeValue(node))); + node = getNodeByName(tradeAgreementChildren, "BasisQuantity"); + if (node != null && node.getAttributes() != null) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); + Node unitCodeAttribute = node.getAttributes().getNamedItem("unitCode"); + if (unitCodeAttribute != null) + { + lineItem.getProduct().setUnit(unitCodeAttribute.getNodeValue()); + } + } + } + + node = getNodeByName(nn.getChildNodes(), "GrossPriceProductTradePrice"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "ChargeAmount"); + lineItem.setGrossPrice(tryBigDecimal(getNodeValue(node))); + } + break; + + case "AssociatedDocumentLineDocument": + + node = getNodeByName(nn.getChildNodes(), "LineID"); + lineItem.setId(getNodeValue(node)); + break; + + case "SpecifiedTradeProduct": + + node = getNodeByName(nn.getChildNodes(), "SellerAssignedID"); + lineItem.getProduct().setSellerAssignedID(getNodeValue(node)); + + node = getNodeByName(nn.getChildNodes(), "BuyerAssignedID"); + lineItem.getProduct().setBuyerAssignedID(getNodeValue(node)); + + node = getNodeByName(nn.getChildNodes(), "Name"); + lineItem.getProduct().setName(getNodeValue(node)); + + node = getNodeByName(nn.getChildNodes(), "Description"); + lineItem.getProduct().setDescription(getNodeValue(node)); + break; + + case "SpecifiedLineTradeDelivery": + case "SpecifiedSupplyChainTradeDelivery": + node = getNodeByName(nn.getChildNodes(), "BilledQuantity"); + lineItem.setQuantity(tryBigDecimal(getNodeValue(node))); + break; + + case "SpecifiedLineTradeSettlement": + node = getNodeByName(nn.getChildNodes(), "ApplicableTradeTax"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "RateApplicablePercent"); + lineItem.getProduct().setVATPercent(tryBigDecimal(getNodeValue(node))); + } + + node = getNodeByName(nn.getChildNodes(), "ApplicableTradeTax"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "CalculatedAmount"); + lineItem.setTax(tryBigDecimal(getNodeValue(node))); + } + + node = getNodeByName(nn.getChildNodes(), "SpecifiedTradeSettlementLineMonetarySummation"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "LineTotalAmount"); + lineItem.setLineTotalAmount(tryBigDecimal(getNodeValue(node))); + } + break; + case "SpecifiedSupplyChainTradeSettlement": + //ZF 1! + + node = getNodeByName(nn.getChildNodes(), "ApplicableTradeTax"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "ApplicablePercent"); + lineItem.getProduct().setVATPercent(tryBigDecimal(getNodeValue(node))); + } + + node = getNodeByName(nn.getChildNodes(), "ApplicableTradeTax"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "CalculatedAmount"); + lineItem.setTax(tryBigDecimal(getNodeValue(node))); + } + + node = getNodeByName(nn.getChildNodes(), "SpecifiedTradeSettlementMonetarySummation"); + if (node != null) + { + node = getNodeByName(node.getChildNodes(), "LineTotalAmount"); + lineItem.setLineTotalAmount(tryBigDecimal(getNodeValue(node))); + } + break; + } + } + } + lineItemList.Add(lineItem); + } + return lineItemList; + } + + /// + /// returns a List of LineItem Nodes from ZUGFeRD XML + /// a List of Node instances + public virtual IList getLineItemNodes() + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final java.util.List lineItemNodes = new java.util.ArrayList<>(); + IList lineItemNodes = new List(); + NodeList nl = null; + try + { + if (getVersion() == 1) + { + nl = getNodeListByPath("//*[local-name() = 'CrossIndustryDocument']//*[local-name() = 'SpecifiedSupplyChainTradeTransaction']//*[local-name() = 'IncludedSupplyChainTradeLineItem']"); + } + else + { + nl = getNodeListByPath("//*[local-name() = 'CrossIndustryInvoice']//*[local-name() = 'SupplyChainTradeTransaction']//*[local-name() = 'IncludedSupplyChainTradeLineItem']"); + } + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + } + + for (int i = 0; i < nl.getLength(); i++) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.Node n = nl.item(i); + Node n = nl.item(i); + lineItemNodes.Add(n); + } + return lineItemNodes; + } + + /// + /// Returns a node, found by name. If more nodes with the same name are present, the first occurence will be returned + /// - A NodeList which may contains the searched node + /// The nodes name + /// a Node or null, if nothing is found + private Node getNodeByName(NodeList nl, string name) + { + for (int i = 0; i < nl.getLength(); i++) + { + if ((nl.item(i).getLocalName() != null) && (nl.item(i).getLocalName().Equals(name))) + { + return nl.item(i); + } + else if (nl.item(i).getChildNodes().getLength() > 0) + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final org.w3c.dom.Node node = getNodeByName(nl.item(i).getChildNodes(), name); + Node node = getNodeByName(nl.item(i).getChildNodes(), name); + if (node != null) + { + return node; + } + } + } + return null; + } + + /// + /// Get a NodeList by providing an path + /// a compliable Path + /// a Nodelist or null, if an error occurs + public virtual NodeList getNodeListByPath(string path) + { + + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final javax.xml.xpath.XPathFactory xpathFact = javax.xml.xpath.XPathFactory.newInstance(); + XPathFactory xpathFact = XPathFactory.newInstance(); + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final javax.xml.xpath.XPath xPath = xpathFact.newXPath(); + XPath xPath = xpathFact.newXPath(); + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final String s = path; + string s = path; + + try + { + //JAVA TO C# CONVERTER WARNING: The original Java variable was marked 'final': + //ORIGINAL LINE: final javax.xml.xpath.XPathExpression xpr = xPath.compile(s); + XPathExpression xpr = xPath.compile(s); + return (NodeList) xpr.evaluate(getDocument(), XPathConstants.NODESET); + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (Exception e) + { + //JAVA TO C# CONVERTER WARNING: The .NET Type.FullName property will not always yield results identical to the Java Class.getName method: + _logger.LogError(e.Message); + return null; + } + } + + /// + /// returns the value of an node + /// the Node to get the value from + /// A String or empty String, if no value was found + private string getNodeValue(Node node) + { + if (node != null) + { + if (node.getFirstChild() != null) + { + return node.getFirstChild().getNodeValue(); + } + } + return ""; + } + + /// + /// tries to convert an String to BigDecimal. + /// The value as String + /// a BigDecimal with the value provides as String or a BigDecimal with value 0.00 if an error occurs + private decimal tryBigDecimal(string nodeValue) + { + try + { + return new decimal(nodeValue); + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception e) + catch (ception) + { + try + { + return new decimal(Convert.ToSingle(nodeValue)); + } + //JAVA TO C# CONVERTER WARNING: 'final' catch parameters are not available in C#: + //ORIGINAL LINE: catch (final Exception ex) + catch (ception) + { + return new decimal("0.00"); + } + } + }*/ + } +} diff --git a/Ghostscript.NET/FacturX/assets/AdobeCompat-v2.icc b/Ghostscript.NET/FacturX/assets/AdobeCompat-v2.icc new file mode 100644 index 0000000..47fb1b1 Binary files /dev/null and b/Ghostscript.NET/FacturX/assets/AdobeCompat-v2.icc differ diff --git a/Ghostscript.NET/Ghostscript.NET.csproj b/Ghostscript.NET/Ghostscript.NET.csproj index 621bc42..ba8b944 100644 --- a/Ghostscript.NET/Ghostscript.NET.csproj +++ b/Ghostscript.NET/Ghostscript.NET.csproj @@ -1,75 +1,38 @@ - - + - Debug - AnyCPU - 8.0.30703 - 2.0 - {8BDBDEEC-CAB1-4C0B-86C2-7B0D0D3FE363} + net6.0 Library - Properties - Ghostscript.NET - Ghostscript.NET - v4.0 - 512 - - - - - - - - - + enable + enable + true + true + true + + + + + + false - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - AnyCPU true - false bin\Debug\Ghostscript.NET.XML - pdbonly - true - bin\Release\ - TRACE - prompt - 4 true - AnyCPU - false bin\Release\Ghostscript.NET.xml - true bin\x64\Debug\ - DEBUG;TRACE true - full - AnyCPU - prompt false false - false bin\x64\Release\ - TRACE - true - pdbonly - AnyCPU - prompt false false true - false true @@ -79,81 +42,20 @@ false + Ghostscript.NET + Managed wrapper library around the Ghostscript native library %2832-bit & 64-bit%29, an interpreter for the PostScript language, PDF, related software and documentation. + Habjan + Ghostscript.NET + Copyright © 2013-2021 by Josip Habjan %28habjan%40gmail.com%29. All Rights Reserved. + 1.2.3 + 1.2.3 - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Ghostscript.NET/Properties/AssemblyInfo.cs b/Ghostscript.NET/Properties/AssemblyInfo.cs index 6fbe3af..8d83b80 100644 --- a/Ghostscript.NET/Properties/AssemblyInfo.cs +++ b/Ghostscript.NET/Properties/AssemblyInfo.cs @@ -1,20 +1,9 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("Ghostscript.NET")] -[assembly: AssemblyDescription("Managed wrapper library around the Ghostscript native library (32-bit & 64-bit), an interpreter for the PostScript language, PDF, related software and documentation.")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Habjan")] -[assembly: AssemblyProduct("Ghostscript.NET")] -[assembly: AssemblyCopyright("Copyright © 2013-2021 by Josip Habjan (habjan@gmail.com). All Rights Reserved.")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: Guid("5b1fe89e-e040-4b7a-9c05-478c1756b6e8")] - - -[assembly: AssemblyVersion("1.2.3")] -[assembly: AssemblyFileVersion("1.2.3")] \ No newline at end of file diff --git a/Ghostscript.NET/app.config b/Ghostscript.NET/app.config new file mode 100644 index 0000000..98e1047 --- /dev/null +++ b/Ghostscript.NET/app.config @@ -0,0 +1,11 @@ + + + + + + + + + + +