This commit is contained in:
Matthias Hochmeister
2026-03-13 19:23:39 +01:00
parent 02d9d808b2
commit bc6d09200a
15 changed files with 610 additions and 74 deletions

View File

@@ -141,6 +141,35 @@ class BookingService {
return rowToBuchung(rows[0]);
}
/**
* Checks whether a vehicle is out of service during the given interval.
* Returns the out-of-service period if there IS a conflict, null otherwise.
*/
async checkOutOfServiceConflict(
fahrzeugId: string,
beginn: Date,
ende: Date
): Promise<{ ausser_dienst_von: Date; ausser_dienst_bis: Date } | null> {
const query = `
SELECT ausser_dienst_von, ausser_dienst_bis
FROM fahrzeuge
WHERE id = $1
AND deleted_at IS NULL
AND status IN ('ausser_dienst_wartung', 'ausser_dienst_schaden')
AND ausser_dienst_von IS NOT NULL
AND ausser_dienst_bis IS NOT NULL
AND ($2::timestamptz, $3::timestamptz) OVERLAPS (ausser_dienst_von, ausser_dienst_bis)
LIMIT 1
`;
const { rows } = await pool.query(query, [fahrzeugId, beginn, ende]);
if (rows.length === 0) return null;
return {
ausser_dienst_von: new Date(rows[0].ausser_dienst_von),
ausser_dienst_bis: new Date(rows[0].ausser_dienst_bis),
};
}
/**
* Checks whether a vehicle is already booked for the given interval.
* Returns true if there IS a conflict.
@@ -171,8 +200,13 @@ class BookingService {
return rows.length > 0;
}
/** Creates a new booking. Throws if the vehicle has a conflicting booking. */
/** Creates a new booking. Throws if the vehicle has a conflicting booking or is out of service. */
async create(data: CreateBuchungData, userId: string): Promise<FahrzeugBuchung> {
const outOfService = await this.checkOutOfServiceConflict(data.fahrzeugId, data.beginn, data.ende);
if (outOfService) {
throw new Error('Fahrzeug ist im gewählten Zeitraum außer Dienst');
}
const hasConflict = await this.checkConflict(
data.fahrzeugId,
data.beginn,
@@ -225,6 +259,15 @@ class BookingService {
data.fahrzeugId != null || data.beginn != null || data.ende != null;
if (timingChanged) {
const outOfService = await this.checkOutOfServiceConflict(
effectiveFahrzeugId,
effectiveBeginn,
effectiveEnde
);
if (outOfService) {
throw new Error('Fahrzeug ist im gewählten Zeitraum außer Dienst');
}
const hasConflict = await this.checkConflict(
effectiveFahrzeugId,
effectiveBeginn,