Files
mDMS/docs/strategy.md
mAi 061ea424ad mAi: #1 - Paperless-ngx Barcode-Splitter aktiviert (Patch-T)
PAPERLESS_CONSUMER_ENABLE_BARCODES=true + DELETE_PAGES=true live auf mDock,
parallel in m/paperless docker-compose.yml (Source-of-Truth) committet
(siehe m/paperless commit 8c1ca3f).

Neu:
- infra/paperless/generate_separator.py — Code-128 PATCHT-Generator (uv inline-deps)
- infra/paperless/separator-patchT.pdf — druckbare Trennseite
- docs/strategy.md — neuer Abschnitt "Multi-page scan + automatic splitting"

Test 2026-05-16: Stapel aus 3 Fake-Schreiben (2 + 1 + 1 Seiten) mit
PATCHT-Separator dazwischen → 3 getrennte Paperless-Dokumente mit
korrekten Seitenzahlen, Trennseiten entsorgt. Test-Dokumente wieder
gelöscht.

Closes: nichts (m schliesst Issues selbst — Label "done" via API)
2026-05-16 15:52:53 +02:00

335 lines
16 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.

# mDMS: Dokumentenmanagement-Strategie
## Aktueller Stand (nach Cleanup 2026-04-06)
### Paperless-ngx (mDock)
- **129 Dokumente** (PDFs), Storage Path aktiv
- **41 Correspondents** — bereinigt (OCR-Duplikate gemergt, Müll entfernt)
- **13 Document Types** — Rechnung, Vertrag, Bescheid, Bescheinigung, Brief, Mitteilung, Abrechnung, Protokoll, Urkunde, Vollmacht, Gutachten, Angebot, Medizinisch
- **16 Tags** — hierarchisch: Kategorie (Steuer, Versicherung, Gesundheit, Wohnung, Arbeit, Finanzen, Erbschaft, Gewährleistung, Anleitung) + Status (offen, wichtig, Frist) + Kontext (Windscheid33, Paul)
- **1 Storage Path**: `{created_year}/{document_type}/{created} - {correspondent} - {title}`
- Dateien strukturiert: `2024/Rechnung/2024-03-15 - DAK - Beitragsrechnung.pdf`
- API-User: `mAi`
- Docker Compose: `~/paperless/` auf mDock, NFS-Mount `/mnt/paperless` von TrueNAS (`mPool/paperless`)
### Was bereinigt wurde
- 68 Webp-Preview-Dokumente gelöscht (keine Originale, nur schlechte Vorschaubilder)
- 51 → 41 Correspondents (OCR-Duplikate gemergt: Hogan Lovells, Matthias Siebels, Ammerländer, Schubert, eprimo, Helios, Paul Siebels, Versorgungswerk etc.)
- 39 → 13 Document Types (Merge-Mapping umgesetzt)
- 172 → 16 Tags (Noise gelöscht, Kategorie-Mapping vor Löschung durchgeführt)
- 13 kaputte SynoResource-Dateien aus Consume gelöscht
- 126 orphaned flat-PDFs aus Originals gelöscht
- 43 Dokumententitel bereinigt (Nummern → beschreibende Titel)
- 5 Birthday-Datumsfehler korrigiert (1987-02-22 → korrekte Dokumentdaten)
### mDocs (Gitea-Repo m/mDocs) — MIGRATION PENDING
- **72 Dateien**, 60 MB (Steuer, Versicherungen, Windscheid33)
- Wird in Paperless inbox migriert, Repo danach löschen
### TrueNAS (mtruenas)
- Dataset `mPool/paperless` existiert bereits
- NFS-Export nach mDock (192.168.178.0/24)
- SMB-Share `mStash` als Referenz für mdms-Share
---
## Entscheidungen
### 1. Storage Path Format
**Format: `{created_year}/{document_type}/{created} - {correspondent} - {title}.pdf`** ✓ Bestätigt
Beispiele:
```
2024/Rechnung/2024-03-15 - DAK - Beitragsrechnung Q1.pdf
2024/Bescheid/2024-01-20 - Finanzamt - Grundsteuerbescheid.pdf
2023/Vertrag/2023-06-01 - Vodafone - GigaTV Vertragsverlängerung.pdf
2025/Abrechnung/2025-01-31 - Hogan Lovells - Gehaltsabrechnung Januar.pdf
```
**Warum dieses Format:**
- **Jahr als Top-Level**: Chronologisches Browsen, ganzen Jahrgang für Steuerberater kopierbar
- **Typ als zweite Ebene**: "Zeig mir alle Rechnungen 2024" = `2024/Rechnung/`
- **Datum + Correspondent + Titel im Dateinamen**: Sortierbar, durchsuchbar, kontextreich
- **Max 2 Ordnerebenen**: Nicht zu tief, Finder/Explorer-freundlich
- **Navigierbar ohne Paperless**: Reiner Dateibrowser funktioniert
**Verworfene Alternativen:**
- `{correspondent}/{year}/...` — zu viele sparse Ordner, schlecht für zeitliche Navigation
- `{year}-{month}/...` — zu granular, monatliche Ordner für oft nur 1-2 Dokumente
- Flach: `{created}-{correspondent}-{title}.pdf` — bei 500+ Dokumenten unbrauchbar
### 2. Dataset-Struktur: mPool/mdms
```
/mnt/mPool/mdms/
├── paperless/ # Paperless storage (originals, archive, thumbnails)
│ ├── documents/
│ │ ├── originals/ # Originaldateien
│ │ └── archive/ # OCR-Versionen
│ └── ...
├── inbox/ # Paperless consume — Auto-Import
│ # mScan-App, Drag-and-Drop, SFTP
├── templates/ # Vertragsvorlagen, Formulare, Muster
│ # Nicht in Paperless — statische Referenzdokumente
├── archive/ # Dokumente die nicht in Paperless passen:
│ # Große Dateien (CAD, Pläne), Sammlungen, Binaries
└── export/ # Paperless-Exporte, Backups, Snapshots
```
### 3. Dokumenten-Routing
| Dokument | Ziel | Begründung |
|----------|------|------------|
| Rechnungen, Bescheide, Briefe | Paperless (inbox/) | OCR + AI-Klassifikation + Suche |
| Verträge, Urkunden | Paperless | Langzeitarchiv mit Volltextsuche |
| Steuerunterlagen | Paperless + Tag "Steuer" | Filterbar für Steuerberater-Export |
| Gehaltsabrechnungen | Paperless + Tag "Arbeit" | Chronologisch abrufbar |
| Arztbriefe, Befunde | Paperless + Tag "Gesundheit" | Suchbar, datiert |
| Phone-Scans (mScan) | inbox/ → Paperless auto-import | Scannen → fertig |
| Vertragsvorlagen, Formulare | templates/ | Keine OCR nötig, statische Referenz |
| Baupläne, CAD, große Dateien | archive/ | Zu groß/speziell für Paperless |
| Fotos von Dokumenten | Paperless | OCR funktioniert auch auf Fotos |
**Nicht in mDMS:**
- Fotos generell → Immich
- Bücher, eBooks → Calibre (mCalibre)
- Arbeitsrechtliche Dokumente (HL) → mWork-Vault (Obsidian, nicht mDMS)
### 4. Paperless Taxonomy — Aufräumen
#### Document Types (39 → 15)
Reduziert auf sinnvolle, stabile Kategorien:
| Behalten | Zusammenführen aus |
|----------|-------------------|
| **Rechnung** | Rechnung, Invoice, Beitragsrechnung |
| **Vertrag** | (neu — für Verträge, Verlängerungen) |
| **Bescheid** | Bescheid, Beitragsbescheid, Versicherungsbescheid |
| **Bescheinigung** | Bescheinigung, Lohnsteuerbescheinigung, Spendenbescheinigung |
| **Brief** | Brief, Anschreiben, Korrespondenz |
| **Mitteilung** | Mitteilung, Benachrichtigung, Information, Erinnerung |
| **Abrechnung** | Abrechnung, Entgeltabrechnung |
| **Protokoll** | Protokoll |
| **Urkunde** | Urkunde |
| **Vollmacht** | Vollmacht |
| **Gutachten** | Gutachten, Befund |
| **Angebot** | Angebot |
| **Energieausweis** | Energieausweis |
| **Schadenmeldung** | Schadenmeldung, Schadenanzeige |
| **Medizinisch** | Arbeitsunfähigkeitsbescheinigung, Aufklärungsbogen |
Entfernen: Empfehlung, Preisanpassungsschreiben, Kündigungsbestätigung, Eintragungsbekanntmachung, Auftragsbestätigung, Testament (→ Tag), Einladung (→ Brief)
#### Tags (172 → ~25 manuell kuratierte)
Die meisten Auto-Tags sind Noise. Ziel: wenige, stabile Kategorie-Tags + manuelle Pflege.
**Kategorie-Tags (Pflicht, einer pro Dokument):**
| Tag | Für |
|-----|-----|
| `Steuer` | Alles steuerrelevante |
| `Versicherung` | Policen, Schäden, Beiträge |
| `Gesundheit` | Arzt, Krankenhaus, Krankenkasse |
| `Wohnung` | Miete, Eigentum, Nebenkosten, WEG |
| `Arbeit` | Gehalt, Arbeitgeber, Kammer |
| `Finanzen` | Bank, Kredit, Altersvorsorge |
| `Erbschaft` | Testament, Nachlassangelegenheiten |
| `Gewährleistung` | Kaufbelege mit Garantie, Reklamationen |
| `Anleitung` | Bedienungsanleitungen, Handbücher, Datenblätter |
**Aktions-Tags (optional):**
| Tag | Bedeutung |
|-----|-----------|
| `wichtig` | Aufbewahrungspflichtig, Schlüsseldokument |
| `Frist` | Hat eine Frist — regelmäßig prüfen |
| `offen` | Noch Handlung erforderlich |
**Kontext-Tags (sparsam, bei Bedarf):**
| Tag | Für |
|-----|-----|
| `Windscheid33` | Immobilie Windscheidstr. 33 |
| `Paul` | Dokumente bzgl. Paul Siebels |
**Löschen:**
- Jahres-Tags ("2022", "2025") — redundant mit created-Datum
- Personen-Tags ("Matthias Siebels") — gehört als Correspondent
- Ultra-granulare Tags ("Finger", "Hand", "Shimano", "Oral-B") — kein Nutzen
- Duplikate ("Rechtsanwalt" + "Rechtsanwälte" + "Rechtsanwaltschaft")
#### Correspondents (51 → ~30)
OCR-Duplikate zusammenführen:
- "Hogan Lovells International LLP" + "Hogan Lovells lnternational LLP" → **Hogan Lovells**
- "HELIÜS Klinikurn Duisburg" + "Helios Klinikum Duisburg" → **Helios Klinikum Duisburg**
- "Herr Matthias Siebels" + "Herrn Matthias Siebels" + "Matthias Siebels" + "Herrn Rechtsanwalt Matthias Siebels" → **Matthias Siebels** (eigene Dokumente)
- "Ammerländer Versicherung VVaG" + "Ammerländer Versicherung WaG" → **Ammerländer Versicherung**
- "SCHUBERT GmbH" + "Schubert GmbH Haus- und Grundbesitzverwaltung" → **Schubert Hausverwaltung**
- "Dr. figegeberH lcankenkas*" → identifizieren oder löschen (OCR-Müll)
- "Dr/Heikö Gemmel" → **Dr. Heiko Gemmel**
- "eprimo CmbH" + "eprimo GmbH" → **eprimo**
- "lndula Shopsystem GmbH" → **Indula Shopsystem**
### 5. SMB-Share
**Ja — mdms als SMB-Share wie mStash.**
Konfiguration auf TrueNAS:
- Share-Name: `mdms`
- Dataset: `mPool/mdms`
- User: `m` (wie mStash)
- Mount auf mBreeze/mPebble: `~/mDMS` (LaunchAgent, analog zu mStash)
Nutzen:
- `~/mDMS/inbox/` für Drag-and-Drop-Import (Paperless consumed automatisch)
- `~/mDMS/templates/` für schnellen Zugriff auf Vorlagen
- `~/mDMS/paperless/documents/originals/` für Dateibrowser-Navigation (via Storage Path)
- `~/mDMS/archive/` für große Dateien
### 6. Vertrauliche Dokumente
**Kein separates Verschlüsselungssystem nötig.** ✓ Bestätigt
- Alles läuft auf HomeServer (mforge/mtruenas), nur via Tailscale erreichbar
- SMB mit User-Auth + Paperless-Login reichen aus
### 7. Obsidian-Integration
Der Storage Path soll als Teil eines Obsidian-Vaults nutzbar sein. Das bedeutet:
- `mdms/paperless/documents/originals/` (oder `archive/`) via SMB als Vault-Ordner einbinden
- Obsidian zeigt die Ordnerstruktur (`2024/Rechnung/...`) direkt im Dateibrowser
- PDFs sind in Obsidian inline-viewbar und verlinkbar (`![[2024-03-15 - DAK - Beitragsrechnung.pdf]]`)
- Keine Sonderzeichen in Dateinamen die Obsidian-Links brechen (Spaces sind ok)
**Umsetzung:**
- Option A: Symlink `~/m2/mDMS/``~/mDMS/paperless/documents/originals/` im Obsidian-Vault
- Option B: Separater Mini-Vault nur für Dokumente
- Option C: mdms als Unterordner im Hauptvault (m2)
Empfehlung: **Option A (Symlink)** — kein Daten-Overhead, Vault bleibt schlank, Dokumente sind trotzdem verlinkbar. Braucht nur einen Symlink pro Maschine.
### 8. E-Mail-Inbox
**docs@msbls.de** — Alias auf mail@msbls.de (Hostinger).
Paperless pollt mail@msbls.de via IMAP und konsumiert Anhänge aus Emails an docs@msbls.de:
- IMAP: `imap.hostinger.com:993` (SSL/TLS), User: `mail@msbls.de`
- Mail-Regel: Filter `To: docs@msbls.de`, nur Attachments, Action: als gelesen markieren
- Correspondent wird automatisch vom Absender übernommen
- Titel vom Dateinamen
**Workflow:** Dokument als PDF an docs@msbls.de weiterleiten → Paperless importiert automatisch.
---
## Paperless-AI Konfiguration
Paperless-AI (Port 3077) soll die Klassifikation übernehmen. Konfigurieren mit:
- **Auto-assign correspondent** basierend auf OCR-Text (Absender-Erkennung)
- **Auto-assign document type** aus den 15 reduzierten Typen
- **Auto-assign 1-2 Kategorie-Tags** aus der Kurzliste
- **Nicht**: Auto-generierte Freitext-Tags (das erzeugt das aktuelle Chaos)
---
## Multi-page scan + automatic splitting (Barcode-Separator)
Issue: #1 (mDMS). Aktiv seit 2026-05-16.
Ein ADF-Scan eines Stapels aus mehreren Schreiben kommt heute als **eine** PDF in `inbox/`. Damit Paperless daraus N getrennte Dokumente macht, nutzen wir den eingebauten **Barcode-Splitter** mit einer Code-128-Patch-T-Seite zwischen den Schreiben.
### Setup (einmalig)
Live auf mDock (`~/paperless/docker-compose.yml`, webserver-Service):
```yaml
PAPERLESS_CONSUMER_ENABLE_BARCODES: "true"
PAPERLESS_CONSUMER_BARCODE_DELETE_PAGES: "true"
```
Standard-Trennstring `PATCHT`, Scanner-Engine `pyzbar`, DPI 300 — alles per Default OK.
`DELETE_PAGES` sorgt dafür, dass die Trennseiten **nicht** im fertigen Dokument landen.
### Trennseite (Patch-T)
- PDF: `infra/paperless/separator-patchT.pdf` (1 Seite A4, Code-128 mit `PATCHT`)
- Generator: `infra/paperless/generate_separator.py` (uv inline-deps, reportlab + python-barcode)
- 1020 Stück ausdrucken, neben dem Scanner stapeln, bei Bedarf nachdrucken
### Workflow
1. Stapel zusammenstellen: `[Schreiben A]` `[PATCHT]` `[Schreiben B]` `[PATCHT]` `[Schreiben C]`
2. Komplett-Stapel in den ADF, Scan-to-SMB als ein einziges PDF
3. PDF landet in `~/mDMS/inbox/` (SMB) → mdms-mover schiebt nach `toprocess/`
4. Paperless erkennt jede `PATCHT`-Seite, splittet, entsorgt die Trennseiten, OCRt + klassifiziert pro Sub-Dokument
### Test (2026-05-16)
- Konstruiert: `TEST-A` (2 Seiten) + `PATCHT` + `TEST-B` (1) + `PATCHT` + `TEST-C` (1) = 6-seitiges PDF
- Drop in `/mnt/mdms/toprocess/mdms-issue1-test-stack.pdf`
- Ergebnis: 3 separate Paperless-Dokumente (`_document_0/1/2`), Seitenzahlen 2/1/1 — Trennseiten verschwunden
- Log-Bestätigung: `[paperless.barcodes] Created new task ... for _document_X.pdf` + `BarcodePlugin requested task exit: Barcode splitting complete!`
- Test-Dokumente nach Verifikation aus Paperless gelöscht
### Edge-Cases / Follow-ups
- **Fehlt eine Trennseite** → die zwei betroffenen Schreiben landen als ein Dokument. Manuell trennen über Paperless-UI (»Split Document«) oder neu scannen.
- **Trennseite ist verknittert / schräg** → Code-128 mit `quiet_zone=8` ist tolerant; falls Detection-Rate sinkt: in `generate_separator.py` `module_width` größer machen und neu drucken.
- **Option B (Blank-Page-Detection im Mover)** und **Option C (LLM-semantisches Splitting)** sind in Issue #1 dokumentiert — kommen erst, wenn Patch-T-Seiten in der Praxis nerven.
- **ASN-Barcodes** (`PAPERLESS_CONSUMER_ENABLE_ASN_BARCODE`) sind orthogonal — separate Funktion für Archiv-Nummern; nicht aktiviert.
---
## Migration: Schritt für Schritt
### Phase 1: TrueNAS Setup ✓ DONE
1. ~~Dataset `mPool/mdms` erstellt~~ (LZ4, 1.24 TiB frei)
2. ~~Unterordner angelegt~~ (paperless, inbox, templates, archive, export)
3. ~~NFS-Export~~ (id:8, 192.168.178.0/24), Mount auf mDock als `/mnt/mdms`
4. ~~SMB-Share `mDMS`~~ (id:3, User `m`)
### Phase 2: Paperless Migration ✓ DONE
5. ~~Paperless auf mDock gestoppt~~
6. ~~Media, data, ai kopiert~~; pgdata als lokales Docker Volume (NFS-Ownership inkompatibel mit Postgres uid 999)
7. ~~consume → inbox kopiert~~
8. ~~SynoResource-Dateien gelöscht~~
9. ~~NFS-Mount `/mnt/mdms` auf mDock~~ (fstab via Proxmox agent)
10. ~~Docker Compose aktualisiert~~ (`~/paperless/docker-compose.yml`)
11. ~~Storage Path konfiguriert~~
12. ~~Paperless verifiziert~~ — 129 Docs, alle Metadaten intakt
**Hinweis:** pgdata lebt als Docker Volume `paperless_pgdata` auf mDock (nicht auf NFS). DB-Backup über `pg_dump` in `mdms/export/` planen.
### Phase 3: Cleanup ✓ DONE
13. ~~Paperless Correspondents zusammenführen~~ → 51 → 41
14. ~~Document Types reduzieren~~ → 39 → 13
15. ~~Tags aufräumen~~ → 172 → 16 (hierarchisch: Kategorie + Status + Kontext)
16. Paperless-AI mit neuer Taxonomy konfigurieren (TODO)
### Phase 4: mDocs Migration
17. mDocs-Repo klonen, alle PDFs nach mdms/inbox/ kopieren
18. Paperless konsumiert und klassifiziert automatisch
19. Manuell verifizieren: Correspondents, Types, Tags korrekt?
20. mDocs-Repo auf Gitea löschen
### Phase 5: Client-Setup
21. SMB-Mount auf mBreeze: `~/mDMS` (LaunchAgent wie mStash)
22. SMB-Mount auf mPebble: `~/mDMS`
23. mScan-App auf mdms/inbox/ konfigurieren (falls SFTP/SMB-Upload möglich)
---
## Offene Punkte
- [x] Paperless Admin-Credentials — mAi-User auf Paperless angelegt
- [x] Paperless Cleanup — Correspondents, Types, Tags bereinigt
- [x] Storage Path konfiguriert und Dateien umbenannt
- [x] Webp-Previews gelöscht, SynoResource-Müll bereinigt
- [x] TrueNAS Dataset `mPool/mdms` erstellt (NFS id:8, SMB `mDMS` id:3)
- [x] Paperless media auf mdms/paperless umgestellt (Docker Compose aktualisiert)
- [x] SMB-Share `mDMS` eingerichtet auf TrueNAS
- [x] mDocs-Migration: 69 PDFs in Paperless inbox, consumption läuft
- [x] **docs@msbls.de** — E-Mail-Inbox für Paperless (IMAP-Polling, Alias auf mail@msbls.de, Regel filtert auf To: docs@msbls.de)
- [ ] Paperless-AI mit neuer Taxonomy konfigurieren
- [ ] Regelmäßiger Export/Backup-Job (Paperless → mdms/export/)
- [ ] `m doc` CLI-Subcommand für Paperless-Zugriff? (search, list, tag)
- [ ] Obsidian-Vault Symlink-Setup auf mBreeze/mPebble