Hosting-Abo: Preis 15 € -> 20 € pro Monat (Vertragsbedingungen v4, Katalog, Leitfaden)

- server/config.js: amountCents 2000, lookup_key webklar_hosting_monatlich_2000
- ensurePrice haengt einen neuen Preis an das vorhandene Stripe-Produkt (metadata.webklar),
  statt ein zweites "WEBklar Hosting-Abo" anzulegen
- abo-bedingungen.html (Uebersicht, Preise, Leistungsbeschreibung) + PDF, Leitfaden + PDF
- Tests auf 20 € umgestellt (399/399)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Opus 5.5 committed 2026-09-29 16:29:01 +00:00
1 parent 78b4d7b7fe
commit e4efdac226
18 files changed
+79 -59

No files matched your search

+10 -10
View File
@@ -25,8 +25,8 @@ const keys = new Map([['price_w', 'wartung'], ['price_h', 'hosting'], ['price_s'
test('Katalog: Preise, lookup_keys, Minuten, Mindestlaufzeit', () => {
assert.equal(getProduct('wartung').amountCents, 5000)
assert.equal(getProduct('hosting').amountCents, 1500)
assert.equal(getProduct('hosting').lookupKey, 'webklar_hosting_monatlich_1500')
assert.equal(getProduct('hosting').amountCents, 2000)
assert.equal(getProduct('hosting').lookupKey, 'webklar_hosting_monatlich_2000')
assert.equal(getProduct('wartung').minutesPerMonth, 60)
assert.equal(getProduct('hosting').minutesPerMonth, 0)
assert.equal(getProduct('hosting').minTermMonths, 12)
@@ -46,7 +46,7 @@ test('Bisherige Werte bleiben gleich', () => {
test('lookup_key → Produkt', () => {
assert.equal(productKeyForLookupKey('webklar_wartung_monatlich_5000'), 'wartung')
assert.equal(productKeyForLookupKey('webklar_hosting_monatlich_1500'), 'hosting')
assert.equal(productKeyForLookupKey('webklar_hosting_monatlich_2000'), 'hosting')
assert.equal(productKeyForLookupKey('webklar_mailspeicher_5gb_monatlich_100'), 'mailStorage')
assert.equal(productKeyForLookupKey('irgendwas'), null)
assert.equal(productKeyForLookupKey(undefined), null)
@@ -55,14 +55,14 @@ test('lookup_key → Produkt', () => {
test('describeItems: Abo-Posten und Zusatzspeicher, Reihenfolge egal', () => {
const items = [
{ id: 'si_s', quantity: 2, price: { id: 'price_s', lookup_key: 'webklar_mailspeicher_5gb_monatlich_100', unit_amount: 100 } },
{ id: 'si_a', quantity: 1, price: { id: 'price_h', lookup_key: 'webklar_hosting_monatlich_1500', unit_amount: 1500 } },
{ id: 'si_a', quantity: 1, price: { id: 'price_h', lookup_key: 'webklar_hosting_monatlich_2000', unit_amount: 2000 } },
]
assert.deepEqual(describeItems(items), {
productKey: 'hosting',
aboItemId: 'si_a',
aboPriceId: 'price_h',
lookupKey: 'webklar_hosting_monatlich_1500',
priceAmount: 1500,
lookupKey: 'webklar_hosting_monatlich_2000',
priceAmount: 2000,
storageItemId: 'si_s',
storageUnits: 2,
})
@@ -85,11 +85,11 @@ test('describeItems: ohne bekannten Abo-Preis', () => {
test('Stunden nur für eine reguläre Wartungs-Zeile über 0 €', () => {
const inv = (...lines) => ({ lines: { data: lines } })
assert.equal(creditMinutesForInvoice(inv(line('price_w', 5000)), keys), 60)
assert.equal(creditMinutesForInvoice(inv(line('price_h', 1500), line('price_s', 200)), keys), 0)
assert.equal(creditMinutesForInvoice(inv(line('price_h', 2000), line('price_s', 200)), keys), 0)
assert.equal(creditMinutesForInvoice(inv(line('price_w', 2300, true)), keys), 0) // anteilige Verrechnung
assert.equal(creditMinutesForInvoice(inv(line('price_w', 0)), keys), 0) // Probezeit
// unbekannter Preis neben einem bekannten Abo-Preis: keine Stunde
assert.equal(creditMinutesForInvoice(inv(line('price_h', 1500), line('price_x', 800)), keys), 0)
assert.equal(creditMinutesForInvoice(inv(line('price_h', 2000), line('price_x', 800)), keys), 0)
const invoiceItem = {
amount: 1200,
pricing: { price_details: { price: 'price_w' } },
@@ -156,7 +156,7 @@ test('productView: vollständige Form, Kopie der features', () => {
assert.deepEqual(Object.keys(v).sort(), ['amountCents', 'features', 'key', 'minTermMonths', 'minutesPerMonth', 'name'].sort())
assert.equal(v.key, 'hosting')
assert.equal(v.name, 'WEBklar Hosting-Abo')
assert.equal(v.amountCents, 1500)
assert.equal(v.amountCents, 2000)
assert.equal(v.minTermMonths, 12)
assert.equal(v.minutesPerMonth, 0)
assert.ok(Array.isArray(v.features) && v.features.length > 0)
@@ -201,7 +201,7 @@ test('regularStorageLine: reguläre Zusatzspeicher-Zeile, keine anteilige, kein
const storage = { ...line('price_s', 300), quantity: 3 }
assert.equal(regularStorageLine(inv(line('price_s', 90, true), line('price_w', 5000), storage), keys), storage)
assert.equal(regularStorageLine(inv(line('price_s', 90, true)), keys), null)
assert.equal(regularStorageLine(inv(line('price_w', 5000), line('price_h', 1500)), keys), null)
assert.equal(regularStorageLine(inv(line('price_w', 5000), line('price_h', 2000)), keys), null)
assert.equal(regularStorageLine(inv({ amount: 5 }), keys), null)
assert.equal(regularStorageLine({}, keys), null)
})