Buchungskalender: Abschluss – L1 Textform-Zustimmung fuer die Aktivierung ohne Zahlung (Server, GET-Feld unterkunft)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4f9fb6b109
commit
6d35674c1e
5 files changed
+179
-9
No files matched your search
@@ -31,6 +31,7 @@ import { driftWarnung, einbauanleitung, ticketStand } from '../../services/termi
|
||||
import { freischaltHindernis, meldeFreigeschaltet } from '../../services/termine/freischaltung.js'
|
||||
import { ladeStand } from '../../services/termine/kontext.js'
|
||||
import { shopTextformNoetig } from '../../services/shop/schalter.js'
|
||||
import { unterkunftTextformNoetig } from '../../services/unterkunft/schalter.js'
|
||||
import { termineTextformNoetig } from '../../services/termine/schalter.js'
|
||||
|
||||
/**
|
||||
@@ -121,8 +122,8 @@ async function notiereK16Fehlt(projectId, doc) {
|
||||
|
||||
const ticketExists = async (ticketId) => (await readTicket(ticketId)) !== null
|
||||
|
||||
/** Verlangt die Aktivierung dieser Funktion fuer diese Adresse die Zustimmung in Textform? Nur Terminplaner und Webshop, je nach Modus und Pilotliste der Funktion. */
|
||||
const textformVerlangt = { termine: termineTextformNoetig, shop: shopTextformNoetig }
|
||||
/** Verlangt die Aktivierung dieser Funktion fuer diese Adresse die Zustimmung in Textform? Nur Terminplaner, Webshop und Buchungskalender, je nach Modus und Pilotliste der Funktion. */
|
||||
const textformVerlangt = { termine: termineTextformNoetig, shop: shopTextformNoetig, unterkunft: unterkunftTextformNoetig }
|
||||
|
||||
/**
|
||||
* Zustimmung des Kunden in Textform fuer die Aktivierung des Terminplaners oder des Webshops durch das Team (F13a; AVV Webshop,
|
||||
@@ -147,7 +148,7 @@ async function unterlagenAlsAnhang(key) {
|
||||
return await featureLegalAttachments(key, { ohne: ['widerruf'] })
|
||||
} catch (err) {
|
||||
console.error('[funktionen-admin] Rechtsunterlagen (PDF) fuer die Freischaltung nicht lesbar:', err.message)
|
||||
const funktion = key === 'shop' ? 'Der Webshop' : 'Der Terminplaner'
|
||||
const funktion = key === 'shop' ? 'Der Webshop' : key === 'unterkunft' ? 'Der Buchungskalender' : 'Der Terminplaner'
|
||||
throw Object.assign(new Error(`Die Rechtsunterlagen (PDF) sind nicht lesbar. ${funktion} wurde nicht freigeschaltet. Bitte später erneut versuchen.`), { status: 503 })
|
||||
}
|
||||
}
|
||||
@@ -199,10 +200,20 @@ async function shopFeld(customerId) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Dasselbe fuer den Buchungskalender (AVV Buchungskalender, Vorbemerkung Abs. 2): Fassung = config.unterkunft.fassung. */
|
||||
async function unterkunftFeld() {
|
||||
const { lb, avv } = featureLegalPaths('unterkunft')
|
||||
return {
|
||||
textformNoetig: unterkunftTextformNoetig(),
|
||||
avvVersion: config.unterkunft.fassung,
|
||||
links: { lb: `${config.publicBaseUrl}${lb}`, avv: `${config.publicBaseUrl}${avv}` },
|
||||
}
|
||||
}
|
||||
|
||||
funktionenAdminRouter.get('/:customerId', async (req, res) => {
|
||||
try {
|
||||
const projects = await adminView(req.params.customerId)
|
||||
res.json({ projects, termine: await termineFeld(req.params.customerId), shop: await shopFeld(req.params.customerId) })
|
||||
res.json({ projects, termine: await termineFeld(req.params.customerId), shop: await shopFeld(req.params.customerId), unterkunft: await unterkunftFeld() })
|
||||
} catch (err) {
|
||||
sendError(res, err)
|
||||
}
|
||||
|
||||
@@ -617,8 +617,8 @@ async function assertAboLaeuftFuerAktivierung(customerId) {
|
||||
const TEXTFORM_WEG = { chat: 'Chat im Kundenportal', email: 'E-Mail' }
|
||||
|
||||
/** Funktionen, die das Team mit Zustimmung des Kunden in Textform aktivieren kann (Modus on), und die Fassung der Unterlagen, auf die sie sich bezieht. */
|
||||
export const TEXTFORM_KEYS = ['termine', 'shop']
|
||||
export const textformFassung = (key) => (key === 'shop' ? config.shop.fassung : config.termine.avvVersion)
|
||||
export const TEXTFORM_KEYS = ['termine', 'shop', 'unterkunft']
|
||||
export const textformFassung = (key) => (key === 'shop' ? config.shop.fassung : key === 'unterkunft' ? config.unterkunft.fassung : config.termine.avvVersion)
|
||||
|
||||
/**
|
||||
* Text des Nachweises, wenn der Kunde dem Terminplaner oder dem Webshop in Textform zugestimmt hat (Aktivierung durch das Team im
|
||||
@@ -629,6 +629,9 @@ export function textformNachweisText({ date, channel }, fassung, key = 'termine'
|
||||
if (key === 'shop') {
|
||||
return `Der Kunde hat am ${tag}.${monat}.${jahr} per ${TEXTFORM_WEG[channel]} in Textform erklärt, dass er der Leistungsbeschreibung Webshop und dem Auftragsverarbeitungsvertrag Webshop (Fassung ${fassung}) zustimmt und die folgenden Erklärungen der Bestelltexte der Fassung ${fassung} abgibt.`
|
||||
}
|
||||
if (key === 'unterkunft') {
|
||||
return `Der Kunde hat am ${tag}.${monat}.${jahr} per ${TEXTFORM_WEG[channel]} in Textform erklärt, dass er der Leistungsbeschreibung Buchungskalender und dem Auftragsverarbeitungsvertrag Buchungskalender (Fassung ${fassung}) zustimmt.`
|
||||
}
|
||||
return `Der Kunde hat der Leistungsbeschreibung Terminplaner und dem Auftragsverarbeitungsvertrag Terminplaner (Fassung ${fassung}) am ${tag}.${monat}.${jahr} per ${TEXTFORM_WEG[channel]} in Textform zugestimmt und bestätigt, dass sein Angebot nicht im Gesundheitsbereich liegt.`
|
||||
}
|
||||
|
||||
@@ -648,13 +651,13 @@ function textformNachweisTexte(textform, fassung, key) {
|
||||
* Freischaltung ohne Zahlung und ohne Ticket (unlockedByPurchase bleibt false). Ausnahme: ein Terminplaner, den ein Kauf
|
||||
* freigeschaltet hat (unlockedByPurchase true), wird nur bei laufendem Wartungs-Abo aktiviert (409 sonst, Lesefehler => Fehler).
|
||||
* News und Dokumente ohne Kauf (Pilot, Kulanz) sind nicht betroffen.
|
||||
* textform (nur Terminplaner und Webshop, schon geprueft: { date, channel }): Zustimmung des Kunden in Textform. Der Nachweis
|
||||
* textform (nur Terminplaner, Webshop und Buchungskalender, schon geprueft: { date, channel }): Zustimmung des Kunden in Textform. Der Nachweis
|
||||
* (featureConsents, ohne Stripe-Sitzung, IP und Browser; Konto = Mitarbeiter; Fassung = textformFassung(key)) wird VOR der Freischaltung
|
||||
* gespeichert: scheitert er, bleibt die Funktion aus. Der Aufrufer sendet danach K16 mit den Unterlagen (meldeFreigeschaltet).
|
||||
*/
|
||||
export async function adminActivate(customerId, projectId, key, { by, adminNote, textform = null, now = new Date() } = {}) {
|
||||
assertKey(key)
|
||||
if (textform && !TEXTFORM_KEYS.includes(key)) throw httpError(400, 'Zustimmung in Textform gibt es nur für den Terminplaner und den Webshop')
|
||||
if (textform && !TEXTFORM_KEYS.includes(key)) throw httpError(400, 'Zustimmung in Textform gibt es nur für den Terminplaner, den Webshop und den Buchungskalender')
|
||||
await assertOwnProject(customerId, projectId)
|
||||
const doc = await ensureFeatureDoc(customerId, projectId, key)
|
||||
if (key === 'termine' && doc.unlockedByPurchase === true) await assertAboLaeuftFuerAktivierung(customerId)
|
||||
|
||||
@@ -24,3 +24,12 @@ export function unterkunftFuerKunde(email) {
|
||||
const adresse = String(email || '').trim().toLowerCase()
|
||||
return adresse !== '' && erlaubt.includes(adresse)
|
||||
}
|
||||
|
||||
/**
|
||||
* Verlangt die Aktivierung durch das Team (WOMS, ohne Bestellung) die Zustimmung des Kunden in Textform (AVV Buchungskalender,
|
||||
* Vorbemerkung Abs. 2)? Anders als beim Webshop auch im Pilot: der Buchungskalender wird zuerst fuer einen echten Kunden (Pilotadresse)
|
||||
* ohne Bestellung freigeschaltet, dessen Zustimmung muss vorliegen. Nur bei off (Funktion ohnehin gesperrt) entfaellt sie.
|
||||
*/
|
||||
export function unterkunftTextformNoetig() {
|
||||
return unterkunftModus() !== 'off'
|
||||
}
|
||||
Reference in new issue
Block a user