This commit is contained in:
Matthias Hochmeister
2026-03-16 14:41:08 +01:00
parent 5f329bb5c1
commit 215528a521
46 changed files with 462 additions and 251 deletions

View File

@@ -314,17 +314,19 @@ class BookingService {
/** Soft-cancels a booking by setting abgesagt=TRUE and recording the reason. */
async cancel(id: string, abgesagt_grund: string): Promise<void> {
await pool.query(
const result = await pool.query(
`UPDATE fahrzeug_buchungen
SET abgesagt = TRUE, abgesagt_grund = $2, aktualisiert_am = NOW()
WHERE id = $1`,
[id, abgesagt_grund]
);
if (result.rowCount === 0) throw new Error('Buchung nicht gefunden');
}
/** Permanently deletes a booking record. */
async delete(id: string): Promise<void> {
await pool.query('DELETE FROM fahrzeug_buchungen WHERE id = $1', [id]);
const result = await pool.query('DELETE FROM fahrzeug_buchungen WHERE id = $1', [id]);
if (result.rowCount === 0) throw new Error('Buchung nicht gefunden');
}
/**
@@ -399,6 +401,22 @@ class BookingService {
const { rows } = await pool.query(query, params);
const now = toIcalDate(new Date());
// iCal escaping and folding helpers
const icalEscape = (val: string): string =>
val.replace(/\\/g, '\\\\').replace(/;/g, '\\;').replace(/,/g, '\\,').replace(/\n/g, '\\n');
const icalFold = (line: string): string => {
if (Buffer.byteLength(line, 'utf-8') <= 75) return line;
let folded = '';
let cur = '';
let bytes = 0;
for (const ch of line) {
const cb = Buffer.byteLength(ch, 'utf-8');
if (bytes + cb > 75) { folded += cur + '\r\n '; cur = ch; bytes = 1 + cb; }
else { cur += ch; bytes += cb; }
}
return folded + cur;
};
const events = rows
.map((row: any) => {
const beschreibung = [row.buchungs_art, row.beschreibung]
@@ -410,8 +428,8 @@ class BookingService {
`DTSTAMP:${now}\r\n` +
`DTSTART:${toIcalDate(new Date(row.beginn))}\r\n` +
`DTEND:${toIcalDate(new Date(row.ende))}\r\n` +
`SUMMARY:${row.titel} - ${row.fahrzeug_name}\r\n` +
`DESCRIPTION:${beschreibung}\r\n` +
icalFold(`SUMMARY:${icalEscape(row.titel)} - ${icalEscape(row.fahrzeug_name)}`) + '\r\n' +
icalFold(`DESCRIPTION:${icalEscape(beschreibung)}`) + '\r\n' +
'END:VEVENT\r\n'
);
})