Buchungskalender: Bestellung auf Anfrage, Freischaltung und Ticket
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
827ee54875
commit
9d01d38a45
7 files changed
+799
-15
No files matched your search
@@ -1,10 +1,87 @@
|
||||
import { Router } from 'express'
|
||||
import { config } from '../../config.js'
|
||||
import { Query, countDocuments, listDocuments } from '../../services/appwriteAdmin.js'
|
||||
import { anfrageAnsichtTeam, entscheideAnfrage } from '../../services/unterkunft/anfrageFunktion.js'
|
||||
import { ladeEinstellungen, listeUnterkuenfte } from '../../services/unterkunft/speicher.js'
|
||||
import { listCustomerFeatureDocs } from '../../services/siteFeatures.js'
|
||||
|
||||
/**
|
||||
* Buchungskalender im Ticketsystem: GET /api/team/unterkunft/:customerId (Stand je Projekt) und
|
||||
* POST /api/team/unterkunft/:customerId/anfrage (Entscheidung ueber die Anfrage der Funktion).
|
||||
* Eingehaengt in routes/team/index.js unter /unterkunft, dort hinter requireStaffJwt. Geruest (Task 5): Task 11 fuellt es.
|
||||
* Buchungskalender im Ticketsystem (Kunden-Reiter "Funktionen"): GET /api/team/unterkunft/:customerId (Stand je Projekt) und
|
||||
* POST /api/team/unterkunft/:customerId/anfrage (Entscheidung ueber die Anfrage der Funktion). Huelle wie routes/team/shop.js.
|
||||
* Eingehaengt in routes/team/index.js unter /unterkunft, dort hinter requireStaffJwt.
|
||||
*/
|
||||
const router = Router()
|
||||
|
||||
const sendError = (res, err) => {
|
||||
const status = err.status >= 400 && err.status < 600 ? err.status : 500
|
||||
if (status >= 500) console.error('[team-unterkunft]', err.message)
|
||||
return res.status(status).json({ error: status >= 500 ? 'Interner Serverfehler' : err.message, ...(err.body?.code ? { code: err.body.code } : {}) })
|
||||
}
|
||||
const route = (fn) => (req, res) => fn(req, res).catch((err) => sendError(res, err))
|
||||
const person = (req) => ({ name: req.session.adminName || req.session.name || '', email: req.session.email || '' })
|
||||
|
||||
/** Zaehler oder null, wenn die Abfrage scheitert (die Uebersicht bleibt lesbar). */
|
||||
async function zaehle(collection, queries, was) {
|
||||
try {
|
||||
return await countDocuments(config.collections[collection], queries)
|
||||
} catch (err) {
|
||||
console.warn(`[team-unterkunft] ${was} nicht lesbar: ${err.message}`)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
const stripeZustand = (einst) => (!einst?.stripeAccountId ? 'keins' : einst.stripeStatus?.charges_enabled === true ? 'aktiv' : 'onboarding')
|
||||
|
||||
async function projektStand(project, feature) {
|
||||
let einst = null
|
||||
let unterkuenfte = 0
|
||||
if (feature) {
|
||||
try {
|
||||
einst = await ladeEinstellungen(feature.$id)
|
||||
} catch (err) {
|
||||
console.warn(`[team-unterkunft] Einstellungen ${feature.$id} nicht lesbar: ${err.message}`)
|
||||
}
|
||||
try {
|
||||
unterkuenfte = (await listeUnterkuenfte(feature.$id)).length
|
||||
} catch (err) {
|
||||
console.warn(`[team-unterkunft] Unterkuenfte ${feature.$id} nicht lesbar: ${err.message}`)
|
||||
unterkuenfte = null
|
||||
}
|
||||
}
|
||||
const offeneAnfragen = feature ? await zaehle('ukAnfragen', [Query.equal('featureId', feature.$id), Query.equal('status', 'neu')], 'Anfragenzahl') : 0
|
||||
return {
|
||||
projectId: project.$id,
|
||||
name: project.projectName || '',
|
||||
state: feature?.state || 'off',
|
||||
anfrage: anfrageAnsichtTeam(einst),
|
||||
stripe: { status: stripeZustand(einst) },
|
||||
unterkuenfte,
|
||||
offeneAnfragen,
|
||||
}
|
||||
}
|
||||
|
||||
// Uebersicht je Projekt des Kunden; archivierte Projekte nur, wenn dort ein Dokument der Funktion existiert
|
||||
router.get('/:customerId', route(async (req, res) => {
|
||||
const customerId = req.params.customerId
|
||||
const [docs, projects] = await Promise.all([
|
||||
listCustomerFeatureDocs(customerId),
|
||||
listDocuments(config.collections.websiteProjects, [Query.equal('customerId', customerId), Query.orderDesc('$createdAt'), Query.limit(1000)]),
|
||||
])
|
||||
const ukDocs = new Map(docs.filter((d) => d.featureKey === 'unterkunft').map((d) => [d.projectId, d]))
|
||||
const sichtbar = projects.filter((p) => !p.archived || ukDocs.has(p.$id))
|
||||
res.json({ projects: await Promise.all(sichtbar.map((p) => projektStand(p, ukDocs.get(p.$id)))) })
|
||||
}))
|
||||
|
||||
router.post('/:customerId/anfrage', route(async (req, res) => {
|
||||
const { projectId, entscheidung, begruendung } = req.body || {}
|
||||
const ergebnis = await entscheideAnfrage({
|
||||
customerId: req.params.customerId,
|
||||
projectId,
|
||||
entscheidung,
|
||||
begruendung,
|
||||
person: person(req),
|
||||
})
|
||||
res.json({ ok: true, anfrage: ergebnis.anfrage, ...(ergebnis.mailFehler ? { mailFehler: true } : {}) })
|
||||
}))
|
||||
|
||||
export default router
|
||||
Reference in new issue
Block a user