Mail T16 je Funktion, neue Vorlage T19 Erstattung faellig

T16 (Funktion bestellt) nennt die Funktion aus dem Register statt fest
"News-Pinnwand": neue Platzhalter funktion, zustand, anleitung_url und
gesundheit_text, neue Bloecke kein_abo, bereits_aktiv, anleitung (Knopf
"Im Ticketsystem oeffnen" zur Einbauanleitung) und gesundheit. teamNotice
und unmatchedNotice fuellen funktion aus featureConfig (ohne bekannten
Schluessel "Funktion"); die neuen Bloecke kein_abo, bereits_aktiv und
gesundheit bleiben aus, bis B10a und D4 sie fuellen. Die News-Mails
bleiben woertlich (HTML, Text und Betreff byte-gleich).

T19 (Erstattung faellig, Team-Hinweis) ist neu: volle Erstattung von
Hand in Stripe, Bloecke zahlung_nach_ende, ticket_offen und rechnung.
Gesendet wird sie spaeter ueber meldeErstattung (B10b).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
ClaudeandClaude Sonnet 5.5 committed 2026-10-04 13:06:39 +00:00
1 parent e200efb7e5
commit 992d7358fa
5 files changed
+419 -25

No files matched your search

+40 -14
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 { featureConfig, featureKeys, ticketTexte } from './featureRegistry.js'
import { anleitungsLink, featureConfig, featureKeys, ticketTexte } from './featureRegistry.js'
import { zustimmungFuerSitzung } from './featureConsents.js'
import { createFeatureTicket } from './ticketAdmin.js'
@@ -572,37 +572,63 @@ async function ticketWoidOf(doc) {
return doc.ticketId ? (await ticketWoid(doc.ticketId)) || '' : ''
}
async function teamNotice(doc, customer, { failed = false } = {}) {
await sendAdminNotice({
/**
* 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". kein_abo, bereits_aktiv und gesundheit sind in der Vorlage
* deklariert und bleiben hier aus (B10a und D4 fuellen sie).
*/
function sendT16({ funktion, ...werte }, bloecke) {
return sendAdminNotice({
template: 'T16',
values: {
kunde_name: '',
email: '',
projekt: '',
funktion: funktion || 'Funktion',
woid: '',
sitekey: '',
sitzung: '',
zustand: '',
anleitung_url: '',
gesundheit_text: '',
...werte,
},
blocks: { zahlung_fehlgeschlagen: false, ungeklaert: false, kein_abo: false, bereits_aktiv: false, anleitung: false, gesundheit: false, ...bloecke },
})
}
async function teamNotice(doc, customer, { failed = 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
await sendT16(
{
kunde_name: customer?.name || customer?.email || doc.customerId,
email: customer?.email || '',
projekt: await projectName(doc.projectId),
funktion: mails?.funktion,
woid: failed ? '' : await ticketWoidOf(doc),
sitekey: failed ? '' : doc.siteKey || '',
sitzung: '',
anleitung_url: anleitung ? anleitungsLink(doc.customerId, doc.projectId) : '',
},
blocks: { zahlung_fehlgeschlagen: failed, ungeklaert: false },
})
{ zahlung_fehlgeschlagen: failed, anleitung }
)
}
/** Bezahlte Sitzung ohne passende Bestellung: das Team muss von Hand klaeren (T16, Block ungeklaert). */
async function unmatchedNotice(session) {
const { customerId, projectId } = session.metadata || {}
const { customerId, projectId, featureKey } = session.metadata || {}
const customer = customerId ? await customerOf(customerId).catch(() => null) : null
await sendAdminNotice({
template: 'T16',
values: {
await sendT16(
{
kunde_name: customer?.name || customer?.email || customerId || 'unbekannt',
email: customer?.email || '',
projekt: projectId ? (await projectName(projectId).catch(() => '')) || projectId : '',
woid: '',
sitekey: '',
funktion: featureConfig(featureKey)?.mails.funktion,
sitzung: `${session.id} (Kunde ${customerId || '-'}, Projekt ${projectId || '-'})`,
},
blocks: { zahlung_fehlgeschlagen: false, ungeklaert: true },
})
{ ungeklaert: true }
)
}
/**