@@ -73,7 +73,7 @@
Reservas Realizadas
diff --git a/pms/tests.py b/pms/tests.py
index 7ce503c2d..861844b46 100644
--- a/pms/tests.py
+++ b/pms/tests.py
@@ -1,3 +1,149 @@
-from django.test import TestCase
+from datetime import date, timedelta
-# Create your tests here.
+from django.test import TestCase, override_settings
+from django.urls import reverse
+
+from .models import Booking, Customer, Room, Room_type
+
+
+@override_settings(STATICFILES_STORAGE="django.contrib.staticfiles.storage.StaticFilesStorage")
+class EditBookingDatesViewTests(TestCase):
+ def setUp(self):
+ self.today = date.today()
+
+ self.room_type = Room_type.objects.create(
+ name="Doble",
+ price=30,
+ max_guests=2,
+ )
+ self.room = Room.objects.create(
+ room_type=self.room_type,
+ name="Room 1.1",
+ description="Test room",
+ )
+ self.customer = Customer.objects.create(
+ name="Test User",
+ email="test@example.com",
+ phone="123456789",
+ )
+ self.booking = Booking.objects.create(
+ room=self.room,
+ customer=self.customer,
+ checkin=self.today,
+ checkout=self.today + timedelta(days=2),
+ guests=2,
+ total=60,
+ code="ABC12345",
+ state=Booking.NEW,
+ )
+ self.url = reverse("edit_booking_dates", args=[self.booking.id])
+
+ def test_edit_dates_page_renders_with_initial_data(self):
+ response = self.client.get(self.url)
+
+ self.assertEqual(response.status_code, 200)
+ self.assertContains(response, str(self.booking.checkin))
+ self.assertContains(response, str(self.booking.checkout))
+
+ def test_valid_date_update_updates_booking_dates(self):
+ new_checkin = self.today + timedelta(days=5)
+ new_checkout = new_checkin + timedelta(days=2)
+
+ response = self.client.post(self.url, {
+ "checkin": new_checkin,
+ "checkout": new_checkout,
+ })
+
+ self.assertEqual(response.status_code, 302)
+ self.booking.refresh_from_db()
+ self.assertEqual(self.booking.checkin, new_checkin)
+ self.assertEqual(self.booking.checkout, new_checkout)
+
+ def test_valid_date_update_recalculates_total(self):
+ new_checkin = self.today + timedelta(days=10)
+ new_checkout = new_checkin + timedelta(days=3)
+
+ response = self.client.post(self.url, {
+ "checkin": new_checkin,
+ "checkout": new_checkout,
+ })
+
+ self.assertEqual(response.status_code, 302)
+ self.booking.refresh_from_db()
+ self.assertEqual(self.booking.total, 3 * self.room_type.price)
+
+ def test_booking_does_not_conflict_with_itself(self):
+ response = self.client.post(self.url, {
+ "checkin": self.booking.checkin,
+ "checkout": self.booking.checkout,
+ })
+
+ self.assertEqual(response.status_code, 302)
+
+ def test_overlapping_new_booking_blocks_date_update(self):
+ Booking.objects.create(
+ room=self.room,
+ customer=self.customer,
+ checkin=self.today + timedelta(days=3),
+ checkout=self.today + timedelta(days=6),
+ guests=2,
+ total=90,
+ code="XYZ12345",
+ state=Booking.NEW,
+ )
+
+ response = self.client.post(self.url, {
+ "checkin": self.today + timedelta(days=4),
+ "checkout": self.today + timedelta(days=7),
+ })
+
+ 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, self.today)
+ self.assertEqual(self.booking.checkout, self.today + timedelta(days=2))
+
+ def test_deleted_booking_does_not_block_date_update(self):
+ new_checkin = self.today + timedelta(days=4)
+ new_checkout = self.today + timedelta(days=7)
+
+ Booking.objects.create(
+ room=self.room,
+ customer=self.customer,
+ checkin=self.today + timedelta(days=3),
+ checkout=self.today + timedelta(days=6),
+ guests=2,
+ total=90,
+ code="DEL12345",
+ state=Booking.DELETED,
+ )
+
+ response = self.client.post(self.url, {
+ "checkin": new_checkin,
+ "checkout": new_checkout,
+ })
+
+ self.assertEqual(response.status_code, 302)
+ self.booking.refresh_from_db()
+ self.assertEqual(self.booking.checkin, new_checkin)
+ self.assertEqual(self.booking.checkout, new_checkout)
+
+ def test_adjacent_dates_follow_same_overlap_rule_as_create(self):
+ Booking.objects.create(
+ room=self.room,
+ customer=self.customer,
+ checkin=self.today + timedelta(days=3),
+ checkout=self.today + timedelta(days=6),
+ guests=2,
+ total=90,
+ code="ADJ12345",
+ state=Booking.NEW,
+ )
+
+ response = self.client.post(self.url, {
+ "checkin": self.today + timedelta(days=6),
+ "checkout": self.today + timedelta(days=8),
+ })
+
+ self.assertEqual(response.status_code, 200)
+ self.assertContains(response, "No hay disponibilidad para las fechas seleccionadas")
diff --git a/pms/urls.py b/pms/urls.py
index c18714abf..2acbd0a22 100644
--- a/pms/urls.py
+++ b/pms/urls.py
@@ -8,6 +8,7 @@
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-dates", views.EditBookingDatesView.as_view(), name="edit_booking_dates"),
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..a431c1774 100644
--- a/pms/views.py
+++ b/pms/views.py
@@ -174,6 +174,46 @@ def post(self, request, pk):
return redirect("/")
+class EditBookingDatesView(View):
+ def get(self, request, pk):
+ booking = Booking.objects.get(id=pk)
+ form = BookingDatesForm(
+ booking=booking,
+ initial={
+ "checkin": booking.checkin,
+ "checkout": booking.checkout,
+ },
+ )
+ context = {
+ "booking": booking,
+ "form": form,
+ }
+ return render(request, "edit_booking_dates.html", context)
+
+ @method_decorator(ensure_csrf_cookie)
+ def post(self, request, pk):
+ booking = Booking.objects.get(id=pk)
+ form = BookingDatesForm(request.POST, booking=booking)
+
+ if form.is_valid():
+ checkin = form.cleaned_data["checkin"]
+ checkout = form.cleaned_data["checkout"]
+ total_days = (checkout - checkin).days
+
+ booking.checkin = checkin
+ booking.checkout = checkout
+ booking.total = total_days * booking.room.room_type.price
+ booking.save()
+
+ return redirect("/")
+
+ context = {
+ "booking": booking,
+ "form": form,
+ }
+ return render(request, "edit_booking_dates.html", context)
+
+
class DashboardView(View):
def get(self, request):
from datetime import date, time, datetime