diff --git a/pms/demo/pms_master_data.xml b/pms/demo/pms_master_data.xml
index a19bd690e..a8bbd9d17 100644
--- a/pms/demo/pms_master_data.xml
+++ b/pms/demo/pms_master_data.xml
@@ -201,7 +201,7 @@
Open Talk Away Room
- 1
+ 10
diff --git a/pms/models/__init__.py b/pms/models/__init__.py
index 8bab3ddac..d0ba83c43 100644
--- a/pms/models/__init__.py
+++ b/pms/models/__init__.py
@@ -46,3 +46,4 @@ from . import folio_sale_line
from . import account_bank_statement_line
from . import account_bank_statement
from . import account_journal
+from . import pms_room_type_availability
diff --git a/pms/models/pms_reservation.py b/pms/models/pms_reservation.py
index 061e7d72c..7af48e7a0 100644
--- a/pms/models/pms_reservation.py
+++ b/pms/models/pms_reservation.py
@@ -598,6 +598,8 @@ class PmsReservation(models.Model):
@api.depends(
"reservation_line_ids.date",
+ "reservation_line_ids.room_id",
+ "reservation_line_ids.occupies_availability",
"overbooking",
"state",
"preferred_room_id",
@@ -618,7 +620,8 @@ class PmsReservation(models.Model):
checkout=reservation.checkout,
room_type_id=False, # Allow chosen any available room
current_lines=reservation.reservation_line_ids.ids,
- pricelist=reservation.pricelist_id.id,
+ pricelist_id=reservation.pricelist_id.id,
+ pms_property_id=reservation.pms_property_id.id,
)
reservation.allowed_room_ids = rooms_available
@@ -1314,7 +1317,8 @@ class PmsReservation(models.Model):
checkin=self.checkin,
checkout=self.checkout,
current_lines=self.reservation_line_ids.ids,
- pricelist=self.pricelist_id.id,
+ pricelist_id=self.pricelist_id.id,
+ pms_property_id=self.pms_property_id.id,
)
# REVIEW: check capacity room
return {
@@ -1358,7 +1362,8 @@ class PmsReservation(models.Model):
self.checkin,
self.checkout,
room_type_id=self.room_type_id.id,
- pricelist=self.pricelist_id.id,
+ pricelist_id=self.pricelist_id.id,
+ pms_property_id=self.pms_property_id.id,
)
if self.preferred_room_id.id in rooms_available.ids:
default["preferred_room_id"] = self.preferred_room_id.id
@@ -1410,7 +1415,8 @@ class PmsReservation(models.Model):
checkin=self.checkin,
checkout=self.checkout,
room_type_id=self.room_type_id.id or False,
- pricelist=self.pricelist_id.id,
+ pricelist_id=self.pricelist_id.id,
+ pms_property_id=self.pms_property_id.id,
)
if rooms_available:
room_chosen = rooms_available[0]
diff --git a/pms/models/pms_reservation_line.py b/pms/models/pms_reservation_line.py
index 194c81f18..77dc99bad 100644
--- a/pms/models/pms_reservation_line.py
+++ b/pms/models/pms_reservation_line.py
@@ -78,6 +78,14 @@ class PmsReservationLine(models.Model):
store=True,
readonly=False,
)
+ avail_id = fields.Many2one(
+ string="Availability Day",
+ comodel_name="pms.room.type.availability",
+ ondelete="restrict",
+ compute="_compute_avail_id",
+ store=True,
+ )
+
discount = fields.Float(string="Discount (%)", digits=("Discount"), default=0.0)
occupies_availability = fields.Boolean(
string="Occupies",
@@ -108,7 +116,7 @@ class PmsReservationLine(models.Model):
key=lambda r: (r.reservation_id, r.date)
):
reservation = line.reservation_id
- if reservation.preferred_room_id or not line.room_id:
+ if reservation.preferred_room_id != line.room_id or not line.room_id:
# If reservation has a preferred_room_id We can allow
# select room_id regardless room_type_id selected on reservation
free_room_select = True if reservation.preferred_room_id else False
@@ -122,7 +130,8 @@ class PmsReservationLine(models.Model):
if not free_room_select
else False,
current_lines=line.reservation_id.reservation_line_ids.ids,
- pricelist=line.reservation_id.pricelist_id.id,
+ pricelist_id=line.reservation_id.pricelist_id.id,
+ pms_property_id=line.pms_property_id.id,
)
# if there is availability for the entire stay
if rooms_available:
@@ -154,6 +163,7 @@ class PmsReservationLine(models.Model):
room_type_id=line.reservation_id.room_type_id.id,
current_lines=line._origin.reservation_id.reservation_line_ids.ids,
pricelist=line.reservation_id.pricelist_id,
+ pms_property_id=line.pms_property_id.id,
):
raise ValidationError(
_("%s: No room type available")
@@ -166,9 +176,11 @@ class PmsReservationLine(models.Model):
# we go through the rooms of the type
for room in self.env["pms.room"].search(
- [("room_type_id", "=", reservation.room_type_id.id)]
+ [
+ ("room_type_id", "=", reservation.room_type_id.id),
+ ("pms_property_id", "=", reservation.pms_property_id.id),
+ ]
):
-
# we iterate the dates from the date of the line to the checkout
for date_iterator in [
line.date + datetime.timedelta(days=x)
@@ -391,6 +403,35 @@ class PmsReservationLine(models.Model):
# else:
# reservation.reservation_line_ids.update({"cancel_discount": 0})
+ @api.depends("room_id", "pms_property_id", "date", "occupies_availability")
+ def _compute_avail_id(self):
+ for record in self:
+ if (
+ record.room_id.room_type_id
+ and record.date
+ and record.pms_property_id
+ and record.occupies_availability
+ ):
+ avail = self.env["pms.room.type.availability"].search(
+ [
+ ("date", "=", record.date),
+ ("room_type_id", "=", record.room_id.room_type_id.id),
+ ("pms_property_id", "=", record.pms_property_id.id),
+ ]
+ )
+ if avail:
+ record.avail_id = avail.id
+ else:
+ record.avail_id = self.env["pms.room.type.availability"].create(
+ {
+ "date": record.date,
+ "room_type_id": record.room_id.room_type_id.id,
+ "pms_property_id": record.pms_property_id.id,
+ }
+ )
+ else:
+ record.avail_id = False
+
# Constraints and onchanges
@api.constrains("date")
def constrains_duplicated_date(self):
diff --git a/pms/models/pms_room_type.py b/pms/models/pms_room_type.py
index 7489b35c1..a7f2e3d6a 100644
--- a/pms/models/pms_room_type.py
+++ b/pms/models/pms_room_type.py
@@ -18,6 +18,25 @@ class PmsRoomType(models.Model):
_inherits = {"product.product": "product_id"}
_order = "sequence, code_type, name"
+ # Defaults and Gets
+ def name_get(self):
+ result = []
+ for room_type in self:
+ name = room_type.name
+ if self._context.get("checkin") and self._context.get("checkin"):
+ avail = self.env[
+ "pms.room.type.availability.plan"
+ ].get_count_rooms_available(
+ checkin=self._context.get("checkin"),
+ checkout=self._context.get("checkout"),
+ room_type_id=room_type.id,
+ pms_property_id=self._context.get("pms_property_id") or False,
+ pricelist_id=self._context.get("pricelist_id") or False,
+ )
+ name += " (%s)" % avail
+ result.append((room_type.id, name))
+ return result
+
# Fields declaration
product_id = fields.Many2one(
"product.product",
diff --git a/pms/models/pms_room_type_availability.py b/pms/models/pms_room_type_availability.py
new file mode 100644
index 000000000..0e029a09c
--- /dev/null
+++ b/pms/models/pms_room_type_availability.py
@@ -0,0 +1,88 @@
+# Copyright 2017 Alexandre Díaz
+# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+
+
+class PmsRoomTypeAvailability(models.Model):
+ _name = "pms.room.type.availability"
+ _description = "Room type availability per day"
+
+ room_type_id = fields.Many2one(
+ comodel_name="pms.room.type",
+ string="Room Type",
+ required=True,
+ ondelete="cascade",
+ readonly=True,
+ )
+ date = fields.Date(
+ string="Date",
+ required=True,
+ readonly=True,
+ )
+ pms_property_id = fields.Many2one(
+ comodel_name="pms.property",
+ string="Property",
+ ondelete="restrict",
+ required=True,
+ readonly=True,
+ )
+ reservation_line_ids = fields.One2many(
+ string="Reservation Lines",
+ comodel_name="pms.reservation.line",
+ inverse_name="avail_id",
+ readonly=True,
+ )
+ real_avail = fields.Integer(
+ compute="_compute_real_avail",
+ store=True,
+ readonly=True,
+ )
+
+ _sql_constraints = [
+ (
+ "room_type_registry_unique",
+ "unique(room_type_id, date, pms_property_id)",
+ "Only can exists one availability in the same \
+ day for the same room type!",
+ )
+ ]
+
+ @api.depends("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),
+ ("pms_property_id", "=", record.pms_property_id.id),
+ ]
+ )
+ room_ids = record.room_type_id.mapped("room_ids.id")
+ rooms_not_avail = RoomLines.search_count(
+ [
+ ("date", "=", record.date),
+ ("room_id", "in", room_ids),
+ ("pms_property_id", "=", record.pms_property_id.id),
+ ("occupies_availability", "=", True),
+ # ("id", "not in", current_lines if current_lines else []),
+ ]
+ )
+ record.real_avail = total_rooms - rooms_not_avail
+
+ @api.constrains(
+ "room_type_id",
+ "pms_property_id",
+ )
+ def _check_property_integrity(self):
+ for rec in self:
+ if rec.pms_property_id and rec.room_type_id:
+ if (
+ rec.room_type_id.pms_property_ids.ids
+ and rec.pms_property_id.id
+ not in rec.room_type_id.pms_property_ids.ids
+ ):
+ raise ValidationError(
+ _("Property not allowed on availability day compute")
+ )
diff --git a/pms/models/pms_room_type_availability_plan.py b/pms/models/pms_room_type_availability_plan.py
index cfb27fd02..2ea1b857a 100644
--- a/pms/models/pms_room_type_availability_plan.py
+++ b/pms/models/pms_room_type_availability_plan.py
@@ -2,7 +2,9 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import datetime
-from odoo import api, fields, models
+from odoo import _, api, fields, models
+from odoo.exceptions import ValidationError
+from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
class PmsRoomTypeAvailability(models.Model):
@@ -69,66 +71,157 @@ class PmsRoomTypeAvailability(models.Model):
checkout,
room_type_id=False,
current_lines=False,
- pricelist=False,
+ pricelist_id=False,
pms_property_id=False,
):
if current_lines and not isinstance(current_lines, list):
current_lines = [current_lines]
-
- rooms_not_avail = (
- self.env["pms.reservation.line"]
- .search(
- [
- ("date", ">=", checkin),
- ("date", "<=", checkout - datetime.timedelta(1)),
- ("occupies_availability", "=", True),
- ("id", "not in", current_lines if current_lines else []),
- ]
- )
- .mapped("room_id.id")
+ free_rooms = self.get_real_free_rooms(
+ checkin, checkout, room_type_id, current_lines, pms_property_id
)
-
- domain_rooms = [
- ("id", "not in", rooms_not_avail if len(rooms_not_avail) > 0 else []),
- ]
domain_rules = [
("date", ">=", checkin),
- ("date", "<=", checkout),
+ (
+ "date",
+ "<=",
+ checkout,
+ ), # TODO: only closed_departure take account checkout date!
]
-
if pms_property_id:
- domain_rooms.append(("pms_property_id", "=", pms_property_id))
domain_rules.append(("pms_property_id", "=", pms_property_id))
if room_type_id:
- domain_rooms.append(("room_type_id", "=", room_type_id))
domain_rules.append(("room_type_id", "=", room_type_id))
+ if pricelist_id:
+ pricelist = self.env["product.pricelist"].browse(pricelist_id)
+ if pricelist and pricelist.availability_plan_id:
+ domain_rules.append(
+ ("availability_plan_id", "=", pricelist.availability_plan_id.id)
+ )
+ rule_items = self.env["pms.room.type.availability.rule"].search(
+ domain_rules
+ )
- free_rooms = self.env["pms.room"].search(domain_rooms)
+ if len(rule_items) > 0:
+ room_types_to_remove = []
+ for item in rule_items:
+ if self.any_rule_applies(checkin, checkout, item):
+ room_types_to_remove.append(item.room_type_id.id)
+ free_rooms = free_rooms.filtered(
+ lambda x: x.room_type_id.id not in room_types_to_remove
+ )
+ elif not pricelist:
+ raise ValidationError(_("Pricelist not found"))
+ return free_rooms.sorted(key=lambda r: r.sequence)
- if pricelist:
+ def get_real_free_rooms(
+ self,
+ checkin,
+ checkout,
+ room_type_id=False,
+ current_lines=False,
+ pms_property_id=False,
+ ):
+ Avail = self.env["pms.room.type.availability"]
+ if isinstance(checkin, str):
+ checkin = datetime.datetime.strptime(
+ checkin, DEFAULT_SERVER_DATE_FORMAT
+ ).date()
+ if isinstance(checkout, str):
+ checkout = datetime.datetime.strptime(
+ checkout, DEFAULT_SERVER_DATE_FORMAT
+ ).date()
+ domain = [
+ ("date", ">=", checkin),
+ ("date", "<=", checkout - datetime.timedelta(1)),
+ ]
+ rooms_not_avail = (
+ Avail.search(domain)
+ .reservation_line_ids.filtered(
+ lambda l: l.id not in current_lines if current_lines else []
+ )
+ .room_id.ids
+ )
+ domain_rooms = [
+ ("id", "not in", rooms_not_avail if rooms_not_avail else []),
+ ]
+ if pms_property_id:
+ domain_rooms.append(("pms_property_id", "=", pms_property_id))
+ if room_type_id:
+ domain_rooms.append(("room_type_id", "=", room_type_id))
+ return self.env["pms.room"].search(domain_rooms)
+
+ @api.model
+ def get_count_rooms_available(
+ self,
+ checkin,
+ checkout,
+ room_type_id,
+ pms_property_id,
+ current_lines=False,
+ pricelist_id=False,
+ ):
+ if current_lines and not isinstance(current_lines, list):
+ current_lines = [current_lines]
+
+ avail = self.get_count_real_free_rooms(
+ checkin, checkout, room_type_id, pms_property_id, current_lines
+ )
+ domain_rules = [
+ ("date", ">=", checkin),
+ (
+ "date",
+ "<=",
+ checkout,
+ ), # TODO: only closed_departure take account checkout date!
+ ("room_type_id", "=", room_type_id),
+ ("pms_property_id", "=", pms_property_id),
+ ]
+ if pricelist_id:
+ pricelist = self.env["product.pricelist"].browse(pricelist_id)
+ if pricelist and pricelist.availability_plan_id:
domain_rules.append(
- ("availability_plan_id.pms_pricelist_ids", "=", pricelist)
+ ("availability_plan_id", "=", pricelist.availability_plan_id.id)
)
rule_items = self.env["pms.room.type.availability.rule"].search(
domain_rules
)
-
if len(rule_items) > 0:
- room_types_to_remove = []
for item in rule_items:
if self.any_rule_applies(checkin, checkout, item):
- room_types_to_remove.append(item.room_type_id.id)
- free_rooms = free_rooms.filtered(
- lambda x: x.room_type_id.id not in room_types_to_remove
- )
+ return 0
+ avail = min(rule_items.mapped("plan_avail"))
+ return avail
- # if pms_property_id:
- # free_rooms = free_rooms.filtered(
- # lambda x: x.pms_property_id = pms_property_id
- # )
-
- return free_rooms.sorted(key=lambda r: r.sequence)
+ def get_count_real_free_rooms(
+ self,
+ checkin,
+ checkout,
+ room_type_id,
+ pms_property_id,
+ current_lines=False,
+ ):
+ Avail = self.env["pms.room.type.availability"]
+ count_free_rooms = len(self.env["pms.room.type"].browse(room_type_id).room_ids)
+ if isinstance(checkin, str):
+ checkin = datetime.datetime.strptime(
+ checkin, DEFAULT_SERVER_DATE_FORMAT
+ ).date()
+ if isinstance(checkout, str):
+ checkout = datetime.datetime.strptime(
+ checkout, DEFAULT_SERVER_DATE_FORMAT
+ ).date()
+ for avail in Avail.search(
+ [
+ ("date", ">=", checkin),
+ ("date", "<=", checkout - datetime.timedelta(1)),
+ ("room_type_id", "=", room_type_id),
+ ("pms_property_id", "=", pms_property_id),
+ ]
+ ):
+ if avail.real_avail < count_free_rooms:
+ count_free_rooms = avail.real_avail
+ return count_free_rooms
@api.model
def splitted_availability(
@@ -138,7 +231,16 @@ class PmsRoomTypeAvailability(models.Model):
room_type_id=False,
current_lines=False,
pricelist=False,
+ pms_property_id=False,
):
+ if isinstance(checkin, str):
+ checkin = datetime.datetime.strptime(
+ checkin, DEFAULT_SERVER_DATE_FORMAT
+ ).date()
+ if isinstance(checkout, str):
+ checkout = datetime.datetime.strptime(
+ checkout, DEFAULT_SERVER_DATE_FORMAT
+ ).date()
for date_iterator in [
checkin + datetime.timedelta(days=x)
for x in range(0, (checkout - checkin).days)
@@ -148,7 +250,8 @@ class PmsRoomTypeAvailability(models.Model):
checkout=date_iterator + datetime.timedelta(1),
room_type_id=room_type_id,
current_lines=current_lines,
- pricelist=pricelist.id,
+ pricelist_id=pricelist.id,
+ pms_property_id=pms_property_id,
)
if len(rooms_avail) < 1:
return False
diff --git a/pms/models/pms_room_type_availability_rule.py b/pms/models/pms_room_type_availability_rule.py
index d99569400..cb816737b 100644
--- a/pms/models/pms_room_type_availability_rule.py
+++ b/pms/models/pms_room_type_availability_rule.py
@@ -59,7 +59,6 @@ class PmsRoomTypeAvailabilityRule(models.Model):
compute="_compute_quota",
help="Generic Quota assigned.",
)
-
max_avail = fields.Integer(
string="Max. Availability",
store=True,
@@ -67,13 +66,12 @@ class PmsRoomTypeAvailabilityRule(models.Model):
compute="_compute_max_avail",
help="Maximum simultaneous availability on own Booking Engine.",
)
-
pms_property_id = fields.Many2one(
comodel_name="pms.property",
string="Property",
ondelete="restrict",
+ required=True,
)
-
allowed_property_ids = fields.Many2many(
"pms.property",
"allowed_availability_move_rel",
@@ -84,6 +82,22 @@ class PmsRoomTypeAvailabilityRule(models.Model):
readonly=True,
compute="_compute_allowed_property_ids",
)
+ avail_id = fields.Many2one(
+ string="Avail record",
+ comodel_name="pms.room.type.availability",
+ compute="_compute_avail_id",
+ store=True,
+ readonly=False,
+ ondelete="restrict",
+ )
+ real_avail = fields.Integer(
+ related="avail_id.real_avail",
+ store="True",
+ )
+ plan_avail = fields.Integer(
+ compute="_compute_plan_avail",
+ store="True",
+ )
_sql_constraints = [
(
@@ -94,6 +108,44 @@ class PmsRoomTypeAvailabilityRule(models.Model):
)
]
+ @api.depends("room_type_id", "date", "pms_property_id")
+ def _compute_avail_id(self):
+ for record in self:
+ if record.room_type_id and record.pms_property_id and record.date:
+ avail = self.env["pms.room.type.availability"].search(
+ [
+ ("date", "=", record.date),
+ ("room_type_id", "=", record.room_type_id.id),
+ ("pms_property_id", "=", record.pms_property_id.id),
+ ]
+ )
+ if avail:
+ record.avail_id = avail.id
+ else:
+ record.avail_id = self.env["pms.room.type.availability"].create(
+ {
+ "date": record.date,
+ "room_type_id": record.room_type_id.id,
+ "pms_property_id": record.pms_property_id.id,
+ }
+ )
+ else:
+ record.avail_id = False
+
+ @api.depends("quota", "max_avail", "real_avail")
+ def _compute_plan_avail(self):
+ for record in self.filtered("real_avail"):
+ real_avail = record.real_avail
+ plan_avail = min(
+ [
+ record.max_avail if record.max_avail >= 0 else real_avail,
+ record.quota if record.quota >= 0 else real_avail,
+ real_avail,
+ ]
+ )
+ if not record.plan_avail or record.plan_avail != plan_avail:
+ record.plan_avail = plan_avail
+
@api.depends("room_type_id")
def _compute_quota(self):
for record in self:
diff --git a/pms/security/ir.model.access.csv b/pms/security/ir.model.access.csv
index 023c5fab7..2587b5b9b 100644
--- a/pms/security/ir.model.access.csv
+++ b/pms/security/ir.model.access.csv
@@ -12,6 +12,7 @@ user_access_pms_room_type_class,user_access_pms_room_type_class,model_pms_room_t
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_room_type_availability_rule,user_access_pms_room_type_availability_rule,model_pms_room_type_availability_rule,pms.group_pms_user,1,0,0,0
+user_access_pms_room_type_availability,user_access_pms_room_type_availability,model_pms_room_type_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
user_access_pms_folio,user_access_pms_folio,model_pms_folio,pms.group_pms_user,1,1,1,1
user_access_pms_room_type,user_access_pms_room_type,model_pms_room_type,pms.group_pms_user,1,0,0,0
@@ -38,6 +39,7 @@ manager_access_pms_room,manager_access_pms_room,model_pms_room,pms.group_pms_man
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_room_type_availability_rule,manager_access_pms_room_type_availability_rule,model_pms_room_type_availability_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_room_type_availability,manager_access_pms_room_type_availability,model_pms_room_type_availability,pms.group_pms_manager,1,1,1,0
manager_access_pms_folio,manager_access_pms_folio,model_pms_folio,pms.group_pms_manager,1,1,1,1
manager_access_pms_room_type,manager_access_pms_room_type,model_pms_room_type,pms.group_pms_manager,1,1,1,1
manager_access_pms_board_service_room_type,manager_access_pms_board_service_room_type,model_pms_board_service_room_type,pms.group_pms_manager,1,1,1,1
diff --git a/pms/tests/test_pms_reservation.py b/pms/tests/test_pms_reservation.py
index f0674cafd..cb294011c 100644
--- a/pms/tests/test_pms_reservation.py
+++ b/pms/tests/test_pms_reservation.py
@@ -271,7 +271,6 @@ class TestPmsReservations(TestHotel):
}
)
r_test.flush()
-
# ASSERT
self.assertEqual(
expected_num_changes,
diff --git a/pms/tests/test_pms_room_type_availability_rules.py b/pms/tests/test_pms_room_type_availability_rules.py
index 60e92a600..d7400765a 100644
--- a/pms/tests/test_pms_room_type_availability_rules.py
+++ b/pms/tests/test_pms_room_type_availability_rules.py
@@ -262,6 +262,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_double.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True, # <- (1/2)
+ "pms_property_id": self.test_property.id,
}
)
# ACT
@@ -269,7 +270,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
checkin=fields.date.today(),
checkout=(fields.datetime.today() + datetime.timedelta(days=4)).date(),
# room_type_id=False, # <- (2/2)
- pricelist=self.test_pricelist1.id,
+ pricelist_id=self.test_pricelist1.id,
)
# ASSERT
self.assertNotIn(
@@ -295,6 +296,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"availability_plan_id": self.test_room_type_availability1.id,
"room_type_id": self.test_room_type_double.id,
"date": (fields.datetime.today() + datetime.timedelta(days=0)).date(),
+ "pms_property_id": self.test_property.id,
}
)
@@ -410,7 +412,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
checkin=checkin,
checkout=checkout,
room_type_id=self.test_room_type_double.id,
- pricelist=self.test_pricelist1.id,
+ pricelist_id=self.test_pricelist1.id,
)
# ASSERT
@@ -437,6 +439,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_double.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
+ "pms_property_id": self.test_property.id,
}
)
checkin = datetime.datetime.now()
@@ -475,6 +478,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_double.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
+ "pms_property_id": self.test_property.id,
}
)
@@ -537,6 +541,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_double.id,
"date": datetime.date.today(),
"quota": 1,
+ "pms_property_id": self.test_property.id,
}
)
r1 = self.env["pms.reservation"].create(
@@ -587,6 +592,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_double.id,
"date": datetime.date.today(),
"quota": test_quota,
+ "pms_property_id": self.test_property.id,
}
)
reservation = self.env["pms.reservation"].create(
@@ -687,7 +693,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
fields.datetime.today() + datetime.timedelta(days=2)
).date(),
room_type_id=self.test_room_type_special.id,
- pricelist=self.test_pricelist1.id,
+ pricelist_id=self.test_pricelist1.id,
pms_property_id=p["property"],
)
# ASSERT
@@ -730,6 +736,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_special.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
+ "pms_property_id": self.test_property1.id,
}
)
# Test cases when creating a availability_rule
@@ -794,6 +801,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"room_type_id": self.test_room_type_special.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
+ "pms_property_id": self.test_property1.id,
}
)
@@ -802,6 +810,3 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
self.availability_rule1.allowed_property_ids.mapped("id"),
"error",
)
-
- # plan 1 property 01 | rule property: False
- # plan 1 property 02 | rule property: False
diff --git a/pms/tests/test_pms_wizard_folio.py b/pms/tests/test_pms_wizard_folio.py
index 6fb60a273..30742edf2 100644
--- a/pms/tests/test_pms_wizard_folio.py
+++ b/pms/tests/test_pms_wizard_folio.py
@@ -150,7 +150,6 @@ class TestPmsWizardMassiveChanges(TestHotel):
# Set values for the wizard and the total price is correct
# Also check the discount is correctly applied to get
# the total folio price
- # (no pricelist applied)
# ARRANGE
# common scenario
@@ -183,6 +182,8 @@ class TestPmsWizardMassiveChanges(TestHotel):
"start_date": checkin,
"end_date": checkout,
"partner_id": self.partner_id.id,
+ "pms_property_id": self.test_property.id,
+ "pricelist_id": self.test_pricelist.id,
}
)
@@ -206,7 +207,6 @@ class TestPmsWizardMassiveChanges(TestHotel):
)
lines_availability_test[0].num_rooms_selected = value
-
for discount in discounts:
with self.subTest(k=discount):
# ACT
@@ -265,6 +265,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"end_date": checkout,
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
}
)
wizard_folio.flush()
@@ -395,6 +396,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"end_date": checkout,
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
}
)
wizard_folio.flush()
@@ -444,6 +446,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"end_date": checkout,
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
}
)
wizard_folio.flush()
@@ -495,6 +498,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"end_date": checkout,
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
}
)
wizard_folio.flush()
@@ -552,6 +556,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"end_date": checkout,
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
}
)
wizard_folio.flush()
@@ -585,6 +590,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"room_type_id": self.test_room_type_double,
"partner_id": self.partner_id.id,
"pricelist_id": folio.pricelist_id.id,
+ "pms_property_id": self.test_property.id,
}
# ASSERT
@@ -593,7 +599,8 @@ class TestPmsWizardMassiveChanges(TestHotel):
with self.subTest(k=key):
self.assertEqual(
reservation[key].id
- if key in ["folio_id", "partner_id", "pricelist_id"]
+ if key
+ in ["folio_id", "partner_id", "pricelist_id", "pms_property_id"]
else reservation[key],
vals[key],
"The value of " + key + " is not correctly established",
@@ -620,6 +627,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
"discount": discount,
+ "pms_property_id": self.test_property.id,
}
)
wizard_folio.flush()
@@ -655,3 +663,87 @@ class TestPmsWizardMassiveChanges(TestHotel):
discount * 100,
"The discount is not correctly established",
)
+
+ def test_check_quota_avail(self):
+ # TEST CASE
+ # Check avail on room type with quota
+
+ # ARRANGE
+ # common scenario
+ self.create_common_scenario()
+
+ # checkin & checkout
+ checkin = fields.date.today()
+ checkout = fields.date.today() + datetime.timedelta(days=1)
+
+ self.env["pms.room.type.availability.rule"].create(
+ {
+ "quota": 1,
+ "room_type_id": self.test_room_type_double.id,
+ "availability_plan_id": self.test_availability_plan.id,
+ "date": fields.date.today(),
+ "pms_property_id": self.test_property.id,
+ }
+ )
+
+ # create folio wizard with partner id => pricelist & start-end dates
+ wizard_folio = self.env["pms.folio.wizard"].create(
+ {
+ "start_date": checkin,
+ "end_date": checkout,
+ "partner_id": self.partner_id.id,
+ "pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
+ }
+ )
+ wizard_folio.flush()
+
+ room_type_plan_avail = wizard_folio.availability_results.filtered(
+ lambda r: r.room_type_id.id == self.test_room_type_double.id
+ ).num_rooms_available
+
+ # ASSERT
+
+ self.assertEqual(room_type_plan_avail, 1, "Quota not applied in Wizard Folio")
+
+ def test_check_min_stay_avail(self):
+ # TEST CASE
+ # Check avail on room type with quota
+
+ # ARRANGE
+ # common scenario
+ self.create_common_scenario()
+
+ # checkin & checkout
+ checkin = fields.date.today()
+ checkout = fields.date.today() + datetime.timedelta(days=1)
+
+ self.env["pms.room.type.availability.rule"].create(
+ {
+ "min_stay": 3,
+ "room_type_id": self.test_room_type_double.id,
+ "availability_plan_id": self.test_availability_plan.id,
+ "date": fields.date.today(),
+ "pms_property_id": self.test_property.id,
+ }
+ )
+
+ # create folio wizard with partner id => pricelist & start-end dates
+ wizard_folio = self.env["pms.folio.wizard"].create(
+ {
+ "start_date": checkin,
+ "end_date": checkout,
+ "partner_id": self.partner_id.id,
+ "pricelist_id": self.test_pricelist.id,
+ "pms_property_id": self.test_property.id,
+ }
+ )
+ wizard_folio.flush()
+
+ room_type_plan_avail = wizard_folio.availability_results.filtered(
+ lambda r: r.room_type_id.id == self.test_room_type_double.id
+ ).num_rooms_available
+
+ # ASSERT
+
+ self.assertEqual(room_type_plan_avail, 0, "Quota not applied in Wizard Folio")
diff --git a/pms/tests/test_pms_wizard_massive_changes.py b/pms/tests/test_pms_wizard_massive_changes.py
index bc947b20e..d5b91f047 100644
--- a/pms/tests/test_pms_wizard_massive_changes.py
+++ b/pms/tests/test_pms_wizard_massive_changes.py
@@ -78,6 +78,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"start_date": fields.date.today(),
"end_date": fields.date.today() + datetime.timedelta(days=days),
"room_type_id": self.test_room_type_double.id,
+ "pms_property_ids": [self.test_property.id],
}
).apply_massive_changes()
@@ -98,7 +99,13 @@ class TestPmsWizardMassiveChanges(TestHotel):
date_from = fields.date.today()
date_to = fields.date.today() + datetime.timedelta(days=3)
- num_room_types = self.env["pms.room.type"].search_count([])
+ num_room_types = self.env["pms.room.type"].search_count(
+ [
+ "|",
+ ("pms_property_ids", "=", False),
+ ("pms_property_ids", "in", self.test_property.id),
+ ]
+ )
num_exp_rules_to_create = ((date_to - date_from).days + 1) * num_room_types
# ACT
@@ -108,6 +115,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"availability_plan_id": self.test_availability_plan.id,
"start_date": date_from,
"end_date": date_to,
+ "pms_property_ids": [self.test_property.id],
}
).apply_massive_changes()
@@ -144,6 +152,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"closed": True,
"closed_arrival": True,
"closed_departure": True,
+ "pms_property_ids": [self.test_property.id],
}
# ACT
@@ -155,6 +164,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
del vals["start_date"]
del vals["end_date"]
del vals["room_type_id"]
+ del vals["pms_property_ids"]
for key in vals:
with self.subTest(k=key):
self.assertEqual(
@@ -190,6 +200,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"room_type_id": self.test_room_type_double.id,
"start_date": date_from,
"end_date": date_to,
+ "pms_property_ids": [self.test_property.id],
}
)
@@ -243,6 +254,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"start_date": fields.date.today(),
"end_date": fields.date.today() + datetime.timedelta(days=days),
"room_type_id": self.test_room_type_double.id,
+ "pms_property_ids": [self.test_property.id],
}
).apply_massive_changes()
# ASSERT
@@ -266,7 +278,13 @@ class TestPmsWizardMassiveChanges(TestHotel):
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today() + datetime.timedelta(days=3)
- num_room_types = self.env["pms.room.type"].search_count([])
+ num_room_types = self.env["pms.room.type"].search_count(
+ [
+ "|",
+ ("pms_property_ids", "=", False),
+ ("pms_property_ids", "in", self.test_property.id),
+ ]
+ )
num_exp_items_to_create = ((date_to - date_from).days + 1) * num_room_types
# ACT
@@ -276,6 +294,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"pricelist_id": self.test_pricelist.id,
"start_date": date_from,
"end_date": date_to,
+ "pms_property_ids": [self.test_property.id],
}
).apply_massive_changes()
@@ -305,8 +324,8 @@ class TestPmsWizardMassiveChanges(TestHotel):
"date_start": date_from,
"date_end": date_to,
"compute_price": "fixed",
- "applied_on": "1_product",
- "product_tmpl_id": self.test_room_type_double.product_id.product_tmpl_id,
+ "applied_on": "0_product_variant",
+ "product_id": self.test_room_type_double.product_id,
"fixed_price": price,
"min_quantity": min_quantity,
}
@@ -321,6 +340,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"room_type_id": self.test_room_type_double.id,
"price": price,
"min_quantity": min_quantity,
+ "pms_property_ids": [self.test_property.id],
}
).apply_massive_changes()
vals["date_start_overnight"] = date_from
@@ -362,6 +382,7 @@ class TestPmsWizardMassiveChanges(TestHotel):
"room_type_id": self.test_room_type_double.id,
"start_date": date_from,
"end_date": date_to,
+ "pms_property_ids": [self.test_property.id],
}
)
for index, test_case in enumerate(test_case_week_days):
diff --git a/pms/views/pms_reservation_views.xml b/pms/views/pms_reservation_views.xml
index 606c795ab..352a17ca6 100644
--- a/pms/views/pms_reservation_views.xml
+++ b/pms/views/pms_reservation_views.xml
@@ -178,6 +178,7 @@
placeholder="Room Type"
on_change="1"
nolabel="1"
+ context="{'checkin': checkin, 'checkout': checkout, 'pms_property_id':pms_property_id, 'pricelist_id':pricelist_id}"
options="{'no_create': True,'no_open': True}"
attrs="{'readonly':[('state','not in',('draft'))]}"
style="margin-right: 30px;"
diff --git a/pms/wizards/wizard_folio.py b/pms/wizards/wizard_folio.py
index 59722ae3c..030dd464d 100644
--- a/pms/wizards/wizard_folio.py
+++ b/pms/wizards/wizard_folio.py
@@ -85,61 +85,35 @@ class FolioWizard(models.TransientModel):
cmds = [(5, 0, 0)]
- for room_type_iterator in self.env["pms.room.type"].search([]):
-
- num_rooms_available_by_date = []
- room_type_total_price_per_room = 0
-
- for date_iterator in [
- record.start_date + datetime.timedelta(days=x)
- for x in range(0, (record.end_date - record.start_date).days)
- ]:
- rooms_available = self.env[
- "pms.room.type.availability.plan"
- ].rooms_available(
- date_iterator,
- date_iterator + datetime.timedelta(days=1),
- room_type_id=room_type_iterator.id,
- pricelist=record.pricelist_id.id,
- )
-
- num_rooms_available_by_date.append(len(rooms_available))
- product = room_type_iterator
- product = product.with_context(
- lang=record.partner_id.lang,
- partner=record.partner_id.id,
- quantity=1,
- date=fields.Date.today(),
- date_overnight=date_iterator,
- pricelist=record.pricelist_id.id,
- uom=product.uom_id.id,
- property=record.pms_property_id.id,
- )
- room_type_total_price_per_room += product.price
-
- # check there are rooms of the type
- if room_type_iterator.total_rooms_count > 0:
-
- # get min availability between start date & end date
- num_rooms_available = min(num_rooms_available_by_date)
-
- cmds.append(
- (
- 0,
- 0,
- {
- "folio_wizard_id": record.id,
- "checkin": record.start_date,
- "checkout": record.end_date,
- "room_type_id": room_type_iterator.id,
- "num_rooms_available": num_rooms_available,
- "price_per_room": room_type_total_price_per_room
- if num_rooms_available
- > 0 # not showing price if there's no availability
- else 0,
- },
- )
+ for room_type_iterator in self.env["pms.room.type"].search(
+ [
+ "|",
+ ("pms_property_ids", "=", False),
+ ("pms_property_ids", "in", record.pms_property_id.id),
+ ]
+ ):
+ num_rooms_available = self.env[
+ "pms.room.type.availability.plan"
+ ].get_count_rooms_available(
+ checkin=record.start_date,
+ checkout=record.end_date,
+ room_type_id=room_type_iterator.id,
+ pricelist_id=record.pricelist_id.id,
+ pms_property_id=record.pms_property_id.id,
+ )
+ cmds.append(
+ (
+ 0,
+ 0,
+ {
+ "folio_wizard_id": record.id,
+ "checkin": record.start_date,
+ "checkout": record.end_date,
+ "room_type_id": room_type_iterator.id,
+ "num_rooms_available": num_rooms_available,
+ },
)
+ )
# remove old items
old_lines = record.availability_results.mapped("id")
for old_line in old_lines:
@@ -158,6 +132,7 @@ class FolioWizard(models.TransientModel):
{
"pricelist_id": record.pricelist_id.id,
"partner_id": record.partner_id.id,
+ "pms_property_id": record.pms_property_id.id,
}
)
for line in record.availability_results:
@@ -170,6 +145,7 @@ class FolioWizard(models.TransientModel):
"room_type_id": line.room_type_id.id,
"partner_id": folio.partner_id.id,
"pricelist_id": folio.pricelist_id.id,
+ "pms_property_id": record.pms_property_id.id,
}
)
res.reservation_line_ids.discount = record.discount * 100
diff --git a/pms/wizards/wizard_folio.xml b/pms/wizards/wizard_folio.xml
index 055bf7391..4a55e9842 100644
--- a/pms/wizards/wizard_folio.xml
+++ b/pms/wizards/wizard_folio.xml
@@ -23,11 +23,13 @@
-
+
diff --git a/pms/wizards/wizard_folio_availability.py b/pms/wizards/wizard_folio_availability.py
index b77340aac..1d6bfad77 100644
--- a/pms/wizards/wizard_folio_availability.py
+++ b/pms/wizards/wizard_folio_availability.py
@@ -33,7 +33,8 @@ class AvailabilityWizard(models.TransientModel):
num_rooms_available = fields.Integer(
string="Available rooms",
- default=0,
+ compute="_compute_num_rooms_available",
+ store="true",
)
price_per_room = fields.Float(
string="Price per room",
@@ -53,6 +54,10 @@ class AvailabilityWizard(models.TransientModel):
price_total = fields.Float(
string="Total price", default=0, compute="_compute_price_total"
)
+ pms_property_id = fields.Many2one(
+ related="folio_wizard_id.pms_property_id",
+ string="Property",
+ )
@api.depends("num_rooms_selected", "checkin", "checkout")
def _compute_price_total(self):
@@ -62,22 +67,13 @@ class AvailabilityWizard(models.TransientModel):
# this field refresh is just to update it and take into account @ xml
record.value_num_rooms_selected = record.num_rooms_selected.value
- num_rooms_available_by_date = []
room_type_total_price_per_room = 0
for date_iterator in [
record.checkin + datetime.timedelta(days=x)
for x in range(0, (record.checkout - record.checkin).days)
]:
- rooms_available = self.env[
- "pms.room.type.availability.plan"
- ].rooms_available(
- date_iterator,
- date_iterator + datetime.timedelta(days=1),
- room_type_id=record.room_type_id.id,
- pricelist=record.folio_wizard_id.pricelist_id.id,
- )
- num_rooms_available_by_date.append(len(rooms_available))
+
partner = record.folio_wizard_id.partner_id
product = record.room_type_id.product_id
product = product.with_context(
@@ -92,10 +88,6 @@ class AvailabilityWizard(models.TransientModel):
)
room_type_total_price_per_room += product.price
- # get the availability for the entire stay (min of all dates)
- if num_rooms_available_by_date:
- record.num_rooms_available = min(num_rooms_available_by_date)
-
# udpate the price per room
record.price_per_room = room_type_total_price_per_room
@@ -117,6 +109,19 @@ class AvailabilityWizard(models.TransientModel):
record.price_total = record.price_per_room * record.num_rooms_selected.value
+ @api.depends("room_type_id", "checkin", "checkout")
+ def _compute_num_rooms_available(self):
+ for record in self:
+ record.num_rooms_available = self.env[
+ "pms.room.type.availability.plan"
+ ].get_count_rooms_available(
+ record.checkin,
+ record.checkout,
+ room_type_id=record.room_type_id.id,
+ pricelist_id=record.folio_wizard_id.pricelist_id.id,
+ pms_property_id=record.folio_wizard_id.pms_property_id.id,
+ )
+
def _compute_dynamic_selection(self):
for record in self:
for elem_to_insert in range(0, record.num_rooms_available + 1):
diff --git a/pms/wizards/wizard_massive_changes.py b/pms/wizards/wizard_massive_changes.py
index 171408497..60e9eed7b 100644
--- a/pms/wizards/wizard_massive_changes.py
+++ b/pms/wizards/wizard_massive_changes.py
@@ -15,6 +15,13 @@ class AvailabilityWizard(models.TransientModel):
return True if self._context.get("pricelist_id") else False
# Fields declaration
+ pms_property_ids = fields.Many2many(
+ comodel_name="pms.property",
+ string="Property",
+ default=lambda self: self.env["pms.property"].browse(
+ self.env.user.get_active_property_ids()[0]
+ ),
+ )
massive_changes_on = fields.Selection(
[("pricelist", "Pricelist"), ("availability_plan", "Availability Plan")],
string="Massive changes on",
@@ -236,6 +243,9 @@ class AvailabilityWizard(models.TransientModel):
if record.pricelist_id:
domain = [
("pricelist_id", "=", record.pricelist_id.id),
+ "|",
+ ("pms_property_ids", "=", False),
+ ("pms_property_ids", "in", record.pms_property_ids.ids),
]
if record.start_date:
@@ -327,41 +337,50 @@ class AvailabilityWizard(models.TransientModel):
continue
if not record.room_type_id:
- rooms = self.env["pms.room.type"].search([])
+ room_types = self.env["pms.room.type"].search(
+ [
+ "|",
+ ("pms_property_ids", "=", False),
+ ("pms_property_ids", "in", record.pms_property_ids.ids),
+ ]
+ )
else:
- rooms = [record.room_type_id]
- for room in rooms:
- if record.massive_changes_on == "pricelist":
-
- self.env["product.pricelist.item"].create(
- {
- "pricelist_id": record.pricelist_id.id,
- "date_start_overnight": date,
- "date_end_overnight": date,
- "compute_price": "fixed",
- "applied_on": "1_product",
- "product_tmpl_id": room.product_id.product_tmpl_id.id,
- "fixed_price": record.price,
- "min_quantity": record.min_quantity,
- }
- )
- else:
- self.env["pms.room.type.availability.rule"].create(
- {
- "availability_plan_id": record.availability_plan_id.id,
- "date": date,
- "room_type_id": room.id,
- "quota": record.quota,
- "max_avail": record.max_avail,
- "min_stay": record.min_stay,
- "min_stay_arrival": record.min_stay_arrival,
- "max_stay": record.max_stay,
- "max_stay_arrival": record.max_stay_arrival,
- "closed": record.closed,
- "closed_arrival": record.closed_arrival,
- "closed_departure": record.closed_departure,
- }
- )
+ room_types = [record.room_type_id]
+ for room_type in room_types:
+ for pms_property in record.pms_property_ids:
+ if record.massive_changes_on == "pricelist":
+ self.env["product.pricelist.item"].create(
+ {
+ "pricelist_id": record.pricelist_id.id,
+ "date_start_overnight": date,
+ "date_end_overnight": date,
+ "compute_price": "fixed",
+ "applied_on": "0_product_variant",
+ "product_id": room_type.product_id.id,
+ "fixed_price": record.price,
+ "min_quantity": record.min_quantity,
+ "pms_property_ids": [pms_property.id],
+ }
+ )
+ else:
+ avail_plan_id = record.availability_plan_id.id
+ self.env["pms.room.type.availability.rule"].create(
+ {
+ "availability_plan_id": avail_plan_id,
+ "date": date,
+ "room_type_id": room_type.id,
+ "quota": record.quota,
+ "max_avail": record.max_avail,
+ "min_stay": record.min_stay,
+ "min_stay_arrival": record.min_stay_arrival,
+ "max_stay": record.max_stay,
+ "max_stay_arrival": record.max_stay_arrival,
+ "closed": record.closed,
+ "closed_arrival": record.closed_arrival,
+ "closed_departure": record.closed_departure,
+ "pms_property_id": pms_property.id,
+ }
+ )
if (
record.massive_changes_on == "pricelist"
and not record.pricelist_readonly
diff --git a/pms/wizards/wizard_massive_changes.xml b/pms/wizards/wizard_massive_changes.xml
index 63ac046c8..4671dd5e9 100644
--- a/pms/wizards/wizard_massive_changes.xml
+++ b/pms/wizards/wizard_massive_changes.xml
@@ -26,6 +26,7 @@
+
+
-