Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .idea/testbookingengine.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 20 additions & 0 deletions pms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,23 @@ class Meta:
'total': forms.HiddenInput(),
'state': forms.HiddenInput(),
}

class BookingDatesForm(forms.ModelForm):
class Meta:
model = Booking
fields = ["checkin", "checkout"]

'''
Receives the check-in and check-out dates for a booking.
Checks that the selected date range is valid.
Returns cleaned data when the form is valid, or errors if validation fails.
'''
def clean(self):
cleaned_data = super().clean()
checkin = cleaned_data.get('checkin')
checkout = cleaned_data.get('checkout')

if checkin and checkout and checkout <= checkin:
raise forms.ValidationError('La fecha de salida debe ser posterior a la fecha de entrada.')

return cleaned_data
28 changes: 28 additions & 0 deletions pms/templates/edit_booking_dates.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{% extends "main.html" %}

{% block content %}
<h1>Editar fechas de la reserva</h1>

<div class="card p-4">
<p><strong>Habitación:</strong> {{ booking.room.name }}</p>

<form method="post">
{% csrf_token %}
{{ form.non_field_errors }}

<div class="mb-3">
{{ form.checkin.label_tag }}
{{ form.checkin }}
{{ form.checkin.errors }}
</div>

<div class="mb-3">
{{ form.checkout.label_tag }}
{{ form.checkout }}
{{ form.checkout.errors }}
</div>

<button type="submit" class="btn btn-primary">Guardar</button>
</form>
</div>
{% endblock content %}
2 changes: 1 addition & 1 deletion pms/templates/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ <h3>Reservas Realizadas</h3>
</div>
<div class="row">
<div class="col">

<a href="{% url 'edit_booking' pk=booking.id%} " >Editar datos de contacto</a>
<a href="{% url 'edit_booking_dates' pk=booking.id %}">Editar fechas</a>
</div>
<div class="col">

Expand Down
96 changes: 95 additions & 1 deletion pms/tests.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,97 @@
from django.test import TestCase
from datetime import date

from django.test import TestCase, override_settings
from django.urls import reverse

from pms.models import Booking, Customer, Room, Room_type

# Create your tests here.
@override_settings(STATICFILES_STORAGE="django.contrib.staticfiles.storage.StaticFilesStorage")
class EditBookingDatesViewTest(TestCase):
def setUp(self):
self.room_type = Room_type.objects.create(
name="Single",
max_guests=1,
price=20
)

self.room_1 = Room.objects.create(name="Room 1.1", room_type=self.room_type)
self.room_2 = Room.objects.create(name="Room 1.2", room_type=self.room_type)

self.customer = Customer.objects.create(
name="John Doe",
email="john@example.com",
phone="123456789"
)

self.booking = Booking.objects.create(
room=self.room_1,
customer=self.customer,
checkin=date(2022, 1, 10),
checkout=date(2022, 1, 12),
guests=1,
total=40,
code="ABC123",
state="NEW"
)

def test_booking_dates_are_updated_when_room_is_available(self):
response = self.client.post(
reverse("edit_booking_dates", kwargs={"pk": self.booking.id}),
{
"checkin": "2022-01-15",
"checkout": "2022-01-18",
}
)

self.assertEqual(response.status_code, 302)

self.booking.refresh_from_db()
self.assertEqual(self.booking.checkin, date(2022, 1, 15))
self.assertEqual(self.booking.checkout, date(2022, 1, 18))

def test_error_is_shown_when_dates_overlap_with_another_booking(self):
Booking.objects.create(
room=self.room_1,
customer=self.customer,
checkin=date(2022, 1, 14),
checkout=date(2022, 1, 16),
guests=1,
total=40,
code="XYZ789",
state="NEW"
)

response = self.client.post(
reverse("edit_booking_dates", kwargs={"pk": self.booking.id}),
{
"checkin": "2022-01-15",
"checkout": "2022-01-17",
}
)

self.assertEqual(response.status_code, 200)
self.assertContains(response, "No hay disponibilidad para las fechas seleccionadas")

self.booking.refresh_from_db()
self.assertEqual(self.booking.checkin, date(2022, 1, 10))
self.assertEqual(self.booking.checkout, date(2022, 1, 12))

def test_error_is_shown_when_checkout_is_not_later_than_checkin(self):
response = self.client.post(
reverse("edit_booking_dates", kwargs={"pk": self.booking.id}),
{
"checkin": "2022-01-15",
"checkout": "2022-01-15",
}
)

self.assertEqual(response.status_code, 200)
self.assertContains(
response,
"La fecha de salida debe ser posterior a la fecha de entrada."
)

self.booking.refresh_from_db()
self.assertEqual(self.booking.checkin, date(2022, 1, 10))
self.assertEqual(self.booking.checkout, date(2022, 1, 12))
1 change: 1 addition & 0 deletions pms/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
path("search/booking/", views.BookingSearchView.as_view(), name="booking_search"),
path("booking/<str:pk>/", views.BookingView.as_view(), name="booking"),
path("booking/<str:pk>/edit", views.EditBookingView.as_view(), name="edit_booking"),
path("booking/<int:pk>/edit-dates/", views.EditBookingDatesView.as_view(), name="edit_booking_dates"),
path("booking/<str:pk>/delete", views.DeleteBookingView.as_view(), name="delete_booking"),
path("rooms/", views.RoomsView.as_view(), name="rooms"),
path("room/<str:pk>/", views.RoomDetailsView.as_view(), name="room_details"),
Expand Down
39 changes: 39 additions & 0 deletions pms/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,45 @@ def post(self, request, pk):
customer_form.save()
return redirect("/")

class EditBookingDatesView(View):
# renders the booking dates edition form
def get(self, request, pk):
booking = Booking.objects.get(id=pk)
form = BookingDatesForm(instance=booking)

context = {
"booking": booking,
"form": form,
}
return render(request, "edit_booking_dates.html", context)

# updates the booking dates after validating room availability
def post(self, request, pk):
booking = Booking.objects.get(id=pk)
form = BookingDatesForm(request.POST, instance=booking)

if form.is_valid():
checkin = form.cleaned_data["checkin"]
checkout = form.cleaned_data["checkout"]

conflicting_bookings = Booking.objects.filter(
room=booking.room,
checkin__lt=checkout,
checkout__gt=checkin,
state="NEW"
).exclude(id=booking.id)

if conflicting_bookings.exists():
form.add_error(None, "No hay disponibilidad para las fechas seleccionadas")
else:
form.save()
return redirect("/")

context = {
"booking": booking,
"form": form,
}
return render(request, "edit_booking_dates.html", context)

class DashboardView(View):
def get(self, request):
Expand Down