Umsatzsteuer je Rechnungsposition setzen und lesen (BG-30)

Thema
VB.NET
SDK-Mitglieder
AddTradeTax() FillZUGFeRD_Structure() GetItemTradeTax() GetVatTypeByCategoryCode() TaxExemptionReasonCodeStr() Trade_ItemTradeTax TradeItemsCount TradeItemTaxValues() VatCategoryCode WriteItemTradeTax()
Business Terms
BG-30 Umsatzsteuerinformationen auf der Ebene der Rechnungsposition BT-151 Code der Umsatzsteuerkategorie des in Rechnung BT-152 Umsatzsteuersatz für den in Rechnung gestellten Artikel BG-23 Umsatzsteueraufschlüsselung BG-25 Rechnungsposition BT-95 Code für die Umsatzsteuerkategorie des Abschlages auf BT-102 Code der für den Zuschlag auf Dokumentenebene BT-118 Code der Umsatzsteuerkategorie
Codebeispiele
VB.NET
Veröffentlicht

Jede Rechnungsposition (BG-25) trägt eine eigene Gruppe Umsatzsteuerinformationen auf Positionsebene (BG-30): den Code der Umsatzsteuerkategorie (BT-151) und den Steuersatz (BT-152). Beim Anlegen einer Position mit AddProduct_Comfort setzen Sie beides bereits mit. Mit WriteItemTradeTax ändern oder ergänzen Sie die Steuer einer bestehenden Position nachträglich; zum Auslesen gibt es GetItemTradeTax, Trade_ItemTradeTax und TradeItemTaxValues. Dazu kommen zwei Hilfsfunktionen für Kategorie- und Befreiungscodes.

Felder und Parameter von WriteItemTradeTax

ParameterFeldInhalt
ItemIndex–Index der Position, beginnend bei 0
RateApplicablePercentBT-152Steuersatz, z. B. 19.00
CategoryCodeBT-151Kategorie: S, Z, E, AE, K, G, O, L, M
ReasonBT-X-96Befreiungsgrund als Text (nur EXTENDED)
ExemptionReasonCodeBT-X-97Befreiungsgrund als VATEX-Code (nur EXTENDED)
CalculatedAmountBT-X-95Steuerbetrag der Position (nur EXTENDED)
TypeCodeBT-151-0Steuerart, Standard und bei leerem Wert VAT

Schreiben

VB.NET – die Positionen 0 und 1 wurden zuvor mit AddProduct_Comfort angelegt:

Dim alo As New Aloaha_ZUGFeRD.XML(Aloaha_ZUGFeRD.iXML.ZUGFeRDProfile.comfort, False, "IHR-LIZENZSCHLUESSEL")
' ... Rechnungskopf und Positionen anlegen

' Position 0: Normalsatz 19 %
alo.WriteItemTradeTax(0, "19.00", alo.VatCategoryCode(Aloaha_ZUGFeRD.iXML.VAT_Category.StandardRate))
' Position 1: ermäßigter Satz 7 %, ebenfalls Kategorie S
alo.WriteItemTradeTax(1, "7.00", "S")

WriteItemTradeTax ersetzt die komplette Steuergruppe der Position. Ist der Index ungültig, passiert nichts. Den Steuersatz schreibt das SDK mit zwei Nachkommastellen in die XML; bei Kategorie O (nicht steuerbar) lässt sie ihn weg.

Mit Befreiungsgrund je Position (Profil EXTENDED), hier für eine steuerfreie innergemeinschaftliche Lieferung:

Dim Code As String = alo.TaxExemptionReasonCodeStr(Aloaha_ZUGFeRD.iXML.TaxExemptionReasonCodes.VATEX_EU_IC)   ' "VATEX-EU-IC"
alo.WriteItemTradeTax(2, "0", "K", "Steuerfreie innergemeinschaftliche Lieferung", Code)

VBA / VB6 (COM)

alo.WriteItemTradeTax 0, "19.00", "S"
alo.WriteItemTradeTax 2, "0", "K", "Steuerfreie innergemeinschaftliche Lieferung", "VATEX-EU-IC"

Wichtig: automatische Umstellung auf EXTENDED

Befreiungsgrund, Befreiungscode und Steuerbetrag auf Positionsebene gibt es nur in ZUGFeRD EXTENDED. Sobald Sie Reason, ExemptionReasonCode oder CalculatedAmount füllen, stellt WriteItemTradeTax das Profil auf EXTENDED um und schaltet eine XRechnung (KoSIT) ab.

Für Reverse Charge ohne diese Parameter gilt das nicht: Rufen Sie die Methode mit Kategorie AE, leerem Satz oder Satz 0 und ohne Grund auf, ergänzt das SDK den Code VATEX-EU-AE auf Positionsebene nur, wenn die Rechnung bereits EXTENDED ist. Das Profil bleibt dabei unverändert; COMFORT (EN 16931) und XRechnung bleiben erhalten. Befreiungsgrund und -code einer Position schreibt das SDK ohnehin nur im Profil EXTENDED in die XML. In älteren Versionen des SDK stellte bereits der automatisch ergänzte Code das Profil auf EXTENDED um. Der Befreiungsgrund der Rechnung gehört in COMFORT und XRechnung in die Umsatzsteueraufschlüsselung (BG-23) mit BT-120 und BT-121, also in AddTradeTax:

alo.AddTradeTax("0.00", "EUR", "800.00", "EUR", "VAT", "K", "0", "Steuerfreie innergemeinschaftliche Lieferung", "", "", "", Code)

Lesen

VB.NET – GetItemTradeTax füllt die Variablen per Referenz; der Index ist 0-basiert:

Dim alo As New Aloaha_ZUGFeRD.XML("IHR-LIZENZSCHLUESSEL")
If alo.FillZUGFeRD_Structure("C:\Rechnungen\eingang.xml", "IHR-LIZENZSCHLUESSEL") Then
    For i As Integer = 0 To alo.TradeItemsCount - 1
        Dim Satz As String = "", Kategorie As String = "", Grund As String = "", GrundCode As String = ""
        alo.GetItemTradeTax(i, Satz, Kategorie, Grund, GrundCode)
        Dim Art As Aloaha_ZUGFeRD.iXML.VAT_Category = alo.GetVatTypeByCategoryCode(Kategorie)
        Console.WriteLine($"Position {i + 1}: {Kategorie} ({Art}) {Satz} % {GrundCode}")
    Next
End If

In VB.NET können Sie auch die ganze Struktur holen. Trade_ItemTradeTax liefert ein iXML.Trade_Tax; bei ZUGFeRD 2.x, Factur-X und XRechnung steht der Satz im Feld RateApplicablePercent:

Dim Steuer As Aloaha_ZUGFeRD.iXML.Trade_Tax = alo.Trade_ItemTradeTax(0)
Console.WriteLine(Steuer.CategoryCode & " " & Steuer.RateApplicablePercent & " " & Steuer.ExemptionReasonCode)

Die Eigenschaft ist auch schreibbar (alo.Trade_ItemTradeTax(0) = Steuer). Anders als WriteItemTradeTax stellt der Setter das Profil aber nicht um und setzt keine Codes automatisch. Befreiungsgrund und -code der Position landen deshalb nur dann in der XML, wenn die Rechnung EXTENDED ist.

TradeItemTaxValues(ItemNo, ApplicablePercent, CalculatedAmount, TypeCode, CategoryCode, Reason) stammt aus ZUGFeRD 1.0 und liest zuerst das dortige Feld ApplicablePercent. Ist es leer, liefert die Methode den Satz aus RateApplicablePercent – sie funktioniert also auch für Rechnungen nach ZUGFeRD 2.x, Factur-X und XRechnung. Den Befreiungscode liefert sie nicht; nutzen Sie für neue Projekte daher GetItemTradeTax. In älteren Versionen des SDK blieben die Ausgaben bei ZUGFeRD-2.x-Rechnungen leer.

Dim Prozent As String = "", Betrag As String = "", Steuerart As String = "", Kat As String = "", Text As String = ""
alo.TradeItemTaxValues(0, Prozent, Betrag, Steuerart, Kat, Text)

Hilfsfunktionen für Codes

GetVatTypeByCategoryCode wandelt einen Kategoriecode (BT-151, ebenso BT-95, BT-102 und BT-118) in die Aufzählung VAT_Category um; VatCategoryCode geht den umgekehrten Weg.

CodeVAT_CategoryBedeutung
SStandardRateNormalsatz (auch ermäßigter Satz)
ZZeroRatedGoodsNullsatz
EExemptFromTaxsteuerbefreit
AEVATReverseChargeUmkehr der Steuerschuldnerschaft
KVATExempt, IntraCommunitySupplyinnergemeinschaftliche Lieferung
GFreeExportItemAusfuhr außerhalb der EU
OOutsideScopeOfTaxnicht steuerbar
L / MCanaryIslands / CeutaMelillaIGIC / IPSI

GetVatTypeByCategoryCode ignoriert führende und folgende Leerzeichen sowie Groß- und Kleinschreibung (" ae" ergibt VATReverseCharge); unbekannte Codes ergeben ohne Fehlermeldung StandardRate. Für die innergemeinschaftliche Lieferung gilt der Code K: VatCategoryCode liefert ihn sowohl für VATExempt als auch für IntraCommunitySupply, und GetVatTypeByCategoryCode("K") ergibt VATExempt. In älteren Versionen des SDK ergab IntraCommunitySupply den ungültigen Code „IC“; solche Altdaten liest GetVatTypeByCategoryCode weiterhin als IntraCommunitySupply.

TaxExemptionReasonCodeStr macht aus einem Wert der Aufzählung TaxExemptionReasonCodes den Code für BT-121 bzw. BT-X-97, indem sie Unterstriche durch Bindestriche ersetzt: VATEX_EU_AE ergibt VATEX-EU-AE, VATEX_EU_G ergibt VATEX-EU-G. Einzige Ausnahme ist VATEX_132_2: Er ergibt den offiziellen Code VATEX-EU-132 (in älteren Versionen des SDK das ungültige „VATEX-132-2“). In VBA übergeben Sie den Code einfach als Text.

Profile und Hinweise

  • BG-30 mit Kategorie und Satz ist ab dem Profil BASIC Pflicht für jede Position.
  • Befreiungsgrund, Befreiungscode und Steuerbetrag je Position: nur EXTENDED (siehe oben).
  • Trade_ItemTradeTax gibt eine .NET-Struktur zurück und lässt sich deshalb aus VBA nicht sinnvoll nutzen. Dort nehmen Sie GetItemTradeTax, siehe Positionswerte in VBA/Access auslesen.
  • Für die Steuersummen der Rechnung siehe Umsatzsteuer / VAT.

Häufige Fragen

Wie ändere ich den Steuersatz einer bereits angelegten Position?

Mit WriteItemTradeTax(Index, Satz, Kategorie). Die Methode ersetzt die gesamte Steuergruppe BG-30 der Position.

Warum ist meine Rechnung nach WriteItemTradeTax plötzlich EXTENDED?

Weil Sie einen Befreiungsgrund, einen Befreiungscode oder einen Steuerbetrag übergeben haben. Diese Angaben gibt es auf Positionsebene nur in EXTENDED. Kategorie AE ohne Grund stellt das Profil nicht um.

Welcher Kategoriecode gilt für die innergemeinschaftliche Lieferung?

K. In der Aufzählung des SDK entspricht das VAT_Category.VATExempt, als Befreiungscode gehört VATEX-EU-IC dazu.

Business Terms in diesem Artikel: BG-30 BT-151 BT-152 BG-23 BG-25 BT-95 BT-102 BT-118 BT-120 BT-121