186 lines
7.4 KiB
TypeScript
186 lines
7.4 KiB
TypeScript
import { Request, Response } from 'express';
|
|
import { z } from 'zod';
|
|
import personalEquipmentService from '../services/personalEquipment.service';
|
|
import logger from '../utils/logger';
|
|
|
|
const uuidString = z.string().regex(
|
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
|
|
'Ungültige UUID',
|
|
);
|
|
|
|
const isoDate = z.string().regex(
|
|
/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/,
|
|
'Erwartet ISO-Datum im Format YYYY-MM-DD',
|
|
);
|
|
|
|
const ZustandEnum = z.enum(['gut', 'beschaedigt', 'abgaengig', 'verloren']);
|
|
|
|
const EigenschaftInput = z.object({
|
|
eigenschaft_id: z.number().int().positive().nullable().optional(),
|
|
name: z.string().min(1).max(200),
|
|
wert: z.string().max(500),
|
|
});
|
|
|
|
const CreateSchema = z.object({
|
|
bezeichnung: z.string().min(1).max(200),
|
|
kategorie: z.string().max(100).optional(),
|
|
artikel_id: z.number().int().positive().optional(),
|
|
user_id: uuidString.optional(),
|
|
benutzer_name: z.string().max(200).optional(),
|
|
groesse: z.string().max(50).optional(),
|
|
seriennummer: z.string().max(100).optional(),
|
|
inventarnummer: z.string().max(50).optional(),
|
|
anschaffung_datum: isoDate.optional(),
|
|
zustand: ZustandEnum.optional(),
|
|
notizen: z.string().max(2000).optional(),
|
|
eigenschaften: z.array(EigenschaftInput).optional(),
|
|
});
|
|
|
|
const UpdateSchema = z.object({
|
|
bezeichnung: z.string().min(1).max(200).optional(),
|
|
kategorie: z.string().max(100).nullable().optional(),
|
|
artikel_id: z.number().int().positive().nullable().optional(),
|
|
user_id: uuidString.nullable().optional(),
|
|
benutzer_name: z.string().max(200).nullable().optional(),
|
|
groesse: z.string().max(50).nullable().optional(),
|
|
seriennummer: z.string().max(100).nullable().optional(),
|
|
inventarnummer: z.string().max(50).nullable().optional(),
|
|
anschaffung_datum: isoDate.nullable().optional(),
|
|
zustand: ZustandEnum.optional(),
|
|
notizen: z.string().max(2000).nullable().optional(),
|
|
eigenschaften: z.array(EigenschaftInput).nullable().optional(),
|
|
});
|
|
|
|
function isValidUUID(s: string): boolean {
|
|
return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s);
|
|
}
|
|
|
|
class PersonalEquipmentController {
|
|
async list(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const filters: Record<string, string> = {};
|
|
if (req.query.user_id) filters.userId = String(req.query.user_id);
|
|
if (req.query.kategorie) filters.kategorie = String(req.query.kategorie);
|
|
if (req.query.zustand) filters.zustand = String(req.query.zustand);
|
|
|
|
const items = await personalEquipmentService.getAll(filters);
|
|
res.status(200).json({ success: true, data: items });
|
|
} catch (error) {
|
|
logger.error('personalEquipment.list error', { error });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht geladen werden' });
|
|
}
|
|
}
|
|
|
|
async getMy(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const items = await personalEquipmentService.getByUserId(req.user!.id);
|
|
res.status(200).json({ success: true, data: items });
|
|
} catch (error) {
|
|
logger.error('personalEquipment.getMy error', { error });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht geladen werden' });
|
|
}
|
|
}
|
|
|
|
async getByUser(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { userId } = req.params as Record<string, string>;
|
|
if (!isValidUUID(userId)) {
|
|
res.status(400).json({ success: false, message: 'Ungültige User-ID' });
|
|
return;
|
|
}
|
|
const items = await personalEquipmentService.getByUserId(userId);
|
|
res.status(200).json({ success: true, data: items });
|
|
} catch (error) {
|
|
logger.error('personalEquipment.getByUser error', { error });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht geladen werden' });
|
|
}
|
|
}
|
|
|
|
async getById(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params as Record<string, string>;
|
|
if (!isValidUUID(id)) {
|
|
res.status(400).json({ success: false, message: 'Ungültige ID' });
|
|
return;
|
|
}
|
|
const item = await personalEquipmentService.getById(id);
|
|
if (!item) {
|
|
res.status(404).json({ success: false, message: 'Nicht gefunden' });
|
|
return;
|
|
}
|
|
res.status(200).json({ success: true, data: item });
|
|
} catch (error) {
|
|
logger.error('personalEquipment.getById error', { error });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht geladen werden' });
|
|
}
|
|
}
|
|
|
|
async create(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const parsed = CreateSchema.safeParse(req.body);
|
|
if (!parsed.success) {
|
|
res.status(400).json({ success: false, message: 'Validierungsfehler', errors: parsed.error.flatten().fieldErrors });
|
|
return;
|
|
}
|
|
const item = await personalEquipmentService.create(parsed.data, req.user!.id);
|
|
res.status(201).json({ success: true, data: item });
|
|
} catch (error) {
|
|
logger.error('personalEquipment.create error', { error });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht erstellt werden' });
|
|
}
|
|
}
|
|
|
|
async update(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params as Record<string, string>;
|
|
if (!isValidUUID(id)) {
|
|
res.status(400).json({ success: false, message: 'Ungültige ID' });
|
|
return;
|
|
}
|
|
const parsed = UpdateSchema.safeParse(req.body);
|
|
if (!parsed.success) {
|
|
res.status(400).json({ success: false, message: 'Validierungsfehler', errors: parsed.error.flatten().fieldErrors });
|
|
return;
|
|
}
|
|
if (Object.keys(parsed.data).length === 0) {
|
|
res.status(400).json({ success: false, message: 'Kein Feld zum Aktualisieren angegeben' });
|
|
return;
|
|
}
|
|
const item = await personalEquipmentService.update(id, parsed.data as any);
|
|
if (!item) {
|
|
res.status(404).json({ success: false, message: 'Nicht gefunden' });
|
|
return;
|
|
}
|
|
res.status(200).json({ success: true, data: item });
|
|
} catch (error: any) {
|
|
if (error?.message === 'No fields to update') {
|
|
res.status(400).json({ success: false, message: 'Kein Feld zum Aktualisieren angegeben' });
|
|
return;
|
|
}
|
|
logger.error('personalEquipment.update error', { error, id: req.params.id });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht aktualisiert werden' });
|
|
}
|
|
}
|
|
|
|
async delete(req: Request, res: Response): Promise<void> {
|
|
try {
|
|
const { id } = req.params as Record<string, string>;
|
|
if (!isValidUUID(id)) {
|
|
res.status(400).json({ success: false, message: 'Ungültige ID' });
|
|
return;
|
|
}
|
|
const deleted = await personalEquipmentService.delete(id);
|
|
if (!deleted) {
|
|
res.status(404).json({ success: false, message: 'Nicht gefunden' });
|
|
return;
|
|
}
|
|
res.status(200).json({ success: true, message: 'Persönliche Ausrüstung gelöscht' });
|
|
} catch (error) {
|
|
logger.error('personalEquipment.delete error', { error, id: req.params.id });
|
|
res.status(500).json({ success: false, message: 'Persönliche Ausrüstung konnte nicht gelöscht werden' });
|
|
}
|
|
}
|
|
}
|
|
|
|
export default new PersonalEquipmentController();
|