docs: Design und Plan „Duplikat → neue Version“

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
bjoernpoettkerandClaude Opus 5.5 committed 2026-11-02 13:52:04 +01:00
1 parent bc2d1cd4b7
commit 62d81dc25f
2 files changed
+512

No files matched your search

@@ -0,0 +1,225 @@
# Duplikat → neue Version (Design)
Stand: 02.11.2026
## Worum es geht
Wird ein Beleg ein zweites Mal mit derselben **internen Belegnummer** nach
Paperless gebracht, soll er nicht als zweites, eigenständiges Dokument landen.
Stattdessen sieht der Benutzer beide Belege nebeneinander und entscheidet:
- **Als neue Version hinzufügen** – die Datei wird über die Versionsfunktion
von Paperless-NGX an das vorhandene Dokument gehängt.
- **Verwerfen** – der Beleg wird nicht importiert.
Typische Fälle:
1. **Korrigierte Rechnung**: Lieferant schickt eine fehlerbereinigte Fassung mit
derselben Rechnungsnummer.
2. **Nachträglich geteilt**: Ein Dokument enthielt zwei Belege. Der Benutzer
teilt das PDF **von Hand** und sendet es neu; der Teil mit der bereits
vergebenen Belegnummer wird zur neuen Version.
## Ziele
- Gleicher Vergleichsdialog im **E-Mail-Import** und im **Posteingang (Scanner)**.
- Oben im Dialog eine Leiste mit **Auffälligkeiten**: abweichende
**Seitenzahl** und abweichende **Wortzahl**. Darunter beide PDFs nebeneinander.
- Maßgeblich für „Belegnummer existiert schon“ ist **Paperless** (Custom Field 7
= interne Belegnummer). Das ist die wichtige Prüfung.
## Nicht-Ziele
- Umbau der Task-Bearbeitung – läuft unverändert weiter.
- **Checksummen-Duplikate umgehen** (gleiche Datei erneut importieren) – bleibt
wie heute, wird in `docs/todos.md` notiert.
- Inhaltliche Analyse (Beträge, Datum, Positionen) für die Auffälligkeiten –
dafür gibt es noch keine Auswertung.
- Metadaten des vorhandenen Dokuments ändern (Titel, Tags, Custom Fields,
Korrespondent bleiben unverändert; nur die Datei kommt als Version dazu).
- Nachgelagerte Automatik für die Version (Postprocessing-Regeln, Mail,
WebDAV-Export, Agrarmonitor-Austausch/Storno) – wird vorerst **unterdrückt**,
die fachliche Logik kommt später (siehe Todos).
## Anti-Ziele (wäre ein Fehlschlag, auch wenn es „funktioniert“)
- Ein Beleg mit vorhandener Belegnummer landet doch als zweites Dokument in
Paperless, ohne dass der Benutzer es so entschieden hat.
- Eine Version wird an das **falsche** Dokument gehängt.
- „Verwerfen“ lässt eine reservierte Belegnummer oder einen halb angelegten
Task zurück.
## Paperless-API (am Live-System geprüft, API v10)
- `POST /api/documents/{id}/update_version/` – multipart, Feld `document`
(Datei, Pflicht), `version_label` (optional, max. 64 Zeichen). Antwort: String
(vermutlich die Consume-Task-ID; Verarbeitung asynchron).
- `PATCH|DELETE /api/documents/{id}/versions/{version_id}/` – Label ändern/löschen.
- `DocumentVersionInfo`: `id`, `added`, `version_label`, `checksum`, `is_root`.
## Ablauf E-Mail-Import (`MailImportWizard.tsx`)
Schritte: 0 Zuordnung → 1 Bearbeitung → 2 Abschluss.
1. In Schritt 1 („Bearbeitung“) hat ein Beleg den Modus **Manuell** und eine
Belegnummer (Jahr + 6-stellige Nummer → `JJJJ-NNNNNN`).
2. Beim Klick auf **Weiter** (Schritt 1 → 2) prüft das Backend für jeden
manuellen Beleg in Paperless, ob die Belegnummer schon vergeben ist (CF7 und
ASN, siehe „Eindeutigkeit des Treffers“).
3. Gibt es Treffer, öffnet sich **vor** dem Schrittwechsel der Vergleichsdialog
– nacheinander für jeden betroffenen Beleg.
- Links: vorhandenes Dokument aus Paperless. Rechts: der neue Beleg (bei
geteilten Anhängen nur die gewählten Seiten).
- **Als neue Version hinzufügen** → Beleg wird für den Import als
„Version zu Dokument X“ markiert.
- **Verwerfen** → Beleg wird auf `IGNORE` gestellt. Stehen danach alle Belege
der Mail auf `IGNORE`, greift die bestehende Logik (Mail als ignoriert
markieren).
- Dialog schließen (X) ohne Entscheidung → kein Schrittwechsel, der Benutzer
bleibt in Schritt 1.
4. Beim **Import ausführen** werden Version-Belege nicht per `post_document`
hochgeladen, sondern per `update_version` an Dokument X gehängt.
- Die ASN-Sperre (`validateAsnNotExists`) und der Belegnummer-Duplikatcheck
entfallen für diese Belege – sonst würde der Import abbrechen.
- Hochgeladen wird wie beim normalen Import das Original-PDF bzw. die
gewählten Seiten, ohne eingebrannten Stempel.
- Kein neuer Enrichment-Task in der `tasks`-Tabelle nötig (Metadaten bleiben).
- Im `Attachment`-Datensatz wird die Dokument-ID X unter dem jeweiligen
Bereich eingetragen, damit der Anhang als importiert gilt.
5. Die Checksummen-Prüfung (`recheckDuplicates`) bleibt unverändert.
## Ablauf Posteingang (`InboxDetailPage.tsx`, `inbox-postprocessor`)
Heute: `runPaperless` meldet ein Duplikat mit `duplicateOfDocumentId`; der
Wizard bietet „Neue Version erstellen“ (= Duplikatprüfung überspringen und als
zweites Dokument hochladen), „Vergleichen“ und „Überspringen“. Im
Vergleichsdialog ist „Neue Version anlegen“ noch ein TODO.
Neu:
- Liefert der Duplikat-Treffer eine Paperless-Dokument-ID, öffnet sich der
Vergleichsdialog **automatisch**.
- **Als neue Version hinzufügen** → Backend verarbeitet den Abschnitt erneut,
lädt die fertige PDF (nach allen Bearbeitungen/Stempeln) aber per
`update_version` an Dokument X hoch statt per `post_document`. Danach ist der
Abschnitt „erfolgreich“.
- **Verwerfen** → entspricht dem heutigen „Überspringen“ (Text wird umbenannt).
- Der bisherige Weg „Duplikatprüfung überspringen und als eigenes Dokument
hochladen“ entfällt in der Oberfläche.
- Duplikate **ohne** Dokument-ID (Checksumme, lokaler Task ohne
`PaperlessDocumentID`) behalten den heutigen Weg: nur Verwerfen/Überspringen.
- Rechts im Dialog wird der **betroffene Abschnitt** gezeigt, nicht das ganze
Inbox-Dokument (heute zeigt der Dialog das ganze Dokument).
## Nachgelagerte Automatik unterdrücken
Entscheidung des Nutzers: Nach dem Hinzufügen einer Version bekommt das
(Stamm-)Dokument den Tag **„neue Version hochgeladen“ (ID 21)**. Der Nutzer
konfiguriert die Postprocessing-Regeln so, dass Belege mit Tag 21 ignoriert
werden. Im Code gibt es **keine** eigene Unterdrückung (keine Markierung, keine
Änderung an der Webhook-Warteschlange).
- Reihenfolge: **erst** Tag 21 setzen (Tags lesen, 21 ergänzen, vorhandene
behalten), **dann** `update_version`. Schlägt der Versions-Upload fehl, wird
Tag 21 wieder entfernt – aber nur, wenn er vorher nicht schon gesetzt war.
- Entfernen von Tag 21 ist Sache des Nutzers.
- Die Anreicherung in `processDocumentById` (Tag 17, bereit/nicht bereit,
Titel-Template) läuft beim Webhook weiterhin – nur die Regeln greifen nicht.
Im **Posteingang** betrifft die Abfrage nur die Aktion „An Paperless senden“.
Die übrigen Aktionen des Barcode-Templates (MAIL, EXPORT) davor und danach
laufen normal: Die Aktionen davor sind beim Erkennen des Duplikats bereits
gelaufen und werden nicht wiederholt; die Aktionen danach werden nach der
Entscheidung (Version **oder** Verwerfen) ganz normal ausgeführt.
## Vergleichsdialog (gemeinsame Komponente)
- Eine Komponente für beide Stellen (aus `CompareModal` herauslösen).
- Titel z. B. „Belegnummer 2026-000123 existiert bereits“.
- **Auffälligkeiten-Leiste** oben (Ant Design `Alert`/`Tag`s):
- Seitenzahl: „Seiten: 2 (vorhanden) → 3 (neu)“ – hervorgehoben bei Abweichung.
- Wortzahl: „Wörter: 412 → 398“ – hervorgehoben bei Abweichung.
- Ist eine Zahl nicht ermittelbar (z. B. PDF ohne Textebene), steht dort
„nicht ermittelbar“ statt einer Abweichung.
- Keine Abweichung → kurzer neutraler Hinweis „Seiten- und Wortzahl gleich“.
- Darunter beide PDFs nebeneinander (mobil untereinander), wie heute.
- Knöpfe: **Verwerfen** / **Als neue Version hinzufügen** (primär).
### Kennzahlen ermitteln (Backend-Endpunkt)
- Vorhanden (Paperless): Seitenzahl aus `page_count` des Dokuments, Wortzahl aus
dessen `content` (OCR-Text von Paperless). Verglichen wird mit der aktuellen
(neuesten) Fassung des Dokuments.
- Neu: Seitenzahl per `pdf-lib`, Wortzahl aus der Textebene per `pdf-parse`
(beides bereits Abhängigkeiten im Backend). Keine Textebene → „nicht
ermittelbar“.
- Wortzählung: Text an Leerraum trennen, nur Tokens mit mindestens einem
Buchstaben oder einer Ziffer zählen.
## Versionsbezeichnung
`version_label` = „Korrektur vom TT.MM.JJJJ“ (Datum des Hinzufügens). Max. 64 Zeichen.
## Eindeutigkeit des Treffers
Geprüft wird immer gegen Paperless, und zwar über **beide** Merkmale, die aus
der internen Belegnummer folgen:
- CF7 = interne Belegnummer (z. B. `2026-000123`)
- ASN = interne Belegnummer ohne Bindestrich (z. B. `2026000123`) – auch im
Posteingang, unabhängig von einem im Template separat hinterlegten ASN-Feld.
„Als neue Version hinzufügen“ wird nur angeboten, wenn alle Treffer auf **genau
ein** Dokument zeigen. Zeigen CF7- und ASN-Treffer auf verschiedene Dokumente
oder gibt es mehrere CF7-Treffer, zeigt der Dialog einen Hinweis und bietet nur
**Verwerfen** an. Dafür muss die Suche alle Treffer liefern, nicht nur den ersten.
## Am Live-System zu prüfen (vor/bei der Umsetzung)
- Antwort von `update_version` (Task-ID?) und wie der Abschluss erkennbar ist.
- Liefern CF7-Suche, `GET /documents/{id}/` (`content`, `page_count`) und
`/download/` bei einem versionierten Dokument die Stamm-ID bzw. die neueste
Fassung? `update_version` muss immer auf die Stamm-ID zielen.
## Todos-Einträge
In `docs/todos.md` ergänzen:
1. „Duplikatprüfung per Checksumme gezielt umgehen können, wenn ein bereits
importiertes Dokument bewusst erneut importiert (z. B. geteilt) werden soll.“
2. „Neue Version eines Belegs in Agrarmonitor nachziehen (derzeit unterdrückt):
- Beleg noch im AM-Posteingang → dort löschen und neue Fassung senden.
- Beleg verarbeitet, aber nicht gebucht → im jeweiligen Einkauf das
vorhandene Dokument löschen und die neue Fassung hochladen.
- Beleg bereits gebucht → Storno-Beleg zum gebuchten Beleg erstellen und die
neue Fassung über die jeweilige E-Mail-Adresse neu in den AM-Posteingang
senden.
Außerdem klären, ob Postprocessing-Regeln (Mail an Buchhaltung, Export) für
Versionen laufen sollen.“
3. „Task-Bearbeitung (`PaperlessTaskProcessorService`, 30-s-Cron) auf den
Paperless-Webhook umstellen. Beim Upload werden die Metadaten schon gesetzt;
übrig bleiben Owner entfernen, Notizen, Anlage-Verknüpfung (Feld 8) und die
lokale Buchführung (Task/Attachment/documents) – die brauchen die
Dokument-ID nach dem Consume.“
## Dem Umsetzer überlassen
- Schnitt der Backend-Endpunkte (eigener Endpunkt für „Belegnummern prüfen“ und
„Kennzahlen“, oder zusammengefasst).
- Wie das Ergebnis von `update_version` verfolgt wird (Task-Polling wie beim
normalen Upload, sofern die Antwort eine Task-ID ist).
- Tests: mindestens Unit-Tests für Wortzählung/Auffälligkeiten und für die
Entscheidung Upload vs. Version im Backend.
## Eigene Entscheidungen (nicht ausdrücklich vom Nutzer)
- Versionsbezeichnung „Korrektur vom …“.
- Version nur bei eindeutigem Treffer (CF7 und ASN zeigen auf dasselbe
Dokument); sonst nur Verwerfen.
- E-Mail-Import: Version wird wie normale Importe ohne eingebrannten Stempel
hochgeladen; keine erneute Barcode-Notiz (die hat das Stammdokument schon).
- Automatisches Öffnen des Dialogs im Posteingang; Wegfall von „als eigenes
Dokument hochladen“.
- Dialog schließen ohne Entscheidung = im Schritt bleiben.
- Rechts nur der betroffene Abschnitt statt des ganzen Inbox-Dokuments.