# Quick-Rechnungsportal

Stand: 1. August 2026

## Einordnung des Projekts

Quick-Rechnungsportal wird als eigenständiges Modul innerhalb der Quick-Produktfamilie entwickelt. Die Anwendung ist keine Buchhaltung und kein Archivsystem. Ihre Aufgabe besteht darin, elektronische Eingangsrechnungen technisch entgegenzunehmen, maschinell auszulesen, in ein neutrales internes Datenmodell zu überführen, technisch zu validieren und für nachgelagerte Systeme bereitzustellen.

Die fachliche Weiterverarbeitung verbleibt außerhalb des Portals. Insbesondere werden keine Buchungssätze im Sinne einer Finanzbuchhaltung erzeugt oder abgeschlossen. Stattdessen stellt das Portal strukturierte Rechnungsdaten, Validierungsergebnisse und Übergabeformate bereit, damit andere Systeme daraus Buchungsvorschläge oder weiterführende Prozesse ableiten können.

Die gesetzeskonforme Archivierung gehört ausdrücklich nicht zum Projektumfang. Wenn ein DMS oder Archivsystem wie Paperless-ngx bereits vorhanden ist, kann es als separater Dokumentenkanal genutzt werden. Das Portal ersetzt dieses System nicht, sondern verarbeitet aus solchen Quellen nur die technischen Rechnungsdaten weiter.

## Technische Grundlage

Die Anwendung basiert aktuell auf folgenden Technologien:

- .NET 10
- Blazor Server
- Radzen-Komponenten für die Oberfläche
- Clean-Architecture-orientierte Projektstruktur
- dateibasierte Speicherung für den MVP
- vorbereitete PostgreSQL-Anbindung, derzeit nicht aktiv genutzt

Die Struktur ist in mehrere Projekte getrennt:

- `QuickRechnungsportal.Domain`
  Enthält die neutralen Domänenobjekte wie Rechnung, Parteien, Positionen, Steuerinformationen, Verarbeitungsprotokolle und Exporthistorie.

- `QuickRechnungsportal.Application`
  Enthält Anwendungslogik, Service-Schnittstellen und Anwendungsservices für Import, Validierung, Export, Mailbox-Abruf und Paperless-Abruf.

- `QuickRechnungsportal.Infrastructure`
  Enthält konkrete technische Implementierungen, etwa Parser, IMAP-Zugriff, Paperless-REST-Zugriff, CSV-Export, dateibasierte Speicherung und vorbereitete EF-Core-/PostgreSQL-Komponenten.

- `QuickRechnungsportal`
  Enthält Web-Host, Blazor-Seiten, Controller, UI-Logik und die Verdrahtung der Anwendung.

## Fachliches Zielbild des aktuellen MVP

Der aktuelle MVP bildet den Eingang elektronischer Rechnungen stabil und nachvollziehbar ab. Das Portal soll vor allem folgende Fragen beantworten:

- Welche Rechnungen sind technisch eingegangen?
- Aus welchem Eingangskanal stammen sie?
- Konnten die Dokumente gelesen und interpretiert werden?
- Welche Daten wurden ausgelesen?
- Gibt es technische Fehler oder Warnungen?
- Welche Rechnungen sollen manuell exportiert werden?
- In welches Übergabeformat wurden sie exportiert?

Der Fokus liegt auf technischer Transparenz und kontrollierter Weitergabe, nicht auf automatischer Buchung, Kontierung oder Archivierung.

## Aktuell umgesetzte Funktionen

### Manueller Import von E-Rechnungen

Im Rechnungseingang können Rechnungen direkt über die Weboberfläche hochgeladen werden. Der Upload führt nicht zu einem sofortigen Export. Stattdessen wird das Dokument zuerst importiert, interpretiert, validiert und anschließend im Portal angezeigt.

Unterstützt werden derzeit:

- UBL-XRechnung als XML
- CII-XRechnung als XML
- ZUGFeRD- beziehungsweise Factur-X-PDFs mit eingebettetem strukturiertem Rechnungsdatensatz

Der manuelle Import ist besonders für Tests, Einzelfälle, Pilotbetrieb und fachliche Sichtprüfung geeignet.

Vor dem Import berechnet das Portal einen SHA-256-Fingerprint des kompletten hochgeladenen Dateiinhalts. Wurde derselbe Inhalt für den Mandanten bereits importiert, wird der Upload als Dublette erkannt und nicht erneut verarbeitet. Die Oberfläche meldet diesen Fall als Hinweis, nicht als technischen Fehler.

### Import über IMAP-Postfächer

Das Portal kann Rechnungen aus konfigurierten IMAP-Postfächern abrufen. Pro Konto können Server, Port, SSL-Verwendung, Ordner, Zugangsdaten und das Verhalten zum Gelesen-Status konfiguriert werden.

Der Abruf wird aktuell manuell aus der Oberfläche gestartet. Ein zyklischer BackgroundService ist als späterer Ausbau vorgesehen.

Die Oberfläche zeigt während des Abrufs einen laufenden Status, sperrt parallele Aktionen und fasst das Ergebnis mit Anzahl der geprüften E-Mails, Anhänge, importierten Rechnungen, Dubletten und Fehler zusammen.

Jeder IMAP-Abruf wird zusätzlich als Importlauf protokolliert. Die Historie enthält Konto, Zeitpunkt, Erfolg oder Fehler, Anzahl geprüfter E-Mails, geprüfter Anhänge, importierter Rechnungen, übersprungener Dubletten und fehlgeschlagener Dokumentimporte.

Der Ablauf beim IMAP-Import:

1. Verbindung zum konfigurierten Postfach herstellen
2. relevanten Ordner öffnen
3. Nachrichten lesen
4. Anhänge extrahieren
5. Anhänge über SHA-256 gegen das Importregister prüfen
6. neue Anhänge dem normalen Rechnungsimport übergeben
7. je nach Einstellung E-Mails als gelesen markieren

### Import aus Paperless-ngx

Paperless-ngx ist als zusätzlicher Eingangskanal vorbereitet und technisch angebunden. Dieser Weg ist sinnvoll, wenn Paperless bereits E-Mails entgegennimmt, Dokumente sammelt oder vorhandene Dokumentenprozesse steuert. Quick-Rechnungsportal holt dann ausgewählte Dokumente aus Paperless ab und verarbeitet sie über denselben Rechnungsimport wie manuelle Uploads oder IMAP-Anhänge.

Der Ablauf beim Paperless-Import:

1. Paperless-Konfiguration aus den Einstellungen lesen
2. per API-Token am Paperless-Server authentifizieren
3. Dokumentliste über eine Suchabfrage laden, standardmäßig `tag:quick-pending`
4. pro Dokument die Originaldatei oder ersatzweise die Archivdatei herunterladen
5. heruntergeladene Datei über SHA-256 gegen das Importregister prüfen
6. neue Dokumente dem normalen Rechnungsimport übergeben
7. erfolgreiche oder fehlerhafte Verarbeitung im Ergebnis anzeigen
8. optional Paperless-Tags aktualisieren

Die Tag-Logik ist bewusst konfigurierbar. Typischerweise wird ein Wartend-Tag nach erfolgreichem Import entfernt und ein Importiert-Tag gesetzt. Bei Fehlern kann stattdessen ein Fehler-Tag gesetzt werden. Die konkreten Tag-IDs müssen aus der Paperless-Installation übernommen werden.

Dieser Kanal ist keine DMS-Übergabe und keine Archivierung. Paperless bleibt das führende Dokumentensystem, Quick-Rechnungsportal nutzt Paperless nur als Quelle für strukturierte Rechnungsextraktion und Export.

Für Paperless steht in den Einstellungen ein Verbindungstest zur Verfügung. Der Test speichert die aktuelle Konfiguration, fragt die Paperless-Dokument-API mit dem konfigurierten API-Token ab und meldet, ob der Server erreichbar ist und wie viele Dokumente zur aktuellen Suchabfrage passen. Paperless-Abrufe werden wie IMAP-Abrufe in der Importlauf-Historie gespeichert.

### Format-Erkennung und Parser-Auswahl

Der Importpfad ist so aufgebaut, dass Parser keinerlei Kenntnis von Zielsystemen haben. Jeder Parser prüft zunächst, ob er ein Dokument lesen kann. Danach wird genau ein geeigneter Parser für die Extraktion verwendet.

Aktuell sind drei Parser integriert:

- `UblInvoiceParser`
- `CiiInvoiceParser`
- `ZugferdPdfInvoiceParser`

Alle Parser überführen ihre Ergebnisse in dasselbe interne Rechnungsmodell. Dadurch bleibt das Portal offen für weitere Zielsysteme, Exportprofile und spätere REST-Connectoren.

Die Parser lesen inzwischen nicht nur Pflichtdaten für Anzeige und Validierung, sondern auch wichtige optionale EN-16931-Informationen ein, soweit sie im jeweiligen Dokument vorhanden sind:

- Leitweg-ID beziehungsweise `BuyerReference`
- Bestellreferenz
- Vertragsreferenz
- Projektreferenz
- Lieferdatum
- Leistungszeitraum
- Freitexthinweise auf Kopfebene
- Zahlungsbedingungen als Text
- Kopf-Rabatte beziehungsweise Abschläge
- Kopf-Zuschläge
- Vorauszahlungen
- Rundungsbeträge
- Zahlbetrag
- Positionshinweise
- Lieferanten- und Käuferartikelnummern auf Positionsebene
- Positionsrabatte und Positionszuschläge

Bei UBL und CII werden diese Werte direkt aus den XML-Strukturen gelesen. Bei ZUGFeRD/Factur-X werden die stabil typisierten Felder der ZUGFeRD-Bibliothek direkt genutzt; zusätzliche optionale Felder werden defensiv nur dann übernommen, wenn die verwendete Bibliotheksversion sie anbietet.

### Neutrales internes Rechnungsmodell

Die eingelesenen Rechnungen werden intern nicht in ein GDL- oder Buchhaltungsschema übersetzt, sondern in ein neutrales Modell überführt. Wichtige Bestandteile sind:

- `Invoice`
- `InvoiceParty`
- `InvoiceLine`
- `InvoiceTax`
- `PaymentInformation`
- `Attachment`
- `InvoiceRawData`
- `ProcessingLog`
- `ExportHistory`

Alle Entitäten verwenden GUIDs als technische Schlüssel. Mandantenfähigkeit wird durchgängig mitgeführt.

Das Modell nimmt technische Importdaten sauber auf, ohne bereits fachliche Entscheidungen für ein bestimmtes Zielsystem zu erzwingen.

Das Kopfdatenmodell enthält zusätzlich optionale Referenzen und Beträge, die für nachgelagerte Buchungssysteme wichtig sein können, aber keine eigene Buchungslogik darstellen. Dazu gehören BuyerReference/Leitweg-ID, Bestell-, Vertrags- und Projektreferenzen, Liefer- und Leistungsdaten, Hinweise, Rabatte, Zuschläge, Vorauszahlungen, Rundungen und Zahlbetrag.

### Rohabbild des strukturierten Eingangsdokuments

Zusätzlich zum neutralen Modell speichert das Portal beim Import ein Rohabbild des eingegangenen Rechnungsdokuments. Dieses Rohabbild ist bewusst kein weiteres fachliches Mapping und keine Interpretation einzelner Felder. Es erhält den ursprünglichen technischen Payload als Bytefolge und macht ihn später wieder herunterladbar.

Für UBL- und CII-Rechnungen wird die originale XML-Datei gespeichert, also genau der strukturierte Rechnungsdatensatz, den der Parser gelesen hat. Die XML-Struktur bleibt dadurch vollständig erhalten, einschließlich Feldern, die im aktuellen neutralen Modell noch nicht explizit angezeigt oder exportiert werden. Ein späterer Parser-Ausbau oder ein externes Zielsystem kann sich bei Bedarf erneut auf dieses Original-XML beziehen.

Für ZUGFeRD- beziehungsweise Factur-X-PDFs wird derzeit der originale PDF-Container gespeichert. Dieser Container ist die importierte Quelldatei und enthält bei gültigen ZUGFeRD-/Factur-X-Rechnungen den eingebetteten strukturierten Rechnungsdatensatz. Damit bleibt auch hier das empfangene Originaldokument technisch erhalten. Eine zusätzliche separate Extraktion und Ablage der eingebetteten XML-Datei kann später ergänzt werden, falls Zielsysteme diesen Zugriff ohne PDF-Container benötigen.

Jeder Rohdatensatz enthält:

- Format, zum Beispiel `UBL`, `CII` oder `ZUGFeRD/Factur-X`
- Rolle des Payloads, zum Beispiel `StructuredXml` oder `OriginalPdfContainer`
- ursprünglicher Dateiname
- MIME-Typ
- Größe in Bytes
- SHA-256-Hash des gespeicherten Payloads
- Zeitpunkt der Erfassung
- Base64-kodierte Nutzdaten für die aktuelle dateibasierte Speicherung

Der SHA-256-Hash dient als technische Prüfsumme. Er erlaubt später nachzuweisen, ob das gespeicherte Rohabbild bytegleich zu einem Referenzdokument ist. Das ist hilfreich für Tests, Fehleranalyse und Schnittstellenentwicklung. Es ersetzt aber keine revisionssichere Archivierung.

In der Rechnungsdetailansicht gibt es dafür den Tab `Rohdaten`. Dort werden die gespeicherten Rohdatensätze angezeigt und können heruntergeladen werden. Bereits vor Einführung dieser Funktion importierte Rechnungen besitzen noch kein Rohabbild; sie müssen bei Bedarf erneut importiert werden.

### Technische Validierung

Nach dem Einlesen wird jede Rechnung technisch validiert. Dabei wird nicht geprüft, ob eine Rechnung buchhalterisch korrekt kontiert ist. Geprüft wird, ob die für Anzeige und Übergabe notwendigen technischen Daten plausibel und ausreichend vorhanden sind.

Aktuell umfasst die Validierung insbesondere:

- Vorhandensein einer Rechnungsnummer
- Vorhandensein eines Rechnungsdatums
- Vorhandensein eines Lieferanten
- Vorhandensein des Rechnungsempfängers
- Vorhandensein von Summenwerten
- Vorhandensein von Positionen, soweit fachlich erwartet

Fehler und Warnungen werden als `ProcessingLog` gespeichert und sowohl in der Übersicht als auch in den Rechnungsdetails angezeigt.

### Rechnungseingang und Übersicht

Die Seite `Rechnungseingang` ist die zentrale Arbeitsoberfläche für den MVP. Dort können Anwender:

- Dateien manuell hochladen
- ein IMAP-Konto auswählen und abrufen
- Paperless-Dokumente über die konfigurierte Suchabfrage abrufen
- importierte Rechnungen in einer Tabelle einsehen
- Rechnungen markieren
- ein Exportprofil auswählen
- einen manuellen Batch-Export starten

Die Tabelle zeigt unter anderem:

- Rechnungsnummer
- Lieferant
- Datum
- Bruttobetrag
- Währung
- Status
- Quelle
- Hinweise zu Fehlern, Warnungen und Exporten

### Rechnungsdetails

Für jede importierte Rechnung steht eine Detailansicht zur Verfügung. Sie zeigt den eingelesenen Inhalt granularer als die Übersicht.

Dargestellt werden derzeit:

- Kopfdaten der Rechnung
- Netto-, Steuer- und Bruttobeträge
- Lieferant und Empfänger
- Positionen
- Steuerzeilen
- Zahlungsinformationen
- Validierungs- und Verarbeitungsprotokolle
- Exporthistorie

Die Detailseite ist aktuell das wichtigste Werkzeug, um Parser-Mapping und technische Qualität der importierten Daten zu prüfen.

## Export in nachgelagerte Systeme

Der Export erfolgt bewusst manuell. Eine Rechnung wird zuerst importiert, validiert und angezeigt. Erst danach entscheidet der Anwender, welche Rechnungen exportiert werden sollen.

Aktuell sind zwei CSV-Profile umgesetzt:

- `StandardCsvBookingSuggestions`
  Dieses Profil erzeugt zeilenorientierte Daten für Buchungsvorschläge, typischerweise gruppiert nach steuerlicher Aufteilung.

- `StandardCsvInvoiceLines`
  Dieses Profil erzeugt eine positionsorientierte Ausgabe, damit Zielsysteme mit Bezug auf einzelne Rechnungspositionen arbeiten können.

Der Export ist als Batch möglich. In der Übersicht können mehrere Rechnungen markiert und anschließend gemeinsam exportiert werden.

Die Exporthistorie wird an der Rechnung gespeichert. Dadurch ist nachvollziehbar, wann eine Rechnung mit welchem Profil exportiert wurde.

Nach einem manuellen Batch-Export zeigt der Rechnungseingang die Exportzusammenfassung direkt auf der Seite an. Enthalten sind Anzahl erfolgreicher und fehlerhafter Exporte sowie die vom Exportmodul gelieferten Zielreferenzen, bei den CSV-Profilen also die erzeugten Dateipfade.

### Allgemeines CSV-Format

Beide Exportprofile werden als CSV-Dateien mit folgenden technischen Eigenschaften geschrieben:

- Zeichenkodierung: UTF-8 mit BOM
- Zeilentrennung: Standard-Zeilenumbruch von .NET auf dem Zielsystem
- Feldtrennzeichen: Semikolon `;`
- Textqualifizierung: Werte werden nur dann in doppelte Anführungszeichen gesetzt, wenn sie Semikolon, Anführungszeichen oder Zeilenumbrüche enthalten
- Escaping: doppelte Anführungszeichen innerhalb eines Wertes werden als `""` geschrieben
- Datumsformat: `yyyy-MM-dd`
- Dezimalformat: Punkt als Dezimaltrennzeichen, keine Lokalisierung, zum Beispiel `1234.56`

Die CSV-Profile enthalten zusätzlich die optionalen Zusatzinformationen aus dem erweiterten neutralen Modell. Importprogramme können diese Felder ignorieren, wenn sie nicht benötigt werden, oder für bessere Buchungsvorschläge verwenden, etwa Leitweg-ID, Bestellreferenz, Vertragsreferenz, Leistungszeitraum, Zahlungsbedingungen, Kopf- und Positionsrabatte sowie Artikelnummern.
- Dateiname: `{InvoiceNumber}-{InvoiceIdN}.csv`, wobei unzulässige Dateinamenzeichen durch `_` ersetzt werden

Jede Exportdatei enthält in der ersten Zeile die Kopfzeile mit den Spaltennamen. Die Reihenfolge der Spalten ist technisch relevant und sollte auf Importseite exakt erwartet oder bewusst gemappt werden.

Leere oder noch nicht gemappte Felder werden als leere CSV-Felder geschrieben. Das betrifft insbesondere vorbereitete Zielsystemfelder wie Sachkonten oder Kostenstellen.

### Profil `StandardCsvBookingSuggestions`

Dieses Profil dient als Übergabeformat für Buchungsvorschläge. Es erzeugt nicht zwingend genau eine Zeile pro Rechnung. Stattdessen wird die Rechnung in steuerliche Buchungseinheiten aufgeteilt.

Die Bildung der Exportzeilen erfolgt nach folgender Logik:

1. Wenn die Rechnung explizite Steuerzeilen im internen Modell enthält, werden diese bevorzugt verwendet.
2. Für jede Steuerzeile wird eine Exportzeile erzeugt.
3. Falls keine Steuerzeilen vorhanden sind, werden die Rechnungspositionen nach `TaxRate` und `TaxCategoryCode` gruppiert.
4. Wenn weder Steuerzeilen noch Positionen sinnvoll vorhanden sind, wird eine Fallback-Zeile aus den Rechnungssummen erzeugt.

Das bedeutet für einen Importer:

- Eine Rechnung kann genau eine oder mehrere Zeilen erzeugen.
- Mehrere Zeilen mit gleicher `InvoiceId` gehören fachlich zusammen.
- Die Aufteilung entspricht einer Buchungsvorschlagslogik nach Steuersatz und Steuerkategorie, nicht einer reinen Positionslogik.

#### Spaltenbeschreibung `StandardCsvBookingSuggestions`

`RecordType`
Kennzeichnet den Datensatztyp. Aktuell wird immer `IncomingInvoice` geschrieben. Ein Importer kann dieses Feld nutzen, um unterschiedliche Satztypen innerhalb eines später erweiterten Formats zu unterscheiden.

`BookingSuggestionId`
Technischer Schlüssel für die einzelne Buchungsvorschlagszeile. Der Wert wird aktuell aus `InvoiceId` plus laufender Nummer gebildet. Dieses Feld ist innerhalb der Exportdatei der eindeutige Identifikator der erzeugten Zeile, nicht der Rechnung als Ganzes.

`InvoiceId`
GUID der Rechnung im Portal im Format `D`, also mit Bindestrichen. Mehrere Zeilen derselben Rechnung tragen dieselbe `InvoiceId`.

`InvoiceNumber`
Fachliche Rechnungsnummer, wie sie aus dem Dokument ausgelesen wurde.

`InvoiceDate`
Rechnungsdatum im Format `yyyy-MM-dd`. Wenn kein Datum vorhanden ist, bleibt das Feld leer.

`DueDate`
Fälligkeitsdatum im Format `yyyy-MM-dd`. Wenn kein Fälligkeitsdatum vorhanden ist, bleibt das Feld leer.

`BookingText`
Automatisch gebildeter Buchungstext. Das Format lautet aktuell `Eingangsrechnung {InvoiceNumber}` oder `Eingangsrechnung {InvoiceNumber} {SupplierName}`, falls ein Lieferantenname verfügbar ist.

`SupplierName`
Name des Lieferanten aus der Rolle `Supplier`.

`SupplierVatId`
Umsatzsteuer-Identifikationsnummer des Lieferanten, sofern vorhanden.

`SupplierTaxNumber`
Steuernummer des Lieferanten, sofern vorhanden.

`SupplierIban`
IBAN aus den eingelesenen Zahlungsinformationen. Aktuell stammt dieses Feld aus `PaymentInformation.Iban`.

`SupplierBic`
BIC aus den eingelesenen Zahlungsinformationen. Aktuell stammt dieses Feld aus `PaymentInformation.Bic`.

`BuyerName`
Name des Rechnungsempfängers aus der Rolle `Buyer`.

`CurrencyCode`
Währungscode der Rechnung, typischerweise `EUR`.

`GrossAmount`
Bruttobetrag der einzelnen Buchungsvorschlagszeile. Bei vorhandenen Steuerzeilen ist dies `NetAmount + TaxAmount` für genau diese Steueraufteilung, nicht zwingend der Gesamtbruttobetrag der ganzen Rechnung.

`NetAmount`
Nettobetrag der einzelnen Buchungsvorschlagszeile. Bei vorhandenen Steuerzeilen wird bevorzugt `TaxableAmount` genutzt. Falls dieser Wert nicht gefüllt ist, wird die Summe der passenden Positionen verwendet.

`TaxAmount`
Steuerbetrag der einzelnen Buchungsvorschlagszeile.

`TaxRate`
Steuersatz der einzelnen Buchungsvorschlagszeile als Dezimalwert, zum Beispiel `19.00` oder `7.00`.

`TaxCategoryCode`
Steuerkategorie der einzelnen Buchungsvorschlagszeile, sofern im Dokument vorhanden.

`PaymentReference`
Zahlungsreferenz aus den Zahlungsinformationen. Wenn keine explizite Zahlungsreferenz vorhanden ist, wird als Fallback die Rechnungsnummer geschrieben.

`DocumentSource`
Technischer Ursprung der Rechnung, zum Beispiel `ManualUpload`, ein IMAP-bezogener Quellwert oder `Paperless:{DocumentId}:{Title}`.

`SuggestedDebitAccount`
Vorbereitetes Zielfeld für ein Sollkonto. Dieses Feld wird aktuell leer geschrieben und ist für spätere Mapping-Regeln gedacht.

`SuggestedCreditAccount`
Vorbereitetes Zielfeld für ein Habenkonto. Dieses Feld wird aktuell leer geschrieben.

`CostCenter`
Vorbereitetes Zielfeld für Kostenstellen- oder Kostenobjektzuordnung. Dieses Feld wird aktuell leer geschrieben.

`LineSummary`
Kurze textliche Zusammenfassung der zugeordneten Rechnungspositionen. Das Feld enthält bis zu drei unterschiedliche Positionsbeschreibungen, getrennt durch ` | `. Es ist als Lesbarkeitshilfe und für einfache Importregeln gedacht, nicht als vollständige Positionsliste.

#### Importhinweise `StandardCsvBookingSuggestions`

Ein Importer für dieses Profil sollte mindestens folgende Regeln beachten:

- Zeilen mit gleicher `InvoiceId` gehören zu derselben Rechnung.
- `BookingSuggestionId` identifiziert die einzelne Aufteilungszeile.
- Die Kombination aus `NetAmount`, `TaxAmount`, `TaxRate` und `TaxCategoryCode` bildet den Kern der steuerlichen Aufteilung.
- Die Felder `SuggestedDebitAccount`, `SuggestedCreditAccount` und `CostCenter` sind aktuell leer und müssen im Zielsystem durch eigene Regeln, Stammdaten oder Benutzerinteraktion befüllt werden.
- `LineSummary` ist rein informativ und nicht für exakte mathematische Verarbeitung gedacht.

### Profil `StandardCsvInvoiceLines`

Dieses Profil dient als positionsorientierte Übergabe. Es erzeugt grundsätzlich eine Zeile pro Rechnungsposition. Ziel ist, dass andere Systeme oder eigene Importprogramme möglichst nah an den eingelesenen Rechnungspositionen weiterarbeiten können.

Die Bildung der Exportzeilen erfolgt nach folgender Logik:

1. Wenn Positionen vorhanden sind, wird für jede Position genau eine Zeile geschrieben.
2. Der Steuerbetrag der Position wird aktuell nicht aus einer expliziten Positionssteuer entnommen, sondern als `LineNetAmount * TaxRate / 100` berechnet und auf zwei Nachkommastellen kaufmännisch gerundet.
3. Wenn keine Positionen vorhanden sind, erzeugt das System genau eine Fallback-Zeile mit den Rechnungssummen.

Das bedeutet für einen Importer:

- Im Regelfall entspricht jede Exportzeile genau einer Rechnungsposition.
- Bei positionlosen Rechnungen muss mit einer künstlich erzeugten Fallback-Zeile gerechnet werden.
- Die Felder `EstimatedLineTaxAmount` und `EstimatedLineGrossAmount` sind berechnete Werte aus dem Portal und nicht zwingend identisch mit ursprünglichen Quellwerten im Dokument.

#### Spaltenbeschreibung `StandardCsvInvoiceLines`

`RecordType`
Kennzeichnet den Datensatztyp. Aktuell wird immer `IncomingInvoiceLine` geschrieben.

`InvoiceId`
GUID der Rechnung im Format `D`, also mit Bindestrichen. Mehrere Positionszeilen derselben Rechnung tragen dieselbe `InvoiceId`.

`InvoiceNumber`
Fachliche Rechnungsnummer.

`InvoiceDate`
Rechnungsdatum im Format `yyyy-MM-dd`. Falls kein Datum vorhanden ist, bleibt das Feld leer.

`DueDate`
Fälligkeitsdatum im Format `yyyy-MM-dd`. Falls kein Datum vorhanden ist, bleibt das Feld leer.

`SupplierName`
Name des Lieferanten.

`SupplierVatId`
Umsatzsteuer-Identifikationsnummer des Lieferanten, sofern vorhanden.

`BuyerName`
Name des Rechnungsempfängers.

`CurrencyCode`
Währungscode der Rechnung.

`LineNumber`
Laufende Positionsnummer aus dem internen Modell. Im Fallback-Fall ohne echte Positionen wird hier `1` geschrieben.

`Description`
Positionsbeschreibung. Im Fallback-Fall ohne echte Positionen wird hier der generierte Buchungstext verwendet.

`Quantity`
Menge der Position. Im Fallback-Fall ohne echte Positionen wird `1.00` geschrieben.

`UnitCode`
Einheitscode der Position, sofern vorhanden. Im Fallback-Fall bleibt das Feld leer.

`UnitPrice`
Einzelpreis der Position. Im Fallback-Fall wird hier der Rechnungsnetto- beziehungsweise Summenwert verwendet.

`LineNetAmount`
Nettobetrag der Position. Im Fallback-Fall wird der Rechnungsnetto-Betrag geschrieben.

`TaxRate`
Steuersatz der Position. Im Regelfall stammt er direkt aus der Position. Im Fallback-Fall wird er aus `TaxAmount / NetAmount * 100` berechnet, sofern `NetAmount` ungleich null ist.

`TaxCategoryCode`
Steuerkategorie der Position, sofern vorhanden. Im Fallback-Fall bleibt das Feld leer.

`EstimatedLineTaxAmount`
Geschätzter Steuerbetrag der Position. Er wird aktuell aus `LineNetAmount * TaxRate / 100` berechnet und kaufmännisch auf zwei Nachkommastellen gerundet.

`EstimatedLineGrossAmount`
Geschätzter Bruttobetrag der Position. Er ergibt sich aus `LineNetAmount + EstimatedLineTaxAmount`.

`PaymentReference`
Zahlungsreferenz aus dem Dokument oder als Fallback die Rechnungsnummer.

`DocumentSource`
Technischer Ursprung der Rechnung, etwa manueller Upload, IMAP-Abruf oder Paperless-Abruf.

`SuggestedExpenseAccount`
Vorbereitetes Zielfeld für ein Aufwandskonto oder eine vergleichbare Kontierungsinformation. Das Feld wird aktuell leer geschrieben.

`CostCenter`
Vorbereitetes Zielfeld für Kostenstellen- oder Kostenträgerzuordnung. Das Feld wird aktuell leer geschrieben.

#### Importhinweise `StandardCsvInvoiceLines`

Ein Importer für dieses Profil sollte mindestens folgende Regeln beachten:

- Zeilen mit gleicher `InvoiceId` gehören zu derselben Rechnung.
- `LineNumber` ist die fachliche Ordnungsnummer der Position, aber nicht global eindeutig.
- `EstimatedLineTaxAmount` und `EstimatedLineGrossAmount` sind technische Rechenwerte des Portals und sollten bei Bedarf gegen Quell- oder Zielsystemregeln validiert werden.
- `SuggestedExpenseAccount` und `CostCenter` sind aktuell Platzhalterfelder und werden nicht automatisch befüllt.
- Bei Rechnungen ohne echte Positionsdaten muss mit einer einzelnen Fallback-Zeile gerechnet werden.

### Empfehlung für Entwickler fremder Importsysteme

Für einen Entwickler, der diese Exportdateien in ein anderes System übernehmen möchte, sind folgende Punkte zentral:

- `StandardCsvBookingSuggestions` ist das geeignetere Format, wenn das Zielsystem aus einer Rechnung steuerlich aufgeteilte Buchungsvorschläge oder Sammelbuchungen bilden soll.
- `StandardCsvInvoiceLines` ist das geeignetere Format, wenn das Zielsystem mit einzelnen Rechnungspositionen, Kostenarten oder positionsbezogenen Regeln arbeitet.
- Beide Formate enthalten bewusst vorbereitete Leerfelder für spätere Zielsystemlogik. Diese Felder sind keine Fehler, sondern Erweiterungspunkte.
- Die CSV-Dateien sind technisch bewusst einfach gehalten. Es gibt keine Subtabellen, keine eingebetteten JSON-Strukturen und keine Mehrsatzdatei mit Footerlogik.
- Die mathematisch relevanten Felder sollten im Zielsystem gegen die eigenen Validierungsregeln geprüft werden, insbesondere bei Rundung, Steueraufteilung und Fallback-Zeilen.

## Aktuelle Speicherstrategie

Der aktuelle MVP verwendet standardmäßig keine relationale Datenbank. Stattdessen wird bewusst ein dateibasierter Ansatz genutzt, weil der aktuelle Arbeitsablauf keine komplexe persistente Fachhaltung verlangt.

Wesentliche Gründe:

- importierte Rechnungen sollen technisch verfügbar sein, aber nicht als dauerhaftes Buchhaltungssystem dienen
- nach dem Export erfolgt die eigentliche Weiterverarbeitung in einem Zielsystem
- der Betriebsaufwand bleibt für den MVP niedrig
- die vorhandenen Repository-Schnittstellen erlauben später dennoch einen Wechsel auf PostgreSQL

Im dateibasierten Betrieb werden Rechnungen, Protokolle, Exporte, Einstellungen und Import-Fingerprints im lokalen Arbeitsverzeichnis gespeichert.

## Wichtige Verzeichnisse und Dateien

Die wichtigsten Ablageorte sind derzeit:

- `data/invoices`
  Hier liegen importierte Rechnungen je Mandant und Rechnung als `invoice.json`.

- `data/exports`
  Hier werden erzeugte CSV-Exportdateien abgelegt.

- `data/logs`
  Hier liegen strukturierte Ereignisprotokolle der Verarbeitung.

- `data/import-registry`
  Hier liegen die SHA-256-Fingerprints bereits importierter Quelldokumente. Das Register wird von manuellem Upload, IMAP und Paperless genutzt.

- `data/import-history`
  Hier liegen kompakte Laufprotokolle für manuell gestartete IMAP- und Paperless-Abrufe. Diese Einträge dienen der Bedienrückmeldung und Fehleranalyse, nicht der revisionssicheren Archivierung.

- `data/settings/portal-settings.json`
  Hier wird die editierbare Portal-Konfiguration gespeichert.

## Duplikatschutz

Ein wichtiger Punkt für den produktiven Import ist die sichere Vermeidung von Doppeltimporten. Das Portal verlässt sich dafür nicht ausschließlich auf Dateinamen, Rechnungsnummern, IMAP-Flags oder Paperless-Tags, weil diese Werte verändert werden können und keine belastbare technische Importhistorie darstellen.

Aktuell ist deshalb eine eigene Duplikatprüfung eingebaut:

- vor dem Import wird über den kompletten Rohinhalt des Dokuments ein SHA-256 berechnet
- dieser Fingerprint wird nach erfolgreichem Import persistent gespeichert
- beim nächsten Abruf wird jedes Dokument erneut gehasht und gegen die bereits importierten Fingerprints geprüft
- identische Inhalte werden als Dublette erkannt und nicht erneut importiert
- das Register ist mandantenbezogen und kann mehrere Eingangskanäle abdecken

Dieser Schutz gilt aktuell für manuelle Uploads, IMAP-Anhänge und Paperless-Dokumente. Entscheidend ist nicht der Dateiname, sondern der unveränderte Dateiinhalt. Eine umbenannte, aber inhaltlich identische Datei wird deshalb ebenfalls erkannt.

## Einstellungsseite

Die Seite `Einstellungen` ist als zentrale Konfigurationsoberfläche für den MVP umgesetzt.

### Arbeitsdaten

- Root-Pfad für die technische Dateihaltung
- Aufbewahrungsdauer technischer Daten in Tagen
- Option zum Behalten von Originaldateien nach dem Export

### Exportpfade

- Zielpfad für Buchungsvorschlags-CSV
- Zielpfad für positionsorientierte CSV
- Anzeige der aufgelösten Zielpfade, damit ein nachgelagertes System dieselben Verzeichnisse überwachen oder gezielt einlesen kann

Die Einstellungen machen außerdem transparent, dass `data/invoices`, `data/logs` und `data/import-registry` technische Arbeitsdaten sind. Diese Daten dienen der Beta-Bedienung, Fehleranalyse und Exportnachvollziehbarkeit, ersetzen aber keine Archivierung.

Für den aktuellen dateibasierten Betrieb ist keine Datenbankkonfiguration erforderlich. Die optionale PostgreSQL-Anbindung wird nur aktiviert, wenn in der Konfiguration explizit `Database:ConnectionString` gesetzt ist. Ohne diesen Wert arbeitet das Portal vollständig dateibasiert.

## Protokollseite

Die Seite `Protokoll` stellt Validierungs-, Verarbeitungs- und Exportmeldungen aus den aktuellen Arbeitsdaten zusammen. Die Daten werden aus den gespeicherten Rechnungen, deren `ProcessingLog`-Einträgen und deren `ExportHistory` abgeleitet.

Die Ansicht bietet:

- Filter nach Schweregrad
- Filter nach Bereich, zum Beispiel Verarbeitung oder Export
- Freitextsuche über Rechnungsnummer, Lieferant, Code, Meldung, Details und Quelle
- Zähler für Fehler und Warnungen
- Direktlink zur betroffenen Rechnung, wenn eine Rechnung zugeordnet ist

Damit ist die Protokollseite für die Beta vor allem ein Arbeitsinstrument für Importtests, Parserprüfung, Validierungsfehler und Exportkontrolle.

Die Importlauf-Historie im Rechnungseingang ergänzt diese Sicht. Sie zeigt nicht einzelne Validierungsmeldungen, sondern den operativen Verlauf kompletter Abrufe aus IMAP und Paperless.

### IMAP-Konten

- Kontoname
- Server
- Port
- SSL
- Ordner
- Benutzername
- Kennwort oder App-Passwort
- Verhalten zum Markieren als gelesen
- Verbindungstest direkt in den Einstellungen

### Paperless-ngx

- Aktivierungsflag
- Server-URL
- API-Token
- Suchabfrage für Importkandidaten
- maximale Dokumentanzahl pro Abruf
- Auswahl, ob Originaldatei oder Archivdatei bevorzugt heruntergeladen wird
- Auswahl, ob Tags nach dem Import aktualisiert werden
- Wartend-Tag-ID zum Entfernen nach erfolgreichem Import
- Importiert-Tag-ID zum Setzen nach erfolgreichem Import
- Fehler-Tag-ID zum Setzen nach fehlgeschlagenem Import
- Verbindungstest direkt in den Einstellungen

### DMS-Übergabe

- Aktivierungsflag
- Connector- oder Zielsystemname
- Zielpfad oder Übergabeverzeichnis

Diese Einstellungen werden derzeit lokal als JSON gespeichert und von den technischen Diensten direkt verwendet. Für produktive Zugangsdaten sollte später ein geschützter Secret-Store angebunden werden.

## Aktuelle Grenzen und bewusste Nicht-Ziele

Der aktuelle Stand ist für einen belastbaren MVP bereits brauchbar, hat aber bewusst mehrere Grenzen:

- keine rechtssichere Archivierung
- keine echte DMS-Übergabe aus dem Portal heraus
- kein periodischer BackgroundService für IMAP oder Paperless
- keine Benutzer- und Rollenlogik
- keine zielsystemspezifische Fachlogik für Kontierung oder Buchung
- keine manuelle Nachbearbeitung von Rechnungsdaten in der UI
- Kennwörter und API-Tokens liegen für den MVP noch in einer lokalen Einstellungsdatei
- Paperless wurde gegen die vorgesehenen API-Endpunkte implementiert und besitzt einen Verbindungstest; ein fachlicher Test mit der konkreten Serverinstallation und echten Tag-IDs bleibt trotzdem erforderlich

Diese Grenzen sind bewusst akzeptiert, weil der Schwerpunkt zunächst auf einem stabilen, nachvollziehbaren technischen Eingang liegt.

## Bewertung des aktuellen Stands

Der aktuelle Stand eignet sich für einen internen oder pilotierten Beta-Betrieb, wenn der Fokus auf folgenden Punkten liegt:

- Testen unterschiedlicher E-Rechnungsformate
- Absicherung der Parser-Ergebnisse
- Sichtprüfung der extrahierten Daten
- kontrollierter manueller Export in Drittsysteme
- erste Erprobung von IMAP-basierten Eingangskanälen
- erste Erprobung von Paperless als vorgeschaltetem Dokumenteneingang

Nicht geeignet ist der aktuelle Stand für Szenarien, in denen bereits jetzt hohe Automatisierung, revisionssichere Ablage, feingranulare Benutzersteuerung oder produktionsreife Geheimnisverwaltung erwartet werden.

## Nächste sinnvolle Entwicklungsschritte

Aus heutiger Sicht sind die folgenden nächsten Schritte fachlich und technisch sinnvoll:

1. BackgroundService für zeitgesteuerten Abruf
   Damit IMAP und Paperless nicht nur manuell, sondern periodisch ausgeführt werden können.

2. JSON-Export beziehungsweise API-Ausgabe
   Zusätzlich zu CSV kann ein neutrales JSON-Übergabeformat bereitgestellt werden, damit Zielsysteme Rechnungsdaten ohne CSV-Mapping übernehmen können.

3. Exportprofile weiter schärfen
   Insbesondere für konkrete Zielsysteme wie GDL-4, Quick-GDLx oder spätere REST-Connectoren.

4. Secret-Handling verbessern
   IMAP-Zugangsdaten und Paperless-Tokens sollten mittelfristig aus der lokalen JSON-Datei in einen geschützten Speicher überführt werden.

5. PostgreSQL nur bei echtem Bedarf aktivieren
   Etwa dann, wenn dauerhaftes Suchen, Reporting, Mehrbenutzerbetrieb oder größere Datenmengen dies wirklich erfordern.
