diff --git a/pms/__manifest__.py b/pms/__manifest__.py
index 830befc96..08ea7965b 100644
--- a/pms/__manifest__.py
+++ b/pms/__manifest__.py
@@ -65,7 +65,6 @@
"views/pms_room_type_class_views.xml",
"views/pms_availability_plan_views.xml",
"views/pms_availability_plan_rule_views.xml",
- "views/pms_shared_room_views.xml",
"views/res_partner_views.xml",
"views/product_pricelist_views.xml",
"views/product_pricelist_item_views.xml",
diff --git a/pms/models/__init__.py b/pms/models/__init__.py
index 2a7be0cf8..5bcb034f5 100644
--- a/pms/models/__init__.py
+++ b/pms/models/__init__.py
@@ -13,7 +13,6 @@ from . import pms_ubication
from . import pms_folio
from . import pms_reservation
from . import pms_room
-from . import pms_shared_room
from . import pms_amenity
from . import pms_amenity_type
from . import pms_room_type
diff --git a/pms/models/pms_availability.py b/pms/models/pms_availability.py
index 3088f4274..3f705cefd 100644
--- a/pms/models/pms_availability.py
+++ b/pms/models/pms_availability.py
@@ -1,5 +1,7 @@
# Copyright 2021 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+import datetime
+
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
@@ -55,6 +57,24 @@ class PmsAvailability(models.Model):
readonly=True,
compute="_compute_real_avail",
)
+ parent_avail_id = fields.Many2one(
+ string="Parent Avail",
+ help="Parent availability for this availability",
+ comodel_name="pms.availability",
+ ondelete="restrict",
+ compute="_compute_parent_avail_id",
+ store=True,
+ check_pms_properties=True,
+ )
+ child_avail_ids = fields.One2many(
+ string="Child Avails",
+ help="Child availabilities for this availability",
+ comodel_name="pms.availability",
+ inverse_name="parent_avail_id",
+ compute="_compute_child_avail_ids",
+ store=True,
+ check_pms_properties=True,
+ )
_sql_constraints = [
(
@@ -69,11 +89,16 @@ class PmsAvailability(models.Model):
"reservation_line_ids",
"reservation_line_ids.occupies_availability",
"room_type_id.total_rooms_count",
+ "parent_avail_id",
+ "parent_avail_id.reservation_line_ids",
+ "parent_avail_id.reservation_line_ids.occupies_availability",
+ "child_avail_ids",
+ "child_avail_ids.reservation_line_ids",
+ "child_avail_ids.reservation_line_ids.occupies_availability",
)
def _compute_real_avail(self):
for record in self:
Rooms = self.env["pms.room"]
- RoomLines = self.env["pms.reservation.line"]
total_rooms = Rooms.search_count(
[
("room_type_id", "=", record.room_type_id.id),
@@ -81,16 +106,159 @@ class PmsAvailability(models.Model):
]
)
room_ids = record.room_type_id.mapped("room_ids.id")
- rooms_not_avail = RoomLines.search_count(
+ count_rooms_not_avail = len(
+ record.get_rooms_not_avail(
+ checkin=record.date,
+ checkout=record.date + datetime.timedelta(1),
+ room_ids=room_ids,
+ pms_property_id=record.pms_property_id.id,
+ )
+ )
+ record.real_avail = total_rooms - count_rooms_not_avail
+
+ @api.depends("reservation_line_ids", "reservation_line_ids.room_id")
+ def _compute_parent_avail_id(self):
+ for record in self:
+ parent_rooms = record.room_type_id.mapped("room_ids.parent_id.id")
+ if parent_rooms:
+ for room_id in parent_rooms:
+ room = self.env["pms.room"].browse(room_id)
+ parent_avail = self.env["pms.availability"].search(
+ [
+ ("date", "=", record.date),
+ ("room_type_id", "=", room.room_type_id.id),
+ ("pms_property_id", "=", record.pms_property_id.id),
+ ]
+ )
+ if parent_avail:
+ record.parent_avail_id = parent_avail
+ else:
+ record.parent_avail_id = self.env["pms.availability"].create(
+ {
+ "date": record.date,
+ "room_type_id": room.room_type_id.id,
+ "pms_property_id": record.pms_property_id.id,
+ }
+ )
+ else:
+ record.parent_avail_id = False
+
+ @api.depends("reservation_line_ids", "reservation_line_ids.room_id")
+ def _compute_child_avail_ids(self):
+ for record in self:
+ child_rooms = record.room_type_id.mapped("room_ids.child_ids.id")
+ if child_rooms:
+ for room_id in child_rooms:
+ room = self.env["pms.room"].browse(room_id)
+ child_avail = self.env["pms.availability"].search(
+ [
+ ("date", "=", record.date),
+ ("room_type_id", "=", room.room_type_id.id),
+ ("pms_property_id", "=", record.pms_property_id.id),
+ ]
+ )
+ if child_avail:
+ record.child_avail_ids = [(4, child_avail.id)]
+ else:
+ record.child_avail_ids = [
+ (
+ 0,
+ 0,
+ {
+ "date": record.date,
+ "room_type_id": room.room_type_id.id,
+ "pms_property_id": record.pms_property_id.id,
+ },
+ )
+ ]
+ else:
+ record.parent_avail_id = False
+
+ @api.model
+ def get_rooms_not_avail(
+ self, checkin, checkout, room_ids, pms_property_id, current_lines=False
+ ):
+ RoomLines = self.env["pms.reservation.line"]
+ rooms = self.env["pms.room"].browse(room_ids)
+ occupied_room_ids = []
+ for room in rooms.filtered("parent_id"):
+ if self.get_occupied_parent_rooms(
+ room=room.parent_id,
+ checkin=checkin,
+ checkout=checkout,
+ pms_property_id=room.pms_property_id.id,
+ ):
+ occupied_room_ids.append(room.id)
+ for room in rooms.filtered("child_ids"):
+ if self.get_occupied_child_rooms(
+ rooms=room.child_ids,
+ checkin=checkin,
+ checkout=checkout,
+ pms_property_id=room.pms_property_id.id,
+ ):
+ occupied_room_ids.append(room.id)
+ occupied_room_ids.extend(
+ RoomLines.search(
[
- ("date", "=", record.date),
+ ("date", ">=", checkin),
+ ("date", "<=", checkout - datetime.timedelta(1)),
("room_id", "in", room_ids),
- ("pms_property_id", "=", record.pms_property_id.id),
+ ("pms_property_id", "=", pms_property_id),
+ ("occupies_availability", "=", True),
+ ("id", "not in", current_lines if current_lines else []),
+ ]
+ ).mapped("room_id.id")
+ )
+ return occupied_room_ids
+
+ @api.model
+ def get_occupied_parent_rooms(self, room, checkin, checkout, pms_property_id):
+ RoomLines = self.env["pms.reservation.line"]
+ if (
+ RoomLines.search_count(
+ [
+ ("date", ">=", checkin),
+ ("date", "<=", checkout - datetime.timedelta(1)),
+ ("room_id", "=", room.id),
+ ("pms_property_id", "=", pms_property_id),
("occupies_availability", "=", True),
- # ("id", "not in", current_lines if current_lines else []),
]
)
- record.real_avail = total_rooms - rooms_not_avail
+ > 0
+ ):
+ return True
+ if room.parent_id:
+ return self.get_occupied_parent_rooms(
+ room=room.parent_room_id,
+ checkin=checkin,
+ checkout=checkout,
+ )
+ return False
+
+ @api.model
+ def get_occupied_child_rooms(self, rooms, checkin, checkout, pms_property_id):
+ RoomLines = self.env["pms.reservation.line"]
+ if (
+ RoomLines.search_count(
+ [
+ ("date", ">=", checkin),
+ ("date", "<=", checkout - datetime.timedelta(1)),
+ ("room_id", "in", rooms.ids),
+ ("pms_property_id", "=", pms_property_id),
+ ("occupies_availability", "=", True),
+ ]
+ )
+ > 0
+ ):
+ return True
+ for room in rooms.filtered("child_ids"):
+ if self.get_occupied_child_rooms(
+ rooms=room.child_ids,
+ checkin=checkin,
+ checkout=checkout,
+ ):
+ return True
+ return False
@api.constrains(
"room_type_id",
diff --git a/pms/models/pms_property.py b/pms/models/pms_property.py
index 37f30f759..2656f4239 100644
--- a/pms/models/pms_property.py
+++ b/pms/models/pms_property.py
@@ -142,7 +142,6 @@ class PmsProperty(models.Model):
pricelist_id = self.env.context.get("pricelist_id", False)
room_type_id = self.env.context.get("room_type_id", False)
-
for pms_property in self:
free_rooms = pms_property.get_real_free_rooms(
checkin, checkout, current_lines
@@ -191,7 +190,6 @@ class PmsProperty(models.Model):
target_rooms = target_rooms.filtered(
lambda r: r.room_type_id.id == room_type_id
)
-
capacity = self.env.context.get("capacity", False)
if capacity:
target_rooms = target_rooms.filtered(lambda r: r.capacity >= capacity)
@@ -210,27 +208,20 @@ class PmsProperty(models.Model):
lambda r: len(set(amenity_ids) - set(r.room_amenity_ids.ids)) == 0
)
- domain_avail = [
- ("date", ">=", checkin),
- ("date", "<=", checkout - datetime.timedelta(1)),
- ("pms_property_id", "=", self.id),
- ]
-
if not current_lines:
current_lines = []
- rooms_not_avail = (
- Avail.search(domain_avail)
- .reservation_line_ids.filtered(
- lambda l: l.occupies_availability and l.id and l.id not in current_lines
- )
- .room_id.ids
+ rooms_not_avail_ids = Avail.get_rooms_not_avail(
+ checkin=checkin,
+ checkout=checkout,
+ room_ids=target_rooms.ids,
+ pms_property_id=self.id,
+ current_lines=current_lines,
)
-
domain_rooms = [("id", "in", target_rooms.ids)]
- if rooms_not_avail:
+ if rooms_not_avail_ids:
domain_rooms.append(
- ("id", "not in", rooms_not_avail),
+ ("id", "not in", rooms_not_avail_ids),
)
return self.env["pms.room"].search(domain_rooms)
@@ -258,7 +249,7 @@ class PmsProperty(models.Model):
).date()
room_type_id = self.env.context.get("room_type_id", False)
pricelist_id = self.env.context.get("pricelist_id", False)
- current_lines = self.env.context.get("current_lines", False)
+ current_lines = self.env.context.get("current_lines", [])
pms_property = self.with_context(
checkin=checkin,
checkout=checkout,
@@ -267,7 +258,6 @@ class PmsProperty(models.Model):
pricelist_id=pricelist_id,
)
count_free_rooms = len(pms_property.free_room_ids)
-
if current_lines and not isinstance(current_lines, list):
current_lines = [current_lines]
diff --git a/pms/models/pms_room.py b/pms/models/pms_room.py
index 4c64cc214..0c03d5cc7 100644
--- a/pms/models/pms_room.py
+++ b/pms/models/pms_room.py
@@ -48,12 +48,19 @@ class PmsRoom(models.Model):
ondelete="restrict",
check_pms_properties=True,
)
- # TODO: design shared rooms
- shared_room_id = fields.Many2one(
- string="Shared Room",
- help="The room can be sold by beds",
- default=False,
- comodel_name="pms.shared.room",
+ parent_id = fields.Many2one(
+ string="Parent Room",
+ help="Indicates that this room is a child of another room",
+ comodel_name="pms.room",
+ ondelete="restrict",
+ check_pms_properties=True,
+ )
+ child_ids = fields.One2many(
+ string="Child Rooms",
+ help="Child rooms of the room",
+ comodel_name="pms.room",
+ inverse_name="parent_id",
+ check_pms_properties=True,
)
ubication_id = fields.Many2one(
string="Ubication",
@@ -79,7 +86,13 @@ class PmsRoom(models.Model):
column2="amenity_id",
check_pms_properties=True,
)
-
+ is_shared_room = fields.Boolean(
+ string="Is a Shared Room",
+ help="allows you to reserve units " " smaller than the room itself (eg beds)",
+ compute="_compute_is_shared_room",
+ readonly=False,
+ store=True,
+ )
description_sale = fields.Text(
string="Sale Description",
help="A description of the Product that you want to communicate to "
@@ -97,6 +110,14 @@ class PmsRoom(models.Model):
)
]
+ @api.depends("child_ids")
+ def _compute_is_shared_room(self):
+ for record in self:
+ if record.child_ids:
+ record.is_shared_room = True
+ elif not record.is_shared_room:
+ record.is_shared_room = False
+
def name_get(self):
result = []
for room in self:
@@ -122,6 +143,17 @@ class PmsRoom(models.Model):
)
)
+ @api.constrains("is_shared_room")
+ def _check_shared_room(self):
+ for record in self:
+ if record.is_shared_room and not record.child_ids:
+ raise ValidationError(
+ _(
+ "The reservation units are required \
+ on shared rooms."
+ )
+ )
+
@api.model
def _check_adults(self, reservation, service_line_ids=False):
for line in reservation.reservation_line_ids:
@@ -146,10 +178,8 @@ class PmsRoom(models.Model):
def get_capacity(self, extra_bed=0):
for record in self:
- if not record.shared_room_id:
- if extra_bed > record.extra_beds_allowed:
- raise ValidationError(
- _("Extra beds can't be greater than allowed beds for this room")
- )
- return record.capacity + extra_bed
- return record.capacity
+ if extra_bed > record.extra_beds_allowed:
+ raise ValidationError(
+ _("Extra beds can't be greater than allowed beds for this room")
+ )
+ return record.capacity + extra_bed
diff --git a/pms/models/pms_room_type.py b/pms/models/pms_room_type.py
index 076465651..116b00caa 100644
--- a/pms/models/pms_room_type.py
+++ b/pms/models/pms_room_type.py
@@ -67,12 +67,6 @@ class PmsRoomType(models.Model):
help="Identification code for a room type",
required=True,
)
- # TODO: Session review to define shared room and "sales rooms packs"
- is_shared_room = fields.Boolean(
- string="Shared Room",
- help="This room type is reservation by beds",
- default=False,
- )
total_rooms_count = fields.Integer(
string="Total Rooms Count",
help="The number of rooms in a room type",
diff --git a/pms/models/pms_shared_room.py b/pms/models/pms_shared_room.py
deleted file mode 100644
index 8566db551..000000000
--- a/pms/models/pms_shared_room.py
+++ /dev/null
@@ -1,143 +0,0 @@
-# Copyright 2017 Alexandre Díaz
-# Copyright 2017 Dario Lodeiros
-# Copyright 2018 Pablo Quesada
-# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
-from odoo import _, api, fields, models
-from odoo.exceptions import ValidationError
-
-
-class PmsSharedRoom(models.Model):
- _name = "pms.shared.room"
- _description = "Shared Room"
- _order = "room_type_id, name"
- _check_pms_properties_auto = True
-
- name = fields.Char(
- string="Room Name", help="Name of the shared room", required=True
- )
- active = fields.Boolean(
- string="Active", help="Determines if shared room is active", default=True
- )
- sequence = fields.Integer(
- string="Sequence",
- help="Field used to change the position of the shared rooms in tree view."
- "Changing the position changes the sequence",
- required=True,
- )
- room_type_id = fields.Many2one(
- string="Room Type",
- help="Room type which the shared room belongs",
- comodel_name="pms.room.type",
- required=True,
- ondelete="restrict",
- domain=[("shared_room", "=", True)],
- )
- # TODO: properties relation
- pms_property_ids = fields.Many2many(
- string="Properties",
- help="Properties with access to the element;"
- " if not set, all properties can access",
- comodel_name="pms.property",
- relation="pms_shared_room_pms_property_rel",
- column1="shared_room_id",
- column2="pms_property_id",
- check_pms_properties=True,
- )
- ubication_id = fields.Many2one(
- string="Ubication",
- help="At which ubication the room is located.",
- comodel_name="pms.ubication",
- ondelete="restrict",
- )
- bed_ids = fields.One2many(
- string="Beds",
- help="Beds in one room",
- comodel_name="pms.room",
- inverse_name="shared_room_id",
- readonly=True,
- )
- beds = fields.Integer(
- string="Number Of Beds", help="Number of beds in a shared room"
- )
- description_sale = fields.Text(
- string="Sale Description",
- help="A description of the Product that you want to communicate to "
- " your customers. This description will be copied to every Sales "
- " Order, Delivery Order and Customer Invoice/Credit Note",
- translate=True,
- )
-
- @api.constrains("beds")
- def _constrain_beds(self):
- self.ensure_one()
- if self.beds < 1:
- raise ValidationError(_("Room beds can't be less than one"))
- if len(self.bed_ids) > self.beds:
- raise ValidationError(
- _(
- "If you want to eliminate beds in the \
- room you must deactivate the beds from your form"
- )
- )
- beds = []
- inactive_beds = self.env["pms.room"].search(
- [("active", "=", False), ("shared_room_id", "=", self.id)]
- )
- for i in range(len(self.bed_ids), self.beds):
- if inactive_beds:
- bed = inactive_beds[0]
- bed.update({"active": True})
- inactive_beds -= bed
- continue
- name = u"{} ({})".format(self.name, i + 1)
- bed_vals = {
- "name": name,
- "capacity": 1,
- "room_type_id": self.room_type_id.id,
- "sequence": self.sequence,
- "ubication_id": self.ubication_id.id if self.ubication_id else False,
- "shared_room_id": self.id,
- }
- beds.append((0, False, bed_vals))
- if beds:
- self.update({"bed_ids": beds})
-
- @api.constrains("active")
- def _constrain_active(self):
- self.bed_ids.write(
- {
- "active": self.active,
- }
- )
-
- @api.constrains("room_type_id")
- def _constrain_room_type_id(self):
- self.bed_ids.write(
- {
- "room_type_id": self.room_type_id.id,
- }
- )
-
- @api.constrains("ubication_id")
- def _constrain_ubication_id(self):
- self.bed_ids.write(
- {
- "ubication_id": self.ubication_id.id,
- }
- )
-
- @api.constrains("sequence")
- def _constrain_sequence(self):
- self.bed_ids.write(
- {
- "sequence": self.sequence,
- }
- )
-
- @api.constrains("descrition_sale")
- def _constrain_descrition_sale(self):
- self.bed_ids.write(
- {
- "description_sale": self.descrition_sale,
- }
- )
diff --git a/pms/security/ir.model.access.csv b/pms/security/ir.model.access.csv
index d313323f6..544f75411 100644
--- a/pms/security/ir.model.access.csv
+++ b/pms/security/ir.model.access.csv
@@ -10,7 +10,6 @@ user_access_pms_board_service,user_access_pms_board_service,model_pms_board_serv
user_access_pms_checkin_partner,user_access_pms_checkin_partner,model_pms_checkin_partner,pms.group_pms_user,1,1,1,1
user_access_pms_room_type_class,user_access_pms_room_type_class,model_pms_room_type_class,pms.group_pms_user,1,0,0,0
user_access_pms_room,user_access_pms_room,model_pms_room,pms.group_pms_user,1,0,0,0
-user_access_shared_pms_room,user_access_pms_shared_room,model_pms_shared_room,pms.group_pms_user,1,0,0,0
user_access_pms_availability_plan_rule,user_access_pms_availability_plan_rule,model_pms_availability_plan_rule,pms.group_pms_user,1,0,0,0
user_access_pms_availability,user_access_pms_availability,model_pms_availability,pms.group_pms_user,1,1,1,0
user_access_pms_reservation,user_access_pms_reservation,model_pms_reservation,pms.group_pms_user,1,1,1,1
@@ -36,7 +35,6 @@ manager_access_pms_board_service,manager_access_pms_board_service,model_pms_boar
manager_access_pms_checkin_partner,manager_access_pms_checkin_partner,model_pms_checkin_partner,pms.group_pms_manager,1,1,1,1
manager_access_pms_room_type_class,manager_access_pms_room_type_class,model_pms_room_type_class,pms.group_pms_manager,1,1,1,1
manager_access_pms_room,manager_access_pms_room,model_pms_room,pms.group_pms_manager,1,1,1,1
-manager_access_pms_shared_room,manager_access_pms_shared_room,model_pms_shared_room,pms.group_pms_manager,1,1,1,1
manager_access_pms_availability_plan_rule,manager_access_pms_availability_plan_rule,model_pms_availability_plan_rule,pms.group_pms_manager,1,1,1,1
manager_access_pms_reservation,manager_access_pms_reservation,model_pms_reservation,pms.group_pms_manager,1,1,1,1
manager_access_pms_availability,manager_access_pms_availability,model_pms_availability,pms.group_pms_manager,1,1,1,0
diff --git a/pms/tests/__init__.py b/pms/tests/__init__.py
index 2976ec8ca..4f21325fd 100644
--- a/pms/tests/__init__.py
+++ b/pms/tests/__init__.py
@@ -37,3 +37,4 @@ from . import test_pms_folio_sale_line
from . import test_pms_wizard_split_join_swap_reservation
from . import test_product_template
from . import test_pms_multiproperty
+from . import test_shared_room
diff --git a/pms/tests/test_shared_room.py b/pms/tests/test_shared_room.py
new file mode 100644
index 000000000..2408805c4
--- /dev/null
+++ b/pms/tests/test_shared_room.py
@@ -0,0 +1,487 @@
+import datetime
+
+from odoo import fields
+from odoo.exceptions import ValidationError
+
+from .common import TestPms
+
+
+class TestPmsSharedRoom(TestPms):
+ def setUp(self):
+ super().setUp()
+ # create a room type availability
+ self.room_type_availability = self.env["pms.availability.plan"].create(
+ {
+ "name": "Availability plan for TEST",
+ "pms_pricelist_ids": [(6, 0, [self.pricelist1.id])],
+ }
+ )
+
+ self.bed_class = self.env["pms.room.type.class"].create(
+ {
+ "name": "Bed Class 1",
+ "default_code": "B1",
+ }
+ )
+
+ # create room type
+ self.room_type_test = self.env["pms.room.type"].create(
+ {
+ "pms_property_ids": [self.pms_property1.id],
+ "name": "Shared Test",
+ "default_code": "SHT",
+ "class_id": self.room_type_class1.id,
+ }
+ )
+
+ self.room_type_bed = self.env["pms.room.type"].create(
+ {
+ "pms_property_ids": [self.pms_property1.id],
+ "name": "Bed Type Test",
+ "default_code": "BTT",
+ "class_id": self.bed_class.id,
+ }
+ )
+
+ # create shared room
+ self.room1 = self.env["pms.room"].create(
+ {
+ "pms_property_id": self.pms_property1.id,
+ "name": "Shared 101",
+ "room_type_id": self.room_type_test.id,
+ "capacity": 2,
+ }
+ )
+
+ # create beds in room1
+ self.r1bed1 = self.env["pms.room"].create(
+ {
+ "pms_property_id": self.pms_property1.id,
+ "name": "101 (1)",
+ "room_type_id": self.room_type_bed.id,
+ "capacity": 1,
+ "parent_id": self.room1.id,
+ }
+ )
+
+ self.r1bed2 = self.env["pms.room"].create(
+ {
+ "pms_property_id": self.pms_property1.id,
+ "name": "101 (2)",
+ "room_type_id": self.room_type_bed.id,
+ "capacity": 2,
+ "parent_id": self.room1.id,
+ }
+ )
+
+ # create partner
+ self.partner1 = self.env["res.partner"].create(
+ {
+ "firstname": "Jaime",
+ "lastname": "García",
+ "email": "jaime@example.com",
+ "birthdate_date": "1983-03-01",
+ "gender": "male",
+ }
+ )
+
+ def test_count_avail_beds_with_room_occupied(self):
+ """
+ Check that not allow to create a bed reservation with a room occupied
+ ----------------
+ Create a room1 reservation and check that the beds room real avail is 0
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.room1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ASSERT
+ self.assertEqual(
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_bed.id,
+ ).availability,
+ 0,
+ "Beds avaialbility should be 0 for room occupied",
+ )
+
+ def test_count_avail_shared_room_with_one_bed_occupied(self):
+ """
+ Check that not allow to create a shared room reservation with a bed occupied
+ ----------------
+ Create a room1's bed reservation and check that the room1 real avail is 0
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ASSERT
+ self.assertEqual(
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_test.id,
+ ).availability,
+ 0,
+ "Shared Room avaialbility should be 0 if it has a bed occupied",
+ )
+
+ def test_avail_in_room_type_with_shared_rooms(self):
+ """
+ Check that a shared room's bed occupied not
+ affect the avail on other rooms with the
+ same room type
+ ----------------
+ Create other room like room_type_test (room2)
+ Create a room1's bed reservation and check that the room1
+ Check that room_type_test real avail is 1
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+ self.room2 = self.env["pms.room"].create(
+ {
+ "pms_property_id": self.pms_property1.id,
+ "name": "Shared 102",
+ "room_type_id": self.room_type_test.id,
+ "capacity": 2,
+ }
+ )
+
+ # ACT
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ASSERT
+ self.assertEqual(
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_test.id,
+ ).availability,
+ 1,
+ "Room not shared affect by the shared room's avail with the same type",
+ )
+
+ def test_count_avail_beds_with_one_bed_occupied(self):
+ """
+ Check the avail of a bed when it has
+ a room with other beds occupied
+ ----------------
+ Create a room1's bed (it has 2 beds)
+ reservation and check that the beds avail = 1
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ res1 = self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+ res1.flush()
+ # ASSERT
+ self.assertEqual(
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_bed.id,
+ ).availability,
+ 1,
+ "Beds avaialbility should be 1 if it has 1 of 2 beds occupied",
+ )
+
+ def test_not_avail_beds_with_room_occupied(self):
+ """
+ Check that not allow to select a bed with a room occupied
+ ----------------
+ Create a room1 reservation and check that the beds are not available
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.room1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ASSERT
+ self.assertNotIn(
+ self.r1bed1.id,
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_bed.id,
+ ).free_room_ids.ids,
+ "room's bed should not be available " "because the entire room is reserved",
+ )
+
+ def test_not_avail_shared_room_with_one_bed_occupied(self):
+ """
+ Check that not allow to select a shared
+ room with a bed occupied
+ ----------------
+ Create a room1's bed reservation and check
+ that the room1 real avail is not available
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ASSERT
+ self.assertNotIn(
+ self.room1.id,
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_bed.id,
+ ).free_room_ids.ids,
+ "Entire Shared room should not be available "
+ "becouse it has a bed occupied",
+ )
+
+ def test_avail_beds_with_one_bed_occupied(self):
+ """
+ Check the select of a bed when it has a
+ room with other beds occupied
+ ----------------
+ Create a room1's bed (it has 2 beds) reservation
+ and check that the other bed is avail
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ASSERT
+ self.assertIn(
+ self.r1bed2.id,
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_bed.id,
+ ).free_room_ids.ids,
+ "The bed2 of the shared room should be available",
+ )
+
+ def test_not_allowed_reservation_in_bed_with_room_occuppied(self):
+ """
+ Check the constrain that not allow to create a reservation in a bed in a
+ room with other reservation like shared
+ ----------------
+ Create a room1's reservation and the try to create a reservation
+ in the room1's bed, we expect an error
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.room1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ACT & ASSERT
+ with self.assertRaises(
+ ValidationError,
+ msg="Reservation created on a bed whose room was already occupied",
+ ):
+ r_test = self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+ r_test.flush()
+
+ def test_not_allowed_reservation_in_shared_room_with_bed_occuppied(self):
+ """
+ Check the constrain that not allow to create a reservation
+ in a shared room in a bed reservation
+ ----------------
+ Create a room1's bed reservation and the try to create
+ a reservation in the room1, we expect an error
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+
+ # ACT & ASSERT
+ with self.assertRaises(
+ ValidationError,
+ msg="Reservation created in a full shared "
+ "room that already had beds occupied",
+ ):
+ r_test = self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.room1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+ r_test.flush()
+
+ def check_room_shared_availability_released_when_canceling_bed_reservations(self):
+ """
+ Check that check availability in shared room is
+ released when canceling bed reservations
+ ----------------
+ Create a room1's bed reservation and then cancel it,
+ check that the room1 real avail is 1
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ r1 = self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.r1bed1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+ r1.action_cancel()
+
+ # ASSERT
+ self.assertEqual(
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_test.id,
+ ).availability,
+ 1,
+ "The parent room avail dont update " "when cancel child room reservation",
+ )
+
+ def check_bed_availability_released_when_canceling_parent_room_reservations(self):
+ """
+ Check that check availability in child room is
+ released when canceling the parent rooms
+ ----------------
+ Create a room1 reservation and then cancel it,
+ check that the beds real avail is 2
+ """
+
+ # ARRANGE
+ today = fields.date.today()
+ tomorrow = fields.date.today() + datetime.timedelta(days=1)
+
+ # ACT
+ r1 = self.env["pms.reservation"].create(
+ {
+ "partner_id": self.partner1.id,
+ "preferred_room_id": self.room1.id,
+ "checkin": today,
+ "checkout": tomorrow,
+ "pms_property_id": self.pms_property1.id,
+ }
+ )
+ r1.action_cancel()
+
+ # ASSERT
+ self.assertEqual(
+ self.pms_property1.with_context(
+ checkin=today,
+ checkout=tomorrow,
+ room_type_id=self.room_type_bed.id,
+ ).availability,
+ 2,
+ "The child room avail dont update when " "cancel parent room reservation",
+ )
diff --git a/pms/views/pms_room_type_views.xml b/pms/views/pms_room_type_views.xml
index 22965b472..e88714a4b 100644
--- a/pms/views/pms_room_type_views.xml
+++ b/pms/views/pms_room_type_views.xml
@@ -37,7 +37,6 @@
-
diff --git a/pms/views/pms_room_views.xml b/pms/views/pms_room_views.xml
index 40094bdf7..2fa9aca2d 100644
--- a/pms/views/pms_room_views.xml
+++ b/pms/views/pms_room_views.xml
@@ -24,15 +24,7 @@
-
-
+
@@ -43,25 +35,16 @@
invisible="0"
force_save="1"
/>
-
+
+
+
-
-
+
+
@@ -88,12 +71,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/pms/views/pms_shared_room_views.xml b/pms/views/pms_shared_room_views.xml
deleted file mode 100644
index 68c9871c6..000000000
--- a/pms/views/pms_shared_room_views.xml
+++ /dev/null
@@ -1,133 +0,0 @@
-
-
-
- pms.shared.room.form
- pms.shared.room
-
-
-
-
-
- pms.shared.room.kanban
- pms.shared.room
- kanban
-
-
- false
-
-
-
-
-
-
-
- -
-
-
-
-
- -
- Room Type:
-
-
- -
-
- Beds
-
-
-
-
-
-
-
-
-
-
-
-
- pms.shared.room.search
- pms.shared.room
-
-
-
-
-
-
-
-
-
- pms.shared.room.tree
- pms.shared.room
-
-
-
-
-
-
-
-
-
-
- Shared Room
- pms.shared.room
-
-
- kanban,tree,form
-
-
-