You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 08:45:39