- Phosphor Icons (Icon.svelte, svg-Registry) - Schema-Abgleich: alle Felder zwischen PB-Migrations und types.ts konsistent - Stripe entfernt, SEPA pain.008 XML-Export implementiert (sepa.ts) - Beiträge: vollständiges CRUD + SEPA-Einzug-Sheet mit Vorschau - Termine: vollständiges CRUD (upcoming/vergangen, datetime-local) - Mitglieder: Formulare um alle Felder erweitert (Adresse, SEPA-Mandat, Notizen) - Nachrichten: Brevo E-Mail via PocketBase-Hook, UI mit Gruppen-Filter - Push-Notifications: VAPID, Custom Service Worker (injectManifest), Subscribe/Send API-Routen, automatische Subscription nach Login - Onboarding: 3-Schritt-Flow für neue Vereine, Guard im App-Layout - Makefile: .env wird vollständig zur DS übertragen
86 lines
2.9 KiB
JavaScript
86 lines
2.9 KiB
JavaScript
onRecordAfterCreateSuccess(function(e) {
|
||
if (!e.record) return;
|
||
|
||
var key = $os.getenv("BREVO_KEY");
|
||
if (!key) {
|
||
console.log("[nachrichten] BREVO_KEY nicht gesetzt – E-Mail übersprungen.");
|
||
return;
|
||
}
|
||
|
||
var vereinId = e.record.getString("verein_id");
|
||
var betreff = e.record.getString("betreff");
|
||
var text = e.record.getString("text");
|
||
var gruppeIds = e.record.getStringSlice("gruppe_ids");
|
||
|
||
// Vereinsname für Absender
|
||
var vereinName = "Ihr Verein";
|
||
try {
|
||
var verein = $app.findRecordById("vereine", vereinId);
|
||
vereinName = verein.getString("name");
|
||
} catch(err) {}
|
||
|
||
// Mitglieder-Filter
|
||
var filter = 'verein_id = "' + vereinId + '" && status = "aktiv" && email != ""';
|
||
if (gruppeIds && gruppeIds.length > 0) {
|
||
var gruppenParts = [];
|
||
for (var i = 0; i < gruppeIds.length; i++) {
|
||
gruppenParts.push('gruppe_ids ~ "' + gruppeIds[i] + '"');
|
||
}
|
||
filter += " && (" + gruppenParts.join(" || ") + ")";
|
||
}
|
||
|
||
var mitglieder;
|
||
try {
|
||
mitglieder = $app.findRecordsByFilter("mitglieder", filter, "nachname", 500, 0);
|
||
} catch(err) {
|
||
console.error("[nachrichten] Mitglieder laden fehlgeschlagen: " + String(err));
|
||
return;
|
||
}
|
||
|
||
var empfaenger = [];
|
||
for (var j = 0; j < mitglieder.length; j++) {
|
||
var m = mitglieder[j];
|
||
var email = m.getString("email");
|
||
if (email) {
|
||
empfaenger.push({
|
||
email: email,
|
||
name: m.getString("vorname") + " " + m.getString("nachname")
|
||
});
|
||
}
|
||
}
|
||
|
||
if (empfaenger.length === 0) {
|
||
console.log("[nachrichten] Keine Empfänger mit E-Mail gefunden.");
|
||
return;
|
||
}
|
||
|
||
var sender = $os.getenv("BREVO_SENDER") || "noreply@vereins.haus";
|
||
var htmlContent = text
|
||
? text.replace(/\n/g, "<br>")
|
||
: "<p>(Kein Inhalt)</p>";
|
||
|
||
// In 50er-Batches senden (Brevo-Limit)
|
||
var BATCH = 50;
|
||
for (var b = 0; b < empfaenger.length; b += BATCH) {
|
||
var batch = empfaenger.slice(b, b + BATCH);
|
||
var body = JSON.stringify({
|
||
sender: { name: vereinName, email: sender },
|
||
to: [batch[0]],
|
||
bcc: batch.slice(1),
|
||
subject: betreff,
|
||
htmlContent: htmlContent
|
||
});
|
||
|
||
try {
|
||
$http.send({
|
||
url: "https://api.brevo.com/v3/smtp/email",
|
||
method: "POST",
|
||
headers: { "api-key": key, "Content-Type": "application/json" },
|
||
body: body
|
||
});
|
||
console.log("[nachrichten] Batch " + (b / BATCH + 1) + " gesendet (" + batch.length + " Empfänger).");
|
||
} catch(err) {
|
||
console.error("[nachrichten] Brevo Fehler Batch " + (b / BATCH + 1) + ": " + String(err));
|
||
}
|
||
}
|
||
}, "nachrichten");
|