Node.js中实现停车场车位数组的增减操作(含预订场景)
停车位预订的车位动态调整实现
一、创建预订时的车位扣减逻辑
当前需求是创建预订时自动扣减1个车位(后续支持用户自定义数量),且totalSpots字段为数组格式(未来将存储具体车位编号列表)。需在现有预订流程中加入车位检查与扣减逻辑,避免超卖:
修改后的createBooking代码
exports.createBooking = async (req, res) => { try { const user = await Auth.findOne({ _id: req.data.id }); if (!user) return res.status(404).json({ error: "用户不存在" }); const { parkingId, date, startTime } = req.body; // 当前固定扣减1个车位,后续可改为req.body.spotNumber const deductSpots = 1; const parking = await Parking.findOne({ _id: parkingId, date }); if (!parking) return res.status(404).json({ error: "停车场信息不存在" }); // 检查剩余车位是否充足 const currentAvailable = parking.totalSpots[0]; if (currentAvailable < deductSpots) { return res.status(400).json({ error: "剩余车位不足" }); } // 创建预订记录 const bookingDetails = new Booking({ user, parking, startTime, duration: req.body.duration, date: moment(req.body.date).format("MMM DD, YYYY"), endTime: req.body.endTime, paymentAmount: req.body.paymentAmount, isFeePaid: req.body.isFeePaid, status: "sent", }); // 先保存预订,再更新车位数量(要求强一致性可使用MongoDB事务) const savedBooking = await bookingDetails.save(); // 扣减车位并更新停车场记录 parking.totalSpots[0] = currentAvailable - deductSpots; await parking.save(); return res.status(200).json({ success: true, msg: "预订成功", data: { details: savedBooking }, }); } catch (error) { return res.status(500).json({ error: error.message }); } };
关键逻辑说明
- 车位充足性校验:提前拦截剩余车位不足的请求,避免无效预订
- 原子性保障:若需更强的数据一致性,可开启MongoDB副本集并使用事务,确保预订保存与车位扣减操作同时成功或失败
- 扩展预留:
deductSpots变量后续可直接替换为用户传入的车位数量,需额外添加合法性校验(如非负、不超过剩余车位)
二、用户驶离时的车位恢复逻辑
当用户驶离停车场(可通过修改预订状态为completed触发),需恢复对应车位数量,且不能超过商家设定的总车位数(建议在Parking模型中新增maxTotalSpots字段存储总车位上限):
示例实现代码
exports.completeBooking = async (req, res) => { try { const { bookingId } = req.params; // 当前恢复1个车位,后续可根据预订记录中的车位数量恢复 const restoreSpots = 1; const booking = await Booking.findById(bookingId).populate("parking"); if (!booking) return res.status(404).json({ error: "预订记录不存在" }); const parking = booking.parking; // 计算恢复后的车位数量,不超过商家设定的总车位 const newAvailable = Math.min( parking.totalSpots[0] + restoreSpots, parking.maxTotalSpots ); // 更新车位数量 parking.totalSpots[0] = newAvailable; await parking.save(); // 更新预订状态 booking.status = "completed"; await booking.save(); return res.status(200).json({ success: true, msg: "车位已恢复,预订完成", data: { updatedAvailable: newAvailable } }); } catch (error) { return res.status(500).json({ error: error.message }); } };
关键逻辑说明
- 上限控制:通过
Math.min确保恢复后的车位数量不超过商家设定的总车位 - 关联数据操作:通过
populate关联停车场信息,确保操作对应日期的停车场数据 - 兼容扩展:后续若
totalSpots改为存储具体车位编号数组(如[1,2,3,...95]),只需调整车位操作逻辑:扣减时移除指定数量的编号,恢复时将编号重新添加回数组(需去重)
三、未来扩展:具体车位编号的兼容方案
当totalSpots改为存储具体车位编号列表时,调整车位操作逻辑即可兼容:
- 扣减车位:从数组中按顺序/随机移除指定数量的编号,并存入预订记录
- 恢复车位:将预订记录中的车位编号重新添加回
totalSpots数组(去重处理)
示例扣减逻辑片段
// 当totalSpots为具体车位编号数组时,扣减1个车位 const spotToAssign = parking.totalSpots.pop(); // 或shift()按顺序分配 bookingDetails.assignedSpots = [spotToAssign]; // 存储到预订记录
示例恢复逻辑片段
// 恢复车位时,将预订中的车位编号加回数组 parking.totalSpots.push(...booking.assignedSpots); // 去重并排序(可选) parking.totalSpots = [...new Set(parking.totalSpots)].sort((a,b) => a-b);
内容的提问来源于stack exchange,提问作者Talc
相关产品推荐
相关产品推荐

