如何创建具有可用性/时段的预订系统架构



我正在做一个个人项目,我一直在思考如何开始为店主实现一个日历,他可以在其中列出服务和可用时间。也就是说,假设我是一名店主/理发师,我提供许多服务,我从早上9点工作到下午5点,有一个小时的休息时间。假设一次理发需要15分钟(持续时间(。

我应该如何继续实现这一点?用事件预先填充数据库好吗?也就是说,允许店主创建他的日历和时间段,并将其插入数据库,每当用户想要预订时,系统都会根据他选择的日期检查可用性。如果在特定月份的特定时间有可用的空闲日,我们可以允许他预订,否则我们会向他显示该日期/日期已满或已预订或类似情况。为了便于论证,假设我允许用户在数据库中预先填充日期列表,这是一个好的做法吗?因为如果你每天有11个时段,持续7天*4周,那就太好了?

如果是这样的话,我只能允许他提前两个月左右。

如果有人能给我一个从哪里开始的建议,那就太好了。

提前感谢

你的问题很开放(这里的人不喜欢!XD(。没有完美的答案,这取决于你的"理发师"的需求。我看到了两种非常不同的实现方式(但我也是一个初学者(:

  1. 您的建议=固定时间段。不要担心用"预订:虚假"来代替这些时段,因为即使一年全天候都是这样,实际上也是一个很小的DB。例如,我正在处理1分钟的时间段,每分钟加载大量数据(交易机器人(,而这仍然是一个约100MB的数据库,持续了一整年
  2. 我的建议=只有当理发师实际预订了一些东西时,才创建一个新的DB文档。最大的优势是:他可以按分钟选择开始和结束时间。现在的问题是,如何防止超额预订(尽管这在飞机上有效,为什么不呢!(

我可以向您展示我将如何启动它的想法:

const bookingSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
startTime: {type:Number, required:true},
endTime: {type:Number, required:true},
clientName: {type:String, required:true}
});
const Booking = mongoose.model('Booking', bookingSchema);

我会将startTimeendTime存储为以毫秒为单位的时间戳,但这是一个选择问题。您可以一直到将Y/M/D/H/M存储在单独的字段中。我更喜欢代码中的逻辑,而不是DB中的逻辑。

现在,当我们添加新的预订时,我们可以使用一些日期逻辑(使用时间戳更容易(来检查是否与先前存在的预订有冲突:

var newStartTime = someTimestamp;
var newEndTime = someOtherTimestamp;
var newClientName = 'John Doe';
var conflictingBookings = await Booking.find()
.where('startTime').lt(newEndTime)
.where('endTime').gt(newStartTime)
.exec();
// This selects all preexisting bookings which have both :
// ---> startTime < newEndTime
// ---> endTime > newStartTime
// You can check yourself : I think it handles all possible overlaps !
// Now, conflictingBookings is an array containing all documents in conflict.
// You can tell your barber the problems :
if (conflictingBookings.length === 0) {
// everything ok, you can book it
// here you add the new booking to your DB...
} else {
conflictingBookings.forEach( booking => {
console.log(`There is already a booking from ${convertToString(booking.startTime)} to ${convertToString(booking.endTime)} with ${booking.clientName} !`);
});
// convertToString() being your custom function to convert timestamps to readable dates (not discussed here).
// we log all conflicting preexisting bookings to the console
}

这是一个良好的开端。我真的很感谢你,因为我很快就会为自己的业务编写这样一个预订迷你应用程序,我需要这个逻辑!

然而,我必须建议你检查是否已经存在一些更容易满足你需求的可视化应用程序,因为你项目的难点实际上是可视化用户界面,我不知道如何做到这一点。也许可以将你的代码/数据库与一些日历API(谷歌日历或其他(集成。

祝你好运,继续努力,告诉我们你的决定!


[EDIT:如果你真的想要实现"时隙"]

对于任何通过预订/预约人工时间(而不是在这里预订位置/房间(工作的工作来说,"时段"的想法都不是现实。因为预约从来不会占用应有的时间,而且因为员工比任何人都更清楚是否可以在其他两个预约之间添加新的预约。。。

但如果你真的想要时间段,我会构建两个独立的集合/数据库。

第一个DB包含预订,如上所述。

第二个DB包含时间段,每个时间段是你的员工精确安排所需的最小时间(可能是5分钟、10分钟、15分钟…(。这些都是"原子"时间段。举个例子,假设为10分钟。这是DB模式:

const slotSchema = mongoose.Schema({
_id: mongoose.Schema.Types.ObjectId,
time: {type:Number, required:true, unique:true}, // starting timestamp of the slot
booked: {type:Boolean, required:true}, // obvious !
bookingId: {type:String} // if booked, the _id of the booking in the other DB
});
const Slot = mongoose.model('Slot', slotSchema);

现在,您可以使用for循环预填充该DB(此处未讨论(。

当员工想要添加新预订时,他会给出开始和结束时间,您可以将其转换为时间戳:startTimeendTime。您现在可以预订相应的时段:

// superBarber wants to book from 10:30am to 11:10am
var startTime = /*the timestamp for 10:30am that day*/
var endTime = /*the timestamp for 11:10am that day*/
// You can check availability as I showed above...
// You insert a new booking in the Booking collection :
var yourNewBooking = await Booking./*do your update...*/;
// And now you can update your time slots :
var slotsToBook = await Slot.find()
.where('time').gte(startTime).lt(endTime)
.exec();
// slotsToBook = [10:30slot, 10:40slot, 10:50slot, 11:00slot]
slotsToBook.forEach(async (slot) => {
if (slot.booked) {
console.log(`Damn, the slot at ${slot.time} is already booked`); 
} else {
await Slot.findByIdAndUpdate(
slot._id,
{$set: {
booked: true, 
bookingId: yourNewBooking._id
}}
);
console.log(`Just booked the ${slot.time} slot !`);
}
});
// Note : here I assume you're working inside async functions and you know how to handle callbacks / promises / await. Another thing entirely...

希望它能帮助。。。

最新更新