mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[IMP] Constrain avail on reservation line
This commit is contained in:
@@ -234,6 +234,11 @@ class PmsReservation(models.Model):
|
|||||||
reservation_type = fields.Selection(
|
reservation_type = fields.Selection(
|
||||||
related="folio_id.reservation_type", default=lambda *a: "normal"
|
related="folio_id.reservation_type", default=lambda *a: "normal"
|
||||||
)
|
)
|
||||||
|
splitted = fields.Boolean(
|
||||||
|
"Splitted",
|
||||||
|
compute="_compute_splitted",
|
||||||
|
store=True,
|
||||||
|
)
|
||||||
invoice_count = fields.Integer(related="folio_id.invoice_count")
|
invoice_count = fields.Integer(related="folio_id.invoice_count")
|
||||||
credit_card_details = fields.Text(related="folio_id.credit_card_details")
|
credit_card_details = fields.Text(related="folio_id.credit_card_details")
|
||||||
cancelled_reason = fields.Selection(
|
cancelled_reason = fields.Selection(
|
||||||
@@ -284,8 +289,6 @@ class PmsReservation(models.Model):
|
|||||||
string="Include customer",
|
string="Include customer",
|
||||||
help="Indicates if the customer sleeps in this room",
|
help="Indicates if the customer sleeps in this room",
|
||||||
)
|
)
|
||||||
# check_rooms = fields.Boolean('Check Rooms')
|
|
||||||
splitted = fields.Boolean("Splitted", default=False)
|
|
||||||
overbooking = fields.Boolean("Is Overbooking", default=False)
|
overbooking = fields.Boolean("Is Overbooking", default=False)
|
||||||
reselling = fields.Boolean("Is Reselling", default=False)
|
reselling = fields.Boolean("Is Reselling", default=False)
|
||||||
nights = fields.Integer("Nights", compute="_computed_nights", store=True)
|
nights = fields.Integer("Nights", compute="_computed_nights", store=True)
|
||||||
@@ -448,7 +451,7 @@ class PmsReservation(models.Model):
|
|||||||
else:
|
else:
|
||||||
reservation.room_type_id = False
|
reservation.room_type_id = False
|
||||||
|
|
||||||
@api.depends("checkin", "checkout", "overbooking", "state", "room_id")
|
@api.depends("reservation_line_ids.date", "overbooking", "state", "room_id")
|
||||||
def _compute_allowed_room_ids(self):
|
def _compute_allowed_room_ids(self):
|
||||||
for reservation in self:
|
for reservation in self:
|
||||||
if reservation.checkin and reservation.checkout:
|
if reservation.checkin and reservation.checkout:
|
||||||
@@ -582,6 +585,14 @@ class PmsReservation(models.Model):
|
|||||||
for reservation in self:
|
for reservation in self:
|
||||||
reservation.last_updated_res = fields.Datetime.now()
|
reservation.last_updated_res = fields.Datetime.now()
|
||||||
|
|
||||||
|
@api.depends("reservation_line_ids", "reservation_line_ids.room_id")
|
||||||
|
def _compute_splitted(self):
|
||||||
|
for reservation in self:
|
||||||
|
if len(reservation.reservation_line_ids.mapped("room_id")) > 1:
|
||||||
|
reservation.splitted = True
|
||||||
|
else:
|
||||||
|
reservation.splitted = False
|
||||||
|
|
||||||
@api.depends("state", "qty_to_invoice", "qty_invoiced")
|
@api.depends("state", "qty_to_invoice", "qty_invoiced")
|
||||||
def _compute_invoice_status(self):
|
def _compute_invoice_status(self):
|
||||||
"""
|
"""
|
||||||
@@ -648,11 +659,10 @@ class PmsReservation(models.Model):
|
|||||||
)
|
)
|
||||||
line.qty_invoiced = qty_invoiced
|
line.qty_invoiced = qty_invoiced
|
||||||
|
|
||||||
@api.depends("checkin", "checkout")
|
@api.depends("reservation_line_ids")
|
||||||
def _computed_nights(self):
|
def _computed_nights(self):
|
||||||
for res in self:
|
for res in self:
|
||||||
if res.checkin and res.checkout:
|
res.nights = len(res.reservation_line_ids)
|
||||||
res.nights = (res.checkout - res.checkin).days
|
|
||||||
|
|
||||||
@api.depends("folio_id", "checkin", "checkout")
|
@api.depends("folio_id", "checkin", "checkout")
|
||||||
def _compute_localizator(self):
|
def _compute_localizator(self):
|
||||||
@@ -728,7 +738,7 @@ class PmsReservation(models.Model):
|
|||||||
|
|
||||||
# TODO: Use default values on checkin /checkout is empty
|
# TODO: Use default values on checkin /checkout is empty
|
||||||
@api.constrains(
|
@api.constrains(
|
||||||
"checkin", "checkout", "state", "room_id", "overbooking", "reselling"
|
"reservation_line_ids.date", "state", "room_id", "overbooking", "reselling"
|
||||||
)
|
)
|
||||||
def check_dates(self):
|
def check_dates(self):
|
||||||
"""
|
"""
|
||||||
@@ -746,31 +756,6 @@ class PmsReservation(models.Model):
|
|||||||
less than the Check Out Date!"
|
less than the Check Out Date!"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (
|
|
||||||
not self.overbooking
|
|
||||||
and self.state not in ("cancelled")
|
|
||||||
and not self._context.get("ignore_avail_restrictions", False)
|
|
||||||
):
|
|
||||||
occupied = self.env["pms.reservation"].get_reservations(
|
|
||||||
self.checkin,
|
|
||||||
(fields.Date.from_string(self.checkout) - timedelta(days=1)).strftime(
|
|
||||||
DEFAULT_SERVER_DATE_FORMAT
|
|
||||||
),
|
|
||||||
)
|
|
||||||
occupied = occupied.filtered(
|
|
||||||
lambda r: r.room_id.id == self.room_id.id and r.id != self.id
|
|
||||||
)
|
|
||||||
occupied_name = ", ".join(str(x.folio_id.name) for x in occupied)
|
|
||||||
if occupied:
|
|
||||||
warning_msg = (
|
|
||||||
_(
|
|
||||||
"You tried to change/confirm \
|
|
||||||
reservation with room those already reserved in this \
|
|
||||||
reservation period: %s "
|
|
||||||
)
|
|
||||||
% occupied_name
|
|
||||||
)
|
|
||||||
raise ValidationError(warning_msg)
|
|
||||||
|
|
||||||
@api.constrains("checkin_partner_ids")
|
@api.constrains("checkin_partner_ids")
|
||||||
def _max_checkin_partner_ids(self):
|
def _max_checkin_partner_ids(self):
|
||||||
@@ -933,6 +918,9 @@ class PmsReservation(models.Model):
|
|||||||
)
|
)
|
||||||
if rooms_available:
|
if rooms_available:
|
||||||
room_chosen = rooms_available[0]
|
room_chosen = rooms_available[0]
|
||||||
|
else:
|
||||||
|
#We can split reserve night on multi rooms
|
||||||
|
room_chosen = False
|
||||||
return room_chosen
|
return room_chosen
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ class PmsReservationLine(models.Model):
|
|||||||
compute="_compute_room_id",
|
compute="_compute_room_id",
|
||||||
store=True,
|
store=True,
|
||||||
readonly=False,
|
readonly=False,
|
||||||
domain="[('id', 'in', reservation_id.allowed_room_ids)]",
|
|
||||||
)
|
)
|
||||||
move_line_ids = fields.Many2many(
|
move_line_ids = fields.Many2many(
|
||||||
"account.move.line",
|
"account.move.line",
|
||||||
@@ -78,6 +77,14 @@ class PmsReservationLine(models.Model):
|
|||||||
store=True,
|
store=True,
|
||||||
help="This record is taken into account to calculate availability")
|
help="This record is taken into account to calculate availability")
|
||||||
|
|
||||||
|
_sql_constraints = [
|
||||||
|
(
|
||||||
|
"rule_availability",
|
||||||
|
"EXCLUDE (room_id WITH =, date WITH =) WHERE (occupies_availability = True)",
|
||||||
|
"Room Occupied"
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
# Compute and Search methods
|
# Compute and Search methods
|
||||||
@api.depends(
|
@api.depends(
|
||||||
"reservation_id.adults",
|
"reservation_id.adults",
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ class PmsRoomTypeAvailability(models.Model):
|
|||||||
return self.room_type_id.default_quota
|
return self.room_type_id.default_quota
|
||||||
|
|
||||||
# Fields declaration
|
# Fields declaration
|
||||||
room_type_id = fields.Many2one('hotel.room.type', 'Room Type',
|
room_type_id = fields.Many2one('pms.room.type', 'Room Type',
|
||||||
required=True,
|
required=True,
|
||||||
ondelete='cascade')
|
ondelete='cascade')
|
||||||
date = fields.Date('Date', required=True, track_visibility='always')
|
date = fields.Date('Date', required=True, track_visibility='always')
|
||||||
@@ -66,6 +66,25 @@ class PmsRoomTypeAvailability(models.Model):
|
|||||||
free_rooms = free_rooms & rooms_linked
|
free_rooms = free_rooms & rooms_linked
|
||||||
return free_rooms.sorted(key=lambda r: r.sequence)
|
return free_rooms.sorted(key=lambda r: r.sequence)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def room_types_available(self, checkin, checkout, room_type_id=False, current_lines=False):
|
||||||
|
domain = self._get_domain_reservations_occupation(
|
||||||
|
dfrom=checkin,
|
||||||
|
dto=checkout - timedelta(1),
|
||||||
|
current_lines=current_lines,
|
||||||
|
)
|
||||||
|
reservation_lines = self.env['pms.reservation.line'].search(domain)
|
||||||
|
reservations_rooms = reservation_lines.mapped("room_id.id")
|
||||||
|
free_rooms = self.env["pms.room"].search(
|
||||||
|
[("id", "not in", reservations_rooms)]
|
||||||
|
)
|
||||||
|
if room_type_id:
|
||||||
|
rooms_linked = (
|
||||||
|
self.env["pms.room.type"].search([("id", "=", room_type_id)]).room_ids
|
||||||
|
)
|
||||||
|
free_rooms = free_rooms & rooms_linked
|
||||||
|
return free_rooms.sorted(key=lambda r: r.sequence)
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def _get_domain_reservations_occupation(self, dfrom, dto, current_lines=False):
|
def _get_domain_reservations_occupation(self, dfrom, dto, current_lines=False):
|
||||||
domain = [
|
domain = [
|
||||||
|
|||||||
@@ -496,19 +496,35 @@
|
|||||||
</group>
|
</group>
|
||||||
<notebook>
|
<notebook>
|
||||||
<page
|
<page
|
||||||
name="services"
|
name="detail"
|
||||||
string="Services"
|
string="Detail"
|
||||||
attrs="{'invisible': ['|',('reservation_type','in',('out')),
|
|
||||||
('parent_reservation','!=',False)]}"
|
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
name="%(action_service_on_day)d"
|
name="%(action_pms_massive_price_change_reservation_days)d"
|
||||||
string="Service on Day"
|
string="Massive Day Prices"
|
||||||
type="action"
|
type="action"
|
||||||
icon="fa-coffee"
|
icon="fa-bolt"
|
||||||
/>
|
/>
|
||||||
|
<field name="reservation_line_ids" nolabel="1">
|
||||||
|
<tree create="false" delete="false" editable="bottom">
|
||||||
|
<field name="room_id" />
|
||||||
|
<field name="date" readonly="1" force_save="1" />
|
||||||
|
<field name="price" />
|
||||||
|
<field name="discount" />
|
||||||
|
<field
|
||||||
|
name="cancel_discount"
|
||||||
|
attrs="{'column_invisible': [('parent.state','!=','cancelled')]}"
|
||||||
|
/>
|
||||||
|
</tree>
|
||||||
|
</field>
|
||||||
|
<button
|
||||||
|
name="%(action_service_on_day)d"
|
||||||
|
string="Service on Day"
|
||||||
|
type="action"
|
||||||
|
icon="fa-coffee"
|
||||||
|
/>
|
||||||
<group
|
<group
|
||||||
string="Reservation Services"
|
string="Services"
|
||||||
name="reservation_services"
|
name="reservation_services"
|
||||||
>
|
>
|
||||||
<field
|
<field
|
||||||
@@ -577,30 +593,6 @@
|
|||||||
</field>
|
</field>
|
||||||
</group>
|
</group>
|
||||||
</page>
|
</page>
|
||||||
<page
|
|
||||||
name="days"
|
|
||||||
string="Day Pricing"
|
|
||||||
attrs="{'invisible': [('reservation_type','in',('out'))]}"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
name="%(action_pms_massive_price_change_reservation_days)d"
|
|
||||||
string="Massive Day Prices"
|
|
||||||
type="action"
|
|
||||||
icon="fa-bolt"
|
|
||||||
/>
|
|
||||||
<field name="reservation_line_ids" nolabel="1">
|
|
||||||
<tree create="false" delete="false" editable="bottom">
|
|
||||||
<field name="id" />
|
|
||||||
<field name="date" readonly="1" force_save="1" />
|
|
||||||
<field name="price" />
|
|
||||||
<field name="discount" />
|
|
||||||
<field
|
|
||||||
name="cancel_discount"
|
|
||||||
attrs="{'column_invisible': [('parent.state','!=','cancelled')]}"
|
|
||||||
/>
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</page>
|
|
||||||
<page
|
<page
|
||||||
name="persons"
|
name="persons"
|
||||||
string="Persons"
|
string="Persons"
|
||||||
|
|||||||
Reference in New Issue
Block a user