Abo-Bedingungen Fassung 5: Unterstützung in § 4, Fassung 4 archiviert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-30 15:26:39 +00:00
1 parent 88854aa2b4
commit 8acc743cf7
10 files changed
+538 -41

No files matched your search

+1 -1
View File
@@ -155,7 +155,7 @@ export const config = {
abo: {
// Bei jeder Textaenderung an Bedingungen oder Bestellseite hochziehen (wird mit der Zustimmung gespeichert)
termsVersion: '2026-09-30-v4',
termsVersion: '2026-09-30-v5',
// Mindestlaufzeit ab Leistungsbeginn; Kuendigung zum Ende bis 1 Monat vorher, danach monatlich
minTermMonths: products.wartung.minTermMonths,
minutesPerMonth: products.wartung.minutesPerMonth,
@@ -10,7 +10,7 @@
Platzhalter: {{name}}, {{produkt}}, {{preis}}, {{angebot_text}}, {{vertragsschluss}}, {{leistungsbeginn}}, {{mindestlaufzeit_bis}}, {{bedingungen_version}}, {{zustimmung_zeitpunkt}}
Optionale Blöcke (zwischen WENN-/ENDE-Kommentaren; bei Nichtzutreffen samt Inhalt entfernen): angebot, hosting, wartung, wartung_v3, sofortbeginn, beginn_nach_widerrufsfrist
produkt = Katalogname ohne „WEBklar “ („Hosting-Abo“, „Wartungs-Abo“), preis z. B. „20,00 € / Monat“; genau einer der Blöcke hosting/wartung/wartung_v3 bringt die Liste „Enthalten“:
hosting und wartung nach Fassung 4 (Spec 3.1), wartung_v3 für ein Wartungs-Abo nach Fassung 3 (termsDocFor nicht v4: „1 E-Mail-Postfach · 1 Stunde Arbeitszeit pro Monat“ wie in den Bedingungen v3 § 3).
hosting und wartung nach Fassung 4 oder 5 (Spec 3.1), wartung_v3 für ein Wartungs-Abo nach Fassung 3 (termsDocFor nicht v4/v5: „1 E-Mail-Postfach · 1 Stunde Arbeitszeit pro Monat“ wie in den Bedingungen v3 § 3).
bedingungen_version und das PDF im Anhang kommen aus derselben Quelle (termsDocFor(subDoc.termsVersion).version): ohne gespeicherte Fassung beides Fassung 3.
-->
<meta name="viewport" content="width=device-width, initial-scale=1">
+4 -4
View File
@@ -18,7 +18,7 @@ import {
reconcilePendingSwitch,
switchToWartung,
} from '../services/planSwitch.js'
import { PRODUCT_KEYS, contractAttachmentFor, describeItems, isTermsV4, productLabel, productView, termsDocFor } from '../services/products.js'
import { PRODUCT_KEYS, contractAttachmentFor, describeItems, isTermsV4OrNewer, productLabel, productView, termsDocFor } from '../services/products.js'
import {
ACTIVE_STATUSES,
cancelAtPeriodEnd,
@@ -418,7 +418,7 @@ async function customerNameOf(sub, fallback = '') {
* K01 an den Kunden: Vertragsbestaetigung je Produkt (Katalogname, Preis, Liste "Enthalten" ueber die Bloecke
* hosting/wartung, fuer ein Wartungs-Abo nach Fassung 3 wartung_v3 mit der Zeile der Fassung 3) mit den
* Vertragsunterlagen der Fassung, der der Kunde zugestimmt hat (§ 312f BGB, contractAttachmentFor: v3 Archiv-PDF,
* v4 aktuelles PDF). Versionsangabe und Anhang kommen aus derselben Quelle (termsDocFor.version): ohne gespeicherte
* v4 Archiv-PDF, v5 aktuelles PDF). Versionsangabe und Anhang kommen aus derselben Quelle (termsDocFor.version): ohne gespeicherte
* Fassung beides Fassung 3. Ohne lesbare Datei geht die Mail ohne Anhang raus.
*/
async function sendContractConfirmation(subDoc, fallbackName = '') {
@@ -448,8 +448,8 @@ async function sendContractConfirmation(subDoc, fallbackName = '') {
blocks: {
angebot: Boolean(subDoc.offerText),
hosting: productKey === 'hosting',
wartung: productKey === 'wartung' && isTermsV4(terms.version),
wartung_v3: productKey === 'wartung' && !isTermsV4(terms.version),
wartung: productKey === 'wartung' && isTermsV4OrNewer(terms.version),
wartung_v3: productKey === 'wartung' && !isTermsV4OrNewer(terms.version),
sofortbeginn: !lateStart,
beginn_nach_widerrufsfrist: lateStart,
},
+23 -9
View File
@@ -25,26 +25,40 @@ export function getProduct(key) {
return product
}
/** Die archivierte Fassung 3 (public/vertragsunterlagen/v3): gilt fuer jede Zustimmung ohne Fassung "-v4". */
/** Die archivierte Fassung 3 (public/vertragsunterlagen/v3): gilt fuer jede Zustimmung ohne Fassung "-v4"/"-v5". */
export const TERMS_VERSION_V3 = '2026-09-25-v3'
/** Ist die Fassung die aktuelle Version 4 (Hosting- und Wartungs-Abo)? Aeltere und fehlende Fassungen: nein. */
export function isTermsV4(termsVersion) {
return typeof termsVersion === 'string' && termsVersion.endsWith('-v4')
/** Aktuelle Fassung 5 (Unterstuetzung in § 4 Abs. 4)? */
export function isCurrentTerms(termsVersion) {
return typeof termsVersion === 'string' && termsVersion.endsWith('-v5')
}
/** Fassung 4 oder neuer (Hosting- und Wartungs-Abo, Zusatzspeicher, Wechsel)? Aeltere und fehlende Fassungen: nein. */
export function isTermsV4OrNewer(termsVersion) {
return typeof termsVersion === 'string' && /-v[45]$/.test(termsVersion)
}
/**
* Vertragsunterlagen zur zugestimmten Fassung: Version 4 (Suffix "-v4") zeigt die aktuellen
* Bedingungen samt PDF, jede aeltere Version (auch unbekannt/keine) das Archiv der Version 3.
* Vertragsunterlagen zur zugestimmten Fassung: Fassung 5 (Suffix "-v5") zeigt die aktuellen Bedingungen samt PDF,
* Fassung 4 das Archiv unter public/vertragsunterlagen/v4, jede aeltere Version (auch unbekannt/keine) das Archiv
* der Version 3.
* version: die Fassung, die eine Mail nennt - die gespeicherte, ohne gespeicherte die archivierte Fassung 3,
* damit Versionsangabe und PDF-Anhang immer zusammenpassen (Task 12 Fix 1).
* endParagraph: der Paragraph zum Vertragsende (Daten, AuthCode, Loeschung) in dieser Fassung, fuer die
* Mails K02/K03/T05/T07 (F08) - in Fassung 4 ist § 9 der Wechsel zwischen den Abos, § 11 das Vertragsende.
* Mails K02/K03/T05/T07 (F08) - ab Fassung 4 ist § 9 der Wechsel zwischen den Abos, § 11 das Vertragsende.
*/
export function termsDocFor(termsVersion) {
if (isTermsV4(termsVersion)) {
if (isCurrentTerms(termsVersion)) {
return { version: termsVersion, url: '/abo-bedingungen.html', pdfFile: 'WEBklar-Abo-Vertragsunterlagen.pdf', endParagraph: '§ 11' }
}
if (isTermsV4OrNewer(termsVersion)) {
return {
version: termsVersion,
url: '/vertragsunterlagen/v4/abo-bedingungen.html',
pdfFile: 'vertragsunterlagen/v4/WEBklar-Abo-Vertragsunterlagen.pdf',
endParagraph: '§ 11',
}
}
return {
version: typeof termsVersion === 'string' && termsVersion ? termsVersion : TERMS_VERSION_V3,
url: '/vertragsunterlagen/v3/abo-bedingungen.html',
@@ -68,7 +82,7 @@ const PUBLIC_DIR = path.join(path.dirname(fileURLToPath(import.meta.url)), '..',
*/
export function contractAttachmentFor(termsVersion) {
const { pdfFile } = termsDocFor(termsVersion)
return { filename: pdfFile, path: path.join(PUBLIC_DIR, pdfFile) }
return { filename: path.basename(pdfFile), path: path.join(PUBLIC_DIR, pdfFile) }
}
/** Ansicht eines Produkts fuers Kundenportal (Vergleich, Bestellseite): Preis und Leistungen. */