Kurz gesagt
Das UStG verlangt eine fortlaufende Nummer, die einmalig vergeben wird; mehrere Nummernkreise sind erlaubt. Eine lückenlose Folge ist nach dem Umsatzsteuer-Anwendungserlass nicht zwingend, aber Lücken müssen sich erklären lassen, weil die GoBD Vollständigkeit und Nachvollziehbarkeit verlangen. Lückenlose Nummern sind der einfachste Nachweis. Technisch heißt das: Nummer erst beim Ausstellen vergeben, in einer Transaktion mit Sperre, und nie wieder ändern.
Was das Umsatzsteuergesetz verlangt
Nach § 14 Abs. 4 Satz 1 Nr. 4 UStG muss jede Rechnung eine fortlaufende Nummer tragen, mit einer oder mehreren Zahlenreihen, die zur Identifizierung der Rechnung vom Aussteller einmalig vergeben wird.
- Einmalig: Dieselbe Nummer darf es im Unternehmen nur einmal geben, über alle Marken, Filialen und Systeme hinweg.
- Fortlaufend: Die Nummern folgen einer erkennbaren Ordnung. Buchstaben und Präfixe wie
RE-2026-sind erlaubt. - Mehrere Nummernkreise: zulässig, etwa einer pro Jahr, Standort oder Belegart, solange jede Nummer eindeutig bleibt.
Der Umsatzsteuer-Anwendungserlass stellt klar, dass eine lückenlose Abfolge nicht zwingend ist. Daraus folgt aber nicht, dass Lücken egal wären.
Was die GoBD dazu sagen
Die GoBD, die Grundsätze zur ordnungsmäßigen Führung und Aufbewahrung von Büchern in elektronischer Form, verlangen unter anderem:
- Vollständigkeit: Alle Geschäftsvorfälle sind erfasst. Eine fehlende Rechnungsnummer wirft die Frage auf, ob eine Rechnung verschwunden ist.
- Nachvollziehbarkeit: Ein sachverständiger Dritter muss in angemessener Zeit nachvollziehen können, was passiert ist.
- Unveränderbarkeit: Eine Buchung oder Aufzeichnung darf nicht so verändert werden, dass der ursprüngliche Inhalt nicht mehr feststellbar ist (§ 146 Abs. 4 AO).
- Aufbewahrung: Rechnungen sind Buchungsbelege und werden 8 Jahre aufbewahrt (§ 147 AO, § 14b UStG).
In der Praxis
Bei einer Betriebsprüfung sind Lücken im Nummernkreis ein klassischer Anlass für Nachfragen. Wer keine Lücken hat, muss nichts erklären. Wer welche hat, braucht eine Dokumentation, warum.
Typische Fehler beim Selbstbau
Die meisten Probleme entstehen nicht durch böse Absicht, sondern durch Technik, die für etwas anderes gebaut wurde:
| Ansatz | Problem |
|---|---|
MAX(nummer) + 1 | Zwei gleichzeitige Anfragen lesen denselben Wert und vergeben dieselbe Nummer |
| Auto-Increment-ID als Rechnungsnummer | Datenbanken vergeben IDs auch bei abgebrochenen Transaktionen; es entstehen Lücken |
| Nummer schon beim Entwurf vergeben | Gelöschte oder verworfene Entwürfe hinterlassen Lücken |
| Rechnung löschen statt stornieren | Lücke und fehlender Beleg zugleich |
| Nummern pro Marke oder System getrennt | Doppelte Nummern im selben Unternehmen |
| Jährlicher Neustart ohne Jahr in der Nummer | 0001 existiert in jedem Jahr; die Nummer ist nicht mehr einmalig |
| Nummer nach dem Ausstellen ändern | Verstoß gegen die Unveränderbarkeit |
Der häufigste Fehler sieht harmlos aus:
// Race Condition: zwei Prozesse lesen dasselbe MAX()
$last = Invoice::max('sequence');
$invoice->sequence = $last + 1;
$invoice->number = sprintf('RE-2026-%04d', $invoice->sequence);
$invoice->save();Wie man es richtig baut
Vier Regeln reichen, um sichere Nummern zu bekommen:
- Nummer erst beim Ausstellen vergeben. Entwürfe haben keine Nummer. So können sie gelöscht werden, ohne eine Lücke zu hinterlassen.
- In einer Transaktion mit Sperre. Der Zähler wird gesperrt (
SELECT … FOR UPDATE), erhöht und zusammen mit der Rechnung gespeichert. Schlägt etwas fehl, rollt alles zurück und die Nummer ist wieder frei. - Eindeutigkeit in der Datenbank absichern. Ein Unique-Index auf die Nummer ist die letzte Verteidigungslinie.
- Nie ändern oder löschen. Fehler korrigierst du mit Storno oder Korrektur, nicht durch Bearbeiten.
Eine Skizze mit Laravel-Mitteln:
use Illuminate\Support\Facades\DB;
// Zählerzeile anlegen, falls sie fehlt (außerhalb der Transaktion)
DB::table('invoice_sequences')->insertOrIgnore(['key' => 'invoice:2026', 'value' => 0]);
DB::transaction(function () use ($invoice) {
// Zähler sperren: parallele Prozesse warten hier
$sequence = DB::table('invoice_sequences')->where('key', 'invoice:2026')->lockForUpdate()->first();
$next = $sequence->value + 1;
DB::table('invoice_sequences')->where('key', 'invoice:2026')->update(['value' => $next]);
$invoice->number = sprintf('RE-2026-%04d', $next);
$invoice->save(); // scheitert das, rollt auch der Zähler zurück
}, 3);Die Details machen es schwer
Deadlocks und Serialisierungsfehler müssen wiederholt werden, SQLite braucht einen anderen Transaktionsmodus, rückdatierte Rechnungen gehören in den Zähler ihres Jahres, und mehrere Marken einer Firma müssen sich einen Nummernraum teilen. Genau das übernimmt Quittio Managed.
Mit Quittio Managed
Quittio Managed vergibt Nummern aus einem Muster und einem Zähler. Mit den deutschen Standards heißen die Rechnungen 2026 RE-2026-0001, RE-2026-0002 und so weiter; 2027 beginnt der Zähler neu.
// config/quittio-managed.php
'numbering' => [
'pattern' => 'RE-{Y}-{seq:4}', // null = Länderpaket (DE: RE-{Y}-{seq:4})
'reset' => 'yearly', // never | yearly | monthly
'start' => 1,
'per_kind' => [
'cancellation' => 'ST-{Y}-{seq:4}', // eigener Kreis für Stornos, null = gemeinsam
'correction' => null,
],
],| Platzhalter | Ersetzt durch |
|---|---|
{Y}, {y} | Jahr des Rechnungsdatums, vier- oder zweistellig |
{m} | Monat, zweistellig |
{seq}, {seq:N} | Laufende Nummer, mit N Stellen aufgefüllt |
{issuer} | Schlüssel des Ausstellerprofils |
{customer} | Kundenkennung (BT-46) |
Die Nummer entsteht erst bei issue(), in der Transaktion des Ausstellens:
$draft = Invoice::draft(Quittio::invoice()->buyer($customer)->line('Consulting', netPrice: '120.00'));
$draft->number; // null: Entwürfe haben keine Nummer
$invoice = $draft->issue();
$invoice->number; // RE-2026-0001- Entwürfe, Validierungsfehler und gescheiterte Stornos verbrauchen keine Nummer; ein Rollback gibt sie zurück.
- Gleichzeitige Ausstellungen werden über eine Zeilensperre serialisiert; Deadlocks und Sperrkonflikte werden bis zu dreimal wiederholt.
- Unique-Indizes auf Nummernraum und Nummer sichern die Eindeutigkeit zusätzlich ab.
- Muster werden geprüft: Ein jährlicher Neustart ohne
{Y}oder zwei Kreise, die dieselbe Nummer erzeugen könnten, werden abgelehnt. - Rückdatierte Rechnungen nutzen den Zähler ihres Zeitraums: Eine Rechnung vom 30.12.2026, ausgestellt im Januar 2027, bekommt die nächste Nummer von 2026.
Mehrere Marken, ein Unternehmen
Nummern müssen pro Unternehmen einmalig sein. Hat eine Firma mehrere Ausstellerprofile, etwa eine pro Marke, teilen sie sich in Quittio Managed einen Nummernraum. Standardmäßig ergibt er sich aus der USt-IdNr. oder der Steuernummer, sodass Profile derselben Firma automatisch zusammengehören. Eine Nummer, die eine Marke vergeben hat, ist für die anderen gesperrt. Gib den Marken deshalb unterschiedliche Muster, zum Beispiel mit {issuer}.
Umstieg von einem anderen System
Wer aus einem bestehenden System kommt, setzt den Zähler einmalig auf den nächsten Wert. Zähler lassen sich nur erhöhen, nie senken, und jede Änderung landet im Audit-Log:
php artisan quittio:sequence:show
php artisan quittio:sequence:set default:invoice:2026 1043