+
diff --git a/pms/tests.py b/pms/tests.py
index 7ce503c2d..141c18764 100644
--- a/pms/tests.py
+++ b/pms/tests.py
@@ -1,3 +1,88 @@
from django.test import TestCase
+from django.utils import timezone
+from datetime import timedelta
+from .models import Room, Room_type, Customer, Booking
+from .forms import EditBookingDateForm
-# Create your tests here.
+class EditBookingDateFormUnitTests(TestCase):
+ def setUp(self):
+ # Date today
+ self.today = timezone.now().date()
+
+ # Setup data
+ self.room_type = Room_type.objects.create(name="Doble", price=50.0, max_guests=2)
+ self.room = Room.objects.create(name="101", room_type=self.room_type)
+ self.customer = Customer.objects.create(name="Test", email="test@test.com", phone="123")
+
+ # Reservation A: stays today & tomorrow
+ self.booking_a = Booking.objects.create(
+ room=self.room, customer=self.customer,
+ checkin=self.today, checkout=self.today + timedelta(days=2),
+ guests=1, total=100.0, code="BKA", state="NEW"
+ )
+
+ # Reservation B stays from day 5 to day 10
+ self.booking_b = Booking.objects.create(
+ room=self.room, customer=self.customer,
+ checkin=self.today + timedelta(days=5), checkout=self.today + timedelta(days=10),
+ guests=1, total=250.0, code="BKB", state="NEW"
+ )
+
+ def test_form_valid_dates(self):
+ """
+ Case: book in week available
+ expect: successfully changed
+ """
+ data = {
+ 'checkin': self.today + timedelta(days=20),
+ 'checkout': self.today + timedelta(days=25)
+ }
+
+ form = EditBookingDateForm(data=data, instance=self.booking_a)
+
+ self.assertTrue(form.is_valid())
+
+ def test_form_invalid_checkout_before_checkin(self):
+ """
+ Case: try to checkout before of checkin
+ expect: invalid form & feedback error message
+ """
+ error_text = "La fecha de salida debe ser posterior a la de entrada."
+ data = {
+ 'checkin': self.today + timedelta(days=5),
+ 'checkout': self.today + timedelta(days=3) # Checkout before of checkin
+ }
+ form = EditBookingDateForm(data=data, instance=self.booking_a)
+
+
+ self.assertFalse(form.is_valid())
+ # Comprobamos que el error es exactamente el que programamos
+ self.assertIn(error_text, form.errors['__all__'])
+
+ def test_form_overlap_with_other_booking(self):
+ """
+ CASE: overlapping with reservation B
+ Expect: invalid form & feedback error message
+ """
+ error_text = "No hay disponibilidad para las fechas seleccionadas"
+ data = {
+ 'checkin': self.today + timedelta(days=6), # Entra en medio de la Reserva B
+ 'checkout': self.today + timedelta(days=8)
+ }
+ form = EditBookingDateForm(data=data, instance=self.booking_a)
+
+ self.assertFalse(form.is_valid())
+ self.assertIn(error_text, form.errors['__all__'])
+
+ def test_form_self_exclusion(self):
+ """
+ Case: Submitting the form with the booking's currently saved dates
+ Expect : valid form
+ """
+ data = {
+ 'checkin': self.booking_a.checkin,
+ 'checkout': self.booking_a.checkout
+ }
+ form = EditBookingDateForm(data=data, instance=self.booking_a)
+
+ self.assertTrue(form.is_valid())
\ No newline at end of file
diff --git a/pms/urls.py b/pms/urls.py
index c18714abf..e905ca58e 100644
--- a/pms/urls.py
+++ b/pms/urls.py
@@ -7,7 +7,8 @@
path("search/room/", views.RoomSearchView.as_view(), name="search"),
path("search/booking/", views.BookingSearchView.as_view(), name="booking_search"),
path("booking/
/", views.BookingView.as_view(), name="booking"),
- path("booking//edit", views.EditBookingView.as_view(), name="edit_booking"),
+ path("booking//edit/contact/", views.EditBookingView.as_view(), name="edit_booking_contact"),
+ path("booking//edit/date/", views.EditBookingDateView.as_view(), name="edit_booking_date"),
path("booking//delete", views.DeleteBookingView.as_view(), name="delete_booking"),
path("rooms/", views.RoomsView.as_view(), name="rooms"),
path("room//", views.RoomDetailsView.as_view(), name="room_details"),
diff --git a/pms/views.py b/pms/views.py
index f38563933..559c1e4b7 100644
--- a/pms/views.py
+++ b/pms/views.py
@@ -1,5 +1,5 @@
from django.db.models import F, Q, Count, Sum
-from django.shortcuts import render, redirect
+from django.shortcuts import render, redirect, get_object_or_404
from django.utils.decorators import method_decorator
from django.views import View
from django.views.decorators.csrf import ensure_csrf_cookie
@@ -244,3 +244,32 @@ def get(self, request):
'rooms': rooms
}
return render(request, "rooms.html", context)
+
+
+class EditBookingDateView(View):
+ # renders the booking date edition form
+ def get(self, request, pk):
+ booking = get_object_or_404(Booking, pk=pk)
+ form = EditBookingDateForm(instance=booking)
+
+ context = {
+ 'form': form,
+ 'booking': booking
+ }
+ return render(request, 'edit_booking_date.html', context)
+
+ # processes the form and updates the dates
+ def post(self, request, pk):
+ booking = get_object_or_404(Booking, pk=pk)
+ form = EditBookingDateForm(request.POST, instance=booking)
+
+ if form.is_valid():
+ form.save()
+ return redirect('/')
+
+ # re-render if form data is invalid
+ context = {
+ 'form': form,
+ 'booking': booking
+ }
+ return render(request, 'edit_booking_date.html', context)