const express = require('express'); const Database = require('better-sqlite3'); const validateSepa = require('../utils/sepaValidator'); const { encrypt } = require('../utils/crypto'); const generateVertragsnummer = require('../utils/vertragsnummer'); const createContractPdf = require('../utils/contractPdf'); const sendContractMail = require('../utils/sendContractMail'); const sendAdminMail = require('../utils/sendAdminMail'); const router = express.Router(); const db = new Database('plusfit.db'); /* ========================= Helper ========================= */ function loadActiveContracts() { return db.prepare(` SELECT * FROM vertragsarten WHERE aktiv = 1 ORDER BY betrag ASC `).all(); } /* ========================= GET /register ========================= */ router.get('/', (req, res) => { const vertragId = req.query.vertrag || null; return res.render('register', { vertragsarten: loadActiveContracts(), selectedVertrag: vertragId, formData: {} }); }); /* ========================= POST /register/create ========================= */ router.post('/create', async (req, res) => { const u = req.body; const vertragsarten = loadActiveContracts(); /* ========================= Vertragsdaten laden ========================= */ const contractData = db.prepare(` SELECT name, laufzeit, betrag FROM vertragsarten WHERE id = ? AND aktiv = 1 `).get(u.vertragsvariante); if (!contractData) { return res.render('register', { vertragsarten, selectedVertrag: u.vertragsvariante, error: 'Vertragsdaten konnten nicht geladen werden.', formData: u }); } /* ========================= Pflicht-Zustimmungen ========================= */ if (!u.agreeConsent || !u.agreeAgb || !u.agreeSepa) { return res.render('register', { vertragsarten, selectedVertrag: u.vertragsvariante, error: 'Bitte bestätige alle rechtlichen Hinweise, um fortzufahren.', formData: u }); } /* ========================= Formale SEPA-Prüfung ========================= */ const sepaError = validateSepa({ ibanValue: u.iban, bic: u.bic, mandatsreferenz: u.mandatsreferenz }); if (sepaError) { return res.render('register', { vertragsarten, selectedVertrag: u.vertragsvariante, error: sepaError, formData: u }); } /* ========================= Logische Prüfungen ========================= */ const mandatsExists = db.prepare(` SELECT id FROM users WHERE mandatsreferenz = ? `).get(u.mandatsreferenz); if (mandatsExists) { return res.render('register', { vertragsarten, selectedVertrag: u.vertragsvariante, error: 'Diese Mandatsreferenz ist bereits vergeben.', formData: u }); } /* ========================= Vertrags- & Zustimmungsdaten ========================= */ const vertragsnummer = generateVertragsnummer(); const zustimmungsDatum = new Date().toISOString(); const zustimmungsIp = ( req.headers['x-forwarded-for'] || req.socket?.remoteAddress || '' ).split(',')[0].trim(); const vertragsversion = 'v1.0'; const widerrufBis = new Date(); widerrufBis.setDate(widerrufBis.getDate() + 14); /* ========================= Verschlüsselung ========================= */ const ibanEncrypted = encrypt(u.iban); const bicEncrypted = encrypt(u.bic); /* ========================= SPEICHERN ========================= */ db.prepare(` INSERT INTO users ( vertragsnummer, vertragsvariante, vorname, nachname, strasse, hausnummer, plz, ort, land, mobil, telefon, email, kontoinhaber, iban, bic, mandatsreferenz, zustimmung_agb, zustimmung_sepa, zustimmung_einverstaendnis, zustimmung_datum, zustimmung_ip, vertragsversion, widerruf_moeglich_bis, status, gesperrt ) VALUES ( ?,?, ?,?, ?,?,?,?,?, ?,?,?, ?,?,?,?, ?,?,?,?, ?,?, ?,?, 0 ) `).run( vertragsnummer, u.vertragsvariante, u.vorname, u.nachname, u.strasse, u.hausnummer, u.plz, u.ort, u.land, u.mobil, u.telefon, u.email, u.kontoinhaber, ibanEncrypted, bicEncrypted, u.mandatsreferenz, u.agreeAgb ? 1 : 0, u.agreeSepa ? 1 : 0, u.agreeConsent ? 1 : 0, zustimmungsDatum, zustimmungsIp, vertragsversion, widerrufBis.toISOString(), 'aktiv' ); /* ========================= Vertrags-PDF ========================= */ const pdfPath = await createContractPdf({ vertragsnummer, vorname: u.vorname, nachname: u.nachname, vertragName: contractData.name, laufzeit: contractData.laufzeit, betrag: contractData.betrag, datum: zustimmungsDatum, ip: zustimmungsIp }); /* ========================= Vertragsmail ========================= */ await sendContractMail({ email: u.email, vorname: u.vorname, vertragsnummer, vertragName: contractData.name, betrag: contractData.betrag, datum: zustimmungsDatum, pdfPath }); await sendAdminMail({ vertragsnummer, vorname: u.vorname, nachname: u.nachname, email: u.email, vertragName: contractData.name, betrag: contractData.betrag, datum: zustimmungsDatum, ip: zustimmungsIp }); /* ========================= ERFOLG ========================= */ return res.render('registerSuccess', { vertragsnummer }); }); module.exports = router;