Kundenansicht P6: Team-Aktivierung mit Abo-Prüfung und Abrechnung (V10), Projektstart ohne Abo nur mit Warnung
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
408f7d0cc2
commit
de8b0c0fca
5 files changed
+285
-22
No files matched your search
@@ -1,6 +1,8 @@
|
||||
import { Router } from 'express'
|
||||
import { config } from '../../config.js'
|
||||
import { aboMemo } from '../../services/aboStatus.js'
|
||||
import { aboModellFuerKunde } from '../../services/aboFunktionen.js'
|
||||
import { ABRECHNUNGEN } from '../../services/aboModell.js'
|
||||
import { FUNKTION_CHANNELS, validateTextform } from '../../services/analyse.js'
|
||||
import { getDocument, updateDocument } from '../../services/appwriteAdmin.js'
|
||||
import { featureConfig, featureHaken } from '../../services/featureRegistry.js'
|
||||
@@ -46,7 +48,9 @@ const adminName = (req) => req.session.adminName || req.session.name || 'Admin'
|
||||
function sendError(res, err) {
|
||||
const status = err.status >= 400 && err.status < 600 ? err.status : 500
|
||||
if (status >= 500) console.error('[funktionen-admin]', err.message)
|
||||
return res.status(status).json({ error: err.message || 'Interner Serverfehler' })
|
||||
// err.body (z. B. code, grund, wechsel der 409 abo_fehlt) geht flach in die Antwort; error bleibt der Text der Meldung
|
||||
const zusatz = err.body && typeof err.body === 'object' && !Array.isArray(err.body) ? err.body : {}
|
||||
return res.status(status).json({ ...zusatz, error: err.message || 'Interner Serverfehler' })
|
||||
}
|
||||
|
||||
/** Neuester Eintrag zuerst; aeltere Eintraege fallen vorn heraus, sobald 300 Zeichen voll sind. */
|
||||
@@ -353,9 +357,23 @@ funktionenAdminRouter.post('/:customerId/:key', async (req, res) => {
|
||||
}
|
||||
await assertOwnProject(customerId, projectId)
|
||||
const by = adminName(req)
|
||||
// Abo-Modell (Kundenansicht neu, V10): nur fuer Kunden der neuen Ansicht zaehlt abrechnung (Vorgabe 'abo'); sonst wird sie ignoriert und
|
||||
// alles laeuft wie heute. Eine ungueltige Abrechnung ist 400, bevor etwas geschrieben wird.
|
||||
const modell = action === 'activate' && (await aboModellFuerKunde(customerId))
|
||||
let abrechnung = null
|
||||
if (modell) {
|
||||
abrechnung = req.body?.abrechnung === undefined ? 'abo' : req.body.abrechnung
|
||||
if (!ABRECHNUNGEN.includes(abrechnung)) return res.status(400).json({ error: 'Unbekannte Abrechnung' })
|
||||
}
|
||||
const rueckmeldung = {} // adminActivate meldet hier die Warnung der Aufbauphase (abo_fehlt)
|
||||
let freigeschaltet = null // Terminplaner oder Webshop mit Zustimmung in Textform: K16 mit den Unterlagen nach der Sperre
|
||||
let ersatzTicket
|
||||
if (key === 'zeiten' && action === 'activate') {
|
||||
if (key === 'zeiten' && action === 'activate' && modell) {
|
||||
// Wie zeitenAktivieren ohne feature-admin: Neubau und Ticket laufen in einschalten, die Sperre wuerde dem Team jede Aktion am Projekt halten
|
||||
const bisher = await getFeatureDoc(customerId, projectId, key)
|
||||
const adminNote = composeAdminNote(bisher?.adminNote, { by, action, note })
|
||||
await adminActivate(customerId, projectId, key, { by, adminNote, abrechnung, rueckmeldung })
|
||||
} else if (key === 'zeiten' && action === 'activate') {
|
||||
await zeitenAktivieren({ customerId, projectId, by, note })
|
||||
} else if (key === 'zeiten' && action === 'disable') {
|
||||
ersatzTicket = await zeitenAbschalten({ customerId, projectId, by, note })
|
||||
@@ -365,9 +383,14 @@ funktionenAdminRouter.post('/:customerId/:key', async (req, res) => {
|
||||
const adminNote = composeAdminNote(doc?.adminNote, { by, action, note })
|
||||
if (action === 'activate') {
|
||||
const textform = await textformFuerAktivierung({ body: req.body, customerId, key, doc })
|
||||
const attachments = textform ? await unterlagenAlsAnhang(key) : []
|
||||
const aktiviert = await adminActivate(customerId, projectId, key, { by, adminNote, textform })
|
||||
if (textform) freigeschaltet = { doc: aktiviert, attachments }
|
||||
if (modell) {
|
||||
// Die Unterlagen gehen mit K38 (aboFunktionenMeldung.js), nicht mit K16
|
||||
await adminActivate(customerId, projectId, key, { by, adminNote, textform, abrechnung, rueckmeldung })
|
||||
} else {
|
||||
const attachments = textform ? await unterlagenAlsAnhang(key) : []
|
||||
const aktiviert = await adminActivate(customerId, projectId, key, { by, adminNote, textform })
|
||||
if (textform) freigeschaltet = { doc: aktiviert, attachments }
|
||||
}
|
||||
} else if (action === 'abnahme') {
|
||||
await freischaltenNachAbnahme({ customerId, projectId, key, by, adminNote })
|
||||
} else if (action === 'ticket') {
|
||||
@@ -392,6 +415,8 @@ funktionenAdminRouter.post('/:customerId/:key', async (req, res) => {
|
||||
// Ergebnis des Ersatz-Tickets beim Abschalten der Zeiten (angelegt | aktuell | fehler), damit ein Fehler im Panel sichtbar wird
|
||||
...(ersatzTicket ? { ersatzTicket } : {}),
|
||||
...(warnung ? { warnung } : {}),
|
||||
// Aufbauphase (E9): im Projekt eingebaut, obwohl noch kein Abo laeuft; der String unterscheidet sich vom alten warnung: true (K16 ging nicht raus)
|
||||
...(rueckmeldung.warnung ? { warnung: rueckmeldung.warnung.code, grund: rueckmeldung.warnung.grund } : {}),
|
||||
})
|
||||
} catch (err) {
|
||||
sendError(res, err)
|
||||
|
||||
Reference in new issue
Block a user