Files
paperlessmanager/docs/superpowers/specs/2026-11-02-duplikat-neue-version-design.md
T

226 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.