Spezifikation nachgeschärft, Plan-Übersicht mit Verträgen der Stränge

Nachträge aus der Planrunde (Fragment-Link, Teamkopie ohne Link, Schalter
AUFTRAEGE_ENABLED, Projekt später zuordnen, Schlussrechnung bis 40 Zeilen,
zusammengesetzte Sperrschlüssel, Zuständigkeiten).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-10-06 12:06:09 +00:00
1 parent e00b4ae572
commit 0bb463eb7d
2 files changed
+434 -16

No files matched your search

@@ -1,6 +1,6 @@
# Aufträge und Rechnungen: Auftragsbestätigung und projektbezogene Rechnungen
Stand: 2026-10-06 · Status: Entwurf zur Freigabe (Abschnitte im Chat einzeln freigegeben)
Stand: 2026-10-06 · Status: freigegeben (Abschnitte im Chat einzeln freigegeben; Nachträge aus der Planrunde eingearbeitet, siehe „Nachträge“ am Ende)
Grundlage: Wunsch des Nutzers vom 06.10.2026 („Auftragsbestätigung und Rechnungen bei uns, wenn wir auf Kunden gehen;
Projekt auswählen, Zusammenfassung sehen, Festbeträge möglich“), Recherche im selben Gespräch (Quellen am Ende),
@@ -117,7 +117,7 @@ Mitarbeiter (ohne Beträge).
### Dialog „Auftragsbestätigung“ (neu)
1. **Projekt** (oder freier Titel, wenn es noch kein Projekt gibt; später zuordenbar) und, falls leer, **Kundenart**.
1. **Projekt** (oder freier Titel, wenn es noch kein Projekt gibt; später zuordenbar über „Projekt zuordnen“ in der AB-Liste, ohne das PDF zu ändern) und, falls leer, **Kundenart**.
2. **Auftrag:** Datum der Absprache und Weg (mündlich, telefonisch, per E-Mail, vor Ort, im Chat). Art **Festpreis**
(Positionen: Beschreibung, Menge, Einzelpreis; Grenzen wie bei Rechnungen) oder **Nach Aufwand** (Stundensatz,
Standard 100 €; Schätzung in Stunden, optional, in 15-Minuten-Schritten).
@@ -138,8 +138,8 @@ Mitarbeiter (ohne Beträge).
`storniert` (von Hand, ohne Mail), `ersetzt` (durch eine neue Fassung) und `widerrufen` (Privatperson).
- **Unveränderlich nach dem Senden.** Änderung = „Neue Fassung“: Kopie als neuer Entwurf mit Vermerk
„Ersetzt AB-… vom …“; beim Senden der neuen AB wird die alte `ersetzt`. Rechnungen der alten AB wandern intern mit
(`projektRechnungen.auftragId` und Stripe-Metadaten auf die neue AB); der auf finalisierten Rechnungen aufgedruckte
Bezug bleibt unverändert.
(`projektRechnungen.auftragId` auf die neue AB); Stripe-Metadaten und der auf finalisierten Rechnungen aufgedruckte
Bezug bleiben unverändert.
### Inhalt des PDFs (A4)
@@ -162,8 +162,8 @@ Mitarbeiter (ohne Beträge).
### Erzeugung und Ablage
- PDF mit **pdfkit** (reines JavaScript; kein Chrome zur Laufzeit wegen knappem Arbeitsspeicher), Schrift Figtree aus
`public/fonts`, Logo aus `public/img`.
- PDF mit **pdfkit** (reines JavaScript; kein Chrome zur Laufzeit wegen knappem Arbeitsspeicher), statische
Figtree-Schnitte (OFL) unter `server/assets/fonts/`, Logo `public/webklar-logo.png`.
- Beim Senden einmal erzeugt und unter `upload-data/auftraege/<kundenId>/<abId>.pdf` abgelegt, SHA-256 im Dokument;
danach wird nur noch diese Datei ausgeliefert. Die Datei liegt in der Hetzner-Serversicherung; jede Mail geht zudem
per BCC an das Team-Postfach.
@@ -172,9 +172,10 @@ Mitarbeiter (ohne Beträge).
### Versand
- Mail **K31 „Auftragsbestätigung“** (Kunde, Design der Mailvorlagen, BCC Team): kurzer Text, Anhänge AB-PDF und
AGB-PDF, Knopf **„Auftrag bestätigen“** → `https://project.webklar.com/auftrag.html?t=<token>`; bei Privatpersonen
Hinweis auf Widerrufsbelehrung und Frühbeginn.
- Mail **K31 „Auftragsbestätigung“** (Kunde, Design der Mailvorlagen, **ohne** BCC ans Team, weil sie den
Bestätigungslink trägt): kurzer Text, Anhänge AB-PDF und AGB-PDF, Knopf **„Auftrag bestätigen“** →
`https://project.webklar.com/auftrag.html#t=<token>` (Fragment: landet nicht in Server-Protokollen); bei
Privatpersonen Hinweis auf Widerrufsbelehrung und Frühbeginn. Das Team bekommt eine Kopie **ohne** Link.
- Token: 32 Zufallsbytes (base64url), gespeichert nur als SHA-256, gültig 60 Tage ab dem letzten Versand.
**„Erinnerung senden“** (WOMS, von Hand) schickt K31 erneut mit Erinnerungs-Hinweis und neuem Token (der alte gilt
nicht mehr).
@@ -182,7 +183,7 @@ Mitarbeiter (ohne Beträge).
### Bestätigung
- **Öffentliche Seite** `auftrag.html?t=…` (ohne Anmeldung, `noindex`, Ratenbegrenzung je IP im Arbeitsspeicher wie
- **Öffentliche Seite** `auftrag.html#t=…` (ohne Anmeldung, `noindex`, Ratenbegrenzung je IP im Arbeitsspeicher wie
bei der Widerrufsseite): Zusammenfassung (Nummer, Datum, Projekt, Positionen bzw. Aufwandsregel, Summe,
Zahlungsplan, Termine), Links auf AB-PDF und AGB-PDF, Häkchen „Ich bestätige den Auftrag zu diesen Bedingungen.“,
Knopf „Auftrag bestätigen“. Nach der Bestätigung zeigt die Seite „Bestätigt am …“. Ungültiger oder abgelaufener Link:
@@ -196,13 +197,13 @@ Mitarbeiter (ohne Beträge).
- **Protokoll am AB:** `bestaetigtAm`, `bestaetigtUeber` (`link` | `portal`), `bestaetigtPdfSha256` (muss
`pdfSha256` entsprechen), `texteFassung`, `fruehbeginn` (ja/nein) und dessen Textfassung. **Keine IP-Adresse.**
Eine zweite Bestätigung ändert nichts (die erste zählt).
- Danach: Mail **K32 „Auftrag bestätigt“** an den Kunden (Eingangsbestätigung mit Datum, Uhrzeit, Frühbeginn ja/nein)
und **T22 „Auftrag bestätigt“** an das Team.
- Danach: Mail **K32 „Auftrag bestätigt“** an den Kunden (Eingangsbestätigung mit Datum, Uhrzeit, Frühbeginn ja/nein;
eine Frühbeginn-Erklärung wird wörtlich wiedergegeben) und **T22 „Auftrag bestätigt“** an das Team.
### Widerruf (Privatperson)
- `widerrufen.html` bekommt die Vertragsart **„Projektauftrag (Auftragsbestätigung)“** mit Feld AB-Nummer. Die
Erklärung läuft über den bestehenden Weg (Eingangsbestätigung an den Kunden, Team-Mail); passt die AB zu Nummer und
- `widerrufen.html` bekommt die Vertragsart **„Projektauftrag (Auftragsbestätigung)“** mit Feld AB-Nummer (optional,
„falls zur Hand“; der Widerruf ist formfrei). Die Erklärung läuft über den bestehenden Weg (Eingangsbestätigung an den Kunden, Team-Mail); passt die AB zu Nummer und
E-Mail-Adresse, wird sie `widerrufen` und WOMS zeigt es. Erstattung und Wertersatz bleiben Handarbeit.
## 3. Rechnungen
@@ -220,7 +221,8 @@ Karte/SEPA, Bankabgleich und Finanzen-Übersicht unverändert).
| `festbetrag` | Projekt | Freie Positionen wie heute (Frau Wolf: „Erstellung der Website anelia-wolf.com, Pauschalpreis laut Absprache“, 500 €). |
| `frei` | „Ohne Projekt“ gewählt | Freie Positionen wie bisher, ohne Zusatzfelder „Projekt“/„Auftrag“ (aber A4). |
Grenzen wie heute (1–20 Positionen inkl. Minuszeilen; Beschreibung ≤ 200 Zeichen). Ergäbe eine Aufwandsrechnung mehr
Grenzen wie heute (1–20 Positionen inkl. Minuszeilen; Beschreibung ≤ 200 Zeichen); eine Schlussrechnung darf bis
40 Zeilen haben (AB-Positionen ≤ 20, Zusatzpositionen ≤ 10, Abzüge ≤ 10). Ergäbe eine Aufwandsrechnung mehr
als 20 Zeilen (zusätzliche Positionen zählen mit), werden die ältesten Tage zu Kalenderwochen zusammengefasst
(„KW 41/2026: … – 6,5 Std. à 100,00 €“), bis höchstens 20 Zeilen bleiben.
@@ -283,7 +285,8 @@ Neue Collections (Setup-Skript `scripts/auftraege-setup.mjs`, idempotent wie `se
`agbFassung`, `pdfDatei`, `pdfSha256`, `gesendetAm`, `gesendetAn`, `mailStatus`, `mailFehler`, `tokenHash`,
`tokenGueltigBis`, `bestaetigtAm`, `bestaetigtUeber`, `bestaetigtPdfSha256`, `fruehbeginn`, `fruehbeginnFassung`,
`ersetztId`, `ersetztDurchId`, `storniertAm`, `widerrufenAm`, `erstelltVon`, `erstelltAm`, `geaendertAm`.
Indizes: `kundenId`, `projektId`, `nummer` (unique), `tokenHash`.
Indizes: `kundenId`, `projektId`, `nummer` (normaler Index: Entwürfe haben keine Nummer; eindeutig über die Sperre
beim Senden), `tokenHash`.
- **`projektRechnungen`**: Dokument-ID = Stripe-Rechnungs-ID; `kundenId`, `projektId`, `auftragId`, `art`,
`betragCents`, `arbeitsblattIds` (string[]), `aktiv` (bool), `erstelltVon`, `erstelltAm`. Indizes: `kundenId`,
`projektId`, `auftragId`.
@@ -378,6 +381,10 @@ Der Nutzer gibt frei; danach lädt Claude die Fassungen in WOMS → Rechtliches
- **Plan 2 – Auftragsbestätigung:** `auftraege`, Kundenart, Steuernummer-Einstellung, PDF, Mails, Bestätigungsseite
und Portal-Abschnitt, Verbraucher-Variante, Widerruf, Arten `anzahlung` und `schluss` (mit Minuszeilen),
WOMS-Dialog und -Liste, Rechtsrunde.
- **Parallel gebaut, gestaffelt live:** Auf Wunsch des Nutzers (06.10.2026) werden beide Pläne gleichzeitig in
parallelen Strängen gebaut (Umsetzungsplan `2026-10-06-auftraege-00-uebersicht.md`). Der AB-Teil (und die Arten
`anzahlung`/`schluss`) hängt hinter dem Schalter `AUFTRAEGE_ENABLED` (`off` | `pilot` | `on`, Vorgabe `off`), so geht
der Rechnungsteil ohne Rechtsrunde live; der Datenschutz-Abschnitt kommt erst mit dem AB-Livegang.
- **Reihenfolge je Plan:** Portal-Server und Kundenseiten zuerst; WOMS-Oberfläche im neuen Design auf Basis der
zusammengeführten Redesign-Stränge Kunden (P4) und Finanzen (P7). Sind die Stränge beim Start der WOMS-Aufgaben noch
nicht zusammengeführt, wird mit dem Nutzer entschieden (warten oder auf `test` bauen und eine Mitnahme-Notiz für das
@@ -400,3 +407,13 @@ Projektmarge und Auswertungen, automatische Erinnerungen.
- Auftragsbestätigung (Inhalt): https://www.lexware.de/wissen/faktura-warenwirtschaft/auftragsbestaetigung-bedeutung-und-inhalt/
- Stripe Rechnungen anpassen: https://docs.stripe.com/invoicing/customize
- Agentur-Abrechnung (Festpreis/Aufwand): https://everhour.com/de/invoices/rechnungssoftware-fuer-digitalagenturen
## Nachträge aus der Planrunde (06.10.2026)
- Kundentexte: Mails, PDF und die öffentliche Bestätigungsseite in Sie-Form; der Abschnitt „Aufträge“ im angemeldeten
Portal in Du-Form wie das übrige Portal.
- Steuernummer-Feld akzeptiert auch eine USt-IdNr. („DE…“).
- Frühbeginn-Erklärung stützt sich auf § 356 Abs. 5 Nr. 2 und § 357a Abs. 2 BGB (Wortlaut in der Rechtsrunde).
- Bei Weg „vor Ort“ und Kundenart Privatperson zeigt der AB-Dialog den Hinweis „zusätzlich ausdrucken und übergeben“
(§ 312f Abs. 1 BGB), bis die Kanzlei-Frage beantwortet ist.
- Team-Mail T22 trägt im Betreff das Präfix „[Aufträge]“ wie die übrigen Team-Mails.