mirror of
https://github.com/Alvin-Zilverstand/Challenge_15_Magazijn_App_Maken.git
synced 2026-03-06 02:56:41 +01:00
208 lines
7.4 KiB
JavaScript
208 lines
7.4 KiB
JavaScript
const express = require('express');
|
|
const { auth, adminOnly } = require('../middleware/auth');
|
|
const Reservation = require('../models/Reservation');
|
|
const Item = require('../models/Item');
|
|
const router = express.Router();
|
|
|
|
// Get all reservations (admin only)
|
|
router.get('/', auth, adminOnly, async (req, res) => {
|
|
try {
|
|
const reservations = await Reservation.find({ status: { $ne: 'ARCHIVED' } })
|
|
.populate('userId', 'username')
|
|
.populate('itemId')
|
|
.exec();
|
|
|
|
if (!reservations) {
|
|
return res.json([]); // Return empty array if no reservations
|
|
}
|
|
|
|
const formattedReservations = reservations
|
|
.filter(reservation => reservation.userId && reservation.itemId) // Filter out any invalid references
|
|
.map(reservation => ({
|
|
_id: reservation._id,
|
|
studentName: reservation.userId.username,
|
|
itemName: reservation.itemId.name,
|
|
location: reservation.itemId.location,
|
|
status: reservation.status,
|
|
quantity: reservation.quantity || 1,
|
|
reservedDate: reservation.reservedDate
|
|
}));
|
|
|
|
res.json(formattedReservations);
|
|
} catch (error) {
|
|
console.error('Error fetching reservations:', error);
|
|
res.status(500).json({
|
|
message: 'Failed to load reservations',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// Get user's reservations
|
|
router.get('/my', auth, async (req, res) => {
|
|
try {
|
|
const reservations = await Reservation.find({
|
|
userId: req.user._id,
|
|
status: { $ne: 'ARCHIVED' }
|
|
}).populate('itemId');
|
|
|
|
// Filter out reservations with deleted items and format the response
|
|
const formattedReservations = reservations
|
|
.filter(reservation => reservation.itemId) // Only include reservations with valid items
|
|
.map(reservation => ({
|
|
_id: reservation._id,
|
|
itemName: reservation.itemId.name,
|
|
location: reservation.itemId.location,
|
|
status: reservation.status,
|
|
quantity: reservation.quantity || 1,
|
|
reservedDate: reservation.reservedDate
|
|
}));
|
|
|
|
res.json(formattedReservations);
|
|
} catch (error) {
|
|
console.error('Error fetching user reservations:', error);
|
|
res.status(500).json({
|
|
message: 'Failed to load reservations',
|
|
error: error.message
|
|
});
|
|
}
|
|
});
|
|
|
|
// Create reservation
|
|
router.post('/', auth, async (req, res) => {
|
|
try {
|
|
const item = await Item.findById(req.body.itemId);
|
|
if (!item) {
|
|
return res.status(404).json({ message: 'Item not found' });
|
|
}
|
|
|
|
const requestedQuantity = parseInt(req.body.quantity) || 1;
|
|
if (item.quantity < item.reserved + requestedQuantity) {
|
|
return res.status(400).json({ message: 'Requested quantity is not available' });
|
|
}
|
|
|
|
const reservation = new Reservation({
|
|
itemId: req.body.itemId,
|
|
userId: req.user._id,
|
|
quantity: requestedQuantity
|
|
});
|
|
|
|
await reservation.save();
|
|
item.reserved += requestedQuantity;
|
|
await item.save();
|
|
|
|
res.status(201).json(reservation);
|
|
} catch (error) {
|
|
res.status(400).json({ message: error.message });
|
|
}
|
|
});
|
|
|
|
// Update reservation status (admin can update any, students can only mark as returned)
|
|
router.patch('/:id', auth, async (req, res) => {
|
|
try {
|
|
const reservation = await Reservation.findById(req.params.id).populate('userId');
|
|
if (!reservation) {
|
|
return res.status(404).json({ message: 'Reservation not found' });
|
|
}
|
|
|
|
// Check authorization
|
|
const isAdmin = req.user.role === 'admin';
|
|
const isOwner = reservation.userId._id.toString() === req.user._id.toString();
|
|
const isReturning = req.body.status === 'RETURNED';
|
|
|
|
if (!isAdmin && (!isOwner || !isReturning)) {
|
|
return res.status(403).json({
|
|
message: 'Not authorized. Students can only return their own items.'
|
|
});
|
|
}
|
|
|
|
// Additional validation for students
|
|
if (!isAdmin && isReturning && reservation.status !== 'APPROVED') {
|
|
return res.status(400).json({
|
|
message: 'Can only return approved items'
|
|
});
|
|
}
|
|
|
|
const item = await Item.findById(reservation.itemId);
|
|
if (!item) {
|
|
return res.status(404).json({ message: 'Item not found' });
|
|
}
|
|
|
|
const oldStatus = reservation.status;
|
|
const newStatus = req.body.status;
|
|
reservation.status = newStatus;
|
|
|
|
// Include quantity in the update if provided
|
|
if (req.body.quantity !== undefined) {
|
|
reservation.quantity = req.body.quantity;
|
|
}
|
|
|
|
await reservation.save();
|
|
|
|
// Update item reserved count based on status change
|
|
if (oldStatus === 'PENDING' && newStatus === 'REJECTED') {
|
|
item.reserved = Math.max(0, item.reserved - (reservation.quantity || 1));
|
|
await item.save();
|
|
} else if (oldStatus === 'APPROVED' && newStatus === 'RETURNED') {
|
|
item.reserved = Math.max(0, item.reserved - (reservation.quantity || 1));
|
|
await item.save();
|
|
}
|
|
|
|
res.json(reservation);
|
|
} catch (error) {
|
|
console.error('Error updating reservation:', error);
|
|
res.status(400).json({ message: error.message });
|
|
}
|
|
});
|
|
|
|
// Delete reservation (admin can delete any, students can only delete their own)
|
|
router.delete('/:id', auth, async (req, res) => {
|
|
try {
|
|
const reservation = await Reservation.findById(req.params.id).populate('userId');
|
|
if (!reservation) {
|
|
return res.status(404).json({ message: 'Reservation not found' });
|
|
}
|
|
|
|
// Check if user is authorized to delete this reservation
|
|
if (req.user.role !== 'admin' && reservation.userId._id.toString() !== req.user._id.toString()) {
|
|
return res.status(403).json({ message: 'Not authorized to delete this reservation' });
|
|
}
|
|
|
|
// Update item's reserved count
|
|
const item = await Item.findById(reservation.itemId);
|
|
if (item) {
|
|
item.reserved = Math.max(0, item.reserved - 1); // Ensure it doesn't go below 0
|
|
await item.save();
|
|
}
|
|
|
|
await Reservation.findByIdAndDelete(req.params.id);
|
|
res.json({ message: 'Reservation deleted successfully' });
|
|
} catch (error) {
|
|
res.status(500).json({ message: error.message });
|
|
}
|
|
});
|
|
|
|
// Archive reservation (admin only)
|
|
router.patch('/:id/archive', auth, adminOnly, async (req, res) => {
|
|
try {
|
|
const reservation = await Reservation.findById(req.params.id);
|
|
if (!reservation) {
|
|
return res.status(404).json({ message: 'Reservation not found' });
|
|
}
|
|
|
|
// Only allow archiving of returned reservations
|
|
if (reservation.status !== 'RETURNED') {
|
|
return res.status(400).json({ message: 'Can only archive returned reservations' });
|
|
}
|
|
|
|
reservation.status = 'ARCHIVED';
|
|
await reservation.save();
|
|
|
|
res.json({ message: 'Reservation archived successfully' });
|
|
} catch (error) {
|
|
console.error('Error archiving reservation:', error);
|
|
res.status(500).json({ message: error.message });
|
|
}
|
|
});
|
|
|
|
module.exports = router; |