This commit is contained in:
Matthias Hochmeister
2026-03-13 21:49:42 +01:00
parent e666ff434e
commit ef9d2ff4a2
6 changed files with 276 additions and 0 deletions

View File

@@ -230,6 +230,47 @@ class MemberController {
res.status(500).json({ success: false, message: 'Fehler beim Aktualisieren des Profils.' });
}
}
/**
* GET /api/members/:userId/befoerderungen
*/
async getBefoerderungen(req: Request, res: Response): Promise<void> {
try {
const { userId } = req.params;
const data = await memberService.getBefoerderungen(userId);
res.status(200).json({ success: true, data });
} catch (error) {
logger.error('getBefoerderungen error', { error, userId: req.params.userId });
res.status(500).json({ success: false, message: 'Fehler beim Laden der Beförderungen.' });
}
}
/**
* GET /api/members/:userId/untersuchungen
*/
async getUntersuchungen(req: Request, res: Response): Promise<void> {
try {
const { userId } = req.params;
const data = await memberService.getUntersuchungen(userId);
res.status(200).json({ success: true, data });
} catch (error) {
logger.error('getUntersuchungen error', { error, userId: req.params.userId });
res.status(500).json({ success: false, message: 'Fehler beim Laden der Untersuchungen.' });
}
}
/**
* GET /api/members/:userId/fahrgenehmigungen
*/
async getFahrgenehmigungen(req: Request, res: Response): Promise<void> {
try {
const { userId } = req.params;
const data = await memberService.getFahrgenehmigungen(userId);
res.status(200).json({ success: true, data });
} catch (error) {
logger.error('getFahrgenehmigungen error', { error, userId: req.params.userId });
res.status(500).json({ success: false, message: 'Fehler beim Laden der Fahrgenehmigungen.' });
}
}
}
export default new MemberController();

View File

@@ -39,6 +39,24 @@ router.post(
memberController.createMemberProfile.bind(memberController)
);
router.get(
'/:userId/befoerderungen',
requirePermission('members:read'),
memberController.getBefoerderungen.bind(memberController)
);
router.get(
'/:userId/untersuchungen',
requirePermission('members:read'),
memberController.getUntersuchungen.bind(memberController)
);
router.get(
'/:userId/fahrgenehmigungen',
requirePermission('members:read'),
memberController.getFahrgenehmigungen.bind(memberController)
);
/**
* Inline middleware for PATCH /:userId.
* Enforces that the caller is either the profile owner OR holds members:write.

View File

@@ -626,6 +626,63 @@ class MemberService {
throw new Error('Failed to fetch member stats');
}
}
/**
* Returns all Beförderungen for a member, newest first.
*/
async getBefoerderungen(userId: string): Promise<any[]> {
try {
const result = await pool.query(
`SELECT id, datum, dienstgrad, created_at
FROM befoerderungen
WHERE user_id = $1
ORDER BY datum DESC NULLS LAST, created_at DESC`,
[userId]
);
return result.rows;
} catch (error) {
logger.error('Error fetching Beförderungen', { error, userId });
return [];
}
}
/**
* Returns all Untersuchungen for a member, newest first.
*/
async getUntersuchungen(userId: string): Promise<any[]> {
try {
const result = await pool.query(
`SELECT id, datum, anmerkungen, art, ergebnis, created_at
FROM untersuchungen
WHERE user_id = $1
ORDER BY datum DESC NULLS LAST, created_at DESC`,
[userId]
);
return result.rows;
} catch (error) {
logger.error('Error fetching Untersuchungen', { error, userId });
return [];
}
}
/**
* Returns all Fahrgenehmigungen for a member, newest first.
*/
async getFahrgenehmigungen(userId: string): Promise<any[]> {
try {
const result = await pool.query(
`SELECT id, ausstellungsdatum, gueltig_bis, behoerde, nummer, klasse, created_at
FROM fahrgenehmigungen
WHERE user_id = $1
ORDER BY ausstellungsdatum DESC NULLS LAST, created_at DESC`,
[userId]
);
return result.rows;
} catch (error) {
logger.error('Error fetching Fahrgenehmigungen', { error, userId });
return [];
}
}
}
export default new MemberService();