Terminplaner: Kurzfassung der Einbauanleitung fuer das Einrichtungs-Ticket, T16-Gesundheitsblock

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-05 00:45:56 +00:00
1 parent 90692b646b
commit 2db3eca357
9 files changed
+1181 -49

No files matched your search

+41 -3
View File
@@ -4,7 +4,7 @@ import { createDocument, getDocument, listDocuments, updateDocument, Query } fro
import { withLocks } from './keyedLock.js'
import { sendAdminNotice, sendCustomerMail } from './mailer.js'
import { getStripe, retrieveCheckoutSession } from './stripeBilling.js'
import { anleitungsLink, featureConfig, featureHaken, featureKeys, ticketFreischaltungKeys, ticketTexte } from './featureRegistry.js'
import { anleitungsLink, featureConfig, featureHaken, featureKeys, kuerze, ticketFreischaltungKeys, ticketTexte } from './featureRegistry.js'
import { zustimmungFuerSitzung } from './featureConsents.js'
import { aboLage, laeuft } from './aboStatus.js'
import { loeschTag } from './termine/frist.js'
@@ -711,7 +711,7 @@ async function ticketWoidOf(doc) {
/**
* T16 an das Team (Funktion bestellt): alle Platzhalter und Bloecke der Vorlage; was nicht genannt wird, bleibt leer bzw. aus.
* Ohne bekannte Funktion heisst sie in Betreff und Text "Funktion". Liefert das Ergebnis von sendAdminNotice ({ sent, reason? }); der
* Block gesundheit bleibt hier aus (D4 fuellt ihn).
* Der Block gesundheit (Terminplaner) steht nur, wenn der Aufrufer ihn mit gesundheit_text einschaltet (teamNotice).
*/
function sendT16({ funktion, ...werte }, bloecke) {
return sendAdminNotice({
@@ -733,11 +733,48 @@ function sendT16({ funktion, ...werte }, bloecke) {
})
}
/** Der Warntext des T16-Blocks gesundheit hat hoechstens so viele Zeichen (ganze Meldungen, danach "… und N weitere"). */
const GESUNDHEIT_TEXT_MAX = 500
/** Meldungen als ein Text: durch "; " getrennt; passt es nicht, so viele ganze Meldungen wie moeglich und "… und N weitere" (nie mitten in einer Meldung). */
function gesundheitText(meldungen) {
const alle = meldungen.join('; ')
if (alle.length <= GESUNDHEIT_TEXT_MAX) return alle
let text = ''
let n = 0
for (const meldung of meldungen) {
const naechster = text ? `${text}; ${meldung}` : meldung
if (`${naechster} … und ${meldungen.length - n - 1} weitere`.length > GESUNDHEIT_TEXT_MAX) break
text = naechster
n += 1
}
return text ? `${text} … und ${meldungen.length - n} weitere` : kuerze(meldungen[0], GESUNDHEIT_TEXT_MAX, { endzeile: '…' })
}
/**
* T16-Hinweis "Gesundheitsbereich pruefen" (nur Terminplaner): die Treffer der Stichwortpruefung ueber die gespeicherte Einstellung des Betriebs
* (gesundheitsMeldungen: wohlgeformt, einzeilig, Klartext; renderMail maskiert sie fuer HTML), hoechstens 500 Zeichen. '' ohne Treffer und bei
* jedem Lesefehler: T16 geht dann ohne Block raus (nie Geld ohne Spur); das Log nennt keine Daten des Betriebs. Dynamische Importe, weil
* termine/kontext.js dieses Modul importiert.
*/
async function gesundheitHinweis(doc) {
if (doc.featureKey !== 'termine') return ''
try {
const [{ ladeEinstellung }, { gesundheitsMeldungen }] = await Promise.all([import('./termine/kontext.js'), import('./termine/einbauanleitung.js')])
const meldungen = gesundheitsMeldungen((await ladeEinstellung(doc.$id))?.einstellung)
return meldungen.length ? gesundheitText(meldungen) : ''
} catch (err) {
console.error(`[funktionen] Gesundheitshinweis fuer T16 (Funktion ${doc.$id}) nicht lesbar, der Block entfaellt:`, err.message)
return ''
}
}
/** keinAbo: die Zahlung ist da, der Kunde hat aber kein laufendes Wartungs-Abo (Block kein_abo, nur bei Funktionen mit requiresWartungsAbo). */
async function teamNotice(doc, customer, { failed = false, keinAbo = false } = {}) {
const mails = featureConfig(doc.featureKey)?.mails
// Knopf zur Einbauanleitung nur bei Funktionen mit Anleitung und nur, wenn bestellt und ein Ticket angelegt wurde
const anleitung = Boolean(mails?.anleitung) && !failed
const gesundheit = failed ? '' : await gesundheitHinweis(doc)
await sendT16(
{
kunde_name: customer?.name || customer?.email || doc.customerId,
@@ -747,8 +784,9 @@ async function teamNotice(doc, customer, { failed = false, keinAbo = false } = {
woid: failed ? '' : await ticketWoidOf(doc),
sitekey: failed ? '' : doc.siteKey || '',
anleitung_url: anleitung ? anleitungsLink(doc.customerId, doc.projectId) : '',
gesundheit_text: gesundheit,
},
{ zahlung_fehlgeschlagen: failed, anleitung, kein_abo: keinAbo }
{ zahlung_fehlgeschlagen: failed, anleitung, kein_abo: keinAbo, gesundheit: gesundheit !== '' }
)
}