Мне нужна помощь в правильной реализации планировщика бронирования и доступности в Django
Этот вопрос уже много раз задавался на StackOverflow и на форумах Django, но ни один из ответов, которые я нашел, не подходит и не является достаточно полным для моей ситуации.
Сначала кратко:
Я создаю веб-приложение для компании по прокату автомобилей. Помимо помощи в организации и централизации их парка, оно также поможет им собирать заказы непосредственно от клиентов. Как и в большинстве случаев с арендой, логистика всего этого может быть несколько запутанной.
Кто-то может разместить заказ на автомобиль сегодня (12 декабря), но фактически забрать автомобиль в период с Рождества по Новый год.
Арендатор может взять автомобиль всего на два дня, а затем продлить бронирование в последнюю минуту. Когда это происходит (часто, очень часто), бизнесу обычно приходится искать другой автомобиль для другого клиента, который должен был получить этот автомобиль на следующий день.
Добавим к этому, что отдельный автомобиль может быть арендован только для одного клиента одновременно, поэтому он не может иметь несколько бронирований на один и тот же период.
Большинство ответов пропагандируют простой подход, который выглядит следующим образом:
models.py
class Booking(models.Model):
car = models.ForeignKey(Car, ...)
start_date = models.dateField(...)
end_date = models.dateField(...)
is_available = models.booleanField(default=True)
forms.py
import datetime
from django import forms
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _
from . import models
class PlaceOrderForm(forms.Form):
"""Initial order forms for customers."""
start_date = forms.DateField(help_text='When do you want the car?')
end_date = forms.DateField(help_text='When will you return the car?')
def clean_data(self, date):
data = self.cleaned_data(date)
# Check that start date is not in the past
if data < datetime.date.today():
raise ValidationError(_('Invalid date: Start in past.'))
# Ensure that start date is not today (to avoid last_minute bookings.)
if data == datetime.date.today():
raise ValidationError(_('Invalid date: Please reserve your car at least 24 hours in advance.'))
return data
cleaned_start_date = clean_data(start_date)
cleaned_end_date = clean_data(end_date)
('_' обозначает )
Бронирование имеет дату начала_даты и дату окончания_даты. Если дата current находится внутри дат начала_даты и конца_даты, автомобиль помечается как недоступный. Если булево поле is_available (не представленное в forms.py выше) имеет значение "False", автомобиль полностью недоступен.
Опять же, из-за уникального характера аренды автомобилей это может стать проблемой. Некоторые люди бронируют автомобиль на шесть месяцев, а другие - на два дня. Если кто-то хочет арендовать автомобиль на длительный срок, но в течение предполагаемого срока будет еще один короткий перерыв, такая проверка не позволит ему полностью оформить заказ!
Но это проблема: возвращаясь к модели аренды, кто-то может забронировать автомобиль в будущем. Автомобиль, который недоступен сейчас, должен иметь возможность быть забронированным на будущую дату.
Кроме того, отдельный автомобиль может быть арендован только для одного человека одновременно, поэтому он не может иметь несколько бронирований на один и тот же период. Опять же, из-за уникальной природы аренды автомобилей это может стать проблемой. Некоторые люди бронируют автомобиль на шесть месяцев, а другие - на два дня. Если кто-то хочет взять машину в долгосрочную аренду, но в течение предполагаемого срока будет еще один короткий промежуток времени, такая проверка не позволит ему полностью оформить заказ!
Таким образом, если возникает конфликт, вместо того, чтобы полностью блокировать бронирование (что, опять же, было бы плохим UX-решением), он должен уведомить бизнес, чтобы они могли назначить другой автомобиль и спланировать все заранее.
Другие клиенты не должны иметь возможность забронировать его на время, на которое он одолжен, но они должны иметь возможность забронировать его на другое время, когда он свободен.
Итак, если кто-то размещает заказ сейчас, скажем, на 24-31 декабря. Эти дни должны быть заблокированы. Однако другой человек должен иметь возможность забронировать его с сегодняшнего дня по 23-е, и с 31-го и далее. И если человек, арендующий машину, должен продлить срок, он должен уведомить об этом прокатный бизнес, чтобы они могли заблаговременно назначить пользователю другую машину.
Возможная идея для продвижения вперед. Основное предположение во всех этих ответах заключается в том, что недоступность бронирования должна обрабатываться в самом Django, в бэкенде. Однако, я строю этот проект с REST фреймворком, и буду использовать фронтенд на основе Js (сейчас изучаю Javascript для этой цели).
Я думаю, что это лучше решать более целостным способом с помощью встроенных функций проверки и сохранения формы.
Рабочий процесс будет выглядеть примерно так:
- Пользователь выбирает автомобиль и выбирает даты начала и окончания из выпадающего календаря на сайте.
- Затем форма проверит, все ли в порядке с базовыми проверками (нельзя ли забронировать автомобиль в прошлом). Если они работают, то заказ размещается и сохраняется в базе данных.
- Если есть конфликт расписания, заказ не блокируется , а передается предприятию, которое может назначить им другой автомобиль на этот период. (Как правило, люди не особо заботятся о получении конкретных автомобилей - в основном это цена, пространство и экономия топлива. Все остальное взаимозаменяемо.
- После этого можно собрать депозит и установить заказ в системе.
Как бы то ни было, это моя предварительная идея, которая объединит лучшее из всех миров и создать отличный опыт как для бизнеса, так и для клиента.
Итак, мой вопрос: как это можно настроить? Что должно быть на фронт-энде и что должно быть на бэк-энде? Я учусь программированию на ходу, так что это может быть просто, но я бьюсь над этим уже неделю, буду благодарен за любую помощь!
Спасибо!
Похоже, что у вас есть два процесса - заказ клиента и назначение автомобиля. Вам нужно спланировать структуру данных, а затем поток процессов. Это поможет вам разобраться во всем до начала работы.
Модели
Используя (скобки) для внешних ключей, Customer_order собирает такие вещи, как:
Customer(User)
desired_start_date
desired_end_date
car_type - this could be many fields
Модель автомобиля
car_type
rental (many to many Rental with through table Rental)
Модель аренды
car (Car)
customer_order(Customer_order)
start_date
end_date
Мы сохранили модель аренды с собственными датами начала и окончания, поскольку пользователь может изменить желаемый период, но он не должен менять даты аренды, не проверив, существуют ли другие в этот период времени для данного автомобиля.
Итак, поток должен идти:
user passes js validation and form submitted to backend
backend checks for car availability based on type and dates
if available, creates rental
if not available, alert user and passes to staff
if a user changes a rental period (via an edit screen for existing customer_orders)
backend checks for same car availability based on existing rentals
if not available, alert user and pass to staff
Вы также создадите представление только для персонала, в котором будут перечислены заказы клиентов, которые не могут быть согласованы (без моделей аренды), а также автомобили запрашиваемого типа, которые не имеют аренды на этот период.
Видя такое представление, мне кажется, что ваш внутренний процесс мог бы использовать нечто подобное для поиска и автоматического назначения другого автомобиля того же типа, если бы вы хотели расширить процесс проверки доступности, уведомляя персонал о том, что это произошло, и обращаясь к персоналу, только если этот тип автомобиля недоступен.
На самом деле программирование всего этого оставлено в качестве упражнения для читателя.