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 @@ - +