[RFC] Availability and free rooms

This commit is contained in:
Dario Lodeiros
2021-07-06 20:04:53 +02:00
parent 17b7921787
commit ff41cad50c
10 changed files with 314 additions and 260 deletions

View File

@@ -1,10 +1,7 @@
# Copyright 2017 Alexandre Díaz
# 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
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from odoo import api, fields, models
class PmsAvailabilityPlan(models.Model):
@@ -72,204 +69,6 @@ class PmsAvailabilityPlan(models.Model):
]
)
@api.model
def rooms_available(
self,
checkin,
checkout,
room_type_id=False,
current_lines=False,
pricelist_id=False,
pms_property_id=False,
):
if current_lines and not isinstance(current_lines, list):
current_lines = [current_lines]
free_rooms = self.get_real_free_rooms(
checkin, checkout, room_type_id, current_lines, pms_property_id
)
domain_rules = [
("date", ">=", checkin),
(
"date",
"<=",
checkout,
), # TODO: only closed_departure take account checkout date!
]
if pms_property_id:
domain_rules.append(("pms_property_id", "=", pms_property_id))
if 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.availability.plan.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
)
elif not pricelist:
raise ValidationError(_("Pricelist not found"))
return free_rooms.sorted(key=lambda r: r.sequence)
def get_real_free_rooms(
self,
checkin,
checkout,
room_type_id=False,
current_lines=False,
pms_property_id=False,
):
Avail = self.env["pms.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)),
]
if not current_lines:
current_lines = []
rooms_not_avail = (
Avail.search(domain)
.reservation_line_ids.filtered(
lambda l: l.occupies_availability and l.id and l.id not in current_lines
)
.room_id.ids
)
domain_rooms = []
if rooms_not_avail:
domain_rooms = [
("id", "not in", rooms_not_avail),
]
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),
]
pricelist = False
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.availability.plan.rule"].search(domain_rules)
if len(rule_items) > 0:
for item in rule_items:
if self.any_rule_applies(checkin, checkout, item):
return 0
avail = min(rule_items.mapped("plan_avail"))
return avail
def get_count_real_free_rooms(
self,
checkin,
checkout,
room_type_id,
pms_property_id,
current_lines=False,
):
Avail = self.env["pms.availability"]
count_free_rooms = len(
self.env["pms.room.type"]
.browse(room_type_id)
.room_ids.filtered(lambda r: r.pms_property_id.id == pms_property_id)
)
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(
self,
checkin,
checkout,
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)
]:
rooms_avail = self.rooms_available(
checkin=date_iterator,
checkout=date_iterator + datetime.timedelta(1),
room_type_id=room_type_id,
current_lines=current_lines,
pricelist_id=pricelist.id,
pms_property_id=pms_property_id,
)
if len(rooms_avail) < 1:
return False
return True
@api.model
def update_quota(self, pricelist_id, room_type_id, date, line):
if pricelist_id and room_type_id and date: