mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
373 lines
14 KiB
Python
373 lines
14 KiB
Python
import datetime
|
|
|
|
from odoo import _, api, fields, models
|
|
from odoo.exceptions import UserError
|
|
|
|
|
|
class ReservationSplitJoinSwapWizard(models.TransientModel):
|
|
_name = "pms.reservation.split.join.swap.wizard"
|
|
_description = "Operations in reservations"
|
|
|
|
operation = fields.Selection(
|
|
string="Operation",
|
|
help="Operation to be applied on the reservation",
|
|
selection=[
|
|
("swap", "Swap rooms"),
|
|
("split", "Split reservation"),
|
|
("join", "Join reservation"),
|
|
],
|
|
default=lambda self: self._context.get("default_operation")
|
|
if self._context.get("default_operation")
|
|
else "swap",
|
|
)
|
|
reservation_id = fields.Many2one(
|
|
string="Reservation",
|
|
default=lambda self: self.env["pms.reservation"]
|
|
.browse(self._context.get("active_id"))
|
|
.id
|
|
if self._context.get("active_id")
|
|
else False,
|
|
comodel_name="pms.reservation",
|
|
)
|
|
checkin = fields.Date(
|
|
string="Check In",
|
|
help="Checkin in reservation",
|
|
default=lambda self: self.env["pms.reservation"]
|
|
.browse(self._context.get("active_id"))
|
|
.checkin
|
|
if self._context.get("active_id")
|
|
else False,
|
|
)
|
|
checkout = fields.Date(
|
|
string="Check Out",
|
|
help="checkout in reservation",
|
|
default=lambda self: self.env["pms.reservation"]
|
|
.browse(self._context.get("active_id"))
|
|
.checkout
|
|
if self._context.get("active_id")
|
|
else False,
|
|
)
|
|
reservation_ids = fields.Many2many(
|
|
string="Reservations",
|
|
readonly=False,
|
|
store=True,
|
|
comodel_name="pms.reservation",
|
|
compute="_compute_reservation_ids",
|
|
)
|
|
room_source = fields.Many2one(
|
|
string="Room Source",
|
|
default=lambda self: self.env["pms.reservation"]
|
|
.browse(self._context.get("active_id"))
|
|
.preferred_room_id
|
|
if self._context.get("active_id")
|
|
and not self.env["pms.reservation"]
|
|
.browse(self._context.get("active_id"))
|
|
.splitted
|
|
else False,
|
|
comodel_name="pms.room",
|
|
domain="[('id', 'in', allowed_rooms_sources)]",
|
|
)
|
|
room_target = fields.Many2one(
|
|
string="Room Target",
|
|
comodel_name="pms.room",
|
|
domain="[('id', 'in', allowed_rooms_target)]",
|
|
)
|
|
allowed_rooms_sources = fields.Many2many(
|
|
string="Allowed rooms source",
|
|
store=True,
|
|
readonly=False,
|
|
comodel_name="pms.room",
|
|
relation="pms_wizard_split_join_swap_reservation_rooms_source",
|
|
column1="wizard_id",
|
|
column2="room_id",
|
|
compute="_compute_allowed_rooms_source",
|
|
)
|
|
allowed_rooms_target = fields.Many2many(
|
|
string="Allowed rooms target",
|
|
comodel_name="pms.room",
|
|
store=True,
|
|
readonly=False,
|
|
relation="pms_wizard_split_join_swap_reservation_rooms_target",
|
|
column1="wizard_id",
|
|
column2="room_id",
|
|
compute="_compute_allowed_rooms_target",
|
|
)
|
|
reservation_lines_to_change = fields.One2many(
|
|
string="Reservations Lines To Change",
|
|
comodel_name="pms.wizard.reservation.lines.split",
|
|
inverse_name="reservation_wizard_id",
|
|
compute="_compute_reservation_lines",
|
|
store=True,
|
|
readonly=False,
|
|
)
|
|
|
|
@api.depends("checkin", "checkout", "room_source", "room_target")
|
|
def _compute_reservation_ids(self):
|
|
for record in self:
|
|
if record.checkin and record.checkout:
|
|
reservation_ids = list()
|
|
for date_iterator in [
|
|
record.checkin + datetime.timedelta(days=x)
|
|
for x in range(0, (record.checkout - record.checkin).days)
|
|
]:
|
|
domain_lines = []
|
|
if record.room_source and record.room_target:
|
|
domain_lines.extend(
|
|
[
|
|
"|",
|
|
("room_id", "=", record.room_source.id),
|
|
("room_id", "=", record.room_target.id),
|
|
]
|
|
)
|
|
|
|
domain_lines.append(("date", "=", date_iterator))
|
|
lines = self.env["pms.reservation.line"].search(domain_lines)
|
|
reservation_ids.extend(lines.mapped("reservation_id.id"))
|
|
reservations = (
|
|
self.env["pms.reservation"]
|
|
.search(
|
|
[
|
|
("id", "in", reservation_ids),
|
|
("rooms", "!=", False),
|
|
]
|
|
)
|
|
.sorted("rooms")
|
|
)
|
|
record.reservation_ids = reservations
|
|
else:
|
|
record.reservation_ids = False
|
|
|
|
@api.depends("reservation_id")
|
|
def _compute_reservation_lines(self):
|
|
for record in self:
|
|
if record.reservation_id:
|
|
cmds = [(5, 0, 0)]
|
|
for line in record.reservation_id.reservation_line_ids:
|
|
cmds.append(
|
|
(
|
|
0,
|
|
0,
|
|
{
|
|
"reservation_wizard_id": record.id,
|
|
"room_id": line.room_id,
|
|
"date": line.date,
|
|
},
|
|
)
|
|
)
|
|
record.reservation_lines_to_change = cmds
|
|
else:
|
|
record.reservation_lines_to_change = False
|
|
|
|
@api.depends("checkin", "checkout")
|
|
def _compute_allowed_rooms_source(self):
|
|
for record in self:
|
|
record.allowed_rooms_sources = (
|
|
record.reservation_ids.reservation_line_ids.mapped("room_id")
|
|
)
|
|
|
|
@api.depends_context("default_operation")
|
|
@api.depends("checkin", "checkout", "room_source", "operation")
|
|
def _compute_allowed_rooms_target(self):
|
|
for record in self:
|
|
record.allowed_rooms_target = False
|
|
record.room_target = False
|
|
if record.checkin and record.checkout:
|
|
pms_property = record.reservation_id.pms_property_id
|
|
pms_property = pms_property.with_context(
|
|
checkin=record.checkin,
|
|
checkout=record.checkout,
|
|
room_type_id=False, # Allows to choose any available room
|
|
current_lines=record.reservation_id.reservation_line_ids.ids,
|
|
pricelist_id=record.reservation_id.pricelist_id.id,
|
|
real_avail=True,
|
|
)
|
|
rooms_available = pms_property.free_room_ids
|
|
|
|
domain = [("capacity", ">=", record.reservation_id.adults)]
|
|
if record.room_source:
|
|
domain.append(("id", "!=", record.room_source.id))
|
|
|
|
if record.operation == "swap":
|
|
domain.append(
|
|
(
|
|
"id",
|
|
"in",
|
|
record.reservation_ids.reservation_line_ids.mapped(
|
|
"room_id"
|
|
).ids,
|
|
)
|
|
)
|
|
else:
|
|
domain.extend(
|
|
[
|
|
("id", "in", rooms_available.ids),
|
|
]
|
|
)
|
|
rooms = self.env["pms.room"].search(domain)
|
|
record.allowed_rooms_target = rooms
|
|
|
|
@api.model
|
|
def reservation_split(self, reservation, date, room):
|
|
if not reservation:
|
|
raise UserError(_("Invalid reservation"))
|
|
if not reservation or not reservation.reservation_line_ids.filtered(
|
|
lambda x: x.date == date
|
|
):
|
|
raise UserError(_("Invalid date for reservation line "))
|
|
|
|
if not self.browse(room.id):
|
|
raise UserError(_("The room does not exist"))
|
|
pms_property = reservation.pms_property_id.with_context(
|
|
checkin=date,
|
|
checkout=(
|
|
datetime.datetime(year=date.year, month=date.month, day=date.day)
|
|
+ datetime.timedelta(days=1)
|
|
).date(),
|
|
current_lines=reservation.reservation_line_ids.ids,
|
|
pricelist_id=reservation.pricelist_id.id,
|
|
real_avail=True,
|
|
class_id=reservation.room_type_id.class_id.id,
|
|
)
|
|
rooms_available = pms_property.free_room_ids
|
|
|
|
if room not in rooms_available:
|
|
raise UserError(_("The room is not available"))
|
|
|
|
reservation.reservation_line_ids.filtered(
|
|
lambda x: x.date == date
|
|
).room_id = room.id
|
|
|
|
@api.model
|
|
def reservation_join(self, reservation, room):
|
|
pms_property = reservation.pms_property_id
|
|
pms_property = pms_property.with_context(
|
|
checkin=reservation.checkin,
|
|
checkout=reservation.checkout,
|
|
current_lines=reservation.reservation_line_ids.ids,
|
|
pricelist_id=reservation.pricelist_id.id,
|
|
real_avail=True,
|
|
)
|
|
rooms_available = pms_property.free_room_ids
|
|
|
|
if room in rooms_available:
|
|
for line in (
|
|
self.env["pms.reservation"]
|
|
.search([("id", "=", reservation.id)])
|
|
.reservation_line_ids
|
|
):
|
|
line.room_id = room.id
|
|
else:
|
|
raise UserError(_("Room {} not available.".format(room.name)))
|
|
|
|
@api.model
|
|
def reservations_swap(self, checkin, checkout, source, target):
|
|
dates = [
|
|
checkin + datetime.timedelta(days=x)
|
|
for x in range(0, (checkout - checkin).days + 1)
|
|
]
|
|
lines = self.env["pms.reservation.line"].search_count(
|
|
[("room_id", "=", source), ("date", "in", dates)]
|
|
)
|
|
if not lines:
|
|
raise UserError(_("There's no reservations lines with provided room"))
|
|
|
|
for date_iterator in dates:
|
|
line_room_source = self.env["pms.reservation.line"].search(
|
|
[("date", "=", date_iterator), ("room_id", "=", source)]
|
|
)
|
|
line_room_target = self.env["pms.reservation.line"].search(
|
|
[("date", "=", date_iterator), ("room_id", "=", target)]
|
|
)
|
|
if line_room_source and line_room_target:
|
|
|
|
# this causes an unique error constraint
|
|
line_room_target.occupies_availability = False
|
|
line_room_source.occupies_availability = False
|
|
|
|
line_room_target.room_id = source
|
|
line_room_source.room_id = target
|
|
|
|
self.flush()
|
|
|
|
line_room_target._compute_occupies_availability()
|
|
line_room_source._compute_occupies_availability()
|
|
|
|
elif line_room_source:
|
|
line_room_source.room_id = target
|
|
elif line_room_target:
|
|
line_room_target.room_id = source
|
|
|
|
def action_split(self):
|
|
for record in self:
|
|
for line in record.reservation_lines_to_change:
|
|
self.reservation_split(
|
|
record.reservation_id,
|
|
line.date,
|
|
line.room_id,
|
|
)
|
|
|
|
def action_join(self):
|
|
for record in self:
|
|
self.reservation_join(record.reservation_id, record.room_target)
|
|
|
|
def action_swap(self):
|
|
self.reservations_swap(
|
|
self.checkin, self.checkout, self.room_source.id, self.room_target.id
|
|
)
|
|
|
|
|
|
class ReservationLinesToSplit(models.TransientModel):
|
|
_name = "pms.wizard.reservation.lines.split"
|
|
_description = "Lines available to split"
|
|
|
|
reservation_wizard_id = fields.Many2one(
|
|
string="Reservation Wizard",
|
|
comodel_name="pms.reservation.split.join.swap.wizard",
|
|
)
|
|
date = fields.Date(
|
|
string="Date",
|
|
)
|
|
room_id = fields.Many2one(
|
|
string="Room",
|
|
comodel_name="pms.room",
|
|
domain="[('id', 'in', allowed_room_ids)]",
|
|
)
|
|
allowed_room_ids = fields.Many2many(
|
|
string="Allowed Rooms",
|
|
help="It contains all available rooms for this line",
|
|
store=True,
|
|
comodel_name="pms.room",
|
|
compute="_compute_allowed_room_ids",
|
|
# readonly=False
|
|
)
|
|
|
|
@api.depends(
|
|
"date",
|
|
"room_id",
|
|
"reservation_wizard_id.reservation_id.pricelist_id",
|
|
)
|
|
def _compute_allowed_room_ids(self):
|
|
for line in self:
|
|
reservation = line.reservation_wizard_id.reservation_id
|
|
rooms_available = False
|
|
if line.date and reservation:
|
|
if reservation.overbooking or reservation.state in ("cancel"):
|
|
line.allowed_room_ids = self.env["pms.room"].search(
|
|
[("active", "=", True)]
|
|
)
|
|
return
|
|
pms_property = reservation.pms_property_id
|
|
pms_property = pms_property.with_context(
|
|
checkin=line.date,
|
|
checkout=line.date + datetime.timedelta(days=1),
|
|
room_type_id=False, # Allows to choose any available room
|
|
pricelist_id=reservation.pricelist_id.id,
|
|
real_avail=True,
|
|
class_id=reservation.room_type_id.class_id.id,
|
|
)
|
|
rooms_available = pms_property.free_room_ids
|
|
rooms_available += line.room_id
|
|
line.allowed_room_ids = rooms_available
|
|
else:
|
|
line.allowed_room_ids = False
|