- activate() schreibt die Zeiten-Felder (aboEndeAt, behaltenSessionId) nur noch über extra
(nur Abo-Rückkehr und Team-Aktivierung der Zeiten); News und Terminplaner laufen auch vor zeiten-setup.mjs
- Abo-Abgleich: K27 gilt als offen, solange der Marker vor disabledAt liegt (kein Zurücksetzen nach disable() nötig);
K27 geht erst nach dem Ersatz-Ticket raus (scheitert es, wiederholt der nächste Lauf beides);
Löschung setzt auch activatedAt zurück
- Zustimmung "beginn" (bezahlt) mit Wertersatz-Satz (§ 357a Abs. 2 BGB) wie bei News und Terminplaner, Fassung 2026-10-05
- Widerruf: Bestellung "zeiten" in ORDERS, FEATURE_OF_ORDER, orderLabel und widerrufen.html
- Team "Ticket nachlegen" der Zeiten ohne Kauf geht über holeZeitenNach statt über den Zahlungsweg
- Einschalten-Route nimmt nur { zustimmung }, nicht die Altform { consent: true }
- Team-Aktivierung behält kauf/unlockedByPurchase bei einem bisher gekauften Dokument
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
schliesseAb ist die einzige Stelle fuer den Status bezahlt: Sperre je Bestellung, Konto muss zum Shop passen,
idempotent, spaete Zahlung nach Ablauf wird angenommen, SEPA erst bei bezahlt, Bestandsabzug mit Ueberverkauft-Hinweis,
G09 an den Kaeufer und K25 an den Haendler (Mailfehler machen nichts rueckgaengig). pruefeOffene und jobs.js minutenJob
gleichen offene Bestellungen mit Stripe ab. fakeStripe: completeSession.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Käufermails laufen über die Warteschlange des Terminplaners (G09/G12 mit Vorrang),
G09 wird bei Überlänge um den AGB-Text gekürzt (Link statt Text). Der Mailteil des
Minutenjobs und die Aufräumschritte des Tagesjobs laufen auch bei TERMINE_ENABLED=off,
solange SHOP_ENABLED nicht off ist.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- routes/shop.js: gemeinsame Pruefung mitShop (Schalter, eigenes Projekt, Funktion setup|active, lesend auch disabled, shopConfig
bei Bedarf anlegen); GET /status erweitert (Bereitschaft, geoeffnet, Snippet, Vorschau, Stripe ohne Konto-ID, Zahlen);
Einstellungen, Artikel (mit Bild-Pruefung, Beanspruchen und Aufraeumen), Sortierung, Rechtstexte (Entwurf, Bestaetigen mit Hash),
Oeffnen/Schliessen, Bild-Upload (octet-stream, 8 MB) und Vorschau; Schreib-Limit 300 je Stunde und Kunde
- services/shop/bilder.js: Artikelbilder nach dem Muster von newsImages.js (1600/480 px WebP, Sidecar, 24-h-Aufraeumen, 40 Uploads/h)
- Kundenansicht: sieben Verwaltungs-Pfade erlaubt und als shop_aenderung protokolliert; Anfrage, Oeffnen, Bestaetigen, Stripe bleiben gesperrt
- Tests: shopRoutes, shopBilder; Erwartungen von kundenansichtGuard, customerViewLog und shopAnfrage angepasst
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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>
Kachel „Öffnungszeiten live“ inline in funktionen.js (keine neuen Importe, keine Zusatzabfrage),
Ansicht #zeiten (zeiten.js, zeiten-bestellen.js, zeiten.css) mit Einschalten im Wartungs-Abo,
Bestellen für 30 € (Widerrufsbelehrung vor dem Knopf, Ruling R32), Behalten nach dem Abo-Ende,
Statuskarte je Zustand, Rückkehr von Stripe und Platz für den Editor (Aufgabe 29).
GET /api/funktionen liefert dafür zeiten.belehrung (Haken belehrung der Funktion).
Co-Authored-By: Claude Opus 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>