Vertragsverwaltung_Plusfit24/routes/register.js

266 lines
6.0 KiB
JavaScript

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;
const vertraege = loadActiveContracts();
// Prüfen ob Vertrag existiert
const selected = vertraege.find((v) => v.id == vertragId);
return res.render("register", {
vertragsarten: vertraege,
selectedVertrag: selected ? selected.id : null,
selectedVertragData: selected || null,
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;