Rechnungen scannen: Warum der Prüfschritt Teil der Automatisierung ist

Im CRM kamen Rechnungen auf zwei Wegen an: über den Synchronisationsordner und über Quick scan.

Das Problem: Erkennung und Speicherung vermischen sich

Ein Scan kann Beträge, Datumsangaben oder Positionen falsch lesen. Wenn die Erkennung sofort einen fertigen Datensatz erzeugt, muss die Person den Fehler anschließend suchen und korrigieren. Bei einem einzelnen Beleg ist ein bearbeitbarer Vorschlag der verständlichere Ablauf.

Die Lösung: Erst lesen, dann bestätigen

Quick scan übernimmt Lieferant, Rechnungsnummer, Datum, Währung und Positionen in normale Formularfelder. Diese bleiben bearbeitbar. Erst mit Create wird die Rechnung gespeichert. Der ursprüngliche Beleg wird beim Speichern angehängt. Ist der Upload inzwischen abgelaufen, meldet die Anwendung die fehlende Anlage ausdrücklich.

Wo die KI keine Entscheidung treffen soll

Die Erkennung wählt kein Aufwandskonto. Diese Zuordnung lässt sich nicht zuverlässig vom Beleg ablesen. Ein Beleg mit einer Gesamtsumme ohne Einzelpositionen erhält eine korrigierbare Position mit dieser Summe. Die Stapelverarbeitung im Synchronisationsordner folgt einem anderen Ablauf: Sie erzeugt Entwürfe zur Freigabe.

Mehrere Anbieter, derselbe Arbeitsablauf

Der dokumentierte Stand unterstützt die Rechnungserkennung über Claude, GPT, Gemini und OpenRouter. Das gewählte Modell muss die hochgeladenen Bilder oder Dokumente verarbeiten können. Eine fehlende Fähigkeit oder falsche Konfiguration soll als verständlicher Fehler sichtbar werden.

Was wir daraus mitnehmen

Eine gute Automatisierung verkürzt die Eingabe und macht ihre Grenzen sichtbar. Der Prüfschritt gehört deshalb zum Produkt. Dieser Beitrag beschreibt den dokumentierten Release-Stand; er behauptet keine gemessene Erkennungsquote.

Ein Scanner, zwei Speicherwege

Warum wir die Dokumenterkennung zusammengeführt haben

Im CRM kamen Rechnungen auf zwei Wegen an: über den Synchronisationsordner und über Quick scan. Beide Wege sollen dieselben Zahlen lesen, aber sie haben unterschiedliche Konsequenzen. Der Hintergrundjob legt einen Entwurf an. Der Scan-Knopf füllt ein noch nicht gespeichertes Formular. Würden beide eine eigene Erkennungslogik pflegen, könnten sich unterstützte Dateitypen, Prompts und Fehlermeldungen auseinanderentwickeln. Wir haben diese gemeinsame Arbeit deshalb im InvoiceScanner gebündelt. Die Entscheidung über das Speichern bleibt beim jeweiligen Aufrufer. Das ist eine kleine Architekturentscheidung mit einer großen Wirkung: Eine Änderung an der Erkennung erreicht beide Wege, ohne den interaktiven Scan plötzlich zu einem automatischen Schreibvorgang zu machen.

Strukturierte Rechnung vor Bilderkennung

Der aktuelle Scanner prüft zuerst, ob die Datei lesbar ist. Bei einem Dokument, das strukturierte Rechnungsdaten enthalten kann, versucht er anschließend den EInvoiceReader. Liefert dieser bereits Daten, werden sie direkt zurückgegeben. Eine Fotografie überspringt diesen Schritt. Erst wenn kein strukturiertes Ergebnis vorliegt, wird der konfigurierte Dokumentanbieter angesprochen. Damit fragen wir kein Sprachmodell nach einer Zahl, die der Lieferant bereits maschinenlesbar geliefert hat. Der folgende Ausschnitt kommt aus InvoiceScanner::read; die umgebende Anbieterwahl ist für das Codefenster gekürzt.

if (! is_readable($path)) {
    throw new RuntimeException("File is no longer readable: {$path}");
}

$mimeType = self::mimeFor($path);
if (! self::isImage($mimeType)) {
    $structured = app(EInvoiceReader::class)->read($path);
    if ($structured !== null) {
        return $structured;
    }
}

// Der Aufrufer entscheidet: Formular füllen oder Entwurf speichern.
// Die gemeinsame Erkennung erzeugt hier noch keine fertige Buchung.

Eine Fähigkeit prüfen, bevor eine entfernte API scheitert

Der nächste Schutz liegt an der Anbietergrenze. Ein konfigurierter Driver muss ReadsDocuments implementieren. Andernfalls entsteht eine gezielte Meldung mit dem Hinweis auf die Modelleinstellungen, statt eines undurchsichtigen Fehlers des entfernten Dienstes. Bei Dateiformaten folgt der Scanner einer bewusst begrenzten Liste: PDF, JPEG, PNG, WebP und GIF. HEIC wird nicht angeboten, weil es von den eingesetzten Drivern nicht unterstützt wird. Diese Prüfung gehört vor die Modellanfrage. Ein erfolgreich hochgeladenes Bild bedeutet noch nicht, dass der gewählte Anbieter es auch verarbeiten kann.

Technische Referenz: PHP: Dateilesbarkeit.

Drei Fälle für die Abnahme

Für die Prüfung sind drei unterschiedliche Belege sinnvoll: eine strukturierte Rechnung, eine Fotografie mit Einzelpositionen und ein Kassenzettel mit nur einer Gesamtsumme. Im letzten Fall soll eine korrigierbare Gesamtposition entstehen. Danach wird kontrolliert, ob vor Create tatsächlich kein Rechnungsdatensatz existiert und ob das Original nach dem Speichern angehängt ist. Ein abgelaufener Upload darf nicht still verschwinden. Auf der Oberfläche müssen fehlende Anlage und fehlende Kontierung sichtbar bleiben. Die Architektur nimmt dem Menschen die Dateneingabe ab, nicht die Verantwortung für eine Buchung. Wie derselbe Grundsatz bei asynchronen Aktionen aussieht, zeigt unser Beitrag zu Hintergrundagenten.

Weiterlesen: Hintergrundagenten: Nach einem Neustart nicht alles wiederholen.