Commit Graph
402 Commits
Author SHA1 Message Date
knsoandClaude Opus 5.5 c3eef4747d Buchungskalender: Abgleich – T22/K34 passen zu den Vorlagen, Config-Werte geprüft
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:55:32 +00:00
knsoandClaude Opus 5.5 fbd07b3d8c Buchungskalender: Abgleich – iCal-Export (Escape, aktive Unterkünfte, ab gestern, Rate-Limit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:54:16 +00:00
knsoandClaude Opus 5.5 95cbd473d0 Buchungskalender: Abgleich – gleichzeitige Zweitzahlung wird erstattet
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:53:36 +00:00
knsoandClaude Opus 5.5 97dd84fbb8 Buchungskalender: Strang mail zusammenführen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:49:33 +00:00
knsoandClaude Opus 5.5 35b0438d00 Buchungskalender: Team-API wie Webshop (anfrage null, Stripe-Status)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:46:30 +00:00
knsoandClaude Opus 5.5 9d01d38a45 Buchungskalender: Bestellung auf Anfrage, Freischaltung und Ticket
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:44:21 +00:00
knsoandClaude Opus 5.5 827ee54875 Buchungskalender: Aufbewahrung – Sperre wie Ablauf, Restpunkte
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:43:44 +00:00
knsoandClaude Opus 5.5 c019d3c3b0 Buchungskalender: Aufbewahrung und Löschfristen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:38:35 +00:00
knsoandClaude Opus 5.5 f57a3d477e Buchungskalender: iCal-Import und -Export
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:32:34 +00:00
knsoandClaude Opus 5.5 e3b399e003 Buchungskalender: Zustimmungs-Test streng, Online-Zahlung nur beim Einschalten prüfen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:32:20 +00:00
knsoandClaude Opus 5.5 32cffb3518 Buchungskalender: Verwaltungs-API – Einstellungen, Zustimmung, Online-Zahlung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:30:20 +00:00
knsoandClaude Opus 5.5 d0ab92658a Buchungskalender: Verwaltungs-API für Vermieter
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:26:46 +00:00
knsoandClaude Opus 5.5 a94b50fbc1 Buchungskalender: Zahlung – Sitzung wiederverwenden, Zahlung nach Storno erstatten
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:23:06 +00:00
knsoandClaude Opus 5.5 ca0f762272 Buchungskalender: Buchungsseite, Stripe-Zahlung und Webhook
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:16:17 +00:00
knsoandClaude Opus 5.5 4553bc8e92 Buchungskalender: Mails – Link-Pflicht und Testprotokoll nur im Test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:16:04 +00:00
knsoandClaude Opus 5.5 e15486263f Buchungskalender: Mails an Gäste, Vermieter und Team
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:12:47 +00:00
knsoandClaude Opus 5.5 40a366b8ae Buchungskalender: ID-Prüfung erlaubt Bindestrich (UUIDs)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:10:46 +00:00
knsoandClaude Opus 5.5 0c5ca76a4d Buchungskalender: öffentliche API gegen manipulierte IDs und Lookups absichern
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:10:30 +00:00
knsoandClaude Opus 5.5 118be44847 Buchungskalender: PDF-Writer und Rechnungs-PDF
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:06:11 +00:00
knsoandClaude Opus 5.5 d7b5b98187 Buchungskalender: Verdrahtung absichern (Outbox, Shop-Webhook, Session)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 14:02:41 +00:00
knsoandClaude Opus 5.5 a68baf10d9 Buchungskalender: Verdrahtung, Router-Gerüste und API-Vertrag
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:59:38 +00:00
knsoandClaude Opus 5.5 1d2ca2791d Buchungskalender: Storno und Erstattung getrennt
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:58:17 +00:00
knsoandClaude Opus 5.5 f7650fe883 Buchungskalender: Storno und Buchung idempotent bei Teilfehlern
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:55:56 +00:00
knsoandClaude Opus 5.5 947e9da2e3 Buchungskalender: Statusmaschine, Token und Rechnungsnummern
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:52:52 +00:00
knsoandClaude Opus 5.5 802b5d3ad4 Buchungskalender: Mengen-Obergrenze für Posten auf 20000
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:50:22 +00:00
knsoandClaude Opus 5.5 bdf191d945 Buchungskalender: Speicher und Belegung
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:49:29 +00:00
knsoandClaude Opus 5.5 c38c8e7c13 Buchungskalender: Preisrechnung nachgeschärft (Summe, Kleinunternehmer, Vollständigkeit)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:49:20 +00:00
knsoandClaude Opus 5.5 84e7a99f41 Buchungskalender: Preisrechnung und Datumshilfen
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:47:41 +00:00
knsoandClaude Opus 5.5 5717a5cdd0 Buchungskalender: Konfiguration, Schalter, Schema und Setup-Skript
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-07 13:45:57 +00:00
ClaudeandClaude Opus 5.5 e87140e5ba Merge remote-tracking branch 'origin/main' into feature/oeffnungszeiten
Zusammenführung von TP2-Abschluss und Webshop (origin/main cab9c33) mit Öffnungszeiten live. Beide
Funktionen bleiben vollständig: jeder Konflikt ist als Vereinigung gelöst, Reihenfolge der Funktionsschlüssel
überall news, termine, shop, zeiten.

Konfliktdateien (28): public/app.js, dashboard.html, funktionen.js, widerrufen.html; scripts/stripe-products.mjs;
server/config.js, index.js, middleware/kundenansichtGuard.js, routes/abo.js, routes/admin/funktionenAdmin.js,
routes/funktionen.js, services/customerAdmin.js, customerViewLog.js, featureRegistry.js, retention.js,
siteFeatures.js, stripeBilling.js; test/customerViewLog, featureFreischaltung, featureRegistry, funktionenRoutes,
funktionenTermine, kundenansichtGuard, mailTemplates, publicForms, siteFeatures, stripeProductsScript (je
.test.js) und test/support/schema.js.

Entscheidungen: Mailvorlagen G01–G15, K01–K30, T01–T21 lückenlos (K24–K26 Webshop, K27–K30 Öffnungszeiten);
Stripe-Katalog mit shopSetup und zeitenSetup; Widerruf kennt shop und zeiten; ABO_FUNKTIONEN bleibt analyse
und termine (kein zeiten); activate() schreibt die Zeiten-Felder nur über extra; kein Halter von
feature-activate:<id> ruft disable() auf; die Aufbewahrungs-Löschung löscht Zeiten-Daten vor dem Abschalten und
hält den Kunden bei einem Fehler (held); die Admin-Antwort trägt ersatzTicket und warnung; Hash-Routen webshop
und zeiten, Ansichten view-webshop und view-zeiten; assertOwnProject behält die Meldung von main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 06:12:23 +00:00
ClaudeandClaude Opus 5.5 c7cd436ec2 Öffnungszeiten: Mails K24–K27 heißen jetzt K27–K30, Feld k24At heißt einschaltMailAt
K24–K26 sind seit dem Webshop-Livegang (main) vergeben; der Mail-Lader sucht die Vorlage über den
Dateianfang, doppelte Nummern hätten die falsche Mail geschickt. Das Feld ist noch nicht in der
Produktion angelegt (zeiten-setup.mjs lief noch nicht), daher jetzt ein sprechender Name.
Spec und Plan behalten die alten Nummern (Hinweis oben im Dokument).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 06:00:17 +00:00
ClaudeandClaude Opus 5.5 cab9c33db6 Webshop nach TP2-Merge: Shop-Mails in der Klasse normal (kein zusätzliches notEqual in der Outbox-Abfrage)
Seit 2c7cd26 kostet jede Art in VORRANG/NACHRANGIG ein notEqual in der Abfrage der Klasse normal; live stößt die URL
bei nginx an (414). G09–G15 laufen deshalb in der Klasse normal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 14:59:12 +00:00
Claude a4a18a1c89 Merge branch 'feature/terminplaner-tp2' into feature/webshop 2026-10-05 14:56:43 +00:00
ClaudeandClaude Sonnet 5.5 2c7cd26532 Termine-Outbox: notEqual mit genau einem Wert (Appwrite 1.8.1), nachrangige Mails kommen wieder dran
Auf der echten Appwrite 1.8.1 lehnt notEqual mit Liste die Abfrage ab (HTTP 400
general_query_invalid, "NotEqual queries require exactly one value"). Die Klasse normal der
Mail-Warteschlange schickte immer eine Liste, jeder Lauf warf dort, und die nachrangige Klasse
(G05, K20, K21) kam nie dran.

- appwriteAdmin: Query.notEqual nimmt genau einen Wert (eine Liste wirft einen TypeError, der
  keinerVon nennt); neu keinerVon(attribute, werte) = je Wert ein notEqual (Appwrite schneidet
  sie); dokumenteUrl() baut die Listen-URL ohne Netz, mit derselben Serialisierung wie die Anfrage.
- outbox: klassenFilter liefert fuer jede Klasse eine Liste von Abfragen (normal = sechs notEqual
  auf art), die Ausschlussliste ist keinerVon('featureId', ...). AUSSCHLUSS_MAX 90 -> 30 (der nginx
  antwortet in dieser Abfrageform ab 46 Funktions-IDs mit 414); der Kommentar "100 Werte je Abfrage"
  entfaellt.
- Nachbau (appwriteMock): notEqual mit Liste oder ohne Wert => 400 wie Appwrite; ein Dokument mit
  Feld null oder ohne Feld passt nicht zu notEqual (SQL-Semantik).
- Tests: Query-Helfer, keinerVon, dokumenteUrl, Nachbau (400, null), ein Lauf bedient alle drei
  Klassen, Ausschlussliste hoechstens 30 und URL unter 6000 Zeichen im schlimmsten Fall.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-05 14:47:29 +00:00
ClaudeandClaude Opus 5.5 43473c0879 Webshop: IP-Hash entfällt mit Zahlung oder Storno, keine Käufer-Telefonnummer mehr gespeichert
schliesseAb und verwirf entfernen ipHash aus dem Bestell-JSON, sobald die Bestellung nicht mehr offen ist
(Begrenzung offener Bestellungen je IP bleibt). customer_details.phone wird nicht mehr in kaeufer.telefon
übernommen; Kundenansicht und Bestelldetail geben auch in alten Datensätzen keine Telefonnummer aus.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 10:26:56 +00:00
ClaudeandClaude Opus 5.5 578a64782b Shop Review B M-6: Stripe-Kasse ohne Telefonnummer, Rechnungsanschrift nur bei Bedarf
phone_number_collection ist aus, billing_address_collection steht auf auto (Datenminimierung).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 10:01:05 +00:00
ClaudeandClaude Opus 5.5 08d837d690 Shop Review B I-6, I-7: Archiv der bestaetigten Rechtstexte, G09 ohne Link-Ersatz
I-6: Neue Collection shopRechtstexteArchiv (ID r + 35 Hex aus sha256(shopId + hash)); das
Bestaetigen legt die Fassung samt Versand-/Zahlungstext und Gewaehrleistungstext ab, G09 zeigt
die Fassung zum rechtstexteHash der Bestellung (Rueckfall mit Warnung auf die aktuell
bestaetigte), loescheShopDaten loescht das Archiv mit.

I-7: Grenzen AGB 20000, Belehrung 12000, Formular 3000 plus Pruefung der maskierten Laenge beim
Speichern; G09 ersetzt die AGB nie mehr durch einen Link, sondern scheitert (Marker bleibt
offen, wird wiederholt). Test mit Texten in Hoechstlaenge gegen die Grenzen der Warteschlange.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:58:31 +00:00
ClaudeandClaude Opus 5.5 2f4f360a21 Shop Review B I-5: Bestaetigen nur ohne Platzhalter, Musterkopf und mit Adresse der Widerrufsfunktion
pruefeBestaetigbar listet die Probleme in Du-Form; POST /api/shop/rechtstexte/bestaetigen
antwortet 400 nicht_bestaetigbar mit der Liste, GET und PUT liefern sie als probleme mit.
Der Reiter Rechtliches zeigt die Punkte im Bestaetigungsblock und sperrt den Knopf.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:53:17 +00:00
ClaudeandClaude Opus 5.5 1f56b86791 Shop Review B I-4: Steuerart und Lieferzeit ohne Vorbelegung
kleinunternehmer ist ab jetzt null (nicht gewaehlt), lieferzeit leer. istVollstaendig verlangt eine
bewusste Wahl (true oder false), der Shop kann sonst nicht geoeffnet werden. Im Reiter
Einstellungen gibt es zwei Pflicht-Radiobuttons ohne Vorauswahl; Preise, Artikel und Muster
rechnen bei null wie bei Regelbesteuerung. Tests und Fixtures angepasst.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:50:54 +00:00
ClaudeandClaude Opus 5.5 72fb37edcc Shop Review B I-1: Muster-AGB § 2 und § 9 passen zum Ablauf, Angaben nach Art. 246c EGBGB
§ 2 beschreibt Bestaetigungsseite, sofortige Bestellbestaetigung bei Karte/Klarna und
Eingangsmail mit spaeterem Vertragsschluss bei SEPA. § 9 nennt technische Schritte,
Berichtigung von Eingabefehlern, Speicherung, Sprache und Verhaltenskodizes. Markdown-Muster
und Test sind angeglichen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:46:19 +00:00
ClaudeandClaude Opus 5.5 77fb8c8f44 Shop Review B I-1: Eingangsmail G15 bei SEPA, G09 nimmt die Bestellung ausdruecklich an
G15 "Wir haben Ihre Bestellung erhalten" geht einmal raus, sobald Stripe die Sitzung
abgeschlossen, die Zahlung aber noch nicht gemeldet hat (meldeEingang, Marker mailsEingangAt,
aus dem Webhook und aus pruefeOffene). G09 sagt ausdruecklich, dass der Kaufvertrag mit der
Mail geschlossen ist, trennt Bestell- und Zahlungsdatum und nennt die Telefonnummer des
Anbieters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:44:48 +00:00
ClaudeandClaude Opus 5.5 1b7aa9ebe3 Shop Review B I-8: Aktivierung des Webshops durch das Team nur mit Zustimmung in Textform
AVV Webshop, Vorbemerkung Abs. 2: Das Team darf den Webshop ohne Online-Bestellung
nur einschalten, wenn der Kunde vorher in Textform zugestimmt hat. Die Textform-Aktivierung
gilt jetzt wie beim Terminplaner auch fuer 'shop' (Modus on, Pilotadressen ausgenommen,
shopTextformNoetig): Nachweis in featureConsents mit Fassung (config.shop.fassung), Datum,
Weg, Mitarbeiter und dem Wortlaut der Erklaerungen der Bestelltexte, K16 mit
Leistungsbeschreibung und AVV als PDF. GET /api/team/funktionen/:kunde liefert zusaetzlich
shop { textformNoetig, avvVersion, links }.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:44:11 +00:00
ClaudeandClaude Opus 5.5 309c98d531 Shop Review A M10: Kontext-Cache des Shops beim Abschalten leeren
disable (und damit disableCustomerFeatures bei Kundenloeschung) leert fuer die Funktion shop den Kontext-Cache dieses siteKeys, per dynamischem Import und best effort.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:38:58 +00:00
ClaudeandClaude Opus 5.5 45487d6c7e Shop Review A M3: Eingangsbestaetigung G12 je Empfaengeradresse begrenzen (3 je Stunde)
Ueber die gemeinsame Empfaenger-Kappe (darfEmpfaenger) geht an dieselbe Adresse hoechstens dreimal je Stunde ein G12. Darueber hinaus wird der Widerruf trotzdem gespeichert und mit eingang beantwortet, es wird aber keine weitere Mail eingereiht (bestaetigungAt bleibt leer).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:38:16 +00:00
ClaudeandClaude Opus 5.5 21805c9a93 Shop Review A M6: Stripe-Status auf 4000 Zeichen begrenzen (30 Eintraege zu 100 Zeichen, notfalls weiter kuerzen)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:35:40 +00:00
ClaudeandClaude Opus 5.5 d4b9e6a5b9 Shop Review A M9: Mindestbetrag 0,50 EUR (Stripe) und Sitzungsende direkt vor dem Stripe-Aufruf nachfuehren
berechne lehnt Gesamtbetraege unter 0,50 EUR mit dem Code mindestbetrag und einem Kaeufertext ab. legeBestellungAn schiebt expires_at um die seit Beginn vergangenen ganzen Sekunden (Warten auf Sperren) weiter und fuehrt ablaufAt auf denselben Wert nach, damit Stripes 30-Minuten-Minimum sicher bleibt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:35:17 +00:00
ClaudeandClaude Opus 5.5 cb6291410d Shop Review A I4: Shop-Limit 300 je Stunde, hoechstens 3 offene Bestellungen je IP und Shop in 30 Minuten
Die IP wird nur als gesalzener Kurz-Hash (sha256, 16 Hex-Zeichen) im Bestell-JSON abgelegt; der Tagesjob entfernt ihn bei der Anonymisierung mit. Die Pruefung laeuft unter der Bestandssperre, Honigtopf und Fehlversuche legen nichts an und zaehlen nicht. Antwort 429 zu_viele_offen mit Retry-After 1800.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:34:03 +00:00
ClaudeandClaude Opus 5.5 55fe1c567f Shop Review A I3: Artikel-Editor ueberschreibt den Bestand nicht mehr (bestandGeladen, Bestand nur bei echter Aenderung schreiben)
Der Editor sendet neben bestand den beim Laden gesehenen Wert (bestandGeladen, je Variantenwert mit id). speichereProdukt behaelt unter der Artikelsperre den aktuell gespeicherten Stand, wenn gesendet gleich geladen ist, und schreibt nur vom Haendler geaenderte Bestaende. bestandGeladen wird nie gespeichert; ohne den Wert (alter Browser) gilt der gesendete Bestand wie bisher.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:32:31 +00:00
ClaudeandClaude Opus 5.5 9c2897a0b0 Shop Review A I1/I2: Statuswechsel und Bestandsabzug unter einer Sperre, fehlende Schritte (Bestand, G09, K25) per Marker nachholen
Der Bestandsabzug laeuft jetzt im selben Block unter shop-bestand und shop-produkte wie der Statuswechsel auf bezahlt, zieheBestandAb haelt keine eigene Sperre mehr. Im Bestell-JSON stehen bestandAbgezogenAt, mailsKaeuferAt und mailsHaendlerAt als Marker; schliesseAb (Webhook-Wiederholung, Statusabruf, Minutenjob) holt fehlende Schritte genau einmal nach, Mails hoechstens fuenfmal versucht. Bezahlte Bestellungen ohne Bestandsabzug zaehlen weiter als reserviert.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:30:36 +00:00
ClaudeandClaude Opus 5.5 172d9f1778 Shop P1b: Bestellnummer im Widerruf freiwillig, ohne Nummer Bestelldatum und Artikel in der Erklärung (§ 356a BGB)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 09:18:14 +00:00