Abo-Baustein (Kernversion) und Platzhalter fuer die Bestellpruefung
aboStatus.js: laeuft(customerId) (Wartungs-Abo, productKey || 'wartung', Status in ACTIVE_STATUSES), bestellbar(customerId) mit den Gruenden kein_abo, gekuendigt, nicht_aktiv in dieser Pruefreihenfolge und aboMemo() (je Aufruf und Kunde nur eine Lesung). Fail-closed: ein Lesefehler wirft, nie false oder ok:false. termine/fragebogen.js: Platzhalter bestellpruefung() mit der endgueltigen Signatur, liefert []; Block C ersetzt ihn. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
786df1230e
commit
d568a3798d
4 files changed
+258
No files matched your search
@@ -0,0 +1,57 @@
|
||||
// KERNVERSION (Block B) – Block E baut aus
|
||||
import { ACTIVE_STATUSES, getCurrentSubscription } from './stripeBilling.js'
|
||||
|
||||
// Abo-Baustein fuer Funktionen, die ein laufendes Wartungs-Abo voraussetzen (Terminplaner; die Analyse zieht in
|
||||
// Block E nach). Fail-closed: ein Lesefehler wirft, er wird nie zu false bzw. ok:false. Wer die Fehler abfaengt,
|
||||
// entscheidet selbst, was dann gilt (Bestellung ablehnen, Kunde im Listenlauf ueberspringen, nie abschalten).
|
||||
|
||||
// Wartungs-Abo: Altbestand ohne productKey gilt als Wartung (wie routes/abo.js productKeyOf), ein anderer
|
||||
// Schluessel (hosting, mailStorage, unbekannt) nicht. Status wie im Portal: active, trialing, past_due.
|
||||
function laeuftAus(sub) {
|
||||
return Boolean(sub) && (sub.productKey || 'wartung') === 'wartung' && ACTIVE_STATUSES.has(sub.status)
|
||||
}
|
||||
|
||||
// Die Gruende gelten in dieser Reihenfolge fuer alle Bloecke: kein laufendes Wartungs-Abo => kein_abo; Kuendigung
|
||||
// vorgemerkt (cancelAtPeriodEnd oder cancelAt, auch bei trialing und past_due) => gekuendigt; Status nicht active
|
||||
// (trialing, past_due) => nicht_aktiv.
|
||||
function bestellbarAus(sub) {
|
||||
if (!laeuftAus(sub)) return { ok: false, grund: 'kein_abo' }
|
||||
if (sub.cancelAtPeriodEnd || sub.cancelAt) return { ok: false, grund: 'gekuendigt' }
|
||||
if (sub.status !== 'active') return { ok: false, grund: 'nicht_aktiv' }
|
||||
return { ok: true }
|
||||
}
|
||||
|
||||
/** Hat der Kunde ein laufendes Wartungs-Abo? Wirft bei Lesefehler. */
|
||||
export async function laeuft(customerId) {
|
||||
return laeuftAus(await getCurrentSubscription(customerId))
|
||||
}
|
||||
|
||||
/** Darf der Kunde jetzt bestellen? { ok: true } oder { ok: false, grund: 'kein_abo' | 'gekuendigt' | 'nicht_aktiv' }. Wirft bei Lesefehler. */
|
||||
export async function bestellbar(customerId) {
|
||||
return bestellbarAus(await getCurrentSubscription(customerId))
|
||||
}
|
||||
|
||||
/**
|
||||
* Zwischenspeicher fuer einen Lauf (eine Anfrage, ein Listenlauf): { laeuft, bestellbar } mit denselben Antworten
|
||||
* wie oben, aber das Abo jedes Kunden wird je aboMemo()-Aufruf nur einmal gelesen (auch bei gleichzeitigen Fragen,
|
||||
* und fuer laeuft und bestellbar gemeinsam). Ein Lesefehler wird nicht gemerkt: der naechste Aufruf liest neu.
|
||||
*/
|
||||
export function aboMemo() {
|
||||
const gelesen = new Map()
|
||||
const lade = (customerId) => {
|
||||
if (!gelesen.has(customerId)) {
|
||||
gelesen.set(
|
||||
customerId,
|
||||
getCurrentSubscription(customerId).catch((err) => {
|
||||
gelesen.delete(customerId)
|
||||
throw err
|
||||
})
|
||||
)
|
||||
}
|
||||
return gelesen.get(customerId)
|
||||
}
|
||||
return {
|
||||
laeuft: async (customerId) => laeuftAus(await lade(customerId)),
|
||||
bestellbar: async (customerId) => bestellbarAus(await lade(customerId)),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// STUB (Block B) – ersetzt Task C2 (bestellpruefung); Task C1 legt in dieser Datei den Rest des Fragebogen-Dienstes an
|
||||
|
||||
/**
|
||||
* Bestellpruefung des Terminplaners: Liste der offenen Punkte `[{ schritt, text }]`, leer = bestellbar.
|
||||
* Die Signatur ist endgueltig (Block C ersetzt nur den Rumpf): `mitAbo !== false` schaltet den Abo-Punkt (h)
|
||||
* dazu, den nur die Vorschau (GET /api/termine/einstellungen) mit `abo` anfordert; der Checkout ruft mit
|
||||
* `mitAbo: false` und ohne `abo`. Der Platzhalter meldet nichts offen.
|
||||
*/
|
||||
export function bestellpruefung({ einstellung, fragebogen, feature, abo, mitAbo = true } = {}) {
|
||||
return []
|
||||
}
|
||||
Reference in new issue
Block a user