v1.8: Schadensmeldung startet Unterhaltung + Bestätigungsmail; 2. Verwaltungspostfach axel@hocks.eu
This commit is contained in:
@@ -189,6 +189,17 @@ tar -czf mp-dist.tar.gz -C dist .
|
|||||||
|
|
||||||
## 8. Verlauf / offene Punkte
|
## 8. Verlauf / offene Punkte
|
||||||
|
|
||||||
|
**Erledigt 02.10. (v1.8):** Schadensmeldungen starten jetzt automatisch eine
|
||||||
|
Unterhaltung (Thread „Schadensmeldung: …" mit erster Nachricht inkl. Kategorie/
|
||||||
|
Priorität, ungelesen für die Gegenseite) – Antworten darauf lösen über
|
||||||
|
`/api/threads/:id/messages` wie gehabt Mails an Verwaltung + Mieter aus.
|
||||||
|
Zusätzlich Eingangsbestätigungs-Mail an den Mieter bei jeder Meldung.
|
||||||
|
Verwaltungs-Mails gehen jetzt an zwei echte Postfächer: joseph@hinterstein-immo.com
|
||||||
|
(Benutzer j.hinterstein, Seed + Live-DB geändert) und axel@hocks.eu (neuer
|
||||||
|
Verwaltungsbenutzer a.hocks, Passwort 0815, Seed + Live-DB). E2E verifiziert:
|
||||||
|
Meldung + Antwort → je Mail an beide Postfächer zugestellt (Postfix status=sent);
|
||||||
|
Mieter-Adressen der Demoseeds sind example.de und bouncen bewusst.
|
||||||
|
|
||||||
**Erledigt 02.10. (v1.7):** Responsive Layout repariert. Sidebar skaliert jetzt in zwei
|
**Erledigt 02.10. (v1.7):** Responsive Layout repariert. Sidebar skaliert jetzt in zwei
|
||||||
Stufen (`w-64` ab `lg`, `xl:w-72`) statt fixer 288 px. Mobile Ansicht (Top-Bar +
|
Stufen (`w-64` ab `lg`, `xl:w-72`) statt fixer 288 px. Mobile Ansicht (Top-Bar +
|
||||||
horizontal scrollende Nav) gilt jetzt bis 1024 px (`md:hidden` → `lg:hidden`) – vorher
|
horizontal scrollende Nav) gilt jetzt bis 1024 px (`md:hidden` → `lg:hidden`) – vorher
|
||||||
|
|||||||
@@ -257,6 +257,27 @@ app.post('/api/tickets', auth, async (req, res, next) => {
|
|||||||
String(category || 'Sonstiges'), ['niedrig', 'mittel', 'hoch'].includes(priority) ? priority : 'mittel',
|
String(category || 'Sonstiges'), ['niedrig', 'mittel', 'hoch'].includes(priority) ? priority : 'mittel',
|
||||||
deutschesDatum()],
|
deutschesDatum()],
|
||||||
)
|
)
|
||||||
|
// ── Automatische Unterhaltung (Kommunikation) zur Meldung anlegen ──
|
||||||
|
// Jede Schadensmeldung startet einen eigenen Thread; Antworten darauf
|
||||||
|
// lösen über /api/threads/:id/messages bereits Mails an beide Seiten aus.
|
||||||
|
const threadId = `m-${Date.now()}`
|
||||||
|
const vonRolle = req.user.rolle === 'verwaltung' ? 'admin' : 'tenant'
|
||||||
|
const threadBetreff = `Schadensmeldung: ${String(title).trim()}`
|
||||||
|
const ersteNachricht =
|
||||||
|
`Schadensmeldung eingegangen – Kategorie: ${String(category || 'Sonstiges')}, ` +
|
||||||
|
`Priorität: ${['niedrig', 'mittel', 'hoch'].includes(priority) ? priority : 'mittel'}.\n\n` +
|
||||||
|
`${String(title).trim()}\n${String(description || '–').trim()}`
|
||||||
|
await pool.query(
|
||||||
|
`INSERT INTO threads (id, unit_id, tenant, subject, unread_by_admin, unread_by_tenant)
|
||||||
|
VALUES ($1,$2,$3,$4,$5,$6)`,
|
||||||
|
[threadId, unitId, mieterName, threadBetreff,
|
||||||
|
vonRolle === 'tenant', vonRolle === 'admin'],
|
||||||
|
)
|
||||||
|
await pool.query(
|
||||||
|
`INSERT INTO messages (id, thread_id, from_role, author, text, at) VALUES ($1,$2,$3,$4,$5,$6)`,
|
||||||
|
[`${threadId}-1`, threadId, vonRolle, mieterName, ersteNachricht, deutschesDatumZeit()],
|
||||||
|
)
|
||||||
|
|
||||||
const label = mail.einheitLabel(mapUnit(unitRows[0]))
|
const label = mail.einheitLabel(mapUnit(unitRows[0]))
|
||||||
const betreff = `Neue Schadensmeldung: ${String(title).trim()} (${label})`
|
const betreff = `Neue Schadensmeldung: ${String(title).trim()} (${label})`
|
||||||
const text =
|
const text =
|
||||||
@@ -277,6 +298,29 @@ app.post('/api/tickets', auth, async (req, res, next) => {
|
|||||||
aktionenHtml: mail.buttonHtml('Zum Mieterportal', `${process.env.PORTAL_URL || 'https://mieterportal.hocks.eu'}/schadensmeldungen`),
|
aktionenHtml: mail.buttonHtml('Zum Mieterportal', `${process.env.PORTAL_URL || 'https://mieterportal.hocks.eu'}/schadensmeldungen`),
|
||||||
})
|
})
|
||||||
mail.benachrichtigeVerwaltung(betreff, text, html)
|
mail.benachrichtigeVerwaltung(betreff, text, html)
|
||||||
|
// Eingangsbestätigung an den Mieter (bei internen Meldungen der
|
||||||
|
// Verwaltung entfällt sie, da diese keine Mieter-E-Mail auslösen soll)
|
||||||
|
if (vonRolle === 'tenant') {
|
||||||
|
const bestText =
|
||||||
|
`Guten Tag,\n\nvielen Dank für Ihre Schadensmeldung „${String(title).trim()}“. ` +
|
||||||
|
`Diese ist bei uns eingegangen und wird von der Verwaltung bearbeitet.\n\n` +
|
||||||
|
`Wohnung: ${label}\nKategorie: ${String(category || 'Sonstiges')}\n\n` +
|
||||||
|
`Sie können den Fortschritt im Mieterportal verfolgen und sich jederzeit ` +
|
||||||
|
`in der zugehörigen Unterhaltung („${threadBetreff}“) an uns wenden.`
|
||||||
|
const bestHtml = mail.baueHtmlMail({
|
||||||
|
titel: 'Schadensmeldung eingegangen',
|
||||||
|
untertitel: label,
|
||||||
|
einleitung: `Vielen Dank für Ihre Schadensmeldung „${String(title).trim()}“. Diese ist bei uns eingegangen und wird von der Verwaltung bearbeitet.`,
|
||||||
|
zeilen: [
|
||||||
|
['Wohnung', label],
|
||||||
|
['Kategorie', String(category || 'Sonstiges')],
|
||||||
|
],
|
||||||
|
statusBox: { hintergrund: '#f0fdfa', farbe: '#0f766e', text: 'Status: offen – eingegangen' },
|
||||||
|
zitat: `${String(title).trim()}\n${String(description || '–').trim()}`,
|
||||||
|
aktionenHtml: mail.buttonHtml('Meldung im Portal ansehen', `${process.env.PORTAL_URL || 'https://mieterportal.hocks.eu'}/nachrichten`),
|
||||||
|
})
|
||||||
|
mail.benachrichtigeMieter(unitId, `Eingangsbestätigung: ${String(title).trim()}`, bestText, bestHtml)
|
||||||
|
}
|
||||||
res.json({ ticket: mapTicket(rows[0]) })
|
res.json({ ticket: mapTicket(rows[0]) })
|
||||||
} catch (e) { next(e) }
|
} catch (e) { next(e) }
|
||||||
})
|
})
|
||||||
|
|||||||
+14
-3
@@ -1,9 +1,9 @@
|
|||||||
/** Handgeschriebene Demo-Daten (vormals src/data/seed.ts).
|
/** Handgeschriebene Demo-Daten (vormals src/data/seed.ts).
|
||||||
*
|
*
|
||||||
* units + transactions kommen maschinell aus seed/generated.json
|
* units + transactions kommen maschinell aus seed/generated.json
|
||||||
* (beispieldaten.py). Die Verwaltungs-E-Mail ist bewusst ein echtes,
|
* (beispieldaten.py). Verwaltungs-E-Mails sind bewusst echte, zustellbare
|
||||||
* zustellbares Postfach (axel@hocks.eu), damit Benachrichtigungen ankommen;
|
* Postfächer (joseph@hinterstein-immo.com, axel@hocks.eu), damit
|
||||||
* im Portal änderbar (Benutzerverwaltung).
|
* Benachrichtigungen ankommen; im Portal änderbar (Benutzerverwaltung).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const DEMO_HASH = 'c57a5df4f97ed6914116e5fd1348406064834f22503d890eb571af442ac4b4c3' // sha256("0815")
|
const DEMO_HASH = 'c57a5df4f97ed6914116e5fd1348406064834f22503d890eb571af442ac4b4c3' // sha256("0815")
|
||||||
@@ -15,6 +15,17 @@ const users = [
|
|||||||
name: 'Joseph Hinterstein',
|
name: 'Joseph Hinterstein',
|
||||||
passwort_hash: DEMO_HASH,
|
passwort_hash: DEMO_HASH,
|
||||||
rolle: 'verwaltung',
|
rolle: 'verwaltung',
|
||||||
|
email: 'joseph@hinterstein-immo.com',
|
||||||
|
einheit_id: null,
|
||||||
|
aktiv: true,
|
||||||
|
erstellt_am: '01.03.2024',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'b-axel',
|
||||||
|
benutzername: 'a.hocks',
|
||||||
|
name: 'Axel Hocks',
|
||||||
|
passwort_hash: DEMO_HASH,
|
||||||
|
rolle: 'verwaltung',
|
||||||
email: 'axel@hocks.eu',
|
email: 'axel@hocks.eu',
|
||||||
einheit_id: null,
|
einheit_id: null,
|
||||||
aktiv: true,
|
aktiv: true,
|
||||||
|
|||||||
Reference in New Issue
Block a user