mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
276 lines
9.9 KiB
Python
276 lines
9.9 KiB
Python
# 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
|
|
|
|
|
|
class PmsAvailability(models.Model):
|
|
_name = "pms.availability"
|
|
_description = "Room type availability per day"
|
|
_check_pms_properties_auto = True
|
|
|
|
room_type_id = fields.Many2one(
|
|
string="Room Type",
|
|
help="Room type for which availability is indicated",
|
|
readonly=True,
|
|
required=True,
|
|
comodel_name="pms.room.type",
|
|
ondelete="cascade",
|
|
check_pms_properties=True,
|
|
)
|
|
date = fields.Date(
|
|
string="Date",
|
|
help="Date for which availability applies",
|
|
readonly=True,
|
|
required=True,
|
|
)
|
|
pms_property_id = fields.Many2one(
|
|
string="Property",
|
|
help="Property to which the availability is directed",
|
|
readonly=True,
|
|
required=True,
|
|
comodel_name="pms.property",
|
|
ondelete="restrict",
|
|
check_pms_properties=True,
|
|
)
|
|
reservation_line_ids = fields.One2many(
|
|
string="Reservation Lines",
|
|
help="They are the lines of the reservation into a reservation,"
|
|
"they corresponds to the nights",
|
|
readonly=True,
|
|
comodel_name="pms.reservation.line",
|
|
inverse_name="avail_id",
|
|
check_pms_properties=True,
|
|
)
|
|
avail_rule_ids = fields.One2many(
|
|
string="Avail record rules",
|
|
comodel_name="pms.availability.plan.rule",
|
|
inverse_name="avail_id",
|
|
check_pms_properties=True,
|
|
)
|
|
real_avail = fields.Integer(
|
|
string="Real Avail",
|
|
help="",
|
|
store=True,
|
|
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 = [
|
|
(
|
|
"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",
|
|
"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"]
|
|
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")
|
|
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.child_avail_ids = 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,
|
|
):
|
|
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,
|
|
):
|
|
occupied_room_ids.append(room.id)
|
|
occupied_room_ids.extend(
|
|
RoomLines.search(
|
|
[
|
|
("date", ">=", checkin),
|
|
("date", "<=", checkout - datetime.timedelta(1)),
|
|
("room_id", "in", room_ids),
|
|
("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):
|
|
RoomLines = self.env["pms.reservation.line"]
|
|
if (
|
|
RoomLines.search_count(
|
|
[
|
|
("date", ">=", checkin),
|
|
("date", "<=", checkout - datetime.timedelta(1)),
|
|
("room_id", "=", room.id),
|
|
("occupies_availability", "=", True),
|
|
]
|
|
)
|
|
> 0
|
|
):
|
|
return True
|
|
if room.parent_id:
|
|
return self.get_occupied_parent_rooms(
|
|
room=room.parent_id, checkin=checkin, checkout=checkout
|
|
)
|
|
return False
|
|
|
|
@api.model
|
|
def get_occupied_child_rooms(self, rooms, checkin, checkout):
|
|
RoomLines = self.env["pms.reservation.line"]
|
|
mapped_properties = list(set(rooms.mapped("pms_property_id.id")))
|
|
if len(mapped_properties) > 1:
|
|
raise ValidationError(_("Rooms shared between different properties"))
|
|
|
|
if (
|
|
RoomLines.search_count(
|
|
[
|
|
("date", ">=", checkin),
|
|
("date", "<=", checkout - datetime.timedelta(1)),
|
|
("room_id", "in", rooms.ids),
|
|
("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",
|
|
"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")
|
|
)
|