Grafik aus dem Amtsblatt (ABl. L vom 2.10.2025, S. 5) ausgeschnitten; Text der Grafik wörtlich für Alternativtext
und Bestellbestätigung.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Laden von shopConfig (Einstellungen, Rechtstexte als Entwurf/bestaetigt, Stripe-Status) mit sicherem Parsen,
30-s-Speicher je siteKey mit generation-Zaehler (active und disabled), bereitschaft() mit den fuenf Punkten,
istGeoeffnet() und oeffentlicheRechtstexte().
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Reine Funktion berechne(): Positionen zusammenfassen, Bestand und Reservierung,
Lieferart und Land, Mindestbestellwert, Versandkosten, enthaltene USt je Satz
(Versand anteilig) und Kleinunternehmer-Hinweis.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Anfrage stellen, zurückziehen und Stand lesen (ensureShopConfig, normalisiereAnfrage,
stelleAnfrage, zieheZurueck, anfrageAnsicht), Router /api/shop mit Rate-Limit 20/h und
Sperre in der Kundenansicht, Vorlage T21 Neue Webshop-Anfrage mit Tests.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Widerrufsbelehrung nach Anlage 1 (Stand 2026, mit Hinweis auf die Widerrufsfunktion), Formular nach Anlage 2,
Muster-AGB ohne OS-Plattform, erzeugter Versand-/Zahlungstext, Gewaehrleistungshinweis (Wortlaut zu pruefen),
Muster-Markdown fuer die Kanzlei und Tests inkl. Abgleich Markdown/Code.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Registereintrag config.features.shop (Bestelltexte mit Fassung config.shop.fassung, Rechtsunterlagen-Getter,
Mailtexte, Ticket), STANDARD_HAKEN.shop (Schalter, Bestellpruefung ueber shop/anfrage.js, Unterlagen, Belehrung),
legalDocs-Satz shop, shopTicketDetails sowie Rumpf von anfrageOffenePunkte. Tests angepasst und um Shop-Faelle erweitert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Konflikte: funktionen.js folgt der Aufteilung aus main (fn-util.js, analyse.js); der Link
'Zu Verträge' der Analyse-Seite kommt jetzt auch in analyse.js aus vertraege-link.js.
Checkout und Team-Ansicht übernehmen assertOwnProject(..., { forNewOrder: true }) und
includeArchived aus main. Test-Pins der absoluten Importe nachgezogen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- PUT /fragebogen: ein Tab mit veralteter Branche bekommt 409 EINSTELLUNG_VERALTET (die Branche wechselt nur die Vorlage), bestaetigt wird mit
dem gespeicherten Stand vereinigt; die ungeprüften Vorlagenpreise können nicht mehr als geprüft gelten
- GET /einstellungen liefert in off aboHinweis (aboMeldung, auch bei nicht lesbarem Abo); die Hinweiskarte zeigt ihn immer und hat „Neu laden“
- Bestellseite und Statuskarte laden bei pageshow (persisted) neu, wenn der Browser sie nach der Zahlungsseite aus dem bfcache holt
- renderBestellen zeichnet „Ändern“ und „Zum Schritt“ nur mit zumSchritt; nach einem 409 bekommt die Meldung den Fokus
- Zusammenfassung nennt „Kleinunternehmer: ja/nein“
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- markOrdered speichert IP und Browser der Bestellung nicht mehr am Funktionsdokument (nur im Nachweis featureConsents, dort mit
Löschfrist); Altwerte werden bei einer neuen Bestellung geleert
- Aufbewahrungslauf (retention): consentIp, consentUserAgent, consentText, consentAt werden an allen Funktionsdokumenten eines fälligen
Kunden geleert, auch an abgeschalteten; Fehlschlag hält den Kunden wie die übrigen abhängigen Daten
- Einmal-Skript scripts/feature-consent-felder-leeren.mjs (Standard Probelauf, --apply leert nur, wo featureConsents die Angabe trägt)
- 30-Tage-Reset (jobs.js): auch eine bezahlte Einrichtung mit Grund abo_ende_vor_einrichtung und noch nicht gemeldetem T19 wird nicht
zurückgesetzt, solange zahlungMeldung nicht gemeldet ist (die Spur der Erstattung bleibt)
- K22: enddatum ist das Abo-Ende (lage.endedAt), sonst der Tag des Abschaltens; loeschdatum bleibt 30 Tage nach dem Abschalten
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- adoptPaidSession übernimmt ein erneut zugestelltes checkout.session.completed nicht mehr, wenn das Dokument nach 30 Tagen zurückgesetzt wurde
(off, purchaseStatus zurueckgesetzt, gleiche Sitzung): kein Setup, kein Ticket, keine K15/T16
- meldeFreigeschaltet liefert true/false; die Staff-Aktivierung in Textform vermerkt eine nicht gesendete K16 mit Unterlagen in adminNote und
antwortet mit warnung: true
- disable() nutzt die Sperre feature-activate:<id> statt feature-disable:<id> (Freischaltung und Abschalten überholen sich nicht)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
bezahlteSitzung weist Sitzungen mit metadata.zweck behalten mit 409 ab. Sonst ginge die Sitzung über onFeaturePaid in bucheBehalten, das
feature-admin:<projekt> nimmt, während die Team-Route sie schon hält: Stillstand und dauerhaft belegter Schlüssel. Test in
test/zeitenTeamBehalten.test.js: 409 binnen Sekunden, Sperre frei, folgende Team-Aktion nicht blockiert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Zeiten nutzen die echte Widerrufsbelehrung wie der Terminplaner (der Platzhalter BELEHRUNG_PLATZHALTER ist
mit TP2 F7 entfallen). Gepinnte Listen als Vereinigung beider Seiten: K15-Blöcke, T16-Blöcke, legal-Schlüssel der
Projektliste, hindernis in der Team-Ansicht für alle Funktionen. Neue Tests: Abnahme (Freischalten) der Zeiten über den
Haken freischaltbar und mit Ersatz-Hash, abnahme gibt für Zeiten nie ab.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
erinnereFeiertage(now): stündlich, nur bei Schalter pilot/on (pilot: nur
freigegebene Kunden) und nur 08:00 bis 20:00 Berliner Zeit; je Funktion in
setup/active zuerst der Merker sha1(featureId|datum) je Tag (409 = schon
erinnert), danach eine Mail K25 mit allen neuen Tagen ohne BCC ans Team;
Merker älter als 30 Tage werden gelöscht. zeitenAboJob (täglich) und
zeitenErinnerungsJob (stündlich) mit eigener Überlappsperre, ohne Wurf;
in server/index.js nach 240 s bzw. 300 s gestartet, mit unref.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Kunde löschen schaltet die Funktion zeiten wie den Terminplaner ab (Grund
kunde_geloescht) und löscht Zeiten, Erinnerungsmerker und Antwortspeicher
sofort; Fehler halten die Kundenlöschung nicht auf. Die Löschfristen löschen
die Zeiten vor dem Abschalten und zählen sie im Bericht.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
gleicheZeitenAboAb(now) koppelt die im Wartungs-Abo enthaltenen Zeiten
(unlockedBy abo) an das Abo (Spec 5, Z11): Abo-Ende erkennen (aboEndeAt, K26),
nach 30 Berliner Kalendertagen abschalten (abo_ende, K27, Ersatz-Ticket),
bei Rückkehr des Abos wieder einschalten (Neubau nach dem Abschalten, K24
wieder), 30 Tage nach dem Abschalten Daten löschen und state off.
Lesefehler beim Abo: Kunde überspringen, nie abschalten oder löschen.
R25: activate() leert aboEndeAt und behaltenSessionId; starteBehalten lehnt
bei laufendem Wartungs-Abo mit 409 ab (Lesefehler 503).
R17: k24Mail mit einbau null und wieder schaltet beide Einbau-Blöcke ab,
K24 bekommt dafür den Block weiter um den Kasten "Wie geht es weiter?".
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neuer Modus neben Bestellen und Einschalten (Spec 3.3): POST /api/funktionen/zeiten/behalten
startet einen Checkout mit zweck 'behalten', ohne den Zustand zu ändern; der Webhook-Zweig
bucht vor markPaid/adoptPaidSession unter feature-admin zum Kauf (Frist weg, stripeSessionId =
Sitzung), schaltet eine abgeschaltete Funktion wieder ein (Neubau nach der Sperre), ohne neues
Ticket, mit K15 im Behalten-Wortlaut. Passt die Sitzung nicht, geht T19 nach der Sperre raus.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Team-Route für zeiten: Aktivieren läuft über den Gratis-Pfad (einschaltenZeiten, setup,
unlockedBy team, Neubau, Einbau-Ticket, keine K24), Abschalten setzt disabled mit Grund team
ohne Löschfrist und legt über nachAbschaltung bei geändertem Wochenplan das Ticket
"Ersatz-Tabelle aktualisieren" an. PATCH /:customerId/zeiten/team speichert die
Team-Einstellungen mit teamVersion. Die Team-Ansicht liefert für zeiten zusätzlich plaene,
team, teamVersion und hindernis.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Der 5-Minuten-Job setzt Öffnungszeiten live nach dem Schließen des Tickets
nur noch auf active, wenn der Kunde Zeiten eingetragen hat (Haken
freischaltbar: Hauptplan gespeichert, mindestens ein Tag nicht "zu";
Lesefehler ergeben false, das Dokument bleibt in setup). Neuer Register-Haken
nachFreischaltung: runActivation ruft ihn je freigeschaltetem Dokument vor der
K16 auf, Fehler werden nur geloggt; für die Zeiten merkt er den Ersatz-Hash
(wochenplanHash). Selbstheilung (Spec 3.2): im Lauf des Jobs (nicht in der
Projektliste mit customerId) holt holeZeitenNach für Zeiten in setup fehlendes
Ticket und K24 nach, je Dokument abgesichert und ohne Kundendaten im Log.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Checkout: neue Stufe 7b pruefeInklusive (Funktionen mit aboInklusive):
laeuft das Wartungs-Abo (auch nicht aktiv), 409 inklusive mit Hinweis aufs
Einschalten; kein Abo, Hosting und gekuendigt zahlen weiter 30 Euro.
Zahlung (markPaid): setup mit unlockedBy kauf, dann Neubau (stosseNeubauAn,
einbau am Dokument), erst danach das Einbau-Ticket mit dem Ergebnis; die
Webhook-Wiederholung baut nicht noch einmal. Spaete Zahlungen aendern ein
vorhandenes unlockedBy abo/team nicht. News und Terminplaner unveraendert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
POST /api/funktionen/zeiten/einschalten (Gratisweg, Spec 3.2): Abo frisch
prüfen, Zustimmung (consentFrei) und Nachweis ohne Stripe-Sitzung, Zustand
setup mit unlockedBy abo, dann Neubau, Einbau-Ticket und K24; ein zweiter
Klick holt Fehlendes nach (holeZeitenNach, eigene Sperre). GET /api/funktionen
liefert das Angebot (zeiten), features.zeiten mit unlockedBy, aboEndeAt, einbau,
loeschungAm sowie zeitenStatus und zeitenLeer je Projekt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
buildZeiten (einbau.js) liefert dem Runner-Auftrag { siteKey } bei Funktion in setup/active,
null bei Sperrliste und Fehlern. stosseNeubauAn (neubau.js) stößt den Neubau unter der
Sperre zeiten-neubau an und meldet angestossen oder manuell.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neue Kundenmails (Du-Form, Skelett von K23):
- K24 eingeschaltet (Blöcke angestossen/manuell nach einbau, wieder nach der Abo-Rückkehr)
- K25 Feiertage prüfen (Blöcke pruefen/mehrere, ohne BCC)
- K26 Abo beendet (abo_ende/hosting/wechsel_widerrufen, Frist, einmalig 30 € behalten)
- K27 abgeschaltet (feste Zeiten, Eingaben bis zum Löschdatum, Wiedereinschalten)
server/services/zeiten/mails.js: Builder k24Mail bis k27Mail und sendeZeitenMail
(wirft nie, ohne Adresse { sent:false, reason:'keine_adresse' }, Log ohne Adresse und Namen).
K15 bekommt den Block behalten (Gegenstück neu für den Einrichtungstext; bestellMail
setzt neu = nicht behalten, Standard unverändert), T16 die Blöcke abo und team
(sendT16 führt sie als Vorgabe aus). Pins in mailTemplates- und featureMails-Tests
angepasst; K26 darf „Wartungs-Abo“ im Betreff führen.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /api/public/zeiten/v1/:siteKey mit CORS *, OPTIONS 204, 405, weichem ETag
ohne stand, Cache-Control max-age=60, Expose-Headers Date, Grenze 120 je Minute
und IP (zeiten/limits.js), 503 ohne Details und 404 für unbekannte Pfade.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Das Website-Skript rechnet keine Zeitzonen und braucht tag (Berliner Kalendertag
bei ab) für „heute“ und die nächsten 14 Tage; wechsel-Einträge sind wieder
{ ab, tag, offen, text, kurz }.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
oeffentlich.js baut die Antwort für das Website-Skript (Pläne mit Woche, 60 Tagen
und Statuswechseln, Hinweise, Kontakt-Leiste, JSON-LD, Firma, Team) und merkt sie
30 Sekunden je siteKey. Ungültige Schlüssel und ausgeschalteter Schalter lösen
weder eine Abfrage noch einen Cache-Eintrag aus; die Funktion antwortet schon in
setup. findActiveBySiteKey nimmt dafür { states } entgegen (Vorgabe wie bisher
nur active).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Neue Team-Aktionen abnahme (Freischalten ohne Ticket-Schliessung, K16
einmal, unter feature-activate:<id> mit Haken freischaltHindernis) und
ticket (Ticket nachlegen: Zahlung bei Stripe pruefen und Webhook-Weg,
geloeschtes Ticket ersetzen, vorhandenes unberuehrt). Ticketanlage aus
markPaid in legeTicketAn herausgeloest.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
GET/PUT /api/zeiten/:projectId und GET .../vorschau für den Editor im Portal.
Zugang nach Funktionszustand (ordered/setup/active lesen und speichern,
disabled mit Daten nur lesen), Version 0 vor dem ersten Speichern, 409
ZEITEN_VERALTET, 60 Speichervorgänge je Kunde und Stunde. Die Kundenansicht darf
speichern (Protokoll zeiten_gespeichert), den WhatsApp-Haken setzt nur der
Kunde selbst: bestaetigtAt kommt vom Server (R12), in der Kundenansicht 403.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
freischaltHindernis (Abo zuerst, dann Einstellung; Abo-Lesefehler = abo_unbekannt)
und meldeFreigeschaltet (K16, Fehler geloggt, mit attachments) in
termine/freischaltung.js. Der Standardhaken freischaltbar fuer termine
delegiert an freischaltHindernis, runActivation an meldeFreigeschaltet.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>