Compare commits

...
4 Commits
Author SHA1 Message Date
florian.wilde 5e5778b1e6 Merge #55: Anleitung zum Jahresabschluss und zu Genossenschaftsanteilen 2026-09-02 20:55:20 +00:00
Florian Wilde cba2e49211 Anleitung: Jahresabschluss und was aussieht wie ein Konto
Zwei Fragen aus der Praxis, die die Anleitung nicht beantwortete.

## Der Jahresabschluss

Sie beschrieb, was in jedem Bericht steht, aber nicht die Reihenfolge und
nicht, was man vorher besorgen muss. Der neue Abschnitt beginnt deshalb
sechs Wochen vor dem Stichtag: Rueckkaufswerte und Bescheinigungen
brauchen Wochen, und wer erst am Stichtag daran denkt, geraet in Verzug.
Danach die Staende mit Quellenangabe, dann die Berichte in der
Reihenfolge, in der sie aufeinander aufbauen.

## Genossenschaftsanteile

Das Gericht fragt einen "Kontoauszug" an, den es nicht gibt: Ein
Geschaeftsguthaben ist kein Zahlungskonto, sondern eine Forderung gegen
die Genossenschaft. Es laufen keine Buchungen darueber, und ausgezahlt
wird erst nach Kuendigung der Mitgliedschaft.

Der Fall fuehrt zu einem stillen Fehler: Wer die Anteile als Konto
anlegt, kann die Bescheinigung nicht am Wert hinterlegen - genau das
Blatt, das das Gericht sehen will. Ein Saldostand traegt eine
Quellenangabe, aber kein Dokument; ein Wertstand am Vermoegensposten
schon. Deshalb steht im Text nicht nur, was zu tun ist, sondern warum -
sonst legt der naechste Leser es wieder als Konto an.

Dazu der Hinweis, dass "der Wert bleibt doch gleich" nicht traegt: Wird
eine Dividende dem Geschaeftsguthaben gutgeschrieben statt ausgezahlt,
waechst es. Genau deshalb fragt man jaehrlich nach, statt den
Vorjahreswert fortzuschreiben.

Eine Uebersicht behandelt die verwandten Faelle mit - Bausparvertrag,
Depot, Verbindlichkeit. Das Depot ist die Ausnahme: Dort laufen Umsaetze,
es gibt einen Auszug, es ist ein Konto. Versicherungen gehoeren an den
Vertrag, nicht ins Vermoegen.

Zehn Pruefungen in tests/anleitung.test.ts, gegen vier Mutationen
geprueft: als Konto geraten, Dividendenhinweis entfernt, Vorlauf
entfernt, Abschnitt entfernt - jede wird rot.

Refs #55
2026-09-02 22:52:41 +02:00
florian.wilde c5db3baac0 Merge: Version 1.12.0 2026-09-01 14:40:22 +00:00
Florian Wilde 274d7666ea chore: Version 1.12.0 2026-09-01 16:39:59 +02:00
9 changed files with 302 additions and 9 deletions
+82 -1
View File
@@ -26,6 +26,86 @@ Wiederherstellung*.
_Noch nichts._
## [1.12.0] – 2026-09-01
Diese Fassung geht aus einer Fehlersuche im laufenden Betrieb hervor. Ein
Schreiben ließ sich nicht in der Akte ablegen — und hinter derselben
Meldung lagen nacheinander drei verschiedene Ursachen. Beim Nachsehen kam
ein vierter Punkt dazu, der schwerer wiegt als alle anderen zusammen.
### Nach dem Update: einmal die Sicherung prüfen
```bash
docker compose up -d
docker compose exec sicherung /bin/sh /sicherung.sh
```
Erwartet werden drei Zeilen: `Datenbank gesichert`, `Dokumente gesichert`
und `Selbstpruefung bestanden - Datenbank und Dokumente.`
### Behoben
- **Deine Dokumente waren in keiner Sicherung.** Der Sicherungsdienst
machte täglich ein `pg_dump` und sonst nichts. Nach einem Plattenschaden
wäre die Akte vollständig wiederhergestellt worden — mit allen
Einträgen, Verweisen und Prüfsummen, aber ohne eine einzige Datei
dahinter. Die Prüfsumme in der Akte hätte dann ein Dokument belegt, das
es nicht mehr gibt.
Je Lauf entstehen jetzt zwei verschlüsselte Dateien mit demselben
Zeitstempel — der Datenbankstand und ein Archiv der Dokumente. Beide mit
Prüfsumme, beide in der Aufbewahrung, beide in der Selbstprüfung.
Schlägt der Dokumententeil fehl, bricht der Lauf ab und räumt den
angefangenen Datenbankstand weg: Eine Sicherung, die nur die halbe
Wahrheit enthält, aber vollständig aussieht, ist schlimmer als gar
keine.
- **Der mitgelieferte Objektspeicher konnte keine Dokumente aufnehmen.**
Die Anwendung verlangte bei jeder Ablage serverseitige Verschlüsselung,
das mitgelieferte MinIO kann sie ohne Zusatzdienst nicht. Wer der
Installationsanleitung folgte, landete zwangsläufig dort. Sie ist jetzt
abschaltbar und standardmäßig aus — gebraucht wird sie nicht, weil die
Anwendung seit 1.11.0 selbst verschlüsselt.
- **„Das Schreiben konnte nicht abgelegt werden" sagte nichts.** Jetzt
steht dort, was los ist: fehlender Ablagebereich mit Verweis auf den
Installationsschritt, abgelehnte Zugangsdaten, nicht erreichbarer
Speicher. Und in jedem Fall, ob deine Eingaben erhalten bleiben.
- **Zwei Einstellungen erreichten die Anwendung nie.**
`ERSTEINRICHTUNG_GEHEIMNIS` und `VERTRAUE_PROXY` standen zwar in der
Anleitung, wurden aber nicht an den Behälter durchgereicht. Bei
`VERTRAUE_PROXY` fiel das nicht auf: Die Anmeldesperre zählte still eine
Dimension weniger.
- **Die Beispielkonfiguration zeigte auf einen fremden Anbieter.**
`S3_ENDPOINT` war mit einer externen Adresse vorbelegt und hebelte damit
den richtigen Standard aus. Die Zeile ist jetzt auskommentiert.
### Neu
- **Die Anwendung prüft ihre Dateiablage selbst.** Sie schreibt eine
winzige Datei, liest sie zurück und räumt sie weg — und beantwortet
damit auf einmal, ob der Speicher erreichbar ist, der Ablagebereich
existiert und geschrieben werden darf. Das Ergebnis steht unter
`/api/gesundheit` und im Log. Bisher fiel eine kaputte Konfiguration
erst auf, wenn jemand ein Dokument ablegen wollte.
- **Ein neuer Abschnitt in der Anleitung: „Wo deine Daten liegen".**
Die drei Orte, der Pfad auf der Platte, welche Schlüssel unverzichtbar
sind — und wie man prüft, ob zu jedem Akteneintrag auch eine Datei
gehört.
### Geändert
- **Ausschlussfristen warnen nur noch, wenn sie näherrücken.** Auf dem
Dashboard standen dauerhaft drei rote Kästen mit Warndreieck — für
Aufwandspauschalen, die 2027, 2028 und 2029 ablaufen. Eine Warnung, die
monatelang dasteht und nichts von einem will, stumpft ab; man übersieht
die vierte, die etwas will. Ab drei Monaten vor Ablauf meldet sich eine
Frist wieder, Versäumtes immer. In der Fristenliste stehen sie
unverändert weiter.
## [1.11.0] – 2026-08-24
Diese Fassung geht aus einer Sicherheitsprüfung hervor. Sie ändert nichts
@@ -1265,7 +1345,8 @@ Was davon wann angegangen wird, steht in [`docs/ROADMAP.md`](docs/ROADMAP.md).
---
[Unveröffentlicht]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.11.0...HEAD
[Unveröffentlicht]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.12.0...HEAD
[1.12.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.11.0...v1.12.0
[1.11.0]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.2...v1.11.0
[1.10.2]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.1...v1.10.2
[1.10.1]: https://git.wilde-server.de/florian.wilde/betreuungs-cockpit/compare/v1.10.0...v1.10.1
+130
View File
@@ -332,6 +332,136 @@ Anwendung jederzeit verlassen. Verlangt eine erneute Anmeldung.
---
## Der Jahresabschluss, Schritt für Schritt
Einmal im Jahr will das Gericht zwei Dinge: einen **Bericht über die
Person** und eine **Rechnung über das Vermögen**. Beides bezieht sich auf
dein Betreuungsjahr, nicht auf das Kalenderjahr.
Die Reihenfolge unten ist keine Formalie. Der erste Schritt liegt sechs
Wochen vor dem Stichtag, weil manche Auskünfte so lange brauchen — wer erst
am Stichtag daran denkt, wartet und gerät in Verzug.
### Sechs Wochen vorher: anfordern, was du nicht selbst hast
Manche Werte kannst du nicht nachsehen, sondern nur erfragen:
- **Rückkaufswerte** aller Lebens-, Renten- und Sterbegeldversicherungen
- **Bescheinigungen** über Geschäftsguthaben, Bausparguthaben, Depotwerte
- **Jahresabrechnungen**, die noch ausstehen
Die Anwendung legt dir dafür rechtzeitig eine Frist an. Schreib die Briefe
gleich, wenn sie fällig wird — unter **Vorgänge** oder direkt am Vertrag.
Jedes Schreiben bekommt eine **Wiedervorlage**: Kommt in drei Wochen keine
Antwort, fasst du nach. Ohne Wiedervorlage geht eine unbeantwortete Anfrage
unter, und das merkst du am Stichtag.
### Am Stichtag: Stände eintragen
**Konten** — *Vermögen & Kasse → Konten → Konto öffnen → „Neuen Kontostand
festhalten"*. Für jedes Konto einzeln: Stichtag, Betrag, **Quelle**.
Die Quelle ist kein Beiwerk. Sie steht später neben der Zahl im Bericht,
und ein Betrag ohne Herkunft ist gegenüber dem Gericht wenig wert. Schreib
hinein, woher du die Zahl hast: „Kontoauszug 11/2026", „Online-Banking,
abgerufen am 07.11.".
Vergiss die kleinen nicht: **Verwahrgeld im Heim** und die **Barkasse**
sind Konten wie jedes andere.
**Vermögen** — *Vermögen & Kasse → Vermögen*. Immobilie, Fahrzeug,
Wertgegenstände, Forderungen, Schulden. Jeder Posten bekommt einen
**Wertstand** zum Stichtag, ebenfalls mit Quelle — und hier kannst du das
**Nachweisdokument gleich anhängen**.
> **Du musst nicht auf den Tag genau treffen.** Die Anwendung nimmt je
> Konto den letzten Stand am oder vor dem Stichtag. Weicht er ab, schreibt
> sie es in den Bericht: „Der Stand von ‚Sparbuch' stammt vom 31.10.2026,
> nicht vom Stichtag." Fehlt ein Stand ganz, steht das Konto ohne Betrag
> drin — mit Hinweis, nicht mit einer erfundenen Null.
### Dann die Berichte
1. **Vermögensübersicht oder Rechnungslegung** — *Vermögen & Kasse →
Berichte*, Betreuungsjahr wählen.
2. **Belegmappe** — *Berichte → Belegmappe*, derselbe Zeitraum. Das ist die
Anlage.
3. **Jahresbericht** — *Berichte → Jahresbericht*. Entwurf überarbeiten,
dann ausgeben.
Vorher lohnt ein Blick ins **Kassenbuch**: Buchungen ohne Beleg und ohne
Begründung fallen dem Gericht auf. Entweder den Beleg nachreichen oder in
einem Satz begründen, warum es keinen gibt.
---
## Was aussieht wie ein Konto, aber keines ist
**Genossenschaftsanteile** sind der Leitfall. Im Alltag redet man von einem
Konto, das Gericht fragt einen „Kontoauszug" an — nur gibt es keinen. Am
Automaten schon gar nicht.
Der Grund: Ein Geschäftsguthaben bei einer Genossenschaft ist **kein
Zahlungskonto**, sondern eine **Forderung gegen die Genossenschaft**. Es
laufen keine Buchungen darüber, es gibt keine Umsätze, und ausgezahlt wird
erst nach Kündigung der Mitgliedschaft — mit Frist.
### Deshalb: als Vermögensposten anlegen, nicht als Konto
*Vermögen & Kasse → Vermögen → Posten anlegen*, Art **Forderung**.
Das ist kein Formalismus, sondern hat zwei handfeste Gründe:
1. **Nur am Vermögensposten kannst du den Nachweis anhängen.** Ein
Kontostand trägt eine Quellenangabe, aber kein Dokument. Die
Bescheinigung der Genossenschaft — genau das Blatt, das das Gericht
sehen will — hätte am Konto keinen Platz.
2. **Als Konto stünde es in der Kontenliste** und würde dort einen Auszug
und Buchungen erwarten, die es nie geben wird.
Trag dann einen **Wertstand** zum Stichtag ein, mit der Bescheinigung als
Nachweisdokument.
### Den „Kontoauszug" bekommst du schriftlich
Die Genossenschaft stellt dir auf Anfrage eine **Bescheinigung über das
Geschäftsguthaben** zum Stichtag aus. Viele verschicken ohnehin einmal
jährlich eine Abrechnung nach der Generalversammlung — dann genügt es,
diese abzuwarten und einzuscannen.
Fehlt sie, schreib hin. Unter **Vorlagen** liegt das *Auskunftsersuchen*
als Kopiervorlage; darin änderst du die Bitte auf „Bescheinigung über das
Geschäftsguthaben zum <Stichtag>". Und setz eine Wiedervorlage.
> **„Der Wert bleibt doch immer gleich."** Meistens ja — aber nicht
> zwangsläufig. Wird eine **Dividende dem Geschäftsguthaben
> gutgeschrieben** statt ausgezahlt, wächst es. Ebenso, wenn weitere
> Anteile gezeichnet wurden. Genau deshalb fragt man einmal im Jahr nach,
> statt den Vorjahreswert fortzuschreiben.
### Dieselbe Bauform, andere Namen
Nach demselben Muster behandelst du alles, was „Konto" heißt und keinen
Auszug kennt:
| Was | Als was anlegen | Nachweis |
|---|---|---|
| Genossenschaftsanteile | Vermögensposten, *Forderung* | Bescheinigung der Genossenschaft |
| Bausparvertrag | Vermögensposten, *Forderung* | Jahreskontoauszug der Bausparkasse |
| Sterbegeld-, Lebensversicherung | **Vertrag**, Rückkaufswert am Vertrag | Rückkaufswertmitteilung |
| Wertpapierdepot | Konto, Art *Depot* | Depotauszug zum Stichtag |
| Darlehen, das die Person schuldet | Vermögensposten, *Verbindlichkeit* | Saldenbestätigung der Bank |
Das Depot ist die Ausnahme: Dort laufen Umsätze, es gibt einen Auszug, und
es verhält sich wie ein Konto.
Bei Versicherungen nimmst du **nicht** den Vermögensbereich, sondern den
Vertrag selbst — dort gehört der Rückkaufswert hin, samt Historie über die
Jahre.
---
## Anmelden mit dem Finger: Passkeys
Drei Felder auszufüllen, nur um kurz eine Frist nachzusehen, ist lästig —
+1 -1
View File
@@ -323,7 +323,7 @@ betreuungs-cockpit-sicherung-1 Up
```bash
# Antwortet die Anwendung? (Port anpassen, falls du APP_PORT gesetzt hast)
curl -s http://127.0.0.1:3000/api/gesundheit
# {"status":"bereit","version":"1.11.1","commit":"...",
# {"status":"bereit","version":"1.12.0","commit":"...",
# "speicher":{"status":"bereit","treiber":"s3"}}
```
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "betreuungs-cockpit",
"version": "1.11.0",
"version": "1.12.0",
"private": true,
"description": "Arbeits- und Dokumentationswerkzeug fuer die ehrenamtliche rechtliche Betreuung",
"engines": {
+2 -2
View File
@@ -100,7 +100,7 @@ echo "$(date -Iseconds) Datenbank wiederhergestellt."
# --- Dokumente ---------------------------------------------------------------
# Zu "cockpit_2026-09-01_0315.dump.enc" gehoert
# "dokumente_2026-09-01_0315.tar.gz.enc" - gleicher Zeitstempel, anderer
# Name. Fehlt sie, stammt die Sicherung aus einer Fassung vor v1.11.1.
# Name. Fehlt sie, stammt die Sicherung aus einer Fassung vor v1.12.0.
ZEITSTEMPEL="$(basename "$DATEI" | sed -n 's/^cockpit_\(.*\)\.dump\.enc$/\1/p')"
DOKUMENTE_DATEI="$(dirname "$DATEI")/dokumente_${ZEITSTEMPEL}.tar.gz.enc"
AUSPACKZIEL="$(dirname "$DATEI")/dokumente-wiederhergestellt_${ZEITSTEMPEL}"
@@ -109,7 +109,7 @@ if [ ! -f "$DOKUMENTE_DATEI" ]; then
echo ""
echo "WARNUNG: Zu dieser Sicherung gibt es kein Dokumentenarchiv."
echo " Erwartet wurde: $DOKUMENTE_DATEI"
echo " Sicherungen aus Fassungen vor v1.11.1 enthalten nur die"
echo " Sicherungen aus Fassungen vor v1.12.0 enthalten nur die"
echo " Datenbank. Die Akte ist dann vollstaendig, die Dateien"
echo " dahinter fehlen."
else
+1 -1
View File
@@ -6,7 +6,7 @@ import { speicherfehlerErkennen } from '@/lib/speicher/fehler'
/**
* Ist die Dateiablage benutzbar?
*
* Bis v1.11.1 fiel eine kaputte Speicherkonfiguration erst auf, wenn
* Bis v1.12.0 fiel eine kaputte Speicherkonfiguration erst auf, wenn
* jemand ein Dokument ablegen wollte. Auf dem Livesystem waren das
* mehrere Wochen nach der Installation - und dann mitten in der Arbeit,
* mit einer Meldung, die nichts sagte.
+1 -1
View File
@@ -17,7 +17,7 @@
*/
/** Muss zur "version" in der package.json passen. */
export const VERSION = '1.11.0'
export const VERSION = '1.12.0'
/**
* Kurzer Git-Stand, beim Bauen hineingereicht:
+83 -1
View File
@@ -104,7 +104,89 @@ describe('Installationsanleitung', () => {
})
it('behauptet nicht mehr, die Dokumente seien ungesichert', () => {
// Stand bis v1.11.1 so drin und stimmt seit der Sicherung nicht mehr.
// Stand bis v1.12.0 so drin und stimmt seit der Sicherung nicht mehr.
expect(anleitung).not.toMatch(/Was das Backup nicht enthält:.*Dateien im Objektspeicher/s)
})
})
/**
* Die Bedienungsanleitung muss die Fragen beantworten, die tatsächlich
* gestellt werden.
*
* Zwei davon kamen aus der Praxis:
*
* 1. „Wie mache ich den Jahresabschluss?" — die Anleitung beschrieb, was
* in jedem Bericht steht, aber nicht die Reihenfolge und nicht, was man
* vorher besorgen muss. Rückkaufswerte brauchen Wochen.
* 2. „Das Gericht will einen Kontoauszug für die Genossenschaftsanteile —
* den kann ich nicht am Automaten holen." Richtig: Es ist kein
* Zahlungskonto, sondern eine Forderung, und der Nachweis ist eine
* Bescheinigung, die man anfordert.
*
* Der zweite Fall ist der wichtigere, weil er zu einem stillen Fehler
* führt: Wer die Anteile als Konto anlegt, kann die Bescheinigung nicht am
* Wert hinterlegen — genau das Dokument, das das Gericht sehen will.
*/
describe('Bedienungsanleitung', () => {
const bedienung = readFileSync('docs/ANLEITUNG.md', 'utf8')
it('erklärt den Jahresabschluss mit Reihenfolge', () => {
expect(bedienung).toMatch(/## Der Jahresabschluss, Schritt für Schritt/)
})
it('sagt, was vor dem Stichtag zu besorgen ist', () => {
// Wer erst am Stichtag daran denkt, wartet Wochen auf die Auskunft.
const abschnitt = bedienung.slice(bedienung.indexOf('## Der Jahresabschluss'))
expect(abschnitt).toMatch(/Sechs Wochen vorher/)
expect(abschnitt).toMatch(/Rückkaufswerte/)
expect(abschnitt).toMatch(/Wiedervorlage/)
})
it('besteht auf der Quellenangabe beim Kontostand', () => {
// Ein Betrag ohne Herkunft ist gegenueber dem Gericht wenig wert.
const abschnitt = bedienung.slice(bedienung.indexOf('## Der Jahresabschluss'))
expect(abschnitt).toMatch(/Quelle/)
expect(abschnitt).toMatch(/Kontoauszug 11\/2026|Online-Banking/)
})
describe('Was aussieht wie ein Konto', () => {
const abschnitt = bedienung.slice(bedienung.indexOf('## Was aussieht wie ein Konto'))
it('gibt es überhaupt', () => {
expect(abschnitt.length).toBeGreaterThan(500)
})
it('führt Genossenschaftsanteile als Forderung, nicht als Konto', () => {
expect(abschnitt).toMatch(/Genossenschaftsanteile/)
expect(abschnitt).toMatch(/Art \*\*Forderung\*\*/)
})
it('nennt den Grund, statt ihn vorauszusetzen', () => {
// Ohne Begruendung legt der naechste Leser es wieder als Konto an.
expect(abschnitt).toMatch(/Nachweis anhängen|Nachweis anhaengen/)
expect(abschnitt).toMatch(/kein Dokument/)
})
it('warnt davor, den Vorjahreswert einfach fortzuschreiben', () => {
// "Der Wert bleibt doch gleich" stimmt meistens - aber eine
// gutgeschriebene Dividende erhoeht das Geschaeftsguthaben.
expect(abschnitt).toMatch(/Dividende/)
})
it('sagt, wie man den Nachweis bekommt', () => {
expect(abschnitt).toMatch(/Bescheinigung über das\s+Geschäftsguthaben/)
expect(abschnitt).toMatch(/Auskunftsersuchen/)
})
it('behandelt die verwandten Fälle mit', () => {
for (const fall of ['Bausparvertrag', 'Depot', 'Verbindlichkeit']) {
expect(abschnitt, `${fall} fehlt in der Übersicht`).toContain(fall)
}
})
it('schickt Versicherungen zum Vertrag, nicht ins Vermögen', () => {
// Der Rueckkaufswert gehoert an den Vertrag, samt Historie.
expect(abschnitt).toMatch(/nicht\*\* den Vermögensbereich|Vertrag selbst/)
})
})
})
+1 -1
View File
@@ -6,7 +6,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
/**
* Die Bereitschaftsprüfung der Dateiablage.
*
* Bis v1.11.1 fiel eine kaputte Speicherkonfiguration erst auf, wenn
* Bis v1.12.0 fiel eine kaputte Speicherkonfiguration erst auf, wenn
* jemand ein Dokument ablegen wollte. Auf dem Livesystem waren das
* mehrere Wochen nach der Installation — und dann mitten in der Arbeit,
* mit einer Meldung, die nichts sagte.