# 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.