diff --git a/pms/demo/airbnb-logo.jpg b/pms/demo/airbnb-logo.jpg
index aacc8d011..65e7ce297 100644
Binary files a/pms/demo/airbnb-logo.jpg and b/pms/demo/airbnb-logo.jpg differ
diff --git a/pms/demo/booking-logo.jpg b/pms/demo/booking-logo.jpg
index c6ea979ef..d1875b2d9 100644
Binary files a/pms/demo/booking-logo.jpg and b/pms/demo/booking-logo.jpg differ
diff --git a/pms/demo/pms_folio.xml b/pms/demo/pms_folio.xml
index ab1bade5d..f4630eebd 100644
--- a/pms/demo/pms_folio.xml
+++ b/pms/demo/pms_folio.xml
@@ -354,8 +354,8 @@
'adults': 1,
'state': 'confirm',
'reservation_type': 'out',
- 'closure_reason_id': ref('pms_room_closure_reason_maintenance'),
- 'out_service_description': 'Door arrangement',
+ 'closure_reason_id': ref('pms_room_closure_reason_vip_privacy'),
+ 'out_service_description': 'Room next to noisy guests.',
})]"
/>
diff --git a/pms/demo/pms_reservation.xml b/pms/demo/pms_reservation.xml
index 99d5219e4..72d159b6b 100644
--- a/pms/demo/pms_reservation.xml
+++ b/pms/demo/pms_reservation.xml
@@ -9,8 +9,33 @@
out
-
+
+ Extra privacy for school field trip.
+
+
+
+
+
+ out
+
+
+
+
+ Carpet replacement.
+
+
+
+
+
+ out
+
+
+
+
+ Carpet replacement.
@@ -22,6 +47,7 @@
+ Wall painting.
@@ -363,7 +389,7 @@
1
-
+
-
+
+ onboard
+
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
+ done
+
+
+
+
+
+
onboard
-
+
@@ -409,7 +462,7 @@
breakfast at 5:00 am
-
+
@@ -423,7 +476,7 @@
}),
]"
/>
-
+
-
+
@@ -450,7 +503,7 @@
Breakfast to take away.
-
+
@@ -466,7 +519,7 @@
-
+
@@ -479,7 +532,7 @@
preferably street view
-
+
@@ -491,7 +544,7 @@
-
+
diff --git a/pms/models/pms_folio.py b/pms/models/pms_folio.py
index 8e7b4fce2..b12d59b8d 100644
--- a/pms/models/pms_folio.py
+++ b/pms/models/pms_folio.py
@@ -1137,7 +1137,7 @@ class PmsFolio(models.Model):
@api.constrains("name")
def _check_required_partner_name(self):
for record in self:
- if not record.partner_name:
+ if not record.partner_name and record.reservation_type != "out":
raise models.ValidationError(_("You must assign a customer name"))
@api.model
diff --git a/pms/models/pms_reservation.py b/pms/models/pms_reservation.py
index 3bef8d607..835f01072 100644
--- a/pms/models/pms_reservation.py
+++ b/pms/models/pms_reservation.py
@@ -125,6 +125,7 @@ class PmsReservation(models.Model):
help="Reason why the reservation cannot be made",
related="folio_id.closure_reason_id",
check_pms_properties=True,
+ readonly=False,
)
company_id = fields.Many2one(
string="Company",
@@ -1670,6 +1671,18 @@ class PmsReservation(models.Model):
record, record.service_ids.service_line_ids
)
+ @api.constrains("closure_reason_id")
+ def _check_closure_reason_id(self):
+ for record in self:
+ if record.reservation_type == "out":
+ if not record.closure_reason_id:
+ raise ValidationError(
+ _(
+ "A closure reason is mandatory when reservation"
+ " type is 'out of service'"
+ )
+ )
+
@api.constrains("reservation_type")
def _check_same_reservation_type(self):
for record in self:
@@ -1802,7 +1815,7 @@ class PmsReservation(models.Model):
default_vals["partner_name"] = folio.partner_name
default_vals["mobile"] = folio.mobile
default_vals["email"] = folio.email
- else:
+ elif vals.get("reservation_type") != "out":
raise ValidationError(_("Partner contact name is required"))
vals.update(default_vals)
elif "pms_property_id" in vals and (
@@ -1819,12 +1832,21 @@ class PmsReservation(models.Model):
folio_vals["partner_name"] = vals.get("partner_name")
folio_vals["mobile"] = vals.get("mobile")
folio_vals["email"] = vals.get("email")
- else:
+ elif vals.get("reservation_type") != "out":
raise ValidationError(_("Partner contact name is required"))
# Create the folio in case of need
# (To allow to create reservations direct)
if vals.get("reservation_type"):
folio_vals["reservation_type"] = vals.get("reservation_type")
+ if vals.get("reservation_type") == "out" and not vals.get(
+ "closure_reason_id"
+ ):
+ raise ValidationError(
+ _(
+ "A closure reason is mandatory when reservation"
+ " type is 'out of service'"
+ )
+ )
folio = self.env["pms.folio"].create(folio_vals)
vals.update(
{
@@ -1832,6 +1854,7 @@ class PmsReservation(models.Model):
"reservation_type": vals.get("reservation_type"),
}
)
+
else:
raise ValidationError(_("The Property are mandatory in the reservation"))
if vals.get("name", _("New")) == _("New") or "name" not in vals:
diff --git a/pms/tests/test_pms_folio.py b/pms/tests/test_pms_folio.py
index 9831814e2..f80ca7715 100644
--- a/pms/tests/test_pms_folio.py
+++ b/pms/tests/test_pms_folio.py
@@ -565,6 +565,12 @@ class TestPmsFolio(TestPms):
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
self.partner1 = self.env["res.partner"].create({"name": "Pedro"})
+ closure_reason = self.env["room.closure.reason"].create(
+ {
+ "name": "test closure reason",
+ "description": "test clopsure reason description",
+ }
+ )
# ACT
reservation = self.env["pms.reservation"].create(
{
@@ -575,6 +581,7 @@ class TestPmsFolio(TestPms):
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "out",
+ "closure_reason_id": closure_reason.id,
}
)
# ASSERT
diff --git a/pms/tests/test_pms_folio_sale_line.py b/pms/tests/test_pms_folio_sale_line.py
index ca0e3c951..b329d93f1 100644
--- a/pms/tests/test_pms_folio_sale_line.py
+++ b/pms/tests/test_pms_folio_sale_line.py
@@ -1234,6 +1234,12 @@ class TestPmsFolioSaleLine(TestPms):
self.partner1 = self.env["res.partner"].create({"name": "Alberto"})
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
+ closure_reason = self.env["room.closure.reason"].create(
+ {
+ "name": "test closure reason",
+ "description": "test clopsure reason description",
+ }
+ )
# ACT
reservation = self.env["pms.reservation"].create(
{
@@ -1244,6 +1250,7 @@ class TestPmsFolioSaleLine(TestPms):
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "out",
+ "closure_reason_id": closure_reason.id,
}
)
# ASSERT
diff --git a/pms/tests/test_pms_reservation.py b/pms/tests/test_pms_reservation.py
index 14dd76f17..e09778a11 100644
--- a/pms/tests/test_pms_reservation.py
+++ b/pms/tests/test_pms_reservation.py
@@ -3062,6 +3062,12 @@ class TestPmsReservations(TestPms):
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
+ closure_reason = self.env["room.closure.reason"].create(
+ {
+ "name": "test closure reason",
+ "description": "test clopsure reason description",
+ }
+ )
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
@@ -3073,6 +3079,7 @@ class TestPmsReservations(TestPms):
"pms_property_id": self.pms_property1.id,
"pricelist_id": self.pricelist1.id,
"reservation_type": "out",
+ "closure_reason_id": closure_reason.id,
}
)
# ASSERT
@@ -3119,6 +3126,12 @@ class TestPmsReservations(TestPms):
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
+ closure_reason = self.env["room.closure.reason"].create(
+ {
+ "name": "test closure reason",
+ "description": "test clopsure reason description",
+ }
+ )
# ACT
self.room_type_double.write({"list_price": 30})
reservation = self.env["pms.reservation"].create(
@@ -3129,6 +3142,7 @@ class TestPmsReservations(TestPms):
"partner_id": self.partner1.id,
"pms_property_id": self.pms_property1.id,
"reservation_type": "out",
+ "closure_reason_id": closure_reason.id,
}
)
@@ -3188,6 +3202,12 @@ class TestPmsReservations(TestPms):
# ARRANGE
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=3)
+ closure_reason = self.env["room.closure.reason"].create(
+ {
+ "name": "test closure reason",
+ "description": "test clopsure reason description",
+ }
+ )
# ACT
reservation = self.env["pms.reservation"].create(
{
@@ -3196,6 +3216,7 @@ class TestPmsReservations(TestPms):
"room_type_id": self.room_type_double.id,
"pms_property_id": self.pms_property1.id,
"reservation_type": "out",
+ "closure_reason_id": closure_reason.id,
"partner_name": "Install furniture",
}
)
@@ -3724,3 +3745,67 @@ class TestPmsReservations(TestPms):
reservation.commission_amount,
"Reservation commission is wrong",
)
+
+ def test_closure_reason_out_of_service_mandatory_not(self):
+ """
+ Ouf of service reservation should contain a closure reason id.
+ -------------
+ Create a reservation of type out of service and check if there's no
+ closure reason id should raises an exception.
+ """
+ # ARRANGE
+ checkin = fields.date.today()
+ checkout = fields.date.today() + datetime.timedelta(days=1)
+ # ACT & ASSERT
+ with self.assertRaises(
+ ValidationError,
+ msg="The reservation has been created and it shouldn't, "
+ "because it doesn't have a closure reason.",
+ ):
+ self.env["pms.reservation"].create(
+ {
+ "checkin": checkin,
+ "checkout": checkout,
+ "room_type_id": self.room_type_double.id,
+ "partner_id": self.partner1.id,
+ "pms_property_id": self.pms_property1.id,
+ "reservation_type": "out",
+ }
+ )
+
+ def test_closure_reason_out_of_service_mandatory(self):
+ """
+ Ouf of service reservation should contain a closure reason id.
+ -------------
+ Create a reservation of type out of service and with a closure reason.
+ """
+ # ARRANGE
+ checkin = fields.date.today()
+ checkout = fields.date.today() + datetime.timedelta(days=1)
+
+ closure_reason = self.env["room.closure.reason"].create(
+ {
+ "name": "Room revision",
+ "description": "Revision of lights, "
+ "fire extinguishers, smoke detectors and "
+ "emergency lights",
+ }
+ )
+ # ACT
+ reservation_out = self.env["pms.reservation"].create(
+ {
+ "checkin": checkin,
+ "checkout": checkout,
+ "room_type_id": self.room_type_double.id,
+ "partner_id": self.partner1.id,
+ "pms_property_id": self.pms_property1.id,
+ "reservation_type": "out",
+ "closure_reason_id": closure_reason,
+ }
+ )
+ # ASSERT
+ self.assertTrue(
+ reservation_out.closure_reason_id,
+ "The out of service reservation should be created properly with "
+ "a closure reason.",
+ )
diff --git a/pms/views/pms_reservation_views.xml b/pms/views/pms_reservation_views.xml
index 07bb9ad15..fd93fbdd6 100644
--- a/pms/views/pms_reservation_views.xml
+++ b/pms/views/pms_reservation_views.xml
@@ -351,7 +351,10 @@
-
+