9. Dez 2024
Lesedauer 17 Min.
Pflichterfüllung
Strukturierte elektronische Rechnungen (E-Invoicing) mit .NET selbst implementiert
.NET-Entwickler können die ab 2025 im B2B-Markt einsetzende Pflicht zur strukturierten elektronischen Rechnungsstellung und -annahme mit Open-Source-Lösungen erfüllen.

Das Thema strukturierter elektronischer Rechnungen (Electronic Billing, E-Invoicing) beschäftigt mich schon seit sehr vielen Jahren. 1998 schrieb ich dazu meine Diplomarbeit im Rahmen meines Wirtschaftsinformatikstudiums an der Universität Essen in Zusammenarbeit mit der damaligen Essener Telefongesellschaft o.tel.o (siehe auch [1]). Meine Diplomarbeit (siehe [2]) habe ich an mehrere Dutzend Firmen verkaufen können, die sich für meine Ideen interessierten. Auch mein erster Fachbeitrag in der Zeitschrift „iX“ in Ausgabe 9/1998 handelte davon. In dem seither vergangenen guten Vierteljahrhundert passierte allerdings zunächst lange Zeit fast nichts. Erst in den letzten Jahren hat das Thema etwas Fahrt aufgenommen, aber nur im B2G- und B2B-Markt (siehe Kasten Zu wenig hat sich getan im B2C-Markt).
Zu wenig hat sich getan im B2C-Markt
Zu den Ideen in meiner Diplomarbeit gehörte auch ein effizienterer Weg für die Bezahlung von Rechnungen durch Endverbraucher. Rechnungssteller wie Telekommunikationsgesellschaften, Einzelhandelsgeschäfte, Ärzte und Behörden könnten Rechnungen elektronisch an die Bank des Kunden schicken. Die Bank benachrichtigt den Rechnungsempfänger, sie präsentiert diesem die Rechnung auf einer Website, und der Zahlungspflichtige kann mit einem Mausklick die Rechnung bestätigen oder zurückweisen. Bei diesem Prozess entfällt nicht nur der Versand der Rechnung, sondern auch das lästige und fehleranfällige Abtippen von Zahlungsempfänger, Kontodaten, Betrag und Rechnungsnummer. Der Zahlungsempfänger könnte sicher sein, dass er alle notwendigen Angaben für die automatisierte Weiterverarbeitung auf der Überweisung erhält. Der Rechnungsempfänger hätte automatisch bei seiner Bank ein elektronisches Rechnungsarchiv; den Buchungspositionen auf dem Konto wäre direkt ein Beleg zugeordnet.
Alternativen zu EDI
Schon seit den 1970er-Jahren gibt es das Konzept Electronic Data Interchange (EDI) [3] mit zahlreichen Standards wie EDIFACT und ODETTE, mit denen Unternehmen auch elektronische Rechnungen austauschen können. Alle diese EDI-Standards waren jedoch komplex in der Umsetzung, entsprechend kostenaufwendig und nur zwischen Großunternehmen verbreitet. Daher entstanden Ende der 1990er-Jahre einige Ideen zur Gestaltung des elektronischen Rechnungsprozesses auf Basis von XML-Daten über das Internet, die nicht nur zwischen Unternehmen, sondern auch zwischen Unternehmen und Endverbrauchern geeignet waren.Schleppende Akzeptanz von PDF-Rechnungen
Viele Jahre war der elektronische Rechnungsversand in Deutschland an die Verwendung einer qualifizierten elektronischen Signatur gebunden. Erst durch das Steuervereinfachungsgesetz 2011 sind seit dem 1. Juli 2011 elektronische Rechnungen ohne Signatur erlaubt [4] und der Papierrechnung gleichgestellt. Auch danach musste aber das Unternehmen innerbetriebliche Kontrollverfahren etablieren, um die Echtheit der Herkunft, die Unversehrtheit des Inhalts und die Lesbarkeit der Rechnung zu gewährleisten. Das hat viele Unternehmen überfordert, und so verlangten sie von ihren Lieferanten stets eine Rechnung auf Papier. Erst die Corona-Pandemie gab bei den Unternehmen flächendeckend den Impuls, Rechnungen als PDF-Dokument per E-Mail anzunehmen.Eine PDF-Rechnung vereinfacht zwar den Versand, aber nicht die Erfassung in der Buchhaltung. Meist werden PDF-Rechnungen manuell erfasst, manchmal durch Screen-Scraping-Software ausgewertet, die aber meist erst angelernt werden muss. Der Einsatz von künstlicher Intelligenz kann dazu beitragen, die Erfolgsquote beim Screen Scraping deutlich erhöhen (siehe [5] und [6]). Das Thema entwickelt sich aber gerade erst noch.ZUGFeRD
Dabei gibt es in Deutschland bereits seit dem Jahr 2014 einen Standard für strukturierte elektronische Rechnungen im XML-Format mit dem eigenwilligen Namen ZUGFeRD. Dieses Akronym steht für „Zentraler User Guide des Forums elektronische Rechnung Deutschland“ [7]. Das Forum elektronische Rechnung Deutschland wurde unter dem Dach der vom Bundesministerium für Wirtschaft und Energie (BMWi) auf Beschluss des Deutschen Bundestages geförderten Arbeitsgemeinschaft für wirtschaftliche Verwaltung (AWV) gegründet. ZUGFeRD basiert auf dem internationalen Standard Cross Industry Invoice (CII), das durch das United Nations Centre for Trade Facilitation and Electronic Business (UN/CEFACT), also dem Zentrum der Vereinten Nationen für Handelserleichterungen und elektronische Geschäftsprozesse, entwickelt wurde.Die XML-Daten werden bei ZUGFeRD in ein PDF-Dokument (PDF/A-3) als Anhang integriert, sodass der XML-Inhalt mit einem einfachen PDF-Viewer entnommen und betrachtet werden kann (siehe Bild 1). Man spricht daher von einem hybriden Format.
Beispiel für eine ZUGFeRD-Rechnung: Ein PDF mit XML-Anhang – hier in Adobe Acrobat Reader, wobei die enthaltene E-Invoice mit Visual Studio Code geöffnet wurde, weil dies die Standardverknüpfung auf dem System für XML-Dateien war (Bild 1)
Autor
Nach der ersten 2014er-Version von ZUGFeRD erschienen die Versionen 2.0 im März 2019 und 2.1 im März 2020. Hier erfolgte dann eine Angleichung an das parallel entwickelte französische Format Factur-X 1.0. Oft wird auch in Deutschland daher vom Factur-X-Format statt ZUGFeRD gesprochen.ZUGFeRD (aktuelle Version: 2.3 vom 18. September 2024) definiert mittlerweile sechs verschiedene Profile für den XML-Inhalt: Minimum, Basic WL, Basic, EN 16931 (ehemals Comfort genannt), Extended und XRechnung, wobei die ersten beiden XML-Formate in Deutschland umsatzsteuerlich nicht als gültige Rechnungen anerkannt sind.
XRechnung
Parallel zu ZUGFeRD ist das Format XRechnung entstanden. XRechnung ist ein reines XML-Format, welches der EU-Norm 16931 folgt. Diese Norm entstand durch die vom Europäischen Parlament und dem Rat der Europäischen Union am 16. April 2014 verabschiedete EU-Richtlinie 2014/55/EU mit dem Ziel, eine gemeinsame europaweit gültige Norm für das semantische Datenmodell der Kernelemente einer elektronischen Rechnung (also eine europäische Norm für die elektronische Rechnungsstellung) zu etablieren. Die Norm wurde von dem Europäischen Komitee für Normung (CEN) entwickelt und am 17. Oktober 2017 im Amtsblatt der EU als EN 16931 1:2017 veröffentlicht. Sie gibt einen Rahmen vor, lässt Mitgliedsstaaten jedoch eigene Spielräume für die rechtliche, organisatorische und technische Ausgestaltung bei Einführung der elektronischen Rechnung. Unter der Voraussetzung, dass die Ausgestaltung nationaler Standards nicht den Vorgaben der europäischen Richtlinie und Norm widerspricht, ist es jedem Mitgliedstaat gestattet, eigene Erweiterungen (Core Invoice Usage Specifications – CIUS) zu entwickeln. So gibt es in Deutschland zum Beispiel eine Erweiterung für Skonto [8], das in anderen Ländern nicht üblich ist.Die deutsche Version dieser EU-Norm, XRechnung, wurde am 22. Juni 2017 vom IT-Planungsrat für Bund und Länder in der Version 1.0 beschlossen. Seit dem 1. Januar 2019 wird XRechnung von der Koordinierungsstelle für IT-Standards (KoSIT) [9] verantwortet.XRechnungen verwenden als XML-Dialekt entweder den XML-Standard Universal Business Language (UBL) mit Wurzeltag <Invoice> oder Cross Industry Invoice (CII, wie bei ZUGFeRD) mit Wurzeltag <CrossIndustryInvoice>, siehe auch [10]. XRechnungen können Anhänge enthalten, zum Beispiel Lieferscheine, Reisekostenbelege oder auch die Rechnung noch mal als PDF-Dokument.Die Bundesbehörden wurden in Deutschland zum Vorreiter bei den elektronischen Rechnungen: Seit dem 27. November 2018 müssen die obersten Bundesbehörden und die Verfassungsorgane des Bundes XRechnungen empfangen können. Seit dem 27. November 2019 gilt dies für alle anderen Bundesbehörden und seit dem 18. April 2020 auch für die Landesbehörden. Seit dem 27. November 2020 sind Lieferanten des Bundes verpflichtet, die B2G-Rechnungsstellung im Rahmen öffentlicher Aufträge für alle Beträge ab 1000 Euro per XRechnung vorzunehmen. Während in einigen Bundesländern auch entsprechende Verpflichtungen auf Landesebene gelten (zum Beispiel Bremen, Baden-Württemberg, Saarland, Hessen, Rheinland-Pfalz), sind in anderen Bundesländern (zum Beispiel Nordrhein-Westfalen, Berlin, Bayern) Papier- und PDF-Rechnungen weiterhin grundsätzlich erlaubt. Behörden steht es aber frei, eine entsprechende Verpflichtung mit dem Lieferanten vertraglich zu vereinbaren.Erwähnt werden muss aber auch, dass innerhalb der EU andere Staaten Deutschland schon sehr weit voraus waren: E-Invoicing-Pflicht für B2G gilt in Dänemark seit dem Jahr 2005 (auf Basis von UBL 1.0 aus dem Jahr 2004), in Schweden seit 2008, Spanien und Finnland seit 2010 sowie seit 2014 in Italien und Österreich.E-Rechnungspflicht für B2B-Rechnungen
Das Gesetz zur Stärkung von Wachstumschancen, Investitionen und Innovation sowie Steuervereinfachung und Steuerfairness (Wachstumschancengesetz) 2024 [11] erweitert die elektronische Rechnungspflicht nun in mehreren Schritten auch auf die Rechnungsstellung zwischen Unternehmen (B2B-Markt), was auch andere Länder schon zuvor eingeführt haben, zum Beispiel Italien seit dem 1. Januar 2019 (dort muss die maschinenlesbare Rechnung auch das Finanzamt gesendet werden). Das deutsche Wachstumschancengesetz wurde am 17. November 2023 im Bundestag beschlossen, kam aber dann in den Vermittlungsausschuss und passierte den Bundesrat erst am 23. März 2024.Elektronische Rechnung im Sinne des Wachstumschancengesetzes bedeutet dabei eine strukturierte elektronische Rechnung gemäß der EU-Norm 16931. Diese erlaubt die Formate ZUGFeRD (ab Version 2.0.1) und XRechnung/Factur-X, aber auch andere europäische Formate wie das italienische „FatturaPA“. Bei hybriden Formaten gilt im Zweifelsfall die eingebettete XML-Datei als Original. Der Rechnungsempfänger muss diese also immer prüfen und darf sich nicht auf das verlassen, was die PDF-Datei anzeigt. EDI-Verfahren bleiben erlaubt, sofern ein Export der Daten in einer der EU-Norm 16931 gemäßen Form möglich ist.Einen bestimmten Übertragungsweg sieht das Wachstumschancengesetz nicht vor, daher ist die Übertragung der elektronischen Rechnung per E-Mail möglich, auch wenn E-Mail keine Zustellungsgarantie bietet und für Phishing anfällig ist. Für die angedachte zukünftige Umsatzsteuermeldung (siehe EU-Projekt „VAT in the Digital Age“ – ViDA) [12], bei der jede einzelne Rechnung unverzüglich an das Finanzamt geht (wie heute schon in Italien, Rumänien und der Türkei), wird wohl eine sicherere und strukturiertere Übertragungsmethode verpflichtend sein. Infrage kommt hier Pan-European Public Procurement OnLine (PEPPOL), siehe [13].Die Pflicht gilt für Rechnungen, Stornorechnungen und Gutschriften zwischen inländischen Unternehmen, auch für Kleinunternehmer beziehungsweise Land- und Forstwirte. Die E-Rechnungs-Pflicht gilt nicht:- wenn der Betrag kleiner als 250 Euro ist,
- für Fahrausweise,
- für Leistungen, die nach § 4 Nummer 8 bis 29 UStG steuerfrei sind (zum Beispiel Bankgeschäfte, Vermietung, Gesundheits- und Pflegedienstleistungen, Schulen),
- wenn Endverbraucher beteiligt sind.
- Bis Ende 2026 dürfen Rechnungen weiterhin auf Papier und elektronische Rechnungen in anderen Formaten (zum Beispiel reines PDF) versendet werden.
- Bis Ende 2027 ist beides immer noch erlaubt, falls der Rechnungsaussteller einen Vorjahresumsatz (Gesamtumsatz nach § 19 Abs. 3 UStG) von maximal 800 000 Euro hat.
- Erst ab 2028 sind die strukturierten elektronischen Rechnungen dann wirklich verpflichtend.

Ausschnitt aus einer XRechnung im Quba-Viewer (Bild 2)
Autor
Bild 2 zeigt auch, dass XRechnung zahlreiche Felder bietet, die optional sind, zum Beispiel für den Abrechnungszeitraum, Projekt- und Vertragsnummern sowie eine Liste früherer Rechnungen.Neben dem Quba-Viewer gibt es für die XRechnung zahlreiche andere Werkzeuge im Netz, zum Beispiel den Validator für XRechnung unter [19].
.NET-Bibliotheken für strukturierte elektronische Rechnungen
Gängige kaufmännische Programme bieten längst Unterstützung für ZUGFeRD und XRechnung. Eine Herausforderung gibt es für Unternehmen,- die nicht mehr gewartete Programme einsetzen,
- Rechnungen mit eigener Software generieren oder
- Rechnungen mit eigener Software automatisiert auswerten.
E-Rechnung erstellen mit ZUGFeRD-csharp
Listing 1 zeigt den Kern der Generierung einer XRechnung unter Einsatz von ZUGFeRD-csharp: Man erstellt zunächst eine Instanz der zentralen Klasse InvoiceDescriptor mit der statischen Methode InvoiceDescriptor.CreateInvoice() unter Angabe der Rechnungsnummer, des Rechnungsdatums und der Währung.Listing 1: Erstellung einer strukturierten elektronischen Rechnung mit der Klasse InvoiceDescriptor
/// &lt;summary&gt;<br/>/// Erstellt eine E-Rechnung mit ZUGFeRD-csharp<br/>/// &lt;/summary&gt;<br/>private InvoiceDescriptor CreateERechnung(<br/> RE_Rechnungen re, P_Partner kunde, AG_Angebote ag)<br/>{<br/> #region --- Ermitteln einiger Werte aus den <br/> #Eingangsdaten<br/> <span class="hljs-built_in">int</span> zahlfristInTagen = re.RE_Zahlfrist ?? <br/> STANDARDZAHLFRIST;<br/> DateTime zahlbarBis = re.RE_DAT.Value.AddDays(<br/> zahlfristInTagen);<br/> <span class="hljs-built_in">decimal</span> summeNetto = re.RP_RechnungsPositionen.Sum(<br/> x =&gt; x.RP_Summe.GetValueOrDefault());<br/> <span class="hljs-built_in">decimal</span> ust = summeNetto * <br/> ((re.UST_Satz.GetValueOrDefault() / <span class="hljs-number">100</span>m));<br/> <span class="hljs-built_in">decimal</span> summeBrutto = summeNetto + ust;<br/> #endregion<br/> <br/> InvoiceDescriptor desc = InvoiceDescriptor.<br/> CreateInvoice(<span class="hljs-string">"R-"</span> + re.RE_ID.ToString(), <br/> re.RE_DAT.Value, CurrencyCodes.EUR);<br/> desc.BusinessProcess = <span class="hljs-string">"urn:fdc:peppol.eu:2017:</span><br/><span class="hljs-string"> poacc:billing:01:1.0"</span>; // Neu ab XRechnung <span class="hljs-number">3.0</span>.<span class="hljs-number">1</span><br/> <br/> #region --- Kopfdaten der Rechnung<br/> <span class="hljs-built_in">if</span> (ag != null) // Es gab ein Angebot zu der Rechnung<br/> {<br/> desc.ReferenceOrderNo = <br/> ag.LeitwegID; // Leitweg-ID für Behörden !!!<br/> desc.AddNote(re.RE_Grund);<br/> desc.AddNote(<span class="hljs-string">"Angebotsnummer: "</span> + ag.AG_GanzeID);<br/> <span class="hljs-built_in">if</span> (ag?.AG_AuftragsDatum != null)<br/> {<br/> desc.AddNote(<span class="hljs-string">"Ihr Auftrag vom "</span> + <br/> ag.AG_AuftragsDatum?.ToShortDateString());<br/> desc.OrderDate = ag.AG_AuftragsDatum;<br/> }<br/> <span class="hljs-built_in">if</span> (ag?.AG_AuftragsNummer != null)<br/> {<br/> {<br/> desc.AddNote(<span class="hljs-string">"Ihre Auftragsnummer: "</span> <br/> + ag.AG_AuftragsNummer);<br/> desc.OrderNo = ag.AG_AuftragsNummer;<br/> }<br/> }<br/> }<br/> <br/> desc.AddNote(<span class="hljs-string">"Falls Sie mehrere Rechnungen von uns </span><br/><span class="hljs-string"> erhalten haben, zahlen Sie diese unbedingt getrennt </span><br/><span class="hljs-string"> unter Angabe der jeweiligen Rechnungsnummer, da die </span><br/><span class="hljs-string"> Buchhaltung vollautomatisiert ist. Zahlungsavis </span><br/><span class="hljs-string"> können nicht verarbeitet werden."</span>);<br/> desc.AddNote(<span class="hljs-string">"Bitte beachten Sie, dass der deutsche </span><br/><span class="hljs-string"> Gesetzgeber uns verpflichtet, alle Nebenleistungen </span><br/><span class="hljs-string"> wie zum Beispiel Reise- und Hotelkosten sowie </span><br/><span class="hljs-string"> Fachbücher zum gleichen Umsatzsteuersatz wie die </span><br/><span class="hljs-string"> Hauptleistung weiter zu berechnen, selbst wenn </span><br/><span class="hljs-string"> dafür ursprünglich ein anderer Steuersatz galt."</span>);<br/> #endregion<br/> <br/> #region --- Informationen über den Rechnungssteller<br/> desc.SetSeller(<br/> <span class="hljs-built_in">na</span><span class="hljs-symbol">me:</span> <span class="hljs-string">"www.IT-Visions.de Dr. Holger Schwichtenberg"</span>,<br/> postco<span class="hljs-symbol">de:</span> <span class="hljs-string">"45257"</span>,<br/> ci<span class="hljs-symbol">ty:</span> <span class="hljs-string">"Essen"</span>,<br/> stre<span class="hljs-symbol">et:</span> <span class="hljs-string">"Fahrenberg 40b"</span>,<br/> <span class="hljs-built_in">count</span><span class="hljs-symbol">ry:</span> CountryCodes.DE,<br/> <span class="hljs-symbol">id:</span> <span class="hljs-string">""</span>,<br/> global<span class="hljs-symbol">ID:</span> new GlobalID(<br/> GlobalIDSchemeIdentifiers.DUNS, <span class="hljs-string">"341344246"</span>)<br/> );<br/> <br/> desc.SetSellerContact(<br/> <span class="hljs-built_in">na</span><span class="hljs-symbol">me:</span> <span class="hljs-string">"Dr. Holger Schwichtenberg"</span>,<br/> orgun<span class="hljs-symbol">it:</span> <span class="hljs-string">"Buchhaltung"</span>,<br/> emailAddre<span class="hljs-symbol">ss:</span> <span class="hljs-string">"Buchhaltung@IT-Visions.de"</span>,<br/> phone<span class="hljs-symbol">no:</span> <span class="hljs-string">"+4920164959044"</span><br/> );<br/> desc.SellerElectronicAddress = new ElectronicAddress() <br/> // Neu ab XRechnung <span class="hljs-number">3.0</span>.<span class="hljs-number">1</span><br/> {<br/> ElectronicAddressSchemeID = ElectronicAddressScheme<br/> Identifiers.EM, // EM = E-Mail<br/> <span class="hljs-built_in">Address</span> = <span class="hljs-string">"Buchhaltung@IT-Visions.de"</span><br/> };<br/> <br/> desc.AddSellerTaxRegistration(<span class="hljs-string">"112/5392/5120"</span>, <br/> TaxRegistrationSchemeID.FC);<br/> desc.AddSellerTaxRegistration(<span class="hljs-string">"DE 187321081"</span>, <br/> TaxRegistrationSchemeID.VA);<br/> #endregion<br/> <br/> #region --- Informationen über den Rechnungsempfänger<br/> desc.SetBuyer(<span class="hljs-built_in">na</span><span class="hljs-symbol">me:</span> kunde.P_Firma,<br/> postco<span class="hljs-symbol">de:</span> kunde.P_PLZ,<br/> ci<span class="hljs-symbol">ty:</span> kunde.P_Ort,<br/> stre<span class="hljs-symbol">et:</span> kunde.P_Strasse,<br/> <span class="hljs-built_in">count</span><span class="hljs-symbol">ry:</span> CountryCodes.DE,<br/> <span class="hljs-symbol">id:</span> kunde.P_ID.ToString());<br/> <br/> desc.BuyerContact = new Contact()<br/> {<br/> Name = kunde.P_Vorname + <span class="hljs-string">" "</span> + kunde.P_Name,<br/> EmailAddress = kunde.P_EMail,<br/> PhoneNo = kunde.P_Telefon<br/> };<br/> <br/> desc.BuyerElectronicAddress = new ElectronicAddress() <br/> // Neu ab XRechnung <span class="hljs-number">3.0</span>.<span class="hljs-number">1</span><br/> {<br/> ElectronicAddressSchemeID = <br/> ElectronicAddressSchemeIdentifiers.EM, <br/> // EM = E-Mail<br/> <span class="hljs-built_in">Address</span> = kunde.P_EMail<br/> };<br/> #endregion<br/> <br/> #region --- Zahlungsbedingungen<br/> desc.SetTradePaymentTerms(<span class="hljs-string">"Bitte überweisen Sie den </span><br/><span class="hljs-string"> Betrag binnen "</span> + zahlfristInTagen + <span class="hljs-string">" Tagen ohne </span><br/><span class="hljs-string"> Abzüge auf unten genanntes Konto. Bitte beachten </span><br/><span class="hljs-string"> Sie, dass Sie nach §286 BGB automatisch in Verzug </span><br/><span class="hljs-string"> kommen."</span>, zahlbarBis); <br/> // wird sich in kommender Version ändern in <br/> // AATradePaymentTerms()<br/> desc.SetPaymentMeans(PaymentMeansTypeCodes.<br/> SEPACreditTransfer, <span class="hljs-string">"Zahlung per SEPA-Überweisung."</span>);<br/> desc.AddCreditorFinancialAccount( <br/> ib<span class="hljs-symbol">an:</span><span class="hljs-string">"DE57360700240109002600"</span>, b<span class="hljs-symbol">ic:</span> <span class="hljs-string">"DEUTDEDBESS"</span>, <br/> <span class="hljs-built_in">na</span><span class="hljs-symbol">me:</span> <span class="hljs-string">"Deutsche Bank Essen"</span>);<br/> desc.AddApplicableTradeTax(<br/> basisAmou<span class="hljs-symbol">nt:</span> summeNetto,<br/> perce<span class="hljs-symbol">nt:</span> (<span class="hljs-built_in">decimal</span>)re.UST_Satz, // <span class="hljs-number">19.0</span> oder <span class="hljs-number">7.0</span><br/> typeCo<span class="hljs-symbol">de:</span> TaxTypes.VAT, // Umsatzsteuer<br/> categoryCo<span class="hljs-symbol">de:</span> re.UST_Satz == <span class="hljs-number">0</span> ? <br/> TaxCategoryCodes.AE <span class="hljs-symbol">:</span> TaxCategoryCodes.S <br/> // <span class="hljs-string">"Reverse Charge"</span> oder <span class="hljs-string">"Standard Tax Rate"</span><br/> );<br/> #endregion<br/> <br/> #region --- Rechnungspositionen einfügen<br/> foreach (<span class="hljs-built_in">var</span> rp in re.RP_RechnungsPositionen)<br/> {<br/> desc.AddTradeLineItem(<br/> <span class="hljs-built_in">na</span><span class="hljs-symbol">me:</span> rp.RP_Text,<br/> unitCo<span class="hljs-symbol">de:</span> QuantityCodes.<span class="hljs-symbol">H87</span>, <br/> // <span class="hljs-symbol">H87</span> = <span class="hljs-string">"Stück"</span> siehe htt<span class="hljs-symbol">ps:</span>//unece.org/trade/<br/> // documents/<span class="hljs-number">2021</span>/<span class="hljs-number">06</span>/uncefact-rec20-<span class="hljs-number">0</span><br/> billedQuanti<span class="hljs-symbol">ty:</span> (<span class="hljs-built_in">decimal</span>)rp.RP_Menge.Value,<br/> netUnitPri<span class="hljs-symbol">ce:</span> (<span class="hljs-built_in">decimal</span>)rp.RP_Betrag.Value,<br/> taxTy<span class="hljs-symbol">pe:</span> TaxTypes.VAT,<br/> categoryCo<span class="hljs-symbol">de:</span> re.UST_Satz == <span class="hljs-number">0</span> ? <br/> TaxCategoryCodes.AE <span class="hljs-symbol">:</span> TaxCategoryCodes.S, <br/> // <span class="hljs-string">"Reverse Charge"</span> oder <span class="hljs-string">"Standard Tax Rate"</span><br/> taxPerce<span class="hljs-symbol">nt:</span> (<span class="hljs-built_in">decimal</span>)re.UST_Satz, <br/> // <span class="hljs-number">19.0</span> oder <span class="hljs-number">7.0</span> oder <span class="hljs-number">0.0</span><br/> lineTotalAmou<span class="hljs-symbol">nt:</span> (<span class="hljs-built_in">decimal</span>)rp.RP_Summe.Value <br/> // optionale Angabe. Wenn vorhanden, muss das <br/> // aber stimmen!<br/> );<br/> }<br/> #endregion<br/> <br/> #region --- Gesamtwerte<br/> desc.SetTotals(<br/> lineTotalAmou<span class="hljs-symbol">nt:</span> summeNetto,<br/> chargeTotalAmou<span class="hljs-symbol">nt:</span> <span class="hljs-number">0.0</span>m,<br/> allowanceTotalAmou<span class="hljs-symbol">nt:</span> <span class="hljs-number">0.0</span>m,<br/> taxBasisAmou<span class="hljs-symbol">nt:</span> summeNetto,<br/> taxTotalAmou<span class="hljs-symbol">nt:</span> ust,<br/> grandTotalAmou<span class="hljs-symbol">nt:</span> summeBrutto,<br/> totalPrepaidAmou<span class="hljs-symbol">nt:</span> <span class="hljs-number">0.0</span>m,<br/> duePayableAmou<span class="hljs-symbol">nt:</span> summeBrutto<br/> );<br/> #endregion<br/> <br/> return desc;<br/>}
Anschließend setzt man mit AddNote() weitere Kopfdaten der Rechnung in reiner Textform. Im Feld ReferenceOrderNo kann man die Auftragsnummer speichern, die der Kunde bei seiner Bestellung genannt hat.Zu beachten ist, dass die Property- und Parameternamen in der .NET-Bibliothek zum Teil von den XML-Tags abweichen. So werden aus der Eigenschaft ReferenceOrderNo in der XRechnung die folgenden XML-Tags:
<span class="hljs-tag"><<span class="hljs-name">ram:BuyerOrderReferencedDocument</span>></span>
<span class="hljs-tag"><<span class="hljs-name">ram:IssuerAssignedID</span>></span>991-80008-08
<span class="hljs-tag"></<span class="hljs-name">ram:IssuerAssignedID</span>></span>
<span class="hljs-tag"></<span class="hljs-name">ram:BuyerOrderReferencedDocument</span>></span>
Bei Rechnungen an Behörden muss (zumindest bisher) über die Property ReferenceOrderNo zwingend die jeweilige Leitweg-ID [27] des Rechnungsempfängers übermittelt werden. Dabei handelt es sich um eine 5- bis 46-stellige Zeichenfolge, inklusive einem oder zwei Bindestrichen, zum Beispiel 991-80008-08 für die Deutsche Bundesbank und 059540036036-31001-59 für die Stadt Witten an der Ruhr. Die Leitweg-ID ermöglicht eine elektronische Adressierung und Weiterleitung der XRechnung durch die zentralen Rechnungseingangsplattformen des Bundes [28] beziehungsweise der Länder (zum Beispiel Bremen unter [29] und Nordrhein-Westfalen unter [30]) an die ERP- beziehungsweise Freigabesysteme der angeschlossenen Behörden und Einrichtungen.Ein öffentlicher Rechnungsempfänger hat mindestens eine Leitweg-ID, es können jedoch mehrere Leitweg-IDs pro Institution genutzt werden. Rechnungsaussteller an Behörden benötigen hingegen keine eigene Leitweg-ID.Wenn übrigens Behörden neben der Leitweg-ID in der Bestellung noch eine weitere Bestellnummer angeben, muss diese mit AddNote() hinzugefügt werden.Seit XRechnung 3.0.1 gibt es ein Tag <URIUniversalCommunication>, bei dem man neben der E-Mail-Adresse auch andere Kommunikationsadressen wie zum Beispiel eine Leitweg-ID angeben kann. In Listing 1 sieht man E-Mail-Adressen bei den Zuweisungen SellerElectronicAddress und BuyerElectronicAddress. Das Bundesministerium des Innern und für Heimat schreibt dazu in [31]: „Nach Absprache mit Ihrem Lieferanten können Sie auch eine Leitweg-ID … angeben beziehungsweise diese einfordern.“ Das Ministerium selbst macht von der Leitweg-ID keinen Gebrauch, sondern legt in [32] und [33] fest, dass immer noch das Feld „BT-10“ (das ist das Tag <BuyerOrderReferencedDocument><IssuerAssignedID>) für die Leitweg-ID verwendet werden muss.Die E-Rechnungsportale des Bundes und der Länder bieten außerdem die Option, eine Rechnung manuell in einer Webmaske zu erfassen und daraus die XRechnung zu generieren und zu versenden. Auch auf verschiedenen Internetseiten findet man XRechnungs-Generatoren, zum Beispiel [34]. Das ist eine Alternative für Unternehmen, die nur sehr selten Rechnungen versenden (etwa Kleingewerbetreibende). Man muss sich aber beim Einsatz solcher Tools bewusst sein, dass der Seitenbetreiber die Rechnungsdaten speichern, einsehen und/oder verwenden könnte.Als Nächstes folgen im Listing 1 Daten über den Rechnungssteller via SetSeller(), SetSellerContact() und SellerElectronicAddress sowie AddSellerTaxRegistration() zur Angabe von nationaler und internationaler Steuernummer. Daran schließen sich dann in entsprechender Weise SetBuyer() und die Befüllung von BuyerElectronicAddress für die Daten des Rechnungsempfängers an. Bei Rechnungssteller und Rechnungsempfänger kann man optional eine eindeutige Identifikationsnummer angeben, zum Beispiel wie in Listing 1 gezeigt eine Nummer aus dem Data Universal Numbering System (D-U-N-S) [35].Danach kommen
- die Zahlungsbedingungen mit SetTradePaymentTerms() mit Angabe in Textform und optional auch mit Datum,
- die Zahlungsart mit SetPaymentMeans(),
- das Zielbankkonto mit AddCreditorFinancialAccount(),
- Steuerinformationen mit AddApplicableTradeTax().
desc.SetTradePaymentTerms(
<span class="hljs-string">"<span class="hljs-subst">#SKONTO</span><span class="hljs-subst">#TAGE</span>=14<span class="hljs-subst">#PROZENT</span>=3.00# "</span>, zahlbarBis);
Beziehungsweise dann in der kommenden Version:
desc.AddTradePaymentTerms(
<span class="hljs-string">"<span class="hljs-subst">#SKONTO</span><span class="hljs-subst">#TAGE</span>=14<span class="hljs-subst">#PROZENT</span>=3.00# "</span>, zahlbarBis);
Daran schließen sich in Listing 1 die einzelnen Rechnungspositionen mit AddTradeLineItem() jeweils unter Angabe von Text, Menge, Nettopreis, Steuersatz und einem TaxCategoryCode an. Standard ist TaxCategoryCodes.S. Andere sind TaxCategoryCodes.AE für Reverse Charge und TaxCategoryCodes.E für Umsatzsteuerausnahmen. Der Programmcode in Listing 1 zeigt nur eine Fallunterscheidung zwischen Standard (S) und Reverse Charge. Anders als bei einer Papier- und PDF-Rechnung muss der Rechnungssteller für jede Rechnungsposition einzeln den Steuertatbestand deklarieren.Merkwürdig erscheint der UnitCode QuantityCodes.H87. Dies ist die Angabe für „Stück“ und basiert auf der Empfehlung 20 „Codes for Units of Measure Used in International Trade“ der United Nations Economic Commission for Europe (UNECE), siehe [37].Eine Rechnungsposition kann auch eine globale Identifikation besitzen, zum Beispiel eine European Article Number (EAN). Dies kommt in Listing 1 nicht vor, weil die dort in Rechnung gestellten Schulungsdienstleistungen und Nebenkosten keine EAN besitzen. Der EAN-Fall soll daher hier noch einmal an einem Beispiel gezeigt werden:
desc.AddTradeLineItem(<span class="hljs-string">name:</span> <span class="hljs-string">"Trennblätter A4"</span>,
<span class="hljs-string">unitCode:</span> QuantityCodes.H87,
<span class="hljs-string">sellerAssignedID:</span> <span class="hljs-string">"TB100A4"</span>,
<span class="hljs-string">id:</span> <span class="hljs-keyword">new</span> GlobalID(GlobalIDSchemeIdentifiers.EAN,
<span class="hljs-string">"400004672"</span>),
<span class="hljs-string">grossUnitPrice:</span> <span class="hljs-number">9.9</span>m,
<span class="hljs-string">netUnitPrice:</span> <span class="hljs-number">9.9</span>m,
<span class="hljs-string">billedQuantity:</span> <span class="hljs-number">20</span>m,
<span class="hljs-string">taxType:</span> TaxTypes.VAT,
<span class="hljs-string">categoryCode:</span> TaxCategoryCodes.S,
<span class="hljs-string">taxPercent:</span> <span class="hljs-number">19</span>m
);
Die Routine zur Erstellung der Instanz von InvoiceDescriptor endet mit dem Setzen der Summenwerte für Netto, Brutto und Umsatzsteuer mit der Methode SetTotals().Hier im Beispiel in Listing 1 sieht man einige konstante Daten aus unserem Unternehmen (www.IT-Visions.de) im Programmcode, die eigentlich in Konfigurationsdaten liegen. Das Inlining dieser Daten als Zeichenketten in Listing 1 dient der besseren Veranschaulichung der Nutzung der Bibliothek. Dynamisch aus der Datenbank geladene Daten (Rechnungsnummer, Rechnungsempfänger, Auftragsdaten, Rechnungspositionen und dergleichen) werden aus einem per Entity Framework befüllten Objektmodell genommen. Hieraus stammen die Typen P_Partner, AG_Angebote und RE_Rechnungen; diese gehören also nicht zur Bibliothek ZUGFeRD-csharp. Die XRechnung, die in Listing 1 erstellt wird, entspricht der PDF-Rechnung aus Bild 1 und dem XRechnung-XML-Dokument, das auszugsweise in Listing 2 dargestellt ist.
Listing 2: Auszüge aus den XML-Inhalten der XRechnung, die in Listing 1 erstellt wurde
<span class="php"><span class="hljs-meta">&lt;?</span>xml version=<span class="hljs-string">"1.0"</span> encoding=<span class="hljs-string">"utf-8"</span><span class="hljs-meta">?&gt;</span></span><br/><span class="hljs-tag">&lt;<span class="hljs-name">rsm:CrossIndustryInvoice</span> <span class="hljs-attr">xmlns:a</span>=<span class="hljs-string">"urn:un:unece:</span></span><br/><span class="hljs-tag"><span class="hljs-string"> uncefact:data:standard:QualifiedDataType:100"</span> </span><br/><span class="hljs-tag"> <span class="hljs-attr">xmlns:rsm</span>=<span class="hljs-string">"urn:un:unece:uncefact:data:standard:</span></span><br/><span class="hljs-tag"><span class="hljs-string"> CrossIndustryInvoice:100"</span> <span class="hljs-attr">xmlns:qdt</span>=<span class="hljs-string">"urn:un:unece:</span></span><br/><span class="hljs-tag"><span class="hljs-string"> uncefact:data:standard:QualifiedDataType:100"</span> </span><br/><span class="hljs-tag"> <span class="hljs-attr">xmlns:ram</span>=<span class="hljs-string">"urn:un:unece:uncefact:data:standard:</span></span><br/><span class="hljs-tag"><span class="hljs-string"> ReusableAggregateBusinessInformationEntity:100"</span> </span><br/><span class="hljs-tag"> <span class="hljs-attr">xmlns:xs</span>=<span class="hljs-string">"http://www.w3.org/2001/XMLSchema"</span> </span><br/><span class="hljs-tag"> <span class="hljs-attr">xmlns:udt</span>=<span class="hljs-string">"urn:un:unece:uncefact:data:standard:</span></span><br/><span class="hljs-tag"><span class="hljs-string"> UnqualifiedDataType:100"</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">rsm:ExchangedDocumentContext</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:BusinessProcessSpecifiedDocumentContext</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Parameter</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ID</span>&gt;</span>urn:fdc:peppol.eu:2017:poacc:billing:<br/> 01:1.0<span class="hljs-tag">&lt;/<span class="hljs-name">ram:ID</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:BusinessProcessSpecifiedDocumentContext</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Parameter</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:GuidelineSpecifiedDocumentContextParameter</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ID</span>&gt;</span>urn:cen.eu:en16931:2017#compliant#urn:<br/> xeinkauf.de:kosit:xrechnung_3.0<span class="hljs-tag">&lt;/<span class="hljs-name">ram:ID</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:GuidelineSpecifiedDocumentContextParameter</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">rsm:ExchangedDocumentContext</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">rsm:ExchangedDocument</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ID</span>&gt;</span>R-2200718<span class="hljs-tag">&lt;/<span class="hljs-name">ram:ID</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TypeCode</span>&gt;</span>380<span class="hljs-tag">&lt;/<span class="hljs-name">ram:TypeCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IssueDateTime</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">udt:DateTimeString</span> </span><br/><span class="hljs-tag"> <span class="hljs-attr">format</span>=<span class="hljs-string">"102"</span>&gt;</span>20240925<span class="hljs-tag">&lt;/<span class="hljs-name">udt:DateTimeString</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IssueDateTime</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Content</span>&gt;</span>Schulung (In-House): <br/> Umstieg von .NET 8.0 auf .NET 9.0<br/> Mo, 23.09.2024 bis Di, 24.09.2024 (2 Tage)<br/> Ort: Musterstraße 71, 12345 Musterstadt<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:Content</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Content</span>&gt;</span>Angebotsnummer: A-2101869820<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:Content</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Content</span>&gt;</span>Ihr Auftrag vom 01.08.2024 <br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:Content</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Content</span>&gt;</span>Ihre Auftragsnummer: 123-4567-89<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:Content</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Content</span>&gt;</span>Falls Sie mehrere Rechnungen von <br/> uns erhalten haben, zahlen Sie diese unbedingt <br/> getrennt unter Angabe der jeweiligen <br/> Rechnungsnummer, da die Buchhaltung <br/> vollautomatisiert ist. Zahlungsavis können <br/> nicht verarbeitet werden.<span class="hljs-tag">&lt;/<span class="hljs-name">ram:Content</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Content</span>&gt;</span>Bitte beachten Sie, dass der <br/> deutsche Gesetzgeber uns verpflichtet, alle <br/> Nebenleistungen wie z.B. Reise- und <br/> Hotelkosten sowie Fachbücher zum gleichen <br/> Umsatzsteuersatz wie die Hauptleistung weiter <br/> zu berechnen, selbst wenn dafür ursprünglich <br/> ein anderer Steuersatz galt.<span class="hljs-tag">&lt;/<span class="hljs-name">ram:Content</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedNote</span>&gt;</span><br/> <br/> ...<br/> <span class="hljs-tag">&lt;<span class="hljs-name">rsm:SupplyChainTradeTransaction</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IncludedSupplyChainTradeLineItem</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:AssociatedDocumentLineDocument</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:LineID</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">ram:LineID</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:AssociatedDocumentLineDocument</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedTradeProduct</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Name</span>&gt;</span>Individuelle, maßgeschneiderte <br/> Schulung vor Ort in Ihrem Unternehmen<span class="hljs-tag">&lt;/<span class="hljs-name">ram:Name</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedTradeProduct</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedLineTradeAgreement</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:NetPriceProductTradePrice</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ChargeAmount</span>&gt;</span>1500.00<span class="hljs-tag">&lt;/<span class="hljs-name">ram:ChargeAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:NetPriceProductTradePrice</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedLineTradeAgreement</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedLineTradeDelivery</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:BilledQuantity</span> <span class="hljs-attr">unitCode</span>=<span class="hljs-string">"H87"</span>&gt;</span>2.0000<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:BilledQuantity</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedLineTradeDelivery</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedLineTradeSettlement</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ApplicableTradeTax</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TypeCode</span>&gt;</span>VAT<span class="hljs-tag">&lt;/<span class="hljs-name">ram:TypeCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:CategoryCode</span>&gt;</span>S<span class="hljs-tag">&lt;/<span class="hljs-name">ram:CategoryCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:RateApplicablePercent</span>&gt;</span>19.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:RateApplicablePercent</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:ApplicableTradeTax</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedTradeSettlementLineMonetary</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Summation</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:LineTotalAmount</span>&gt;</span>3000.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:LineTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedTradeSettlementLineMonetary</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Summation</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedLineTradeSettlement</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IncludedSupplyChainTradeLineItem</span>&gt;</span><br/> ...<br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ApplicableHeaderTradeDelivery</span> /&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ApplicableHeaderTradeSettlement</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:InvoiceCurrencyCode</span>&gt;</span>EUR<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:InvoiceCurrencyCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedTradeSettlementPaymentMeans</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TypeCode</span>&gt;</span>58<span class="hljs-tag">&lt;/<span class="hljs-name">ram:TypeCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Information</span>&gt;</span>Zahlung per <br/> SEPA-Überweisung.<span class="hljs-tag">&lt;/<span class="hljs-name">ram:Information</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:PayeePartyCreditorFinancialAccount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:IBANID</span>&gt;</span>DE57360700240109002600<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:IBANID</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:AccountName</span>&gt;</span>Deutsche Bank Essen<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:AccountName</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:PayeePartyCreditorFinancialAccount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:PayeeSpecifiedCreditorFinancial</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Institution</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:BICID</span>&gt;</span>DEUTDEDBESS<span class="hljs-tag">&lt;/<span class="hljs-name">ram:BICID</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:PayeeSpecifiedCreditorFinancial</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Institution</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedTradeSettlementPaymentMeans</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ApplicableTradeTax</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:CalculatedAmount</span>&gt;</span>658.73<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:CalculatedAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TypeCode</span>&gt;</span>VAT<span class="hljs-tag">&lt;/<span class="hljs-name">ram:TypeCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:BasisAmount</span>&gt;</span>3467.00<span class="hljs-tag">&lt;/<span class="hljs-name">ram:BasisAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:CategoryCode</span>&gt;</span>S<span class="hljs-tag">&lt;/<span class="hljs-name">ram:CategoryCode</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:RateApplicablePercent</span>&gt;</span>19.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:RateApplicablePercent</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:ApplicableTradeTax</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedTradePaymentTerms</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:Description</span>&gt;</span>Bitte überweisen Sie den <br/> Betrag binnen 10 Tagen ohne Abzüge auf unten <br/> genanntes Konto. Bitte beachten Sie, dass <br/> Sie nach §286 BGB automatisch in Verzug <br/> kommen.<span class="hljs-tag">&lt;/<span class="hljs-name">ram:Description</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:DueDateDateTime</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">udt:DateTimeString</span> <span class="hljs-attr">format</span>=<span class="hljs-string">"102"</span>&gt;</span>20241005<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">udt:DateTimeString</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:DueDateDateTime</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedTradePaymentTerms</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:SpecifiedTradeSettlementHeaderMonetary</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Summation</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:LineTotalAmount</span>&gt;</span>3467.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:LineTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:ChargeTotalAmount</span>&gt;</span>0.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:ChargeTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:AllowanceTotalAmount</span>&gt;</span>0.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:AllowanceTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TaxBasisTotalAmount</span>&gt;</span>3467.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:TaxBasisTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TaxTotalAmount</span> <span class="hljs-attr">currencyID</span>=<span class="hljs-string">"EUR"</span>&gt;</span>658.73<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:TaxTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:GrandTotalAmount</span>&gt;</span>4125.73<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:GrandTotalAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:TotalPrepaidAmount</span>&gt;</span>0.00<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:TotalPrepaidAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;<span class="hljs-name">ram:DuePayableAmount</span>&gt;</span>4125.73<br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:DuePayableAmount</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:SpecifiedTradeSettlementHeaderMonetary</span></span><br/><span class="hljs-tag"> <span class="hljs-attr">Summation</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">ram:ApplicableHeaderTradeSettlement</span>&gt;</span><br/> <span class="hljs-tag">&lt;/<span class="hljs-name">rsm:SupplyChainTradeTransaction</span>&gt;</span><br/><span class="hljs-tag">&lt;/<span class="hljs-name">rsm:CrossIndustryInvoice</span>&gt;</span>
Speichern der elektronischen Rechnung
Eine elektronische Rechnung speichert man ganz einfach ins Dateisystem, indem man in der Klasse InvoiceDescriptor die Methode Save() aufruft. Dabei kann man die gewünschte ZUGFeRD-Version und das Profil angeben, hier als Beispiel XRechnung:
<span class="hljs-selector-tag">desc</span><span class="hljs-selector-class">.Save</span>(<span class="hljs-selector-tag">ZielXMLPath</span>, <span class="hljs-selector-tag">ZUGFeRDVersion</span><span class="hljs-selector-class">.Version22</span>,
<span class="hljs-selector-tag">s2industries</span><span class="hljs-selector-class">.ZUGFeRD</span><span class="hljs-selector-class">.Profile</span><span class="hljs-selector-class">.XRechnung</span>);
Das Profil für EN 16931 heißt in der Profile-Enumeration noch Comfort. Alternativ kann mit die XML-Daten bei Save() an ein Objekt des Typs System.IO.Stream übergeben und dann zum Beispiel per Netzwerk versenden.
<span class="hljs-selector-tag">desc</span><span class="hljs-selector-class">.Save</span>(<span class="hljs-selector-tag">stream</span>, <span class="hljs-selector-tag">ZUGFeRDVersion</span><span class="hljs-selector-class">.Version22</span>, <span class="hljs-selector-tag">s2industries</span>.
<span class="hljs-selector-tag">ZUGFeRD</span><span class="hljs-selector-class">.Profile</span><span class="hljs-selector-class">.XRechnung</span>, <span class="hljs-selector-tag">ZUGFeRDFormats</span><span class="hljs-selector-class">.UBL</span>);
Bei dieser Überladung von Save() kann man auch für XRechnung das Unterformat UBL mit Wurzeltag <Invoice> wählen. Das Save(), das in eine XML-Datei speichert, erzeugt immer das Unterformat CII mit Wurzeltag <CrossIndustryInvoice>.Für das Anhängen der XML-Datei an ein PDF bietet die Bibliothek ZUGFeRD-csharp leider keine eigene Lösung. Hier greift man zum Beispiel auf die kostenfreie Community-Lösung PdfSharp [38] zurück. Der Name des Anhangs sollte xrechnung.xml sein:
<span class="hljs-attribute">var ZielPDFDateiname</span> = PDFDateiname.Replace(<span class="hljs-string">".pdf"</span>,
<span class="hljs-string">".ZUGFeRD.pdf"</span>);
<span class="hljs-attribute">s</span><span class="hljs-attribute">t</span><span class="hljs-attribute">r</span><span class="hljs-attribute">i</span><span class="hljs-attribute">n</span><span class="hljs-attribute">g</span> <span class="hljs-attribute">Z</span><span class="hljs-attribute">i</span><span class="hljs-attribute">e</span><span class="hljs-attribute">l</span><span class="hljs-attribute">P</span><span class="hljs-attribute">D</span><span class="hljs-attribute">F</span><span class="hljs-attribute">P</span><span class="hljs-attribute">f</span><span class="hljs-attribute">a</span><span class="hljs-attribute">d</span> = $@<span class="hljs-string">"I:\Rechnungswesen\" +</span>
<span class="hljs-string"> "</span>AusgehendeRechnungen\{jahr}\{ZielPDFDateiname}<span class="hljs-string">";</span>
<span class="hljs-string">PdfDocument document = PdfReader.Open(PDFPfad);</span>
<span class="hljs-string">document.AddEmbeddedFile("</span>xrechnung.xml<span class="hljs-string">", </span>
<span class="hljs-string"> ZielXMLPfad);</span>
<span class="hljs-string">document.Save(ZielPDFPfad);</span>
Ausschnitte aus dem resultierenden umfangreichen XRechnung-XML-Dokument zeigt Listing 2, das Sie in vollständiger Fassung in den Downloads zum Artikel finden.
Einlesen einer elektronischen Rechnung
Das Einlesen einer eingehenden E-Invoice in XML-Form erfolgt in einer Zeile via Load() aus einem Stream oder einer Datei:
<span class="hljs-attribute">InvoiceDescriptor desc</span> =
InvoiceDescriptor.Load(XMLPath);
Sofern das ohne Laufzeitfehler klappt, ist die Datei strukturell in Ordnung. Nun kann man auf die zahlreichen Eigenschaften des InvoiceDescriptor-Objekts zugreifen, zum Beispiel
- desc.Seller.Name
- desc.TradeLineItems
- desc.TaxTotalAmount
- desc.GrandTotalAmount
- Validierung mithilfe des Standard-XSL (die die KoSIT unter [39] bereitstellt)
- Vollständige Unterstützung des UBL-Formats (Lesen und Schreiben). Im Test konnte jedoch mit ZUGFeRD-csharp in der bei Abfassung dieses Artikels aktuellen Version 14.1 die von der KoSIT bereitgestellte aktuellste Muster-UBL-Datei 03.06a-INVOICE_ubl.xml ohne Fehler eingelesen werden.
- Rechnungsvisualisierung
desc.AddApplicableTradeTax(basisAmount: summeNetto,
percent: (decimal)re.UST_Satz, <span class="hljs-regexp">//</span> <span class="hljs-number">19.0</span> oder <span class="hljs-number">7.0</span>
typeCode: TaxTypes.VAT, <span class="hljs-regexp">//</span> Umsatzsteuer
categoryCode: TaxCategoryCodes.S,
<span class="hljs-regexp">//</span> <span class="hljs-string">"Standard Tax Rate"</span>
exemptionReason: <span class="hljs-string">"Bitte beachten Sie, dass der </span>
<span class="hljs-string"> deutsche Gesetzgeber uns verpflichtet, alle </span>
<span class="hljs-string"> Nebenleistungen wie zum Beispiel Reise- und </span>
<span class="hljs-string"> Hotelkosten sowie Fachbücher zum gleichen </span>
<span class="hljs-string"> Umsatzsteuersatz wie die Hauptleistung weiter zu </span>
<span class="hljs-string"> berechnen, selbst wenn dafür ursprünglich ein </span>
<span class="hljs-string"> anderer Steuersatz galt."</span>
);
Es gibt damit im Validator die Fehlermeldung in Bild 3. Richtig ist: Der Hinweis zum Steuersatz muss mit AddNote() übergeben werden, wie Listing 1 zeigt. Dann ist der Validator zufrieden, siehe Bild 4. Im Prüfbericht erhält man auf Wunsch ein visuelles Ergebnis. Der Validator erkennt mathematische Fehler, also wenn zum Beispiel bei einer Rechnungszeile der <LineTotalAmount> nicht dem Produkt aus <ChargeAmount> und <BilledQuantity> entspricht. AddTradeLineItem() in der Bibliothek ZUGFeRD-csharp beschwert sich aber nicht, wenn man bei der Eingabe einen derartigen Fehler macht.

Der XRechnung-Validator mag nicht, dass man einen Text in das Tag geschrieben hat, wenn auf „S“ (Standard) gesetzt wurde (Bild 3)
Autor

Der XRechnung-Validator des Landes Baden-Württemberg ist einverstanden mit der XRechnung (Bild 4)
Autor
XRechnung aus PDF extrahieren
Wenn man keine eigenständige XML-Datei, sondern eine PDF-Datei mit Anhang erhält, muss man wieder auf eine PDF-Bibliothek zurückgreifen. PdfSharp bietet hier leider keine Lösung. Listing 3 zeigt das Extrahieren aller Anhänge aus einer PDF-Datei mit PDFClown [41]. Die Methode ExtractAttachments() liefert ein Byte-Array zurück, das man dann in einen MemoryStream geben kann, den man wiederum mit der Klasse InvoiceDescriptor laden kann:Listing 3: Extrahieren aller Anhänge aus einer PDF-Datei mit PDFClown
<span class="hljs-keyword">using</span> <span class="hljs-type">System</span>;<br/><span class="hljs-keyword">using</span> <span class="hljs-type">System</span>.<span class="hljs-type">Collections</span>.<span class="hljs-type">Generic</span>;<br/><span class="hljs-keyword">using</span> org.pdfclown.documents;<br/><span class="hljs-keyword">using</span> org.pdfclown.documents.files;<br/><span class="hljs-keyword">using</span> org.pdfclown.documents.interaction.annotations;<br/><span class="hljs-keyword">using</span> org.pdfclown.objects;<br/> <br/>namespace <span class="hljs-type">ITVisions</span>;<br/> <br/>internal class <span class="hljs-type">PDFUtil</span><br/>{<br/> /// &lt;summary&gt;<br/> /// <span class="hljs-type">Extrahieren</span> aller <span class="hljs-type">Anh</span>änge aus einer <span class="hljs-type">PDF</span>-<span class="hljs-type">Datei</span> <br/> /// mit <span class="hljs-type">PDFClown</span> (https://pdfclown.org/)<br/> /// &lt;/summary&gt;<br/> /// &lt;param name=<span class="hljs-string">"pdfPath"</span>&gt;&lt;/param&gt;<br/> /// &lt;returns&gt;&lt;/returns&gt;<br/> public <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt; <br/> <span class="hljs-type">ExtractAttachments</span>(<span class="hljs-built_in">string</span> pdfPath)<br/> {<br/> <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt; allAttachments = <br/> new <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt;();<br/> <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt; documentAttachments = <br/> new <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt;();<br/> <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt; pageAttachments = <br/> new <span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, byte[]&gt;();<br/> <br/> <span class="hljs-keyword">using</span> (org.pdfclown.files.<span class="hljs-type">File</span> file = <br/> new org.pdfclown.files.<span class="hljs-type">File</span>(pdfPath))<br/> {<br/> <span class="hljs-type">Document</span> document = file.<span class="hljs-type">Document</span>;<br/> <br/> // <span class="hljs-number">1</span>. <span class="hljs-type">Embedded</span> files (document level).<br/> foreach (<span class="hljs-type">KeyValuePair</span>&lt;<span class="hljs-type">PdfString</span>, <br/> <span class="hljs-type">FileSpecification</span>&gt; entry <br/> <span class="hljs-keyword">in</span> document.<span class="hljs-type">Names</span>.<span class="hljs-type">EmbeddedFiles</span>)<br/> {<br/> <span class="hljs-type">EvaluateDataFile</span>(documentAttachments, <br/> entry.<span class="hljs-type">Value</span>);<br/> }<br/> <span class="hljs-type">Console</span>.<span class="hljs-type">WriteLine</span>(<br/> <span class="hljs-string">"PDF-Anhänge auf Dokumentebene: "</span> + <br/> documentAttachments.<span class="hljs-type">Count</span>);<br/> <br/> // <span class="hljs-number">2</span>. <span class="hljs-type">File</span> attachments (page level).<br/> foreach (org.pdfclown.documents.<span class="hljs-type">Page</span> page <span class="hljs-keyword">in</span> <br/> document.<span class="hljs-type">Pages</span>)<br/> {<br/> foreach (org.pdfclown.documents.interaction.<br/> annotations.<span class="hljs-type">Annotation</span> annotation <span class="hljs-keyword">in</span> <br/> page.<span class="hljs-type">Annotations</span>)<br/> {<br/> <span class="hljs-keyword">if</span> (annotation <span class="hljs-keyword">is</span> <span class="hljs-type">FileAttachment</span>)<br/> { <span class="hljs-type">EvaluateDataFile</span>(pageAttachments, <br/> ((<span class="hljs-type">FileAttachment</span>)annotation).<span class="hljs-type">DataFile</span>); }<br/> }<br/> }<br/> <span class="hljs-type">Console</span>.<span class="hljs-type">WriteLine</span>(<span class="hljs-string">"PDF-Anhänge auf Seitenebene: "</span> <br/> + pageAttachments.<span class="hljs-type">Count</span>);<br/> }<br/> allAttachments.<span class="hljs-type">AddRange</span>(documentAttachments);<br/> allAttachments.<span class="hljs-type">AddRange</span>(pageAttachments);<br/> <br/> <span class="hljs-type">Console</span>.<span class="hljs-type">WriteLine</span>(<span class="hljs-string">"PDF-Anhänge insgesamt: "</span> + <br/> allAttachments.<span class="hljs-type">Count</span>);<br/> <br/> <span class="hljs-keyword">return</span> allAttachments;<br/> }<br/> <br/> private <span class="hljs-built_in">void</span> <span class="hljs-type">EvaluateDataFile</span>(<span class="hljs-type">Dictionary</span>&lt;<span class="hljs-built_in">string</span>, <br/> byte[]&gt; attachments, <span class="hljs-type">FileSpecification</span> dataFile)<br/> {<br/> <span class="hljs-keyword">if</span> (dataFile <span class="hljs-keyword">is</span> <span class="hljs-type">FullFileSpecification</span>)<br/> {<br/> <span class="hljs-type">EmbeddedFile</span> embeddedFile = <br/> ((<span class="hljs-type">FullFileSpecification</span>)dataFile).<span class="hljs-type">EmbeddedFile</span>;<br/> <span class="hljs-keyword">if</span> (embeddedFile != null)<br/> { attachments[dataFile.<span class="hljs-type">Path</span>] = <br/> embeddedFile.<span class="hljs-type">Data</span>.<span class="hljs-type">ToByteArray</span>(); }<br/> }<br/> }<br/>}
<span class="hljs-keyword">var</span> attachments =
<span class="hljs-keyword">new</span><span class="hljs-type"></span> PDFUtil().ExtractAttachments(ZielPDFPfad);
<span class="hljs-keyword">var</span> xRechnungAttachment = attachments.FirstOrDefault(
x => x.Key.ToLower().Contains(<span class="hljs-string">"xrechnung.xml"</span>));
<span class="hljs-keyword">using</span> (<span class="hljs-keyword">var</span> stream =
<span class="hljs-keyword">new</span><span class="hljs-type"></span> MemoryStream(xRechnungAttachment.Value))
{
<span class="hljs-keyword">var</span> desc = InvoiceDescriptor.Load(stream);
<span class="hljs-comment">// Weiterverarbeitung der Daten</span>
<span class="hljs-comment">}</span>
Leider ist PDFClown etwas in die Jahre gekommen, und in der Dokumentation lässt sich auch nicht finden, wie man PDF-Anhänge damit erstellen kann. Wenn Sie sich wünschen, für das Einbetten und das Extrahieren von PDF-Anhängen nicht zwei verschiedene Open-Source-Bibliotheken verwenden zu müssen, dann könnten Sie kommerzielle Lösungen wie TextControl [42], iTextSharp [43], iText Core [44] oder Aspose.PDF [45] in Betracht ziehen, die jeweils beide Wege beherrschen.
Fazit
Dank der kostenfreien Lösung ZUGFeRD-csharp ist das Erstellen und Auslesen von strukturierten elektronischen Rechnungen in .NET-Anwendungen sehr einfach. Auch für das Anhängen von XML-Rechnungen an PDF-Dokumenten beziehungsweise die Extraktion gibt es kostenfreie Community-Lösungen.Da XRechnung bei den Behörden Pflicht ist und ZUGFeRD auch ein Profil für XRechnung bietet, zeichnet sich ab, dass sich das XML-Format von XRechnung durchsetzen wird. Spannend bleibt die Frage, was sich behaupten wird: Reines XML oder PDF mit XML-Anhang (also ZUGFeRD) sowie bei den XRechnung-Formaten UBL oder CII.Fussnoten
- [1] o.tel.o communications bei Wikipedia, http://www.dotnetpro.de/SL2501DataAccess1
- [2] Holger Schwichtenberg, Internet Bill Presentment and Payment als neue Form des Electronic Billing, Diplomarbeit 1998, http://www.dotnetpro.de/SL2501DataAccess2
- [3] Electronic data interchange bei Wikipedia, http://www.dotnetpro.de/SL2501DataAccess3
- [4] nwb Datenbank: Umsatzsteuer; Vereinfachung der elektronischen Rechnungsstellung zum 1. Juli 2011 durch das Steuervereinfachungsgesetz 2011, http://www.dotnetpro.de/SL2501DataAccess4
- [5] avanade, Künstliche Intelligenz für Rechnungen, http://www.dotnetpro.de/SL2501DataAccess5
- [6] InvoiceNet, Deep neural network to extract intelligent information from invoice documents, http://www.dotnetpro.de/SL2501DataAccess6
- [7] Forum elektronische Rechnung Deutschland, https://www.ferd-net.de
- [8] Aloaha SDK, Skonto und Verzugszinsen, http://www.dotnetpro.de/SL2501DataAccess7
- [9] KoSIT, https://www.xoev.de
- Koordinierungsstelle für IT-Standards, XRechnung Test Suite, http://www.dotnetpro.de/SL2501DataAccess8
- Bundesgesetzblatt, Wachstumschancengesetz 2024, http://www.dotnetpro.de/SL2501DataAccess9
- European Commission, ViDA, http://www.dotnetpro.de/SL2501DataAccess10
- BMI, Der Übertragungskanal Peppol, http://www.dotnetpro.de/SL2501DataAccess11
- Sage-Lexikon, E-Rechnung, http://www.dotnetpro.de/SL2501DataAccess12
- Haufe Online, Verpflichtung zur elektronischen Rechnung, http://www.dotnetpro.de/SL2501DataAccess13
- Prototype Fund, https://prototypefund.de
- Quba-Quellcode auf GitHub, http://www.dotnetpro.de/SL2501DataAccess14
- Quba E-Rechnungs-View, https://quba-viewer.org
- Validator für XRechnung, http://www.dotnetpro.de/SL2501DataAccess15
- ZUGFeRD.NET, https://konik.io
- ZUGFeRD.NET bei NuGet, http://www.dotnetpro.de/SL2501DataAccess16
- Aloaha ZUGFeRD SDK, https://www.zugferdpro.com
- Aloaha ZUGFeRD SDK bei NuGet, http://www.dotnetpro.de/SL2501DataAccess17
- ZUGFeRD-csharp, http://www.dotnetpro.de/SL2501DataAccess18
- ZUGFeRD-csharp bei NuGet, http://www.dotnetpro.de/SL2501DataAccess19
- ZUGFeRD, Open-Source Libraries and Tools, http://www.dotnetpro.de/SL2501DataAccess20
- BMI, FAQ zum Thema Leitweg-ID, http://www.dotnetpro.de/SL2501DataAccess21
- ZRE, https://xrechnung.bund.de
- Bremer E-Rechnungsportal, https://www.e-rechnung.bremen.de
- E-Rechnungsportal in NRW, https://erechnung.nrw
- BMI, Neue Version Standard XRechnung 3.0.1 verfügbar, http://www.dotnetpro.de/SL2501DataAccess22
- BBMI, E-Rechnung für Rechnungssteller der Bundesverwaltung, http://www.dotnetpro.de/SL2501DataAccess23
- BMI, Übersicht über die BT-Felder der OZG-RE, http://www.dotnetpro.de/SL2501DataAccess24
- Manfred Durm, XRechnung nach aktuellem Standard erstellen, https://xrechnung-erstellen.com
- Dun & Bradstreet, Data Universal Numbering System, https://www.dnb.com/duns-number.html
- Klasse InvoiceDescriptor in ZUGFeRD-csharp auf GitHub, http://www.dotnetpro.de/SL2501DataAccess25
- UNECE-Recommendation No. 20, http://www.dotnetpro.de/SL2501DataAccess26
- PdfSharp, https://www.pdfsharp.net
- GitHub-Seite der Koordinierungsstelle für IT-Standards, https://github.com/itplr-kosit
- Land Baden-Württemberg, E-Rechnungs-Validator, http://www.dotnetpro.de/SL2501DataAccess27
- PDFClown, https://pdfclown.org
- TextControl, https://www.textcontrol.com
- iTextSharp, https://itextpdf.com/products/itextsharp
- iText Core, https://itextpdf.com/products/itext-core
- Aspose.PDF, https://products.aspose.com/pdf/
- Manfred Durm, Zahlen mit Code, https://zahlen-mit-code.com