Abo: Uebernahmegutschrift fuer beim Altanbieter bezahlte Leistungen
- Kunde (Dashboard, nur mit laufendem Abo): Antrag mit Leistung, Anbieter, Domain, Rechnungsbetrag/-zeitraum, Grund, Rechnungsnachweis (PDF/JPG/PNG) und E-Mail fuer die Antwort; Eingangsbestaetigung per Mail, Status und Antwort auf Rueckfragen im Portal - Admin-Mail mit Link admin.html?gutschrift=<id> (Login leitet zurueck) - Admin-Tab "Gutschriften": Kunde und Vertrag, Nachweise, Verlauf, automatische Pruefungen (Duplikate per Datei-Hash/Domain, Abo, Zeitraum, DNS-Abgleich Nameserver/MX mit Anbieter), Pflicht-Checkliste, Rechner (tagesgenau anteilig), Genehmigen/Rueckfrage/Ablehnen mit Kundenmail - Genehmigte Gutschrift als Stripe-Kundenguthaben (idempotent, Nachbuchen bei Stripe-Stoerung) - Nachweise in upload-data/ (gitignored), Loeschung abgelehnter nach 6 Monaten - Stundenkontingent auch fuer Monate, die ein Guthaben komplett deckt (invoice.total statt amount_paid) - Datenschutzerklaerung Abschnitt 7 ergaenzt, PDF neu erzeugt - Collection takeoverCredits in setup-abo-collections.mjs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
dbabbf1c0b
commit
48b13f4488
14 files changed
+2040
-9
No files matched your search
+16
-1
@@ -4,7 +4,7 @@ import { fileURLToPath } from 'node:url'
|
||||
import { config, assertServerConfig, WOMS_DATABASE_ID } from './config.js'
|
||||
import { verifyDatabaseAccess } from './services/appwriteAdmin.js'
|
||||
import { syncPreviewTls } from './services/previewDeploy.js'
|
||||
import { sessionMiddleware } from './middleware/session.js'
|
||||
import { requireSession, sessionMiddleware } from './middleware/session.js'
|
||||
import authRoutes from './routes/auth.js'
|
||||
import projectsRoutes from './routes/projects.js'
|
||||
import featuresRoutes from './routes/features.js'
|
||||
@@ -12,6 +12,8 @@ import customerDataRoutes from './routes/customerData.js'
|
||||
import portalAdminRoutes from './routes/portalAdmin.js'
|
||||
import chatRoutes from './routes/chat.js'
|
||||
import aboRoutes from './routes/abo.js'
|
||||
import takeoverCreditRoutes from './routes/takeoverCredits.js'
|
||||
import { purgeExpiredUploads } from './services/takeoverCredits.js'
|
||||
import giteaWebhookRoutes from './routes/webhook/gitea.js'
|
||||
import adminGiteaRoutes from './routes/admin/gitea.js'
|
||||
import adminWebsiteProjectsRoutes from './routes/admin/websiteProjects.js'
|
||||
@@ -28,6 +30,10 @@ assertServerConfig()
|
||||
const app = express()
|
||||
app.set('trust proxy', 1)
|
||||
app.use(sessionMiddleware())
|
||||
// Uebernahmegutschrift: Nachweise kommen als Base64 im JSON (max. 10 MB Dateien) -> eigenes Limit,
|
||||
// muss vor dem globalen Parser stehen (der ueberspringt bereits geparste Bodies). Login-Pruefung
|
||||
// zuerst, damit niemand ohne Session grosse Bodies parsen laesst.
|
||||
app.use('/api/abo/takeover-credits', requireSession, express.json({ limit: '15mb' }))
|
||||
// rawBody wird fuer die HMAC-Verifikation des Gitea-Webhooks benoetigt
|
||||
app.use(express.json({ limit: '2mb', verify: (req, _res, buf) => { req.rawBody = buf } }))
|
||||
|
||||
@@ -49,6 +55,7 @@ app.use('/api/projects', projectsRoutes)
|
||||
app.use('/api/features', featuresRoutes)
|
||||
app.use('/api', customerDataRoutes)
|
||||
app.use('/api/chat', chatRoutes)
|
||||
app.use('/api/abo/takeover-credits', takeoverCreditRoutes)
|
||||
app.use('/api/abo', aboRoutes)
|
||||
app.use('/api/portal-admin', portalAdminRoutes)
|
||||
app.use('/api/admin/gitea', adminGiteaRoutes)
|
||||
@@ -103,6 +110,14 @@ const server = app.listen(config.port, '0.0.0.0', () => {
|
||||
)
|
||||
if (result.reason) console.error(`[startup] Appwrite: ${result.reason}`)
|
||||
})
|
||||
|
||||
// Nachweise abgelehnter Uebernahmegutschriften nach Ablauf der Aufbewahrungsfrist loeschen (taeglich)
|
||||
const purge = () =>
|
||||
purgeExpiredUploads()
|
||||
.then((r) => r.purged && console.log(`[takeover] Nachweise von ${r.purged} abgelehnten Anträgen gelöscht`))
|
||||
.catch((err) => console.warn('[takeover] Aufräumen fehlgeschlagen:', err.message))
|
||||
setTimeout(purge, 60 * 1000).unref()
|
||||
setInterval(purge, 24 * 60 * 60 * 1000).unref()
|
||||
})
|
||||
|
||||
server.on('error', (err) => {
|
||||
|
||||
Reference in new issue
Block a user