new features

This commit is contained in:
Matthias Hochmeister
2026-03-23 16:58:46 +01:00
parent 948b211f70
commit 55ded22a6f
8 changed files with 452 additions and 43 deletions

View File

@@ -132,6 +132,75 @@ class EquipmentService {
}
}
async createCategory(data: { name: string; kurzname: string; sortierung?: number; motorisiert?: boolean }): Promise<AusruestungKategorie> {
try {
const result = await pool.query(
`INSERT INTO ausruestung_kategorien (id, name, kurzname, sortierung, motorisiert)
VALUES (uuid_generate_v4(), $1, $2, COALESCE($3, (SELECT COALESCE(MAX(sortierung),0)+1 FROM ausruestung_kategorien)), COALESCE($4, false))
RETURNING *`,
[data.name, data.kurzname, data.sortierung ?? null, data.motorisiert ?? null]
);
logger.info('Equipment category created', { id: result.rows[0].id, name: data.name });
return result.rows[0] as AusruestungKategorie;
} catch (error) {
logger.error('EquipmentService.createCategory failed', { error });
throw new Error('Failed to create equipment category');
}
}
async updateCategory(id: string, data: { name?: string; kurzname?: string; sortierung?: number; motorisiert?: boolean }): Promise<AusruestungKategorie | null> {
try {
const fields: string[] = [];
const values: unknown[] = [];
let p = 1;
if (data.name !== undefined) { fields.push(`name = $${p++}`); values.push(data.name); }
if (data.kurzname !== undefined) { fields.push(`kurzname = $${p++}`); values.push(data.kurzname); }
if (data.sortierung !== undefined) { fields.push(`sortierung = $${p++}`); values.push(data.sortierung); }
if (data.motorisiert !== undefined) { fields.push(`motorisiert = $${p++}`); values.push(data.motorisiert); }
if (fields.length === 0) throw new Error('No fields to update');
values.push(id);
const result = await pool.query(
`UPDATE ausruestung_kategorien SET ${fields.join(', ')} WHERE id = $${p} RETURNING *`,
values
);
if (result.rows.length === 0) return null;
logger.info('Equipment category updated', { id });
return result.rows[0] as AusruestungKategorie;
} catch (error) {
logger.error('EquipmentService.updateCategory failed', { error, id });
throw error;
}
}
async deleteCategory(id: string): Promise<{ deleted: boolean; error?: string }> {
try {
// Check if any equipment items reference this category
const usage = await pool.query(
`SELECT COUNT(*) AS cnt FROM ausruestung WHERE kategorie_id = $1 AND deleted_at IS NULL`,
[id]
);
const count = parseInt(usage.rows[0].cnt, 10);
if (count > 0) {
return { deleted: false, error: `Kategorie wird von ${count} Ausrüstungsgegenständen verwendet und kann nicht gelöscht werden.` };
}
const result = await pool.query(
`DELETE FROM ausruestung_kategorien WHERE id = $1 RETURNING id`,
[id]
);
if (result.rows.length === 0) {
return { deleted: false, error: 'Kategorie nicht gefunden' };
}
logger.info('Equipment category deleted', { id });
return { deleted: true };
} catch (error) {
logger.error('EquipmentService.deleteCategory failed', { error, id });
throw new Error('Failed to delete equipment category');
}
}
// =========================================================================
// CRUD
// =========================================================================