Files
Paperless-Contracts/README.md
2025-10-11 01:17:31 +02:00

140 lines
6.9 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# Paperless Contract Companion (TypeScript + React)
Begleitservice zur Verwaltung von Vertragsmetadaten (Laufzeiten, Kündigungsfristen, Preise) als Ergänzung zu einer bestehenden [paperless-ngx](https://github.com/paperless-ngx/paperless-ngx) Instanz. Dokumente verbleiben in paperless, der Service liefert zusätzliche Struktur, Fristüberwachung, Web-GUI und optionale Mail-Benachrichtigungen.
## Features
- REST-API (Express) zum Anlegen, Aktualisieren und Löschen von Verträgen.
- Speicherung der Metadaten in SQLite (via `better-sqlite3`).
- Periodischer Scheduler prüft anstehende Kündigungsfristen und schreibt diese ins Log bzw. versendet auf Wunsch E-Mails.
- Paperless-Integration ruft zugehörige Dokument-Metadaten über API-Token ab.
- JWT-basierte Authentifizierung mit Login-Endpunkt (optional aktivierbar).
- Moderne React-UI (Vite + MUI) mit Dashboard, Tabellen, Kalender und Settings.
- Einstellbare Integrationen direkt im Browser (Paperless, Mail, ntfy, Scheduler).
- Komfortable Paperless-Suche beim Verknüpfen von Dokumenten.
- Optionaler ntfy-Push für Fristenmeldungen.
- iCal-Feed zum Abonnieren der Kündigungsfristen.
- Test-Buttons für Mail- und ntfy-Konfiguration direkt in der Oberfläche.
- Läuft als Docker-Container, konfigurierbar über Umgebungsvariablen oder `.env` (beim Kopieren auf den Zielhost).
## Projektstruktur
```
backend/
src/
index.ts # Express-Server und Routing
config.ts # Umgebungsvariablen & Defaults
db.ts # SQLite-Initialisierung
contractsStore.ts # CRUD-Logik auf DB-Ebene
scheduler.ts # Fristenmonitor
paperlessClient.ts # HTTP-Client für paperless-ngx
notifications.ts # SMTP-Integration (optional)
validators.ts # Zod-Schemas für Payloads
frontend/
src/ # React App (Dashboard, Login, Verträge, Kalender, Settings)
```
## Frontend (Vite + React)
Die Web-Oberfläche liegt im Ordner `frontend/` und kommuniziert ausschließlich über die gesicherte REST-API.
```bash
cd frontend
npm install
npm run dev # Lokale Entwicklung (http://localhost:5173)
npm run build # Produktionsbuild in frontend/dist
```
## Build & Run (Docker)
```bash
docker compose up --build
```
Die API lauscht per Default auf Port `8000`, extern über Compose auf `8080`. Die SQLite-Datenbank wird im Volume `contracts-data` unter `/app/data/contracts.db` persistiert. Das Frontend ist über `http://localhost:8081` (laut Compose) erreichbar.
### Wichtige Umgebungsvariablen
| Variable | Standard | Beschreibung |
| --- | --- | --- |
| `PORT` | `8000` | HTTP-Port des Dienstes. |
| `LOG_LEVEL` | `info` | `debug`, `info`, `warn`, `error`. |
| `DATABASE_PATH` | `/app/data/contracts.db` | Pfad zur SQLite-Datei (Volume nicht vergessen). |
| `PAPERLESS_BASE_URL` | *(leer)* | Basis-URL der paperless-ngx API (z.B. `http://paperless:8000`). |
| `PAPERLESS_EXTERNAL_URL` | *(leer)* | Optionale externe URL für Direkt-Link aus der Web-Oberfläche (z.B. `https://paperless.example.com`). |
| `PAPERLESS_TOKEN` | *(leer)* | Personal Token aus paperless-ngx (read-only genügt). |
| `SCHEDULER_INTERVAL_MINUTES` | `60` | Prüffrequenz für Fristen (mind. 5). |
| `ALERT_DAYS_BEFORE` | `30` | Wie viele Tage vor Deadline gewarnt wird. |
| `AUTH_USERNAME` / `AUTH_PASSWORD` | *(leer)* | Aktiviert das Login (JWT) beide Werte müssen gesetzt werden. |
| `AUTH_JWT_SECRET` | *(leer)* | Geheimnis zum Signieren der Tokens (Pflicht, wenn Auth aktiv). |
| `AUTH_TOKEN_EXPIRES_IN_HOURS` | `12` | Lebensdauer der JWTs. |
| `NTFY_SERVER_URL` / `NTFY_TOPIC` | *(leer)* | ntfy-Server & Topic für Push-Benachrichtigungen. |
| `NTFY_TOKEN` / `NTFY_PRIORITY` | *(leer)* | Optionaler Bearer-Token & Priorität für ntfy. |
| `MAIL_*` | *(leer)* | Optional: SMTP-Einstellungen für Benachrichtigungs-E-Mails. |
| `ICAL_SECRET` | *(leer)* | Optional vordefiniertes Token für den iCal-Feed (ansonsten automatisch). |
Mail-Setup (optional): `MAIL_SERVER`, `MAIL_PORT`, `MAIL_USERNAME`, `MAIL_PASSWORD`, `MAIL_USE_TLS`, `MAIL_FROM`, `MAIL_TO`.
> Tipp: Bei gesetzter Authentifizierung muss sich die Web-UI einmalig per Login anmelden; Tokens werden im LocalStorage gespeichert.
## API Übersicht
- `GET /healthz` einfacher Gesundheitscheck.
- `GET /auth/status` zeigt, ob Authentifizierung aktiviert ist.
- `POST /auth/login` Login mit Benutzername/Passwort, liefert JWT.
- `GET /contracts?skip=0&limit=100` Liste aller Verträge (max. 500 pro Anfrage).
- `POST /contracts` Neuen Vertrag anlegen.
- `GET /contracts/:id` Einzelnen Vertrag abrufen.
- `PUT /contracts/:id` Vertrag aktualisieren (Felder optional/teilweise).
- `DELETE /contracts/:id` Vertrag löschen.
- `GET /contracts/:id/paperless-document` Zugehöriges paperless-Dokument abrufen (wenn verknüpft).
- `GET /reports/upcoming?days=N` Anstehende Kündigungsdeadlines innerhalb der nächsten `N` Tage (Default = `ALERT_DAYS_BEFORE`).
Beispiel-JSON für Create/Update:
```json
{
"title": "KFZ-Versicherung 2024",
"paperlessDocumentId": 123,
"provider": "Versicherung AG",
"category": "Automotive",
"contractStartDate": "2024-01-01",
"contractEndDate": "2025-12-31",
"terminationNoticeDays": 30,
"renewalPeriodMonths": 12,
"autoRenew": true,
"price": 54.99,
"currency": "EUR",
"tags": ["kfz", "privat"],
"notes": "SFR prüfen im Herbst."
}
```
## Lokale Entwicklung Backend
> Hinweis: Im aktuellen Arbeitsverzeichnis wurden noch keine Node-Module installiert (`npm install`). Auf dem Zielhost bitte einmal ausführen, damit `package-lock.json` entsteht und der Build reproduzierbar wird.
```bash
npm install
npm run dev # Hot-Reload via tsx
# oder
npm run build && npm start
```
Die API ist anschließend unter `http://localhost:8000` erreichbar. Für Tests ohne paperless-Verbindung kann `PAPERLESS_*` weggelassen werden.
## Integration mit paperless-ngx
- Companion-Service und paperless-Container sollten im gleichen Docker-Netz laufen, damit `http://paperless:8000` erreichbar ist.
- Token in paperless-ngx erstellen (`Einstellungen → Tokens`) und als `PAPERLESS_TOKEN` setzen.
- Contract-IDs können mit Custom Fields/Tags in paperless verknüpft werden; die Companion-API hält zusätzliche Metadaten und erinnert an Fristen.
- Nutze `PAPERLESS_EXTERNAL_URL`, wenn die API intern erreichbar ist, die Benutzer im Browser aber eine andere URL (z.B. Reverse-Proxy mit TLS) verwenden sollen.
- Einstellungen (Paperless, Mail, ntfy, Scheduler) lassen sich komfortabel unter „Einstellungen“ in der Weboberfläche pflegen.
- Aktiviere Push-Benachrichtigungen via ntfy oder abonniere den iCal-Feed unter `https://<host>/api/calendar/feed.ics?token=<...>` (Token im Settings-Dialog sichtbar).
## Weiterführende Ideen
- Webhook/Chat-Integration (z.B. Matrix, Slack).
- ICS/CalDAV-Export der Deadlines.
- Intelligente Importer, die paperless-Tags automatisch auswerten.
- Multi-User-Unterstützung inkl. Rollen und Audit-Logs.
- Optionaler Reverse-Proxy mit TLS-Termination und Single-Sign-On.