Baseline commit: Pflegepilot Alpha v2 (lauffähiger Stand vor Refactoring)

Fixt außerdem UnicodeEncodeError in start.py (▶-Zeichen crashte auf
Windows-Konsolen mit cp1252-Codepage vor app.run()) durch UTF-8-Zwang
auf stdout/stderr.
This commit is contained in:
admin committed 2026-07-18 10:19:28 +02:00
commit f234399d28
18 files changed
+6308

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
# Python
__pycache__/
*.pyc
# SQLite DB - runtime data, may contain real patient data
pflegepilot_alpha_v2/pflegepilot/db/*.db
# Patient-generated files - never commit real patient data
pflegepilot_alpha_v2/pflegepilot/static/briefe/
pflegepilot_alpha_v2/pflegepilot/static/dokumente/
pflegepilot_alpha_v2/pflegepilot/static/fotos/
# Local Claude Code settings
.claude/
pflegepilot_alpha_v2/pflegepilot/.claude/settings.local.json
# graphify output - regeneratable
graphify-out/
+3
View File
@@ -0,0 +1,3 @@
pflegepilot_alpha_v2/pflegepilot/static/briefe/**
pflegepilot_alpha_v2/pflegepilot/static/dokumente/**
pflegepilot_alpha_v2/pflegepilot/static/fotos/**
+42
View File
@@ -0,0 +1,42 @@
# Anleitung: So bauen wir den "Pflegepilot" 🚀
Hallo! Keine Sorge, wenn du "keine Ahnung" hast. Das ist sogar gut, weil wir so alles ganz einfach halten. Hier ist dein Fahrplan, wie wir aus deiner Idee eine echte Hilfe für Menschen machen.
## Was ist der Pflegepilot?
Stell dir vor, jemand in der Familie wird alt oder krank. Plötzlich gibt es 1000 Formulare, Ämter und Begriffe wie "Pflegegrad", die niemand versteht.
Der **Pflegepilot** ist wie ein kluger Freund (eine KI), der Händchen hält, Formulare erklärt und sagt: "Mach als nächstes das hier."
---
## Schritt 1: Den "Dschungel" verstehen (Die Vorbereitung)
Bevor wir programmieren, müssen wir wissen, wo es brennt.
* **Was wir tun:** Wir suchen uns ein echtes Problem aus. Zum Beispiel: "Wie bekomme ich einen Pflegegrad?"
* **Dein Job:** Überleg dir: Was war das Nervigste, was du oder Bekannte beim Thema Pflege erlebt haben? Schreib das auf.
## Schritt 2: Die KI füttern (Das Wissen)
Eine KI ist wie ein Baby: Sie weiß am Anfang nichts. Wir müssen ihr "Bücher" (Daten) geben.
* **Was wir tun:** Wir sammeln offizielle Infos von der Pflegekasse, Gesetze und einfache Erklärungen.
* **Dein Job:** Du sagst mir: "Hey, such mal alle Infos zum Thema 'Antrag auf Pflegegrad' zusammen."
## Schritt 3: Den "Baby-Piloten" bauen (Der Prototyp)
Wir bauen nicht sofort ein riesiges Raumschiff. Wir bauen erst mal ein Dreirad.
* **Was wir tun:** Wir erstellen eine einfache Chat-Seite. Man kann eine Frage stellen, und der Pflegepilot antwortet ganz einfach, ohne Beamtendeutsch.
* **Dein Job:** Du testest das Dreirad. Wenn die KI Quatsch redet, sagst du: "Stopp, das versteht doch keiner!"
## Schritt 4: Firmen einladen (Die Entlastung)
Pflegedienste haben zu viel Papierkram.
* **Was wir tun:** Wir bringen der KI bei, wie sie den Pflegediensten beim Ausfüllen von Berichten hilft. So haben die mehr Zeit für die echten Menschen.
* **Dein Job:** Wir überlegen gemeinsam: Was hassen Pflegedienste am meisten? (Meistens ist es das Tippen am Computer).
---
## Wie wir jetzt konkret anfangen:
1. **Sammeln:** Wir suchen die wichtigsten Dokumente (PDFs von Ämtern).
2. **Strukturieren:** Wir bringen der KI bei, diese Dokumente zu lesen.
3. **Chatten:** Wir bauen ein Fenster, wo du fragen kannst: "Wie helfe ich meiner Oma?"
**Keine Angst vor der Technik!** Ich (dein KI-Assistent) kümmere mich um den Code. Du bist der Chef, der sagt, ob es für normale Menschen verständlich ist.
### Dein erster Auftrag:
Sag mir einfach: **"Lass uns mit dem Thema 'Pflegegrad beantragen' anfangen."** Dann lege ich los und suche die ersten Infos für uns.
+62
View File
@@ -0,0 +1,62 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository layout
This is not a single project but a working directory with one active app plus reference/planning material:
- **`pflegepilot_alpha_v2/pflegepilot/`** — the active codebase (Flask + SQLite web app). All code work happens here.
- **`pflegepilot_alpha/`** — superseded v1. Source files have been deleted; only a stale `__pycache__` remains. Do not develop here.
- **`pflegepilot_erp.html`** — a standalone static HTML mockup/prototype, not wired to the Flask app. Not part of the running system.
- **`Anleitung.md`, `Leistungen.md`, `Leistungen2.md`, `Pflegegrad.md`, `Musterbrief.md`** — German-language domain reference notes (care-benefits catalog research, sample letters, project rationale) used as source material for `katalog.py` and the letter generators. Not code.
- **`refactoring.md`** — the current architecture-change brief from the product owner (see "Planned architecture pivot" below). Read this before any structural work.
No git repository is initialized in this directory.
## Commands
Run from `pflegepilot_alpha_v2/pflegepilot/`:
```bash
pip install flask
python start.py # initializes/migrates the SQLite DB, then serves on http://localhost:5050
```
`start.py` runs with `debug=False`; running `app.py` directly instead uses `debug=True` on the same port. There is no test suite, linter, or build step in this project.
Default login after first start: `admin` / `admin` (created automatically by `init_db()` when the `nutzer` table is empty).
## Architecture
**Single-file Flask backend, vanilla-JS SPA frontend, zero build tooling.**
- `app.py` — the entire backend: all `/api/*` routes, SQLite access, auth, SMTP email sending, file upload handling. There's no blueprint/module split — everything lives in this one file.
- `templates/index.html` — the entire frontend. One Jinja template that is actually a client-rendered SPA: vanilla JS, string-templated HTML, no framework, no bundler. Key conventions in the `<script>` block:
- `go(name, extra)` is the client-side router; it maps a page name to a `pg*()` render function (`pgDash`, `pgPatienten`, `pgKatalog`, `pgBackend`, …).
- `S(id, html)` sets innerHTML by id; `R(html, title, actions)` sets the main content/title/toolbar in one call.
- `api(path, opts)` is the shared `fetch` wrapper for JSON API calls (raw `fetch` is used directly for multipart file uploads).
- PDF documents (Musterbrief, Widerspruch, Pflegetagebuch, Patientenakte) are rendered **client-side** via `html2pdf.js`, then the resulting blob is base64-uploaded to a server endpoint (e.g. `POST /api/patienten/<pid>/briefe`, `POST /api/patienten/<pid>/dokumente`) for permanent storage under `static/`.
- `katalog.py` — static data module: `KATALOG`, a list of ~82 care-benefit entries (Pflegekasse/Krankenkasse services under SGB XI), each tagged with `zielgruppe` (target group: `alterspflege`/`beduerftige`/`behinderte`) and a `pflegegrad_min`/`pflegegrad_max` range, plus legal basis (`rechtsgrundlage`), amounts, and optional `abhaengigkeiten` (cross-references to related/conflicting benefits). Filtering helpers (`get_by_zielgruppe`, `get_by_pflegegrad`, `search`, …) are used both by `/api/katalog` and to compute a patient's `empfohlene_leistungen`.
- `krankenkassen.py` — static directory of ~86 health/care insurers (GKV/PKV in Germany, SV in Austria, KVG in Switzerland) with postal addresses, used to auto-fill recipient addresses in generated letters. Has a `land` field (`DE`/`AT`/`CH`) with helpers `get_by_land`, `search(q, land=None)`.
- `db/schema.sql` — base SQLite schema (`patienten`, `antraege`, `leistungen`, `aufgaben`, `pflegetagebuch`, `einstellungen`, `dokumente`) plus demo seed rows.
- **Schema evolution pattern**: `init_db()` in `app.py` runs `schema.sql` once, then re-applies a hardcoded list of `ALTER TABLE` / `CREATE TABLE IF NOT EXISTS` statements on every startup, each wrapped in its own try/except so an already-applied migration is silently skipped. When adding a column or table, add a new entry to that list rather than editing `schema.sql` (existing DBs won't be recreated) — and keep entries idempotent/backward-compatible since this list re-runs on every process start.
- **Auth**: session-cookie based. `_get_current_user()` / `_check_admin()` read `session["nutzer_id"]`; `login_required` / `admin_required` decorators guard individual routes, while `global_auth_check()` (a Flask `before_request` hook) blanket-blocks any `/api/*` path not in the small public allowlist (`/api/auth/login`, `/api/auth/me`, `/api/einstellungen/public`). Two roles exist: `admin` and `nutzer`. Passwords are hashed with `werkzeug.security` (PBKDF2).
- **File storage**: everything is local under `static/` — `static/fotos/<patient_id>.<ext>` (profile photos), `static/briefe/<patient_id>/…` (generated letter PDFs), `static/dokumente/<patient_id>/…` (uploaded documents), `static/logo/` (company branding). No object storage/CDN involved.
- **Settings**: a generic key-value `einstellungen` table (accessed via `get_setting()`) holds SMTP credentials, company branding/address, and an (unused-in-current-flow) Claude API token — surfaced through `/api/admin/einstellungen`.
## Planned architecture pivot (see `refactoring.md`)
The app currently runs as a **central multi-patient service**: any logged-in user can see all patients. The product owner has specified a pivot to:
1. **Per-account patient isolation** — a logged-in user (a family member/informal caregiver) should only ever see their own 1–3 patients, with no way to browse or discover other patients. This is a real authorization boundary to add to every `/api/patienten*` (and related) route, not just a UI filter.
2. **No-AI interview flow** — a plain web-form "interview" for onboarding a new patient, aimed at non-technical relatives, replacing/supplementing the current `pgNeu()` single-form patient creation.
3. **Admin dashboard** — for the operator: lock/delete accounts, and export archived patient data under lawful (attorney/court) order, with GDPR (DSGVO) compliance as a hard requirement — this affects both the operator's own liability and every caregiver's/patient's rights.
The user has explicitly asked to be asked clarifying questions about architecture, data model, and server structure before this refactor is implemented — don't assume a specific multi-tenancy design (e.g. per-user `nutzer_id` foreign key on `patienten` vs. a separate `familien`/account entity) without confirming it first.
## Known constraints worth knowing before touching auth/security-sensitive code
- `app.secret_key` in `app.py` is a hardcoded string, not loaded from an environment variable.
- The default admin account (`admin`/`admin`) is created automatically and nothing forces a password change.
- These are pre-existing conditions in the current alpha, relevant context if working on the auth/admin-dashboard parts of the refactor above.
+53
View File
@@ -0,0 +1,53 @@
# Welche Hilfen und Gelder gibt es? (Leistungen) 💰
Hier listen wir auf, was man von der Kasse bekommen kann. Es gibt zwei "Töpfe", aus denen Geld kommen kann: die **Krankenkasse** (für Medizin) und die **Pflegekasse** (für den Alltag).
---
## 1. Gesetzlich oder Privat – was ist der Unterschied? 🏥
* **Gesetzlich versichert (GKV):** Die meisten Menschen sind hier. Die Kasse bezahlt die Rechnungen oft direkt (z. B. beim Arzt oder Pflegedienst).
* **Privat versichert (PKV):** Hier bekommt man oft erst eine Rechnung, bezahlt sie selbst und holt sich das Geld dann von der Versicherung zurück.
* **Wichtig:** Die Leistungen für die Pflege sind bei beiden fast gleich! Niemand wird im Regen stehen gelassen.
---
## 2. Geld und Hilfe von der Pflegekasse 👵👴
Das bekommst du, wenn du einen **Pflegegrad** (Stufe 1 bis 5) hast:
### A. Geld für die Tasche (Pflegegeld)
Wenn Angehörige oder Freunde die Pflege zu Hause machen, überweist die Kasse monatlich Geld direkt auf dein Konto. Du kannst damit machen, was du willst (z. B. den Helfern eine Freude machen).
### B. Profi-Hilfe zu Hause (Pflegesachleistung)
Wenn ein professioneller Pflegedienst kommt (zum Waschen oder Anziehen), bezahlt die Kasse diesen Dienst bis zu einem bestimmten Betrag.
### C. Der "Gutschein" für Hilfe (Entlastungsbetrag)
Jeder (ab Pflegegrad 1) bekommt **125 € im Monat**. Das ist wie ein Gutschein. Damit kann man jemanden bezahlen, der beim Putzen hilft, einkaufen geht oder einfach mal Zeit mit der Person verbringt.
### D. Wenn die Helfer Urlaub brauchen (Verhinderungspflege)
Wenn die Person, die normalerweise hilft, krank ist oder Urlaub macht, bezahlt die Kasse für ein paar Wochen eine Ersatz-Hilfe.
### E. Mal woanders schlafen (Kurzzeitpflege)
Wenn es zu Hause gar nicht mehr geht (z. B. nach dem Krankenhaus), kann man für kurze Zeit in ein Pflegeheim gehen. Die Kasse übernimmt einen großen Teil der Kosten.
### F. Hilfe für die Wohnung (Wohnumfeldverbesserung)
Wenn das Bad umgebaut werden muss (z. B. eine Dusche statt einer Wanne), gibt die Kasse bis zu **4.000 €** dazu.
### G. Kleine Helfer (Pflegehilfsmittel)
* **Verbrauchssachen:** Man bekommt **40 € im Monat** für Dinge wie Einmalhandschuhe, Desinfektionsmittel oder Betteinlagen.
* **Technik:** Dinge wie ein Pflegebett oder ein Hausnotruf (der rote Knopf am Handgelenk) werden auch bezahlt oder geliehen.
---
## 3. Hilfe von der Krankenkasse 🩺
Das gibt es auch ohne Pflegegrad, wenn ein Arzt es aufschreibt:
* **Medizinische Hilfe zu Hause:** Wenn jemand kommen muss, um Spritzen zu geben oder Verbände zu wechseln.
* **Haushaltshilfe:** Wenn man wegen einer Krankheit (oder nach einer OP) den Haushalt nicht alleine schafft.
---
## 4. Zusammenfassung für unseren "Pflegepiloten" 🤖
Unsere KI muss den Usern helfen, das Maximum herauszuholen. Viele wissen zum Beispiel gar nichts von den 125 € (Punkt C) oder den 40 € für Handschuhe (Punkt G).
**Nächster Schritt:** Wir könnten eine Checkliste machen: "Hast du schon deine 125 € für diesen Monat genutzt?"
+86
View File
@@ -0,0 +1,86 @@
# Komplette Liste aller Leistungen (Input für Pflegepilot) 📋
Diese Liste enthält alle erdenkbaren Leistungen der Krankenkasse und Pflegekasse in Deutschland.
---
## 1. Leistungen der PFLEGEKASSE (Bei Pflegegrad 1-5)
### Geld-Leistungen (Direkt aufs Konto)
- **Pflegegeld:** Für Pflege durch Angehörige (Betrag steigt je nach Pflegegrad).
- **Pflegeunterstützungsgeld:** Lohnersatz, wenn man kurzfristig (bis 10 Tage) die Pflege eines Angehörigen organisieren muss.
- **Entlastungsbetrag (125 € / ab 2025: 131 €):** Monatliches Budget für Haushaltshilfe, Alltagsbegleiter oder Einkaufshilfe.
### Sach-Leistungen (Profi-Hilfe)
- **Pflegesachleistungen:** Budget für den ambulanten Pflegedienst (Waschen, Pflegen).
- **Tages- und Nachtpflege:** Kosten für die Betreuung in einer Einrichtung tagsüber oder nachts.
- **Vollstationäre Pflege:** Zuschuss zu den Kosten im Pflegeheim.
- **Leistungszuschlag Pflegeheim:** Die Kasse zahlt extra dazu, je länger man im Heim wohnt (15% bis 75% Rabatt auf den Eigenanteil).
### Flexi-Budgets (Ersatz-Pflege)
- **Verhinderungspflege:** Geld für Ersatzkräfte, wenn die Hauptpflegeperson Urlaub macht oder krank ist.
- **Kurzzeitpflege:** Vorübergehende Unterbringung im Heim (z. B. nach Krankenhausaufenthalt).
- **Gemeinsamer Jahresbetrag (ab Juli 2025):** Zusammenfassung von Verhinderungs- und Kurzzeitpflege zu einem großen Topf (3.539 €).
### Hilfsmittel & Wohnen
- **Pflegehilfsmittel zum Verbrauch (40 € / ab 2025: 42 €):** Monatlich für Handschuhe, Bettschutzeinlagen, Desinfektion.
- **Technische Pflegehilfsmittel:** Pflegebetten, Lagerungshilfen, Notrufsysteme (Leihgabe oder Zuschuss).
- **Wohnumfeldverbesserung (bis 4.000 € / ab 2025: 4.180 €):** Zuschuss für Badumbau, Treppenlift, Türverbreiterung.
- **Digitale Pflegeanwendungen (DiPA):** Apps, die bei der Pflege helfen (Zuschuss bis 50 € mtl.).
### Sonstiges (Pflegekasse)
- **Pflegekurse:** Kostenlose Schulungen für Angehörige.
- **Rentenbeiträge für Pflegende:** Die Pflegekasse zahlt Renten-, Arbeitslosen- und Unfallversicherung für pflegende Angehörige.
- **Wohngruppen-Zuschlag:** Extra Geld (ca. 214 €), wenn man in einer Pflege-WG lebt.
---
## 2. Leistungen der KRANKENKASSE (Medizinisch notwendig)
### Behandlung & Vorsorge
- **Ärztliche Behandlung:** Hausarzt, Facharzt, Zahnarzt.
- **Medikamente:** Übernahme der Kosten (minus gesetzliche Zuzahlung).
- **Krankenhausbehandlung:** Stationäre Aufenthalte und Operationen.
- **Vorsorgeuntersuchungen:** Check-ups, Krebsfrüherkennung, Zahn-Vorsorge.
- **Impfungen:** Alle von der STIKO empfohlenen Impfungen (oft auch Reiseimpfungen als Bonus).
### Therapie & Heilmittel
- **Physiotherapie / Krankengymnastik:** Auf Rezept.
- **Ergotherapie:** Hilfe zur Selbstständigkeit im Alltag.
- **Logopädie:** Sprach- und Sprechtherapie.
- **Podologie:** Medizinische Fußpflege (besonders bei Diabetes).
### Hilfsmittel (Krankenkasse)
- **Sehhilfen:** Zuschüsse für Brillen (meist nur für Kinder oder bei Sehbehinderung).
- **Hörgeräte:** Zuschuss zum Gerät und zur Anpassung.
- **Prothesen / Orthesen:** Künstliche Gliedmaßen oder Schienen.
- **Rollstühle / Gehhilfen:** Rollatoren, Rollstühle, Gehböcke.
- **Kompressionsstrümpfe:** Bei Venenleiden.
- **CPAP-Geräte:** Schlafapnoe-Masken.
- **Digitale Gesundheitsanwendungen (DiGA):** "Apps auf Rezept" (z.B. gegen Rückenweh oder Angst).
### Unterstützung im Alltag (Krankenkasse)
- **Häusliche Krankenpflege (HKP):** Spritzen geben, Verband wechseln durch Pflegedienst (wenn kein Pflegegrad vorliegt).
- **Haushaltshilfe:** Wenn man wegen Krankheit den Haushalt nicht führen kann (z.B. nach OP oder bei schwerer Krankheit).
- **Fahrtkosten:** Krankentransport zum Arzt oder Krankenhaus (unter bestimmten Bedingungen).
- **Krankengeld:** Lohnersatz bei langer Krankheit (nach 6 Wochen Lohnfortzahlung).
### Zähne
- **Zahnfüllungen:** Jetzt auch hochwertige Alternativen zu Amalgam (kostenfrei).
- **Zahnersatz:** Festzuschuss für Kronen, Brücken, Prothesen (Bonusheft pflegen!).
- **Kieferorthopädie:** Spangen für Kinder (bei Erwachsenen nur in schweren Fällen).
---
## 3. Leistungen für PRIVAT VERSICHERTE (PKV)
- **Kostenerstattung:** Man bekommt fast die gleichen Leistungen wie oben, muss aber oft erst die Rechnung einreichen.
- **Chefarzt / Einbettzimmer:** Je nach Wahltarif im Vertrag enthalten.
- **Heilpraktiker:** Oft im Vertrag enthalten (anders als bei der GKV).
- **Pflege-Pflichtversicherung:** Privat Versicherte haben eine eigene Pflegeversicherung, die EXAKT die gleichen Sätze zahlt wie die gesetzliche (z.B. Pflegegeld, 125 € Entlastungsbetrag).
---
## 4. Wichtig für den Pflegepiloten
- **Kombinationsleistung:** Man kann Pflegegeld und Pflegesachleistung mischen (z. B. 50% Geld, 50% Pflegedienst).
- **Zuzahlungsbefreiung:** Wenn man mehr als 2% (chronisch Kranke 1%) des Einkommens für Zuzahlungen ausgibt, kann man sich befreien lassen.
+47
View File
@@ -0,0 +1,47 @@
# Muster-Brief: Antrag auf Pflege-Leistungen 📝
Diesen Brief kannst du einfach kopieren. Er ist so geschrieben, dass die Krankenkasse sofort weiß, was zu tun ist. Alles in Klammern **[wie das hier]** musst du mit deinen echten Infos füllen.
---
### Der Brief-Inhalt:
**Absender:**
[Dein Vorname und Nachname]
[Deine Straße und Hausnummer]
[Deine Postleitzahl und dein Wohnort]
[Deine Telefonnummer für Rückfragen]
**Datum:** [Heutiges Datum]
**An die:**
[Name der Krankenkasse, z. B. AOK Plus]
[Straße der Krankenkasse]
[Postleitzahl und Ort der Krankenkasse]
**Betreff: Antrag auf Leistungen der Pflegekasse**
Sehr geehrte Damen und Herren,
hiermit stelle ich einen Antrag auf Leistungen der Pflegeversicherung für:
**Name der Person:** [Vorname und Nachname der Person, die Hilfe braucht]
**Geburtsdatum:** [Wann wurde die Person geboren?]
**Versichertennummer:** [Diese Nummer steht auf der Gesundheitskarte der Person]
Bitte bestätigen Sie mir kurz, dass dieser Brief bei Ihnen angekommen ist. Senden Sie mir danach bitte alle weiteren Formulare zu, die Sie von mir benötigen.
Mit freundlichen Grüßen,
(Unterschrift)
[Dein Vorname und Nachname]
---
### Was du jetzt tun musst:
1. **Ausfüllen:** Fülle die Lücken in den Klammern aus.
2. **Abschicken:** Per Post (am besten als "Einschreiben", dann hast du einen Beleg) oder per Fax. Manche Kassen nehmen das auch per E-Mail an.
3. **Warten:** Die Kasse schickt dir jetzt dicke Formulare zu. Keine Angst, dabei hilft dir später unser "Pflegepilot".
4. **Wichtig:** Behalte eine Kopie von dem Brief für deine Unterlagen!
+47
View File
@@ -0,0 +1,47 @@
# Thema: Hilfe von der Pflegekasse bekommen (Schritt für Schritt) 📄
**Wichtige Regel für dieses Projekt:** Wir benutzen keine komplizierten Fachwörter oder Abkürzungen. Wenn wir ein Wort benutzen müssen, das man nicht im Alltag verwendet, erklären wir es sofort. So versteht jeder – egal ob Enkel oder Oma – was zu tun ist.
---
## 1. Was ist das überhaupt? 🤔
Ganz einfach: Wenn jemand Hilfe im Alltag braucht (z. B. beim Waschen, Anziehen oder Kochen), gibt es Geld und Unterstützung vom Staat. Damit man das bekommt, muss man beweisen, dass man Hilfe braucht. Das nennt man "einen Pflegegrad bekommen". Es gibt 5 Stufen: Stufe 1 heißt "ein bisschen Hilfe", Stufe 5 heißt "sehr viel Hilfe".
---
## 2. Der Fahrplan zum Erfolg 🗺️
### Schritt A: Den Stein ins Rollen bringen (Der Antrag)
Man muss kein langes Formular ausfüllen. Ein einfacher Satz an die Krankenkasse reicht: "Ich brauche Hilfe im Alltag und möchte Leistungen der Pflegekasse beantragen."
* **Warum das Datum wichtig ist:** Wenn du heute den Brief abschickst oder anrufst, zählt das Geld ab heute. Wartest du bis zum nächsten Monat, schenkst du der Kasse Geld.
* **Was wir tun:** Wir halten fest, an welchem Tag wir die Kasse informiert haben.
### Schritt B: Der Besuch der Prüfer (Das Gutachten)
Die Krankenkasse schickt jemanden vorbei, der sich alles genau anschaut. Früher hießen die oft "MDK" (Medizinischer Dienst), aber wir nennen sie einfach **die Prüfer**.
* **Was die Prüfer machen:** Sie kommen nach Hause und schauen: Kann die Person noch alleine Treppen steigen? Kann sie sich alleine waschen? Vergisst sie wichtige Dinge?
* **Vorbereitung ist alles:** Wir schreiben vorher in ein Heft (ein **Pflegetagebuch**), was im Alltag schwierig ist. Zum Beispiel: "Opa hat heute Hilfe beim Schuhebinden gebraucht." Das zeigen wir den Prüfern.
### Schritt C: Der Brief mit der Antwort (Der Bescheid)
Nach ein paar Wochen schickt die Krankenkasse einen Brief.
* **Gute Nachricht:** "Ja, du bekommst Hilfe!" (Pflegegrad genehmigt). Ab jetzt gibt es Geld oder Hilfe vom Pflegedienst.
* **Schlechte Nachricht:** "Nein, wir glauben, du brauchst keine Hilfe." (Antrag abgelehnt).
* **Was wir dann tun:** Wir schreiben einen "Beschwerde-Brief" (das nennt man **Widerspruch**). Wir sagen: "Das stimmt nicht, die Person braucht doch Hilfe, schaut bitte nochmal genau hin."
---
## 3. Was unsere KI (der Pflegepilot) lernen muss 🤖
Damit unsere KI wirklich eine Hilfe ist, muss sie diese Dinge ganz einfach erklären können:
1. **Wer ist meine Krankenkasse?** (Und wo schicke ich den Brief hin?)
2. **Welche Fragen stellen die Prüfer?** (Damit man keine Angst vor dem Besuch hat).
3. **Wie viel Zeit haben die?** (Die Krankenkasse muss normalerweise innerhalb von etwa 5 Wochen antworten).
---
## 4. Unsere nächsten Aufgaben (ToDo-Liste) 📝
- [ ] Namen der großen Krankenkassen sammeln (damit wir wissen, wohin die Briefe gehen).
- [ ] Einen ganz einfachen Muster-Brief schreiben (den man nur noch unterschreiben muss).
- [ ] Eine Liste machen mit Dingen, die man den Prüfern zeigen sollte.
---
**Notiz für uns:** Wir bleiben bei dieser einfachen Sprache. Keine Abkürzungen wie "MDK" mehr ohne Erklärung.
+325
View File
@@ -0,0 +1,325 @@
# Pflegepilot Alpha 🏥
Lokale Web-App zur Verwaltung von Pflegepatienten, Anträgen und Formularen.
Alle Daten bleiben **lokal** in einer SQLite-Datenbank – kein Cloud-Zwang.
---
## Schnellstart (3 Schritte)
### Voraussetzungen
- Python 3.9+ (bereits auf den meisten Systemen)
- pip
### 1. Abhängigkeiten installieren
```bash
pip install flask
```
> **Login:** Standard-Zugangsdaten nach Erststart: `admin` / `admin`
> Bitte im Backend unter **Nutzerverwaltung** sofort ändern.
### 2. App starten
```bash
python start.py
```
### 3. Im Browser öffnen
```
http://localhost:5050
```
---
## Funktionen
| Bereich | Beschreibung |
|---|---|
| **Dashboard** | Übersicht Patienten, Anträge, Aufgaben |
| **Patientenverwaltung** | CRUD mit Stammdaten & Pflegestatus |
| **Antrag Pflegegrad** | Prozessführung + Pflegetagebuch-Checkliste |
| **Widerspruch-Generator** | KI-gestützt nach SGB XI & SGG · PDF-Export |
| **Musterbrief** | Erstantrag Live-Vorschau · PDF-Export |
| **Leistungsrechner** | Alle Beträge Pflege-/Krankenkasse 2025 |
| **Leistungskatalog** | 82 Leistungen mit Abhängigkeiten · direkte Patientenzuweisung |
| **Patientenakte** | Profilfoto hochladen (JPEG/PNG) · direkt in der Akte klicken |
| **Pflegetagebuch** | Alle 6 SGB XI-Begutachtungsmodule · Verlauf · MDK-Vorbereitung |
| **Aufgabenverwaltung** | Fristen & Prioritäten |
---
## Widerspruch-Generator – Rechtliche Grundlagen
Der Generator erzeugt Widersprüche nach:
- **§ 15 SGB XI** – Pflegebedürftigkeit und Pflegegrade
- **§ 18 SGB XI** – Begutachtungsverfahren (MDK/MDS-Richtlinien)
- **§ 37 SGB XI** – Pflegegeld (materieller Schaden)
- **§ 84 SGG** – Widerspruchsfrist (1 Monat)
- **§ 86 SGG** – Widerspruchsrecht
- **§§ 36, 38a SGB XI** – Pflegesachleistungen
---
## Datenschutz
- Alle Daten lokal in `db/pflegepilot.db` (SQLite)
- Kein Internetzugang erforderlich (außer KI-Widerspruchsgenerator)
- Für Produktivbetrieb: Zugangsbeschränkung empfohlen
---
## Projektstruktur
```
pflegepilot/
├── start.py ← Hier starten
├── app.py ← Flask Backend + API
├── katalog.py ← 82 Leistungen mit Abhängigkeitsdaten
├── krankenkassen.py ← ~86 GKV/PKV/SV/KVG (DE, AT, CH) mit korrekten Adressen
├── db/
│ ├── schema.sql ← Datenbankschema + Demo-Daten
│ └── pflegepilot.db ← Wird automatisch erstellt
├── static/
│ └── fotos/ ← Patientenfotos (JPEG/PNG)
└── templates/
└── index.html ← Vollständige SPA
```
---
## Changelog
### Alpha v1.0 (11.05.2026)
**Österreich & Schweiz – Krankenkassen-Stammdaten**
- `krankenkassen.py` um 26 Einträge für AT und CH erweitert (bisher nur DE)
- **Österreich (SV)**: ÖGK Hauptstelle + alle 9 Landesstellen (Wien, NÖ, OÖ, Steiermark, Kärnten, Salzburg, Tirol, Vorarlberg, Burgenland), SVS (Selbständige), BVAEB (öffentlich Bedienstete)
- **Schweiz (KVG)**: Helsana, CSS, SWICA, Sanitas, Concordia, Visana, KPT, Assura, Groupe Mutuel, Atupri, Sympany, EGK, Aquilana, Galenos, Sana24, Kolping
- Neues Feld `land` (`"DE"` / `"AT"` / `"CH"`) in allen Einträgen – DE-Einträge nutzen `get("land","DE")` für Rückwärtskompatibilität
- Neue Hilfsfunktionen: `get_by_land(land)`, `search(q, land=None)`, `get_all(land=None)` (optional gefiltert)
- **API** `GET /api/krankenkassen`: neuer Query-Parameter `?land=AT|CH|DE` für länderspezifische Abfrage
- **Dropdown im Frontend**: Länder-Tab-Leiste (🇩🇪 DE / 🇦🇹 AT / 🇨🇭 CH / Alle) direkt im Suchfeld-Overlay
- Typ-Badges: SV (rot, AT) und KVG (amber, CH) ergänzen die bisherigen GKV (grün) / PKV (blau)
- `getKKAdr()` ergänzt bei AT/CH den Ländercode in der postalischen Adresse
---
### Alpha v0.9 (11.05.2026)
**E-Mail-Versand direkt aus der App**
- Neuer Backend-Endpoint `POST /api/email/senden` – versendet E-Mail mit optionalem PDF-Anhang via SMTP (`smtplib` + STARTTLS)
- Neuer Backend-Endpoint `POST /api/email/test` – sendet Test-E-Mail an die konfigurierte Absender-Adresse zur Verbindungsprüfung
- Hilfsfunktion `_smtp_cfg()` liest SMTP-Einstellungen aus der `einstellungen`-Tabelle
- Fehlermeldungen differenziert: Authentifizierungsfehler, Verbindungsfehler, fehlende Konfiguration
- **Widerspruch-Generator**: neuer Button „E-Mail" in der Vorschau (erscheint nach „Widerspruch erstellen")
- **Musterbrief**: neuer Button „E-Mail" neben PDF und Kopieren
- `sendMailModal(typ)`: öffnet Modal mit vorausgefülltem Betreff, Empfänger (aus Patientenstammdaten wenn vorhanden), Anschreiben-Textarea und Checkbox „PDF-Anhang beifügen"
- `sendMail(typ)`: generiert PDF on-the-fly via html2pdf, konvertiert zu Base64, sendet an API – mit Lade-Indikator im Button während des Versands
- **Backend-Admin → E-Mail**: neuer „Test-E-Mail"-Button prüft SMTP-Konfiguration mit einem Klick
---
### Alpha v0.8 (11.05.2026)
**Login / Mehrbenutzer**
- Neue Datenbanktabelle `nutzer` (id, benutzername, passwort_hash, name, rolle, aktiv)
- Passwörter gehasht mit `werkzeug.security` (PBKDF2-SHA256) – keine Klartextspeicherung
- Standard-Admin `admin/admin` wird automatisch beim Erststart angelegt
- Login-Overlay zeigt sich beim App-Start, solange kein gültiger Session-Cookie vorliegt
- `before_request`-Hook schützt alle API-Routen außer `/api/auth/*` und `/api/einstellungen/public`
- Neue Endpunkte: `POST /api/auth/login`, `POST /api/auth/logout`, `GET /api/auth/me`
- Rollen: `admin` (vollständiger Zugriff, Backend, Nutzerverwaltung) und `nutzer` (Patientendaten)
- Sidebar zeigt Anzeigename, Rolle und Abmelden-Button des angemeldeten Nutzers
- Admin-Bereich in der Sidebar wird für Nutzer ohne Admin-Rolle ausgeblendet
**Nutzerverwaltung (im Backend-Admin)**
- Neue Endpunkte: `GET/POST /api/nutzer`, `PUT/DELETE /api/nutzer/<uid>`
- Nutzer anlegen, Rolle ändern, Passwort zurücksetzen, Nutzer deaktivieren/löschen
- Eigenen Account kann man nicht löschen (serverseitig verhindert)
- Übersicht aller Nutzer mit Avatar, Anzeigename, Benutzername, Rolle, Status
**Backend-Einstellungen – Firmen-Adresse**
- Neue Felder: Straße, PLZ, Ort, Telefon, Betriebs-E-Mail
- Öffentlicher Endpunkt `GET /api/einstellungen/public` gibt Branding-Daten (Name, Logo, Adresse) ohne Auth zurück – wird von `initApp()` genutzt
- Firmen-Adresse steht in `_einstellungen` und fließt in PDF-Briefköpfe ein
**Dokumenten-Upload – Verbesserungen**
- Drag-&-Drop-Uploadbereich: Datei ablegen oder klicken zum Auswählen
- Dateiname und Dateigröße werden direkt nach Auswahl angezeigt
- Bezeichnung wird automatisch aus dem Dateinamen vorausgefüllt
- Dokumentenliste: Bildvorschau (JPEG/PNG direkt als Thumbnail), separate Öffnen- und Download-Schaltflächen
- PDFs mit rotem Icon deutlich gekennzeichnet
---
### Alpha v0.7 (11.05.2026)
**Patiententagebuch – PDF-Export (MDK-fertig)**
- `dlTB(pid)` exportiert alle Einträge als A4-PDF in Courier-Schrift
- Deckblatt mit Patientenstammdaten, Versicherung, Pflegegrad und Zeitraum
- Tabellarische Darstellung aller 6 SGB XI-Begutachtungsmodule (M1–M6) je Datum
- Automatische Paginierung „Seite X von N" (via `addPageNums`)
- Korrekte Seitenränder auf allen Seiten (`margin:[20,20,25,25]` mm)
- Rechtlicher Hinweis: § 630f BGB Aufbewahrungspflicht 10 Jahre
- Button direkt in der Patientenakte und im Pflegetagebuch-View
**Erinnerungsfunktion für Tagebucheinträge (tägliche Browser-Notification)**
- Neuer Endpoint `GET /api/tagebuch/reminder-status`: liefert alle aktiven Patienten mit Pflegegrad > 0 und ob heute ein Tagebucheintrag vorliegt
- `checkTagebuchReminder()` wird bei App-Start und bei jedem Dashboard-Aufruf ausgeführt
- Browser-Notification (einmal pro Tag, via `Notification API`): listet Patienten ohne heutigen Eintrag auf
- Dashboard-Banner (gelb/amber): zeigt fehlende Patienten mit Direktlinks zum Tagebuch
- Badge-Zähler am Navigations-Eintrag „Pflegetagebuch" (analog Aufgaben-Badge)
- Benachrichtigungserlaubnis kann im Fristen-Kalender aktiviert werden
**Automatische Fristenüberwachung – Tagebuch-Events**
- `/api/kalender` enthält jetzt einen neuen Event-Typ `tagebuch_erinnerung`
- Aktive Patienten mit Pflegegrad > 0 ohne heutigen Tagebucheintrag erscheinen im Fristen-Kalender
- Priorisierung: `hoch` wenn letzter Eintrag ≥ 2 Tage zurückliegt, sonst `mittel`
- `checkReminders()` berücksichtigt Tagebuch-Events für Browser-Notifications
- Icon im Kalender: `ti-notebook`
---
### Alpha v0.6 (11.05.2026)
**Widerspruch-Generator – Vollständiger Umbau (kein KI-API-Aufruf mehr)**
- 30 vordefinierte Widerspruchsgründe nach Rechtsnorm organisiert (`WGRUENDE`-Konstante)
- Normen: § 18 SGB XI (5), § 15 SGB XI (7), § 14 SGB XI (3), § 37 SGB XI (2), § 36/39/45b/40/43 SGB XI (je 1), § 33/24 SGB X (3), § 18 Abs. 3 SGB XI (2), Verfahrensrecht (3)
- Auswahl per kollabierbare Checkbox-Gruppen mit Norm-Tag und Gruppenbezeichnung
- Briefgenerierung vollständig lokal per Template – kein API-Call, kein Internetzugang nötig
- Struktur: Briefkopf → Betreff → Sachverhalt → Rechtliche Begründung (nach Norm gruppiert) → Beweismittel → Antrag → Grußformel
- KI-Endpoint `POST /api/widerspruch/generate` bleibt als Stub erhalten (gibt sofort `{"ok": true}`)
- Neue CSS-Klassen: `.wg-group`, `.wg-group-hd`, `.wg-group-body`, `.wg-item`, `.wg-norm-tag`
**PDF-Export – Korrekte Seitenränder & automatische Paginierung**
- Alle PDF-Exporte (Musterbrief, Widerspruch, Pflegetagebuch, Patientenakte) verwenden jetzt html2pdf-native `margin`-Array `[25, 20, 28, 25]` mm statt CSS-Padding
- CSS-Padding auf dem Exportcontainer auf `0` gesetzt – Randabstände gelten jetzt korrekt auf jeder Seite, nicht nur der ersten
- Neue Hilfsfunktion `addPageNums(pdf)`: schreibt „Seite X von N" zentriert am Seitenfuß (H−9 mm) auf jede Seite
- Umsetzung über jsPDF-Chain `.toPdf().get('pdf').then(pdf=>{ addPageNums(pdf); ... })` für saubere Trennung von Seitenzahl-Injection, Download und Server-Upload
**Notizen in Patientenakte – Bearbeitung gemäß ISO 9001**
- Notizen sind jetzt inline bearbeitbar – Klick auf „Bearbeiten" öffnet ein Modal mit vorausgefülltem Textarea und Pflichtfeld „Änderungsgrund"
- Jede Änderung wird unveränderlich protokolliert: Inhalt vorher, Inhalt nachher, Änderungsgrund, Zeitstempel (ISO 9001:2015 Abschn. 7.5 – Lenkung dokumentierter Informationen)
- Verlauf-Button (Uhren-Icon) neben „Bearbeiten": zeigt/versteckt den vollständigen Audit-Trail (rot = alter Text, grün = neuer Text)
- Neue Datenbanktabelle `notizen_verlauf` (Migration automatisch beim Start)
- Neue API-Endpoints:
- `POST /api/patienten/<pid>/notizen` – Notiz speichern + Verlaufseintrag anlegen (400 ohne Änderungsgrund)
- `GET /api/patienten/<pid>/notizen/verlauf` – Änderungshistorie abrufen (neueste zuerst)
- Neue JS-Funktionen: `editNotizen(pid)`, `saveNotizen(pid)`, `loadNotizenVerlauf(pid)`, `escH(s)`
---
### Alpha v0.5.1 (10.05.2026)
**PDF dauerhaft in Patientenakte hinterlegen**
- PDFs werden jetzt serverseitig in `static/briefe/<patient_id>/` gespeichert
- Gilt für Musterbrief (`dlM()`) und Widerspruch-Generator (`dlW()`)
- Ablauf: `html2pdf` erzeugt Blob → Browser-Download → Base64-Upload an Server → Datei gespeichert
- Neuer Endpoint `POST /api/patienten/<pid>/briefe` akzeptiert jetzt `pdf_base64` + `pdf_dateiname`
- Neue Spalte `pdf_pfad` in Tabelle `antraege` (Migration automatisch beim Start)
- Patientenakte: Antraege-Tabelle zeigt neue Spalte **Dokument** mit klickbarem „PDF öffnen"-Link
- Zweifache Bestätigung per Toast: „PDF heruntergeladen" + „PDF dauerhaft gespeichert"
---
### Alpha v0.5 (10.05.2026)
**Krankenkassen-Stammdaten (neue Datei `krankenkassen.py`)**
- ~60 Kassen mit vollständigen Adressen: 12 AOK-Regionalverbände, TK, Barmer, DAK, KKH, hkk, HEK, Knappschaft, 4× IKK, 10+ BKK, und 17 PKV-Gesellschaften
- Separate Einträge für GKV und PKV (Typ-Kennzeichnung)
- Neuer API-Endpoint `GET /api/krankenkassen` (optional gefiltert per `?q=…`)
**Searchable Dropdown für Krankenkassen**
- Ersetzte alle bisherigen Dropdowns (8 Einträge) durch ein vollständiges Suchfeld
- Live-Filterung nach Name, Kurzname und Ort (bis 70 Treffer gleichzeitig)
- Jeder Eintrag zeigt Name, Ort und Typ-Badge (GKV grün / PKV blau)
- Auswahl setzt Versicherungsart (GKV/PKV) im Formular automatisch
**Musterbrief – Adresse automatisch aus Stammdaten**
- KK-Empfänger im Musterbrief nutzt jetzt das Suchfeld
- Vollständige Postanschrift (Straße + PLZ + Ort) wird automatisch in den Brief eingesetzt
- Patientenauswahl befüllt Empfänger-Krankenkasse automatisch
- `[Anschrift der Krankenkasse]` entfällt bei bekannten Kassen
---
### Alpha v0.4 (10.05.2026)
**Patientenakte – Profilfoto**
- Klick auf den Avatar-Kreis im Stammdaten-Header öffnet einen Datei-Dialog
- Unterstützte Formate: JPEG, PNG, GIF, WebP
- Foto wird lokal in `static/fotos/<patient_id>.ext` gespeichert und in der Akte angezeigt
- Neuer Endpoint `POST /api/patienten/<pid>/foto` (Multipart/Form-Data)
- Neue Spalte `foto_pfad` in Tabelle `patienten` (Migration automatisch beim Start)
**Pflegetagebuch nach SGB XI**
- Vollständige Struktur der 6 Begutachtungsmodule (Begutachtungsinstrument MDK):
- **Modul 1** – Mobilität (§ 14 Abs. 2 Nr. 1 SGB XI)
- **Modul 2** – Kognition & Kommunikation (§ 14 Abs. 2 Nr. 2/3 SGB XI)
- **Modul 4** – Selbstversorgung: Körperpflege, An-/Ausziehen, Ernährung (§ 14 Abs. 2 Nr. 4 SGB XI)
- **Modul 5** – Medizinische Anforderungen: Medikamente, Verbände, Injektionen (§ 14 Abs. 2 Nr. 5 SGB XI)
- **Modul 6** – Sozialleben & Alltagsgestaltung (§ 14 Abs. 2 Nr. 6 SGB XI)
- Aufruf direkt aus Patientenakte (Schnellvorschau letzte 2 Einträge) oder über Seitenleiste
- Einträge chronologisch gelistet, einzeln löschbar
- Neue Endpoints: `GET /POST /api/patienten/<pid>/tagebuch`, `DELETE /api/tagebuch/<tid>`
- Bestehende Tabelle `pflegetagebuch` aus Schema wird genutzt (kein Schema-Change)
---
### Alpha v0.3 (10.05.2026)
**PDF-Export**
- Musterbrief und Widerspruch-Generator exportieren jetzt als **A4-PDF** statt TXT
- Rendering über `html2pdf.js` (client-seitig) – Umlaute und Sonderzeichen vollständig unterstützt
- Brief-Layout in Courier-Schrift, druckfertig mit korrekten Seitenrändern
**Leistungskatalog – Abhängigkeiten**
- 22 von 82 Einträgen haben das neue Feld `abhaengigkeiten`
- Drei Abhängigkeitstypen werden farblich unterschieden:
- **Rot – Voraussetzung**: z. B. alle Merkzeichen erfordern zuerst den Schwerbehindertenausweis
- **Blau – Gut kombinierbar**: z. B. Pflegegeld + Rentenbeiträge + ALV + Unfall für pflegende Angehörige
- **Orange – Ab 07/2025 ersetzt durch**: Gemeinsamer Jahresbetrag ersetzt Verhinderungs- und Kurzzeitpflege
- Klick auf eine Abhängigkeit öffnet direkt deren Detailansicht
**Leistungskatalog – Patientenzuweisung**
- Leistungen lassen sich direkt aus dem Katalog einem Patienten zuweisen
- Im Patientendetail öffnet „Alle Leistungen prüfen" den Katalog im Patienten-Kontext: alle Karten zeigen einen „Zuweisen"-Button
- Beim Klick auf eine Katalog-Karte erscheint im Modal „[Patientenname] zuweisen"
- Zugewiesene Leistungen sind im Patientendetail mit einem Katalog-Icon (📋) gekennzeichnet
- Doppelzuweisungen werden serverseitig verhindert (HTTP 409)
- Neue API-Endpoints:
- `POST /api/patienten/<pid>/leistungen/katalog` – Katalog-Leistung zuweisen
- `POST /api/leistungen/<lid>/deaktivieren` – Leistung deaktivieren
**Datenbank**
- Tabelle `patienten`: neue Spalte `zielgruppe` (Migration automatisch beim Start)
- Tabelle `leistungen`: neue Spalte `katalog_id` – Verknüpfung zur Katalog-ID
---
### Alpha v0.3.1 (10.05.2026)
**Bug #1 – Antrag-Formular: Patientendaten nach Auswahl**
- Nach Auswahl eines Patienten im Dropdown erscheint jetzt eine Infobox mit Name, Zielgruppe, Pflegegrad, Krankenkasse und Anschrift
- Bei Vorauswahl (Aufruf aus Patientendetail) wird die Infobox automatisch befüllt
**Feature #2 – PDF-Dateiname & digitale Kopie**
- PDF-Dateiname enthält jetzt Patientennachname, Antragstyp und Datum (z. B. `Huber_Erstantrag_2026-05-10.pdf`)
- Nach dem PDF-Export wird automatisch eine Kopie des Brieftexts in der Patientenakte gespeichert (neuer Eintrag in der Antragsliste mit Status „PDF erstellt")
- Gilt für Musterbrief und Widerspruch-Generator
- Neuer Endpoint `POST /api/patienten/<pid>/briefe`
---
## Nächste Schritte (Beta-Plan)
- [x] Login / Mehrbenutzer (Flask-Login) *(Alpha v0.8)*
- [x] Dokumenten-Upload (Atteste, Gutachten) *(Alpha v0.8)*
- [x] E-Mail-Versand direkt aus der App *(Alpha v0.9)*
- [x] Automatische Fristenüberwachung mittels Kalender und Remindern *(Alpha v0.7)*
- [x] Erweiterung um österreichische (ÖGK, SVS, BVAEB) und Schweizer Kassen (SWICA, Helsana, Sanitas…) *(Alpha v1.0)*
- [x] Backend für Individuelle Einstellungen nach Betrieben (API-Token Claude, Mailadressen, Account-Verwaltung, Firmen-Logo) *(Alpha v0.8)*
- [ ] Lizenz-Model entwickeln und implementieren
- [x] Patiententagebuch – PDF-Export der Verlaufsdokumentation für MDK-Termin *(Alpha v0.7)*
- [x] Erinnerungsfunktion für Tagebucheinträge (tägliche Browser-Notification) *(Alpha v0.7)*
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,126 @@
-- Pflegepilot Alpha – SQLite Schema
CREATE TABLE IF NOT EXISTS patienten (
id INTEGER PRIMARY KEY AUTOINCREMENT,
vorname TEXT NOT NULL,
nachname TEXT NOT NULL,
geburtsdatum TEXT,
strasse TEXT,
plz TEXT,
ort TEXT,
telefon TEXT,
email TEXT,
krankenkasse TEXT,
versichertennummer TEXT,
versicherungsart TEXT DEFAULT 'GKV',
pflegegrad INTEGER DEFAULT 0,
pflegeperson TEXT,
zielgruppe TEXT DEFAULT 'alterspflege',
notizen TEXT,
erstellt_am TEXT DEFAULT (datetime('now','localtime')),
geaendert_am TEXT DEFAULT (datetime('now','localtime')),
patient_status TEXT DEFAULT 'aktiv',
status_datum TEXT,
archiv_frist TEXT,
archiv_hinweis TEXT
);
CREATE TABLE IF NOT EXISTS antraege (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER NOT NULL REFERENCES patienten(id) ON DELETE CASCADE,
typ TEXT NOT NULL, -- 'erstantrag', 'widerspruch', 'hoeherst'
status TEXT DEFAULT 'offen', -- 'offen', 'eingereicht', 'in_pruefung', 'genehmigt', 'abgelehnt'
antragsdatum TEXT,
bescheid_datum TEXT,
widerspruch_frist TEXT,
gutachter_termin TEXT,
beantragter_pflegegrad INTEGER,
zugeteilter_pflegegrad INTEGER,
notizen TEXT,
brief_text TEXT,
pdf_pfad TEXT,
erstellt_am TEXT DEFAULT (datetime('now','localtime'))
);
CREATE TABLE IF NOT EXISTS leistungen (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER NOT NULL REFERENCES patienten(id) ON DELETE CASCADE,
typ TEXT NOT NULL,
bezeichnung TEXT NOT NULL,
betrag REAL,
einheit TEXT DEFAULT 'monatlich',
aktiv INTEGER DEFAULT 1,
seit TEXT,
katalog_id TEXT,
notizen TEXT
);
CREATE TABLE IF NOT EXISTS aufgaben (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER REFERENCES patienten(id) ON DELETE CASCADE,
titel TEXT NOT NULL,
beschreibung TEXT,
faellig_am TEXT,
prioritaet TEXT DEFAULT 'normal', -- 'hoch', 'mittel', 'normal'
erledigt INTEGER DEFAULT 0,
erstellt_am TEXT DEFAULT (datetime('now','localtime'))
);
CREATE TABLE IF NOT EXISTS pflegetagebuch (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER NOT NULL REFERENCES patienten(id) ON DELETE CASCADE,
datum TEXT NOT NULL,
koerperpflege TEXT,
anziehen TEXT,
ernaehrung TEXT,
mobilitaet TEXT,
orientierung TEXT,
medikamente TEXT,
soziales TEXT,
allgemein TEXT,
erstellt_am TEXT DEFAULT (datetime('now','localtime'))
);
CREATE TABLE IF NOT EXISTS einstellungen (
schluessel TEXT PRIMARY KEY,
wert TEXT
);
CREATE TABLE IF NOT EXISTS dokumente (
id INTEGER PRIMARY KEY AUTOINCREMENT,
patient_id INTEGER NOT NULL REFERENCES patienten(id) ON DELETE CASCADE,
typ TEXT NOT NULL DEFAULT 'sonstiges',
bezeichnung TEXT NOT NULL,
dateiname TEXT NOT NULL,
pfad TEXT NOT NULL,
datum TEXT,
notizen TEXT,
erstellt_am TEXT DEFAULT (datetime('now','localtime'))
);
-- Demo-Daten
INSERT OR IGNORE INTO patienten (id,vorname,nachname,geburtsdatum,strasse,plz,ort,telefon,krankenkasse,versichertennummer,versicherungsart,pflegegrad,pflegeperson,notizen)
VALUES
(1,'Erika','Huber','1942-03-12','Hauptstraße 4','82256','Fürstenfeldbruck','08141/55432','AOK Bayern','A123456789','GKV',3,'Tochter (privat)','Demenz, leichte Einschränkungen Mobilität'),
(2,'Klaus','Meier','1938-11-07','Bahnhofstr. 21','80331','München','089/123456','TK','B987654321','GKV',0,'Pflegedienst ambulant','Antrag läuft – Gutachter-Termin offen'),
(3,'Inge','Müller','1950-06-23','Rosenweg 7','82256','Fürstenfeldbruck','08141/77821','Barmer','C555444333','GKV',2,'Ehemann','Widerspruch eingereicht – Grad zu niedrig');
INSERT OR IGNORE INTO antraege (id,patient_id,typ,status,antragsdatum,bescheid_datum,beantragter_pflegegrad,zugeteilter_pflegegrad,notizen)
VALUES
(1,1,'erstantrag','genehmigt','2025-01-15','2025-02-22',3,3,'Erstantrag genehmigt, Grad 3'),
(2,2,'erstantrag','in_pruefung','2025-04-02',NULL,3,NULL,'Gutachter-Termin noch nicht vereinbart'),
(3,3,'erstantrag','abgelehnt','2024-11-10','2025-01-05',3,2,'Nur Grad 2 – Widerspruch eingereicht');
INSERT OR IGNORE INTO leistungen (patient_id,typ,bezeichnung,betrag,einheit,seit)
VALUES
(1,'pflegegeld','Pflegegeld Grad 3',573,'monatlich','2025-03-01'),
(1,'entlastung','Entlastungsbetrag',131,'monatlich','2025-03-01'),
(1,'hilfsmittel','Pflegehilfsmittel Verbrauch',42,'monatlich','2025-03-01'),
(3,'pflegegeld','Pflegegeld Grad 2',332,'monatlich','2025-02-01'),
(3,'entlastung','Entlastungsbetrag',131,'monatlich','2025-02-01');
INSERT OR IGNORE INTO aufgaben (patient_id,titel,prioritaet,faellig_am,beschreibung)
VALUES
(2,'Gutachter-Termin vereinbaren','hoch','2025-05-13','Krankenkasse anrufen und Termin für MDK-Gutachter festlegen'),
(3,'Widerspruchsbescheid abwarten','mittel','2025-05-16','Krankenkasse hat 3 Monate Zeit – ggf. nachfassen'),
(1,'Entlastungsbetrag Mai abrufen','normal','2025-05-31','Monatliche 131 € über anerkannte Stelle abrechnen');
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,405 @@
"""
Pflegepilot – Krankenkassen-Stammdaten
Adressen Stand 2025. Vor Verwendung bitte auf Aktualität prüfen.
Pflegegrad-Bescheide werden meist über die zuständige Pflegekasse abgewickelt,
die in der Regel identisch mit der Krankenkasse ist.
"""
KRANKENKASSEN = [
# ── GKV: AOK ──────────────────────────────────────────────────────────────
{"name": "AOK Bayern – Die Gesundheitskasse",
"kurzname": "AOK Bayern", "typ": "GKV",
"strasse": "Carl-Wery-Straße 28", "plz": "81739", "ort": "München"},
{"name": "AOK Baden-Württemberg",
"kurzname": "AOK BW", "typ": "GKV",
"strasse": "Presselstraße 19", "plz": "70191", "ort": "Stuttgart"},
{"name": "AOK Berlin-Brandenburg",
"kurzname": "AOK BE/BB", "typ": "GKV",
"strasse": "Wilhelmstraße 1", "plz": "10963", "ort": "Berlin"},
{"name": "AOK Bremen/Bremerhaven",
"kurzname": "AOK Bremen", "typ": "GKV",
"strasse": "Bürgermeister-Smidt-Straße 95", "plz": "28195", "ort": "Bremen"},
{"name": "AOK Hessen",
"kurzname": "AOK Hessen", "typ": "GKV",
"strasse": "Berner Straße 2", "plz": "60437", "ort": "Frankfurt am Main"},
{"name": "AOK Niedersachsen",
"kurzname": "AOK Niedersachsen", "typ": "GKV",
"strasse": "Hildesheimer Straße 273", "plz": "30519", "ort": "Hannover"},
{"name": "AOK Nordost – Die Gesundheitskasse",
"kurzname": "AOK Nordost", "typ": "GKV",
"strasse": "Warnowufer 54", "plz": "18057", "ort": "Rostock"},
{"name": "AOK NordWest – Die Gesundheitskasse",
"kurzname": "AOK NordWest", "typ": "GKV",
"strasse": "Kopenhagener Straße 1", "plz": "44269", "ort": "Dortmund"},
{"name": "AOK PLUS – Die Gesundheitskasse für Sachsen und Thüringen",
"kurzname": "AOK PLUS", "typ": "GKV",
"strasse": "Sternplatz 7", "plz": "01067", "ort": "Dresden"},
{"name": "AOK Rheinland/Hamburg – Die Gesundheitskasse",
"kurzname": "AOK Rheinland/HH", "typ": "GKV",
"strasse": "Kaiserstraße 80", "plz": "40479", "ort": "Düsseldorf"},
{"name": "AOK Rheinland-Pfalz/Saarland – Die Gesundheitskasse",
"kurzname": "AOK RLP/SL", "typ": "GKV",
"strasse": "Virchowstraße 30", "plz": "67304", "ort": "Eisenberg"},
{"name": "AOK Sachsen-Anhalt – Die Gesundheitskasse",
"kurzname": "AOK ST", "typ": "GKV",
"strasse": "Doctor-Eisenbart-Ring 2", "plz": "39120", "ort": "Magdeburg"},
# ── GKV: Große Kassen ─────────────────────────────────────────────────────
{"name": "Barmer",
"kurzname": "Barmer", "typ": "GKV",
"strasse": "Lichtscheider Straße 89", "plz": "42285", "ort": "Wuppertal"},
{"name": "DAK-Gesundheit",
"kurzname": "DAK", "typ": "GKV",
"strasse": "Nagelsweg 27–31", "plz": "20097", "ort": "Hamburg"},
{"name": "Techniker Krankenkasse",
"kurzname": "TK", "typ": "GKV",
"strasse": "Bramfelder Straße 140", "plz": "22305", "ort": "Hamburg"},
{"name": "KKH – Kaufmännische Krankenkasse",
"kurzname": "KKH", "typ": "GKV",
"strasse": "Karl-Wiechert-Allee 61", "plz": "30625", "ort": "Hannover"},
{"name": "HEK – Hanseatische Krankenkasse",
"kurzname": "HEK", "typ": "GKV",
"strasse": "Wandsbeker Zollstraße 86–90", "plz": "22041", "ort": "Hamburg"},
{"name": "hkk – Handelskrankenkasse",
"kurzname": "hkk", "typ": "GKV",
"strasse": "Martinistraße 26", "plz": "28195", "ort": "Bremen"},
{"name": "Knappschaft",
"kurzname": "Knappschaft", "typ": "GKV",
"strasse": "Pieperstraße 14–28", "plz": "44789", "ort": "Bochum"},
# ── GKV: IKK ──────────────────────────────────────────────────────────────
{"name": "IKK classic",
"kurzname": "IKK classic", "typ": "GKV",
"strasse": "Tannenstraße 4", "plz": "01099", "ort": "Dresden"},
{"name": "IKK gesund plus",
"kurzname": "IKK gesund plus", "typ": "GKV",
"strasse": "Guerickestraße 2", "plz": "39104", "ort": "Magdeburg"},
{"name": "IKK Nord",
"kurzname": "IKK Nord", "typ": "GKV",
"strasse": "Heßstraße 35", "plz": "20097", "ort": "Hamburg"},
{"name": "IKK Südwest",
"kurzname": "IKK Südwest", "typ": "GKV",
"strasse": "Europaallee 9", "plz": "67657", "ort": "Kaiserslautern"},
# ── GKV: BKK ──────────────────────────────────────────────────────────────
{"name": "BKK VBU",
"kurzname": "BKK VBU", "typ": "GKV",
"strasse": "Koppenstraße 4–46", "plz": "10243", "ort": "Berlin"},
{"name": "BKK firmus",
"kurzname": "BKK firmus", "typ": "GKV",
"strasse": "Gewerbering 4", "plz": "27356", "ort": "Rotenburg (Wümme)"},
{"name": "BKK ProVita",
"kurzname": "BKK ProVita", "typ": "GKV",
"strasse": "Am Westpark 8", "plz": "81373", "ort": "München"},
{"name": "energie BKK",
"kurzname": "energie BKK", "typ": "GKV",
"strasse": "Lübeckertordamm 1–3", "plz": "20099", "ort": "Hamburg"},
{"name": "mhplus BKK",
"kurzname": "mhplus", "typ": "GKV",
"strasse": "Eisenbahnstraße 66", "plz": "73207", "ort": "Plochingen"},
{"name": "Novitas BKK",
"kurzname": "Novitas", "typ": "GKV",
"strasse": "Wintgensstraße 27", "plz": "47058", "ort": "Duisburg"},
{"name": "Pronova BKK",
"kurzname": "Pronova BKK", "typ": "GKV",
"strasse": "Harrlachweg 1", "plz": "68163", "ort": "Mannheim"},
{"name": "R+V Betriebskrankenkasse",
"kurzname": "R+V BKK", "typ": "GKV",
"strasse": "Raiffeisenplatz 1", "plz": "65189", "ort": "Wiesbaden"},
{"name": "SBK – Siemens-Betriebskrankenkasse",
"kurzname": "SBK", "typ": "GKV",
"strasse": "Heimeranstraße 31", "plz": "80339", "ort": "München"},
{"name": "Vivida BKK",
"kurzname": "Vivida BKK", "typ": "GKV",
"strasse": "Wilhelm-Beck-Straße 6–8", "plz": "88662", "ort": "Überlingen"},
{"name": "mkk – meine krankenkasse",
"kurzname": "mkk", "typ": "GKV",
"strasse": "Maximilianstraße 2", "plz": "83435", "ort": "Bad Reichenhall"},
{"name": "WMF BKK",
"kurzname": "WMF BKK", "typ": "GKV",
"strasse": "Eberhardstraße 14", "plz": "73312", "ort": "Geislingen an der Steige"},
# ── GKV: Weitere ──────────────────────────────────────────────────────────
{"name": "BIG direkt gesund",
"kurzname": "BIG", "typ": "GKV",
"strasse": "Westhellweg 41", "plz": "44137", "ort": "Dortmund"},
{"name": "Heimat Krankenkasse",
"kurzname": "Heimat KK", "typ": "GKV",
"strasse": "Bielefeldstraße 1", "plz": "33606", "ort": "Bielefeld"},
{"name": "Viactiv Krankenkasse",
"kurzname": "Viactiv", "typ": "GKV",
"strasse": "Huyssenallee 52–56", "plz": "45128", "ort": "Essen"},
{"name": "actimonda BKK",
"kurzname": "actimonda", "typ": "GKV",
"strasse": "Brunnenstraße 1", "plz": "45128", "ort": "Essen"},
{"name": "Audi BKK",
"kurzname": "Audi BKK", "typ": "GKV",
"strasse": "Ettingerstraße 1", "plz": "85045", "ort": "Ingolstadt"},
{"name": "BMW BKK",
"kurzname": "BMW BKK", "typ": "GKV",
"strasse": "Moosacher Straße 90", "plz": "80809", "ort": "München"},
# ── PKV: Private Krankenversicherung ──────────────────────────────────────
{"name": "Allianz Private Krankenversicherungs-AG",
"kurzname": "Allianz PKV", "typ": "PKV",
"strasse": "Königinstraße 28", "plz": "80802", "ort": "München"},
{"name": "AXA Krankenversicherung AG",
"kurzname": "AXA", "typ": "PKV",
"strasse": "Colonia-Allee 10–20", "plz": "51067", "ort": "Köln"},
{"name": "Barmenia Krankenversicherung a.G.",
"kurzname": "Barmenia", "typ": "PKV",
"strasse": "Kronprinzenallee 12–18", "plz": "42094", "ort": "Wuppertal"},
{"name": "Continentale Krankenversicherung a.G.",
"kurzname": "Continentale", "typ": "PKV",
"strasse": "Ruhrallee 92", "plz": "44139", "ort": "Dortmund"},
{"name": "Debeka Krankenversicherungsverein a.G.",
"kurzname": "Debeka", "typ": "PKV",
"strasse": "Ferdinand-Sauerbruch-Straße 18", "plz": "56058", "ort": "Koblenz"},
{"name": "DKV Deutsche Krankenversicherung AG",
"kurzname": "DKV", "typ": "PKV",
"strasse": "Aachener Straße 300", "plz": "50933", "ort": "Köln"},
{"name": "Gothaer Krankenversicherung AG",
"kurzname": "Gothaer", "typ": "PKV",
"strasse": "Gothaer Allee 1", "plz": "50969", "ort": "Köln"},
{"name": "Hallesche Krankenversicherung a.G.",
"kurzname": "Hallesche", "typ": "PKV",
"strasse": "Reinsburgstraße 10", "plz": "70178", "ort": "Stuttgart"},
{"name": "HanseMerkur Krankenversicherung AG",
"kurzname": "HanseMerkur", "typ": "PKV",
"strasse": "Siegfried-Wedells-Platz 1", "plz": "20354", "ort": "Hamburg"},
{"name": "Inter Krankenversicherung AG",
"kurzname": "Inter", "typ": "PKV",
"strasse": "Erzbergerstraße 9–15", "plz": "68165", "ort": "Mannheim"},
{"name": "LVM Krankenversicherung AG",
"kurzname": "LVM", "typ": "PKV",
"strasse": "Kolde-Ring 21", "plz": "48126", "ort": "Münster"},
{"name": "Münchener Verein Krankenversicherung a.G.",
"kurzname": "Münchener Verein", "typ": "PKV",
"strasse": "Pettenkoferstraße 19", "plz": "80336", "ort": "München"},
{"name": "NÜRNBERGER Krankenversicherung AG",
"kurzname": "NÜRNBERGER", "typ": "PKV",
"strasse": "Ostendstraße 100", "plz": "90334", "ort": "Nürnberg"},
{"name": "ottonova Krankenversicherung AG",
"kurzname": "ottonova", "typ": "PKV",
"strasse": "Maximiliansplatz 5", "plz": "80333", "ort": "München"},
{"name": "R+V Krankenversicherung AG",
"kurzname": "R+V PKV", "typ": "PKV",
"strasse": "Raiffeisenplatz 1", "plz": "65189", "ort": "Wiesbaden"},
{"name": "SDK – Süddeutsche Krankenversicherung a.G.",
"kurzname": "SDK", "typ": "PKV",
"strasse": "Raiffeisenplatz 1", "plz": "70736", "ort": "Fellbach"},
{"name": "Signal Iduna Krankenversicherung AG",
"kurzname": "Signal Iduna", "typ": "PKV",
"strasse": "Joseph-Scherer-Straße 3", "plz": "44139", "ort": "Dortmund"},
{"name": "UNIVERSA Krankenversicherung a.G.",
"kurzname": "UNIVERSA", "typ": "PKV",
"strasse": "Sulzbacher Straße 1–7", "plz": "90489", "ort": "Nürnberg"},
{"name": "Württembergische Krankenversicherung AG",
"kurzname": "WKV", "typ": "PKV",
"strasse": "Gutenbergstraße 30", "plz": "70176", "ort": "Stuttgart"},
{"name": "Bayerische Beamtenkrankenkasse AG",
"kurzname": "BBKK", "typ": "PKV",
"strasse": "Maximilianstraße 53", "plz": "81537", "ort": "München"},
{"name": "Mecklenburgische Krankenversicherung AG",
"kurzname": "Mecklenburgische", "typ": "PKV",
"strasse": "Platz der Göttinger Sieben 1", "plz": "30169", "ort": "Hannover"},
# ── Österreich: Sozialversicherung (SV) ───────────────────────────────────
# Österreichische Gesundheitskasse – Hauptstelle
{"name": "Österreichische Gesundheitskasse",
"kurzname": "ÖGK", "typ": "SV", "land": "AT",
"strasse": "Kundmanngasse 21", "plz": "1031", "ort": "Wien"},
# ÖGK Landesstellen
{"name": "ÖGK Landesstelle Wien",
"kurzname": "ÖGK Wien", "typ": "SV", "land": "AT",
"strasse": "Wienerbergstraße 15–19", "plz": "1100", "ort": "Wien"},
{"name": "ÖGK Landesstelle Niederösterreich",
"kurzname": "ÖGK NÖ", "typ": "SV", "land": "AT",
"strasse": "Kremser Landstraße 3", "plz": "3100", "ort": "St. Pölten"},
{"name": "ÖGK Landesstelle Oberösterreich",
"kurzname": "ÖGK OÖ", "typ": "SV", "land": "AT",
"strasse": "Gruberstraße 77", "plz": "4021", "ort": "Linz"},
{"name": "ÖGK Landesstelle Steiermark",
"kurzname": "ÖGK Stmk", "typ": "SV", "land": "AT",
"strasse": "Josef-Pongratz-Platz 1", "plz": "8011", "ort": "Graz"},
{"name": "ÖGK Landesstelle Kärnten",
"kurzname": "ÖGK Ktn", "typ": "SV", "land": "AT",
"strasse": "Kempfstraße 8", "plz": "9021", "ort": "Klagenfurt"},
{"name": "ÖGK Landesstelle Salzburg",
"kurzname": "ÖGK Sbg", "typ": "SV", "land": "AT",
"strasse": "Engelbert-Weiß-Weg 10", "plz": "5020", "ort": "Salzburg"},
{"name": "ÖGK Landesstelle Tirol",
"kurzname": "ÖGK Tirol", "typ": "SV", "land": "AT",
"strasse": "Klara-Pölt-Weg 2", "plz": "6020", "ort": "Innsbruck"},
{"name": "ÖGK Landesstelle Vorarlberg",
"kurzname": "ÖGK Vbg", "typ": "SV", "land": "AT",
"strasse": "Jahngasse 4", "plz": "6850", "ort": "Dornbirn"},
{"name": "ÖGK Landesstelle Burgenland",
"kurzname": "ÖGK Bgld", "typ": "SV", "land": "AT",
"strasse": "Esterházyplatz 3", "plz": "7001", "ort": "Eisenstadt"},
# Weitere AT Sozialversicherungsträger
{"name": "Sozialversicherungsanstalt der Selbständigen",
"kurzname": "SVS", "typ": "SV", "land": "AT",
"strasse": "Wiedner Hauptstraße 84–86", "plz": "1051", "ort": "Wien"},
{"name": "Versicherungsanstalt öffentlich Bediensteter, Eisenbahnen und Bergbau",
"kurzname": "BVAEB", "typ": "SV", "land": "AT",
"strasse": "Josefstädter Straße 80", "plz": "1080", "ort": "Wien"},
# ── Schweiz: Krankenversicherung nach KVG ─────────────────────────────────
{"name": "Helsana Versicherungen AG",
"kurzname": "Helsana", "typ": "KVG", "land": "CH",
"strasse": "Zürichstrasse 130", "plz": "8600", "ort": "Dübendorf"},
{"name": "CSS Versicherung AG",
"kurzname": "CSS", "typ": "KVG", "land": "CH",
"strasse": "Tribschenstraße 21", "plz": "6005", "ort": "Luzern"},
{"name": "SWICA Krankenversicherung AG",
"kurzname": "SWICA", "typ": "KVG", "land": "CH",
"strasse": "Römerstraße 38", "plz": "8401", "ort": "Winterthur"},
{"name": "Sanitas Krankenversicherung",
"kurzname": "Sanitas", "typ": "KVG", "land": "CH",
"strasse": "Jägergasse 3", "plz": "8021", "ort": "Zürich"},
{"name": "Concordia Schweizerische Kranken- und Unfallversicherung AG",
"kurzname": "Concordia", "typ": "KVG", "land": "CH",
"strasse": "Bundesplatz 15", "plz": "6003", "ort": "Luzern"},
{"name": "Visana Versicherungen AG",
"kurzname": "Visana", "typ": "KVG", "land": "CH",
"strasse": "Weltpoststrasse 19", "plz": "3015", "ort": "Bern"},
{"name": "KPT Krankenkasse AG",
"kurzname": "KPT", "typ": "KVG", "land": "CH",
"strasse": "Wankdorfallee 3", "plz": "3014", "ort": "Bern"},
{"name": "Assura-Basis SA",
"kurzname": "Assura", "typ": "KVG", "land": "CH",
"strasse": "Avenue Charles-Ferdinand-Ramuz 70", "plz": "1009", "ort": "Pully"},
{"name": "Groupe Mutuel Versicherungen GmbH",
"kurzname": "Groupe Mutuel", "typ": "KVG", "land": "CH",
"strasse": "Rue des Cèdres 5", "plz": "1919", "ort": "Martigny"},
{"name": "Atupri Gesundheitsversicherung",
"kurzname": "Atupri", "typ": "KVG", "land": "CH",
"strasse": "Zieglerstrasse 29", "plz": "3007", "ort": "Bern"},
{"name": "Sympany AG",
"kurzname": "Sympany", "typ": "KVG", "land": "CH",
"strasse": "Peter Merian-Weg 4", "plz": "4052", "ort": "Basel"},
{"name": "EGK Gesundheitskasse",
"kurzname": "EGK", "typ": "KVG", "land": "CH",
"strasse": "Brislachstrasse 2", "plz": "4242", "ort": "Laufen"},
{"name": "Aquilana Versicherungen",
"kurzname": "Aquilana", "typ": "KVG", "land": "CH",
"strasse": "Bruggerstrasse 46", "plz": "5401", "ort": "Baden"},
{"name": "Galenos Krankenversicherung AG",
"kurzname": "Galenos", "typ": "KVG", "land": "CH",
"strasse": "Militärstrasse 36", "plz": "8004", "ort": "Zürich"},
{"name": "Sana24 AG",
"kurzname": "Sana24", "typ": "KVG", "land": "CH",
"strasse": "Weltpoststrasse 19", "plz": "3015", "ort": "Bern"},
{"name": "Kolping Krankenkasse AG",
"kurzname": "Kolping", "typ": "KVG", "land": "CH",
"strasse": "Raemistrasse 5", "plz": "8024", "ort": "Zürich"},
]
def get_all(land=None):
if land:
return [k for k in KRANKENKASSEN if k.get("land", "DE") == land]
return KRANKENKASSEN
def get_by_land(land):
return [k for k in KRANKENKASSEN if k.get("land", "DE") == land]
def get_by_name(name):
name_l = name.lower()
for k in KRANKENKASSEN:
if k["name"].lower() == name_l or k["kurzname"].lower() == name_l:
return k
return None
def search(q, land=None):
q = q.lower()
results = [k for k in KRANKENKASSEN
if q in k["name"].lower()
or q in (k["kurzname"] or "").lower()
or q in k["ort"].lower()]
if land:
results = [k for k in results if k.get("land", "DE") == land]
return results
+28
View File
@@ -0,0 +1,28 @@
#!/usr/bin/env python3
"""
Pflegepilot Alpha – Startskript
Initialisiert die SQLite-Datenbank und startet den Webserver.
"""
import os, sys
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
sys.stderr.reconfigure(encoding="utf-8")
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASE_DIR)
from app import app, init_db
if __name__ == "__main__":
print("=" * 55)
print(" Pflegepilot Alpha – Lokaler Server")
print("=" * 55)
print(" Datenbank wird initialisiert…")
init_db()
print(" OK – SQLite Datenbank bereit")
print()
print(" ▶ Öffne im Browser: http://localhost:5050")
print(" Strg+C zum Beenden")
print("=" * 55)
app.run(debug=False, port=5050, host="127.0.0.1")
Binary file not shown.

After

Width:  |  Height:  |  Size: 189 KiB

File diff suppressed because it is too large. Load diff
+503
View File
@@ -0,0 +1,503 @@
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{font-family:var(--font-sans);background:var(--color-background-tertiary);color:var(--color-text-primary);font-size:14px}
.app{display:flex;height:100vh;min-height:600px}
.sidebar{width:220px;min-width:220px;background:var(--color-background-primary);border-right:0.5px solid var(--color-border-tertiary);display:flex;flex-direction:column;overflow:hidden}
.logo{padding:18px 16px 14px;border-bottom:0.5px solid var(--color-border-tertiary)}
.logo-text{font-size:16px;font-weight:500;color:var(--color-text-primary)}
.logo-sub{font-size:11px;color:var(--color-text-tertiary);margin-top:2px}
.nav{flex:1;overflow-y:auto;padding:8px 0}
.nav-section{padding:12px 16px 4px;font-size:11px;font-weight:500;color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.05em}
.nav-item{display:flex;align-items:center;gap:9px;padding:8px 16px;cursor:pointer;border-radius:0;font-size:13.5px;color:var(--color-text-secondary);transition:background .12s}
.nav-item:hover{background:var(--color-background-secondary);color:var(--color-text-primary)}
.nav-item.active{background:var(--color-background-secondary);color:var(--color-text-primary);font-weight:500;border-left:2px solid #1D9E75}
.nav-item i{font-size:16px;width:18px;flex-shrink:0}
.nav-badge{margin-left:auto;background:var(--color-background-danger);color:var(--color-text-danger);font-size:11px;padding:1px 6px;border-radius:10px}
.main{flex:1;display:flex;flex-direction:column;overflow:hidden}
.topbar{background:var(--color-background-primary);border-bottom:0.5px solid var(--color-border-tertiary);padding:0 20px;height:52px;display:flex;align-items:center;gap:12px;flex-shrink:0}
.page-title{font-size:15px;font-weight:500;flex:1}
.btn{display:inline-flex;align-items:center;gap:6px;padding:7px 14px;border:0.5px solid var(--color-border-secondary);border-radius:var(--border-radius-md);background:transparent;color:var(--color-text-primary);cursor:pointer;font-size:13px;font-family:var(--font-sans);transition:background .12s}
.btn:hover{background:var(--color-background-secondary)}
.btn-primary{background:#1D9E75;border-color:#1D9E75;color:#fff}
.btn-primary:hover{background:#0F6E56;border-color:#0F6E56;color:#fff}
.content{flex:1;overflow-y:auto;padding:20px}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.card{background:var(--color-background-primary);border:0.5px solid var(--color-border-tertiary);border-radius:var(--border-radius-lg);padding:16px 18px}
.card-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:14px}
.card-title{font-size:13px;font-weight:500;color:var(--color-text-secondary)}
.metric-val{font-size:26px;font-weight:500;margin-top:4px}
.metric-sub{font-size:12px;color:var(--color-text-tertiary);margin-top:3px}
.badge{display:inline-flex;align-items:center;padding:2px 9px;border-radius:10px;font-size:12px}
.badge-green{background:#EAF3DE;color:#3B6D11}
.badge-amber{background:#FAEEDA;color:#854F0B}
.badge-blue{background:#E6F1FB;color:#185FA5}
.badge-red{background:#FCEBEB;color:#A32D2D}
.badge-gray{background:#F1EFE8;color:#5F5E5A}
.table{width:100%;border-collapse:collapse}
.table th{text-align:left;padding:8px 12px;font-size:12px;font-weight:500;color:var(--color-text-secondary);border-bottom:0.5px solid var(--color-border-tertiary)}
.table td{padding:10px 12px;border-bottom:0.5px solid var(--color-border-tertiary);font-size:13px;vertical-align:middle}
.table tr:last-child td{border-bottom:none}
.table tr:hover td{background:var(--color-background-secondary)}
.table-link{color:var(--color-text-info);cursor:pointer;text-decoration:none}
.table-link:hover{text-decoration:underline}
.avatar{width:28px;height:28px;border-radius:50%;display:inline-flex;align-items:center;justify-content:center;font-size:11px;font-weight:500;flex-shrink:0}
.av-teal{background:#E1F5EE;color:#0F6E56}
.av-blue{background:#E6F1FB;color:#185FA5}
.av-amber{background:#FAEEDA;color:#854F0B}
.av-coral{background:#FAECE7;color:#993C1D}
.form-row{display:grid;gap:10px;margin-bottom:12px}
.form-row.cols2{grid-template-columns:1fr 1fr}
.form-row.cols3{grid-template-columns:1fr 1fr 1fr}
.form-group{display:flex;flex-direction:column;gap:4px}
label{font-size:12px;color:var(--color-text-secondary);font-weight:500}
input,select,textarea{border:0.5px solid var(--color-border-secondary);border-radius:var(--border-radius-md);padding:7px 10px;font-size:13px;font-family:var(--font-sans);background:var(--color-background-primary);color:var(--color-text-primary)}
input:focus,select:focus,textarea:focus{outline:none;border-color:#1D9E75}
.progress-bar{height:6px;background:var(--color-background-secondary);border-radius:4px;overflow:hidden;margin-top:6px}
.progress-fill{height:100%;border-radius:4px;background:#1D9E75;transition:width .4s}
.step-list{display:flex;flex-direction:column;gap:2px}
.step{display:flex;align-items:flex-start;gap:10px;padding:8px 0;border-bottom:0.5px solid var(--color-border-tertiary)}
.step:last-child{border-bottom:none}
.step-icon{width:24px;height:24px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:12px;flex-shrink:0;margin-top:1px}
.step-done{background:#EAF3DE;color:#3B6D11}
.step-active{background:#E6F1FB;color:#185FA5}
.step-pending{background:#F1EFE8;color:#888780}
.step-text{flex:1}
.step-title{font-size:13px;font-weight:500}
.step-desc{font-size:12px;color:var(--color-text-tertiary);margin-top:2px}
.section-divider{font-size:12px;font-weight:500;color:var(--color-text-tertiary);text-transform:uppercase;letter-spacing:.05em;margin:18px 0 10px;padding-bottom:6px;border-bottom:0.5px solid var(--color-border-tertiary)}
.tag{display:inline-flex;align-items:center;gap:4px;padding:3px 8px;border-radius:var(--border-radius-md);background:var(--color-background-secondary);font-size:12px;border:0.5px solid var(--color-border-tertiary)}
.leistung-row{display:flex;align-items:center;justify-content:space-between;padding:9px 0;border-bottom:0.5px solid var(--color-border-tertiary)}
.leistung-row:last-child{border-bottom:none}
.leistung-name{font-size:13px}
.leistung-val{font-size:13px;font-weight:500;color:#0F6E56}
.alert{display:flex;align-items:flex-start;gap:10px;padding:12px 14px;border-radius:var(--border-radius-md);margin-bottom:12px}
.alert-info{background:#E6F1FB;border:0.5px solid #B5D4F4}
.alert-info i{color:#185FA5}
.alert-text{font-size:13px;color:var(--color-text-primary)}
.hidden{display:none}
</style>
<h2 class="sr-only">Pflegepilot – ERP-Verwaltungsoberfläche für Pflegeleistungen und Patientendaten</h2>
<div class="app">
<div class="sidebar">
<div class="logo">
<div class="logo-text"><i class="ti ti-heartbeat" aria-hidden="true" style="color:#1D9E75;margin-right:6px"></i>Pflegepilot</div>
<div class="logo-sub">Verwaltungssystem</div>
</div>
<nav class="nav">
<div class="nav-section">Übersicht</div>
<div class="nav-item active" onclick="showPage('dashboard')"><i class="ti ti-layout-dashboard" aria-hidden="true"></i>Dashboard</div>
<div class="nav-section">Patienten</div>
<div class="nav-item" onclick="showPage('patienten')"><i class="ti ti-users" aria-hidden="true"></i>Patientenliste</div>
<div class="nav-item" onclick="showPage('neu')"><i class="ti ti-user-plus" aria-hidden="true"></i>Neuer Patient</div>
<div class="nav-section">Formulare</div>
<div class="nav-item" onclick="showPage('antrag')"><i class="ti ti-file-text" aria-hidden="true"></i>Antrag Pflegegrad</div>
<div class="nav-item" onclick="showPage('leistungen')"><i class="ti ti-checklist" aria-hidden="true"></i>Leistungsübersicht</div>
<div class="nav-item" onclick="showPage('musterbrief')"><i class="ti ti-mail" aria-hidden="true"></i>Musterbrief</div>
<div class="nav-section">Aufgaben</div>
<div class="nav-item" onclick="showPage('aufgaben')"><i class="ti ti-bell" aria-hidden="true"></i>Offene Aufgaben<span class="nav-badge">3</span></div>
</nav>
</div>
<div class="main">
<div class="topbar">
<div class="page-title" id="page-title">Dashboard</div>
<button class="btn" onclick="showPage('neu')"><i class="ti ti-plus" aria-hidden="true"></i>Neuer Patient</button>
<button class="btn btn-primary" onclick="showPage('musterbrief')"><i class="ti ti-file-export" aria-hidden="true"></i>Brief erstellen</button>
</div>
<div class="content" id="content">
</div>
</div>
</div>
<script>
const pages = {
dashboard: {
title: 'Dashboard',
render: () => `
<div class="grid-4" style="margin-bottom:16px">
<div class="card">
<div class="card-title">Aktive Patienten</div>
<div class="metric-val">12</div>
<div class="metric-sub"><span class="badge badge-green">+2 diesen Monat</span></div>
</div>
<div class="card">
<div class="card-title">Offene Anträge</div>
<div class="metric-val">4</div>
<div class="metric-sub"><span class="badge badge-amber">Bearbeitung läuft</span></div>
</div>
<div class="card">
<div class="card-title">Bescheide erwartet</div>
<div class="metric-val">3</div>
<div class="metric-sub"><span class="badge badge-blue">In Prüfung</span></div>
</div>
<div class="card">
<div class="card-title">Widersprüche</div>
<div class="metric-val">1</div>
<div class="metric-sub"><span class="badge badge-red">Fristenkontrolle</span></div>
</div>
</div>
<div class="grid-2">
<div class="card">
<div class="card-header"><span class="card-title">Aktuelle Patienten</span><button class="btn" onclick="showPage('patienten')">Alle anzeigen</button></div>
<table class="table">
<thead><tr><th>Name</th><th>Pflegegrad</th><th>Status</th></tr></thead>
<tbody>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-teal">EH</div><span class="table-link" onclick="showPage('patient_detail')">Erika Huber</span></div></td><td>Grad 3</td><td><span class="badge badge-green">Genehmigt</span></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-blue">KM</div><span class="table-link" onclick="showPage('patient_detail')">Klaus Meier</span></div></td><td>Beantragt</td><td><span class="badge badge-amber">In Prüfung</span></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-amber">IM</div><span class="table-link" onclick="showPage('patient_detail')">Inge Müller</span></div></td><td>Grad 2</td><td><span class="badge badge-blue">Widerspruch</span></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-coral">GS</div><span class="table-link" onclick="showPage('patient_detail')">Georg Schulz</span></div></td><td>Grad 5</td><td><span class="badge badge-green">Genehmigt</span></td></tr>
</tbody>
</table>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Offene Aufgaben</span><button class="btn" onclick="showPage('aufgaben')">Alle</button></div>
<div class="step-list">
<div class="step"><div class="step-icon step-active"><i class="ti ti-clock" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Gutachter-Termin: Klaus Meier</div><div class="step-desc">Termin bestätigen – fällig in 3 Tagen</div></div></div>
<div class="step"><div class="step-icon step-active"><i class="ti ti-file-alert" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Widerspruch: Inge Müller</div><div class="step-desc">Brief muss bis Freitag abgesendet werden</div></div></div>
<div class="step"><div class="step-icon step-pending"><i class="ti ti-mail" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Antrag: Hildegard Braun</div><div class="step-desc">Erstantrag noch nicht abgeschickt</div></div></div>
</div>
</div>
</div>
`
},
patienten: {
title: 'Patientenliste',
render: () => `
<div class="card" style="margin-bottom:14px">
<div style="display:flex;gap:10px">
<input type="text" placeholder="Patient suchen..." style="flex:1" />
<select><option>Alle Pflegegrade</option><option>Grad 1</option><option>Grad 2</option><option>Grad 3</option><option>Grad 4</option><option>Grad 5</option></select>
<select><option>Alle Status</option><option>Genehmigt</option><option>In Prüfung</option><option>Abgelehnt</option><option>Widerspruch</option></select>
</div>
</div>
<div class="card">
<table class="table">
<thead><tr><th>Name</th><th>Geburtsdatum</th><th>Krankenkasse</th><th>Pflegegrad</th><th>Antragsdatum</th><th>Status</th><th>Aktion</th></tr></thead>
<tbody>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-teal">EH</div><span class="table-link" onclick="showPage('patient_detail')">Erika Huber</span></div></td><td>12.03.1942</td><td>AOK Bayern</td><td><span class="tag">Grad 3</span></td><td>15.01.2025</td><td><span class="badge badge-green">Genehmigt</span></td><td><button class="btn" onclick="showPage('patient_detail')"><i class="ti ti-eye"></i></button></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-blue">KM</div><span class="table-link" onclick="showPage('patient_detail')">Klaus Meier</span></div></td><td>07.11.1938</td><td>TK</td><td><span class="tag">Beantragt</span></td><td>02.04.2025</td><td><span class="badge badge-amber">In Prüfung</span></td><td><button class="btn" onclick="showPage('patient_detail')"><i class="ti ti-eye"></i></button></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-amber">IM</div><span class="table-link" onclick="showPage('patient_detail')">Inge Müller</span></div></td><td>23.06.1950</td><td>Barmer</td><td><span class="tag">Grad 2</span></td><td>10.11.2024</td><td><span class="badge badge-blue">Widerspruch</span></td><td><button class="btn" onclick="showPage('patient_detail')"><i class="ti ti-eye"></i></button></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-coral">GS</div><span class="table-link" onclick="showPage('patient_detail')">Georg Schulz</span></div></td><td>14.08.1935</td><td>DAK</td><td><span class="tag">Grad 5</span></td><td>05.03.2024</td><td><span class="badge badge-green">Genehmigt</span></td><td><button class="btn" onclick="showPage('patient_detail')"><i class="ti ti-eye"></i></button></td></tr>
<tr><td><div style="display:flex;align-items:center;gap:8px"><div class="avatar av-teal">HB</div><span class="table-link" onclick="showPage('patient_detail')">Hildegard Braun</span></div></td><td>30.09.1947</td><td>AOK Bayern</td><td><span class="tag badge-gray">Offen</span></td><td>–</td><td><span class="badge badge-gray">Neu</span></td><td><button class="btn" onclick="showPage('antrag')"><i class="ti ti-file-plus"></i></button></td></tr>
</tbody>
</table>
</div>
`
},
patient_detail: {
title: 'Patient: Erika Huber',
render: () => `
<div class="alert alert-info"><i class="ti ti-shield-lock" style="font-size:18px;margin-top:1px" aria-hidden="true"></i><div class="alert-text"><strong>Datenschutz:</strong> Diese Ansicht enthält personenbezogene Daten. Bitte sicherstellen, dass nur befugtes Personal Zugang hat.</div></div>
<div class="grid-2" style="margin-bottom:14px">
<div class="card">
<div class="card-header"><span class="card-title">Stammdaten</span><button class="btn"><i class="ti ti-edit"></i>Bearbeiten</button></div>
<div class="form-row cols2">
<div class="form-group"><label>Vorname</label><input value="Erika" /></div>
<div class="form-group"><label>Nachname</label><input value="Huber" /></div>
</div>
<div class="form-row cols2">
<div class="form-group"><label>Geburtsdatum</label><input value="12.03.1942" /></div>
<div class="form-group"><label>Versichertennummer</label><input value="A123456789" /></div>
</div>
<div class="form-row">
<div class="form-group"><label>Anschrift</label><input value="Musterstraße 12, 82256 Fürstenfeldbruck" /></div>
</div>
<div class="form-row cols2">
<div class="form-group"><label>Telefon</label><input value="08141 / 55432" /></div>
<div class="form-group"><label>Krankenkasse</label><input value="AOK Bayern" /></div>
</div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Pflegestatus</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegegrad</span><span class="badge badge-green" style="font-size:14px;padding:4px 12px">Grad 3</span></div>
<div class="leistung-row"><span class="leistung-name">Antragsdatum</span><span>15.01.2025</span></div>
<div class="leistung-row"><span class="leistung-name">Bescheid erhalten</span><span>22.02.2025</span></div>
<div class="leistung-row"><span class="leistung-name">Gutachter-Besuch</span><span>08.02.2025</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegeperson</span><span>Tochter (privat)</span></div>
<div style="margin-top:14px">
<div style="font-size:12px;color:var(--color-text-secondary);margin-bottom:4px">Fortschritt: Pflegegrad-Prozess</div>
<div class="progress-bar"><div class="progress-fill" style="width:100%"></div></div>
<div style="font-size:11px;color:var(--color-text-tertiary);margin-top:4px">Abgeschlossen ✓</div>
</div>
</div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Aktive Leistungen</span></div>
<div class="grid-3">
<div style="padding:10px;background:var(--color-background-secondary);border-radius:var(--border-radius-md)">
<div style="font-size:12px;color:var(--color-text-tertiary)">Pflegegeld (mtl.)</div>
<div style="font-size:18px;font-weight:500;color:#0F6E56;margin-top:2px">773 €</div>
</div>
<div style="padding:10px;background:var(--color-background-secondary);border-radius:var(--border-radius-md)">
<div style="font-size:12px;color:var(--color-text-tertiary)">Entlastungsbetrag</div>
<div style="font-size:18px;font-weight:500;color:#0F6E56;margin-top:2px">131 €</div>
</div>
<div style="padding:10px;background:var(--color-background-secondary);border-radius:var(--border-radius-md)">
<div style="font-size:12px;color:var(--color-text-tertiary)">Hilfsmittel (mtl.)</div>
<div style="font-size:18px;font-weight:500;color:#0F6E56;margin-top:2px">42 €</div>
</div>
</div>
</div>
`
},
neu: {
title: 'Neuer Patient',
render: () => `
<div class="card">
<div class="section-divider">Persönliche Daten</div>
<div class="form-row cols3">
<div class="form-group"><label>Vorname *</label><input placeholder="Vorname" /></div>
<div class="form-group"><label>Nachname *</label><input placeholder="Nachname" /></div>
<div class="form-group"><label>Geburtsdatum *</label><input type="date" /></div>
</div>
<div class="form-row cols2">
<div class="form-group"><label>Straße & Hausnummer</label><input placeholder="Musterstraße 1" /></div>
<div class="form-group"><label>PLZ / Ort</label><input placeholder="82256 Fürstenfeldbruck" /></div>
</div>
<div class="form-row cols2">
<div class="form-group"><label>Telefon</label><input placeholder="08141 / ..." /></div>
<div class="form-group"><label>E-Mail (optional)</label><input placeholder="email@beispiel.de" /></div>
</div>
<div class="section-divider">Krankenversicherung</div>
<div class="form-row cols3">
<div class="form-group"><label>Krankenkasse *</label>
<select>
<option>– bitte wählen –</option>
<option>AOK Bayern</option><option>TK (Techniker Krankenkasse)</option>
<option>Barmer</option><option>DAK-Gesundheit</option>
<option>IKK classic</option><option>hkk</option>
<option>BKK</option><option>Privat versichert (PKV)</option>
</select>
</div>
<div class="form-group"><label>Versichertennummer *</label><input placeholder="A000000000" /></div>
<div class="form-group"><label>Versicherungsart</label>
<select><option>Gesetzlich (GKV)</option><option>Privat (PKV)</option></select>
</div>
</div>
<div class="section-divider">Pflegesituation</div>
<div class="form-row cols3">
<div class="form-group"><label>Aktueller Pflegegrad</label>
<select><option>Noch kein Antrag</option><option>Grad 1</option><option>Grad 2</option><option>Grad 3</option><option>Grad 4</option><option>Grad 5</option><option>Antrag laufend</option></select>
</div>
<div class="form-group"><label>Pflegeperson</label>
<select><option>Angehörige (privat)</option><option>Pflegedienst (ambulant)</option><option>Pflegeheim (stationär)</option><option>Kombination</option></select>
</div>
<div class="form-group"><label>Antragsdatum (falls vorhanden)</label><input type="date" /></div>
</div>
<div class="form-row">
<div class="form-group"><label>Notizen / Besonderheiten</label><textarea rows="3" placeholder="z. B. Demenzerkrankung, Mobilitätseinschränkungen ..."></textarea></div>
</div>
<div style="display:flex;gap:10px;margin-top:6px;justify-content:flex-end">
<button class="btn" onclick="showPage('patienten')">Abbrechen</button>
<button class="btn btn-primary" onclick="showPage('patienten')"><i class="ti ti-check" aria-hidden="true"></i>Patient anlegen</button>
</div>
</div>
`
},
antrag: {
title: 'Antrag Pflegegrad',
render: () => `
<div class="grid-2">
<div>
<div class="card" style="margin-bottom:14px">
<div class="card-header"><span class="card-title">Prozess: Pflegegrad beantragen</span></div>
<div class="step-list">
<div class="step"><div class="step-icon step-done"><i class="ti ti-check" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Schritt A – Antrag stellen</div><div class="step-desc">Brief / Anruf bei der Krankenkasse – Datum festhalten!</div></div></div>
<div class="step"><div class="step-icon step-active"><i class="ti ti-user-check" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Schritt B – Gutachter-Besuch</div><div class="step-desc">Prüfer kommt nach Hause. Pflegetagebuch vorbereiten.</div></div></div>
<div class="step"><div class="step-icon step-pending"><i class="ti ti-mail" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Schritt C – Bescheid abwarten</div><div class="step-desc">Krankenkasse hat 25 Arbeitstage Zeit. (~5 Wochen)</div></div></div>
<div class="step"><div class="step-icon step-pending"><i class="ti ti-file-alert" aria-hidden="true"></i></div><div class="step-text"><div class="step-title">Schritt D – Ggf. Widerspruch</div><div class="step-desc">Bei Ablehnung: Widerspruch innerhalb 1 Monat!</div></div></div>
</div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Patient zuordnen</span></div>
<div class="form-group" style="margin-bottom:10px"><label>Patient auswählen</label>
<select><option>– Patient wählen –</option><option>Hildegard Braun (neu)</option><option>Klaus Meier</option></select>
</div>
<div class="form-group" style="margin-bottom:10px"><label>Antragsdatum</label><input type="date" /></div>
<div class="form-group" style="margin-bottom:14px"><label>Krankenkasse</label>
<select><option>AOK Bayern</option><option>TK</option><option>Barmer</option><option>DAK</option></select>
</div>
<button class="btn btn-primary" style="width:100%" onclick="showPage('musterbrief')"><i class="ti ti-file-export" aria-hidden="true"></i>Musterbrief für diesen Patienten generieren</button>
</div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Pflegetagebuch-Checkliste</span></div>
<div class="alert alert-info"><i class="ti ti-info-circle" style="font-size:18px" aria-hidden="true"></i><div class="alert-text">Diese Punkte sollten <strong>vor dem Gutachter-Besuch</strong> täglich dokumentiert werden.</div></div>
<div style="display:flex;flex-direction:column;gap:8px">
${[
['Körperpflege','Waschen, Duschen, Haare kämmen'],
['Anziehen','Hilfe beim Ankleiden'],
['Ernährung','Hilfe beim Essen / Trinken'],
['Mobilität','Treppen, Gehen, Aufstehen'],
['Orientierung','Vergessen, Verwirrtheit, Tag/Nacht'],
['Medikamente','Selbstständige Einnahme möglich?'],
['Soziale Aktivitäten','Kontakte, Hobbys, Selbstständigkeit'],
].map(([t,d]) => `<div style="display:flex;align-items:flex-start;gap:8px"><input type="checkbox" style="margin-top:3px;width:auto;flex-shrink:0"><div><div style="font-size:13px;font-weight:500">${t}</div><div style="font-size:12px;color:var(--color-text-tertiary)">${d}</div></div></div>`).join('')}
</div>
</div>
</div>
`
},
leistungen: {
title: 'Leistungsübersicht',
render: () => `
<div class="grid-2">
<div class="card">
<div class="card-header"><span class="card-title">Pflegekasse – Geldleistungen (monatlich)</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegegeld (Grad 1)</span><span class="leistung-val">0 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegegeld (Grad 2)</span><span class="leistung-val">332 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegegeld (Grad 3)</span><span class="leistung-val">573 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegegeld (Grad 4)</span><span class="leistung-val">765 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegegeld (Grad 5)</span><span class="leistung-val">947 €</span></div>
<div class="leistung-row" style="background:var(--color-background-secondary);border-radius:var(--border-radius-md);padding:9px 8px;border:none;margin-top:8px"><span class="leistung-name" style="font-weight:500">Entlastungsbetrag (alle Grade)</span><span class="leistung-val">131 €</span></div>
<div class="leistung-row"><span class="leistung-name">Hilfsmittel (Verbrauch)</span><span class="leistung-val">42 €</span></div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Pflegekasse – Sachleistungen & Einmalig</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegesachleistung Grad 2</span><span class="leistung-val">761 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegesachleistung Grad 3</span><span class="leistung-val">1.432 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegesachleistung Grad 4</span><span class="leistung-val">1.778 €</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegesachleistung Grad 5</span><span class="leistung-val">2.200 €</span></div>
<div class="leistung-row"><span class="leistung-name">Wohnumfeldverbesserung (max.)</span><span class="leistung-val">4.180 €</span></div>
<div class="leistung-row"><span class="leistung-name">Gemeinsamer Jahresbetrag (ab 07/2025)</span><span class="leistung-val">3.539 €</span></div>
<div class="leistung-row"><span class="leistung-name">Wohngruppen-Zuschlag</span><span class="leistung-val">214 €</span></div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Krankenkasse – Hilfsmittel (Auswahl)</span></div>
<div class="leistung-row"><span class="leistung-name">Rollstuhl / Rollator</span><span class="badge badge-green">Kassenleistung</span></div>
<div class="leistung-row"><span class="leistung-name">Hörgerät</span><span class="badge badge-green">Zuschuss</span></div>
<div class="leistung-row"><span class="leistung-name">Kompressionsstrümpfe</span><span class="badge badge-green">Kassenleistung</span></div>
<div class="leistung-row"><span class="leistung-name">Pflegebett (technisch)</span><span class="badge badge-blue">Leihe / Zuschuss</span></div>
<div class="leistung-row"><span class="leistung-name">DiPA (Pflege-Apps)</span><span class="leistung-val">bis 50 €</span></div>
<div class="leistung-row"><span class="leistung-name">Hausnotruf</span><span class="badge badge-blue">Pflegekasse</span></div>
</div>
<div class="card">
<div class="card-header"><span class="card-title">Therapie (Krankenkasse, auf Rezept)</span></div>
<div class="leistung-row"><span class="leistung-name">Physiotherapie</span><span class="badge badge-green">Kassenleistung</span></div>
<div class="leistung-row"><span class="leistung-name">Ergotherapie</span><span class="badge badge-green">Kassenleistung</span></div>
<div class="leistung-row"><span class="leistung-name">Logopädie</span><span class="badge badge-green">Kassenleistung</span></div>
<div class="leistung-row"><span class="leistung-name">Podologie (bes. Diabetes)</span><span class="badge badge-green">Kassenleistung</span></div>
<div class="leistung-row"><span class="leistung-name">Häusliche Krankenpflege</span><span class="badge badge-blue">Mit Rezept</span></div>
<div class="leistung-row"><span class="leistung-name">DiGA (Digitale Therapie-Apps)</span><span class="badge badge-blue">Auf Rezept</span></div>
</div>
</div>
`
},
musterbrief: {
title: 'Musterbrief erstellen',
render: () => `
<div class="grid-2">
<div class="card">
<div class="card-header"><span class="card-title">Briefdaten eingeben</span></div>
<div class="section-divider">Absender (Antragsteller)</div>
<div class="form-row cols2">
<div class="form-group"><label>Vorname</label><input id="v_vor" placeholder="Maria" /></div>
<div class="form-group"><label>Nachname</label><input id="v_nach" placeholder="Mustermann" /></div>
</div>
<div class="form-row"><div class="form-group"><label>Straße & Hausnummer</label><input id="v_str" placeholder="Musterstraße 1" /></div></div>
<div class="form-row cols2">
<div class="form-group"><label>PLZ</label><input id="v_plz" placeholder="82256" /></div>
<div class="form-group"><label>Ort</label><input id="v_ort" placeholder="Fürstenfeldbruck" /></div>
</div>
<div class="form-row"><div class="form-group"><label>Telefon</label><input id="v_tel" placeholder="08141 / 12345" /></div></div>
<div class="section-divider">Empfänger (Krankenkasse)</div>
<div class="form-row"><div class="form-group"><label>Krankenkasse</label>
<select id="kk"><option>AOK Bayern</option><option>TK – Techniker Krankenkasse</option><option>Barmer</option><option>DAK-Gesundheit</option><option>IKK classic</option></select>
</div></div>
<div class="section-divider">Versicherte Person</div>
<div class="form-row cols2">
<div class="form-group"><label>Vorname</label><input id="p_vor" placeholder="Vorname" /></div>
<div class="form-group"><label>Nachname</label><input id="p_nach" placeholder="Nachname" /></div>
</div>
<div class="form-row cols2">
<div class="form-group"><label>Geburtsdatum</label><input id="p_geb" type="date" /></div>
<div class="form-group"><label>Versichertennummer</label><input id="p_vnr" placeholder="A000000000" /></div>
</div>
<button class="btn btn-primary" style="width:100%;margin-top:8px" onclick="generateLetter()"><i class="ti ti-refresh" aria-hidden="true"></i>Brief aktualisieren</button>
</div>
<div class="card" id="letter-preview" style="font-family:var(--font-sans);line-height:1.7;font-size:13.5px">
<div style="color:var(--color-text-secondary);font-size:12px;margin-bottom:14px;display:flex;align-items:center;gap:6px"><i class="ti ti-eye" aria-hidden="true"></i>Vorschau – wird live aktualisiert</div>
<div id="letter-body" style="white-space:pre-wrap;color:var(--color-text-primary)">← Formular links ausfüllen, um den Brief zu generieren.</div>
<div style="margin-top:16px;display:flex;gap:8px">
<button class="btn" onclick="copyLetter()"><i class="ti ti-copy" aria-hidden="true"></i>Text kopieren</button>
</div>
</div>
</div>
`
},
aufgaben: {
title: 'Offene Aufgaben',
render: () => `
<div class="card">
<table class="table">
<thead><tr><th>Aufgabe</th><th>Patient</th><th>Fällig</th><th>Priorität</th><th>Status</th></tr></thead>
<tbody>
<tr><td>Gutachter-Termin bestätigen</td><td><span class="table-link" onclick="showPage('patient_detail')">Klaus Meier</span></td><td>13.05.2025</td><td><span class="badge badge-red">Hoch</span></td><td><button class="btn" style="font-size:12px;padding:4px 10px">Erledigt</button></td></tr>
<tr><td>Widerspruch-Brief absenden</td><td><span class="table-link" onclick="showPage('patient_detail')">Inge Müller</span></td><td>16.05.2025</td><td><span class="badge badge-red">Hoch</span></td><td><button class="btn" style="font-size:12px;padding:4px 10px">Erledigt</button></td></tr>
<tr><td>Erstantrag ausfüllen & absenden</td><td><span class="table-link" onclick="showPage('patient_detail')">Hildegard Braun</span></td><td>20.05.2025</td><td><span class="badge badge-amber">Mittel</span></td><td><button class="btn" style="font-size:12px;padding:4px 10px">Erledigt</button></td></tr>
<tr><td>Entlastungsbetrag prüfen (Mai)</td><td><span class="table-link" onclick="showPage('patient_detail')">Erika Huber</span></td><td>31.05.2025</td><td><span class="badge badge-gray">Normal</span></td><td><button class="btn" style="font-size:12px;padding:4px 10px">Erledigt</button></td></tr>
</tbody>
</table>
</div>
`
}
};
function showPage(id) {
const page = pages[id];
if (!page) return;
document.getElementById('page-title').textContent = page.title;
document.getElementById('content').innerHTML = page.render();
document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.nav-item').forEach(el => {
if(el.getAttribute('onclick') && el.getAttribute('onclick').includes(id)) el.classList.add('active');
});
if(id === 'musterbrief') setTimeout(generateLetter, 100);
}
function generateLetter() {
const g = id => (document.getElementById(id) || {}).value || '';
const date = new Date().toLocaleDateString('de-DE');
const brief = `${g('v_vor')||'[Vorname]'} ${g('v_nach')||'[Nachname]'}
${g('v_str')||'[Straße Nr.]'}
${g('v_plz')||'[PLZ]'} ${g('v_ort')||'[Ort]'}
Tel: ${g('v_tel')||'[Telefon]'}
Datum: ${date}
An die:
${document.getElementById('kk')?.value||'[Krankenkasse]'}
Betreff: Antrag auf Leistungen der Pflegekasse
Sehr geehrte Damen und Herren,
hiermit stelle ich einen Antrag auf Leistungen der Pflegeversicherung für:
Name: ${g('p_vor')||'[Vorname]'} ${g('p_nach')||'[Nachname]'}
Geburtsdatum: ${g('p_geb') ? new Date(g('p_geb')).toLocaleDateString('de-DE') : '[Geburtsdatum]'}
Versichertennummer: ${g('p_vnr')||'[Versichertennummer]'}
Bitte bestätigen Sie mir kurz, dass dieser Brief bei Ihnen angekommen ist. Senden Sie mir danach bitte alle weiteren Formulare zu.
Mit freundlichen Grüßen,
_______________________
${g('v_vor')||'[Vorname]'} ${g('v_nach')||'[Nachname]'}`;
const el = document.getElementById('letter-body');
if(el) el.textContent = brief;
}
function copyLetter() {
const text = document.getElementById('letter-body')?.textContent;
if(text) navigator.clipboard.writeText(text).catch(()=>{});
}
showPage('dashboard');
</script>
+28
View File
@@ -0,0 +1,28 @@
Wir müssen umbauen,
aktuell läuft das System als Zentraler Dienst für mehrere Patienten.
Nach Rücksprache habe ich erfahren, das Projekt soll wie folgt erstellt sein.
Webseite für Informationen über die App -> Login in die App -> Innerhalb der App kann man nur seine eigenen Patienten sehen im Regelfall 1-3 Patienten als das nahe Familien Umfeld das man verwaltet. Keine Möglichkeit andere Patienten irgendwie zu finden oder zu lokalisieren.
Für das Anlegen eines Patienten, um es den Angehörigen so leicht wie möglich zu gestalten, wäre ein Interview als reine Web-Application ohne KI Anbietung von Vorteil.
Für mich als Administrator fehlt eine Dashboard/Admin-Seite um Konten zu sperren oder zu löschen, alternativ um auf Anwaltliche Anordnung Archivierte Inhalte zu exportieren, beachte hierbei die DSGVO das muss Rechtlich komplett abgesichert sein für mich als Betreiber und für die alle Verwalter sowie Patienten.
Bezüglich des Refactoring - Stelle mir fragen über die Achritektur, Strukuturen, Serverstruktur und den Aufbau.