mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
[REF] pms: rename availability plans to pms.room.type.availability & .rules
This commit is contained in:
committed by
Eric Antones
parent
6080db54be
commit
ebe851aa24
@@ -29,7 +29,7 @@ This module is an all-in-one property management system (PMS) focused on medium-
|
||||
for managing every aspect of your property's daily operations.
|
||||
|
||||
You can manage hotel properties with multi-hotel and multi-company support, including your rooms inventory,
|
||||
reservations, check-in, daily reports, board services, rate and restriction plans among other hotel functionalities.
|
||||
reservations, check-in, daily reports, board services, rate and availability plans among other hotel functionalities.
|
||||
|
||||
.. IMPORTANT::
|
||||
This is an alpha version, the data model and design can change at any time without warning.
|
||||
|
||||
@@ -52,8 +52,8 @@
|
||||
"views/account_move_views.xml",
|
||||
"views/res_users_views.xml",
|
||||
"views/pms_room_type_class_views.xml",
|
||||
"views/pms_room_type_restriction_views.xml",
|
||||
"views/pms_room_type_restriction_item_views.xml",
|
||||
"views/pms_room_type_availability_views.xml",
|
||||
"views/pms_room_type_availability_rule_views.xml",
|
||||
"views/pms_service_views.xml",
|
||||
"views/pms_service_line_views.xml",
|
||||
"views/pms_shared_room_views.xml",
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
<odoo>
|
||||
<data noupdate="1">
|
||||
<!-- Basic pms -->
|
||||
<record id="main_pms_room_type_restriction" model="pms.room.type.restriction">
|
||||
<field name="name">Restriction Plan</field>
|
||||
<record id="main_pms_room_type_availability" model="pms.room.type.availability">
|
||||
<field name="name">Availability Plan</field>
|
||||
</record>
|
||||
<record id="main_pms_property" model="pms.property">
|
||||
<field name="name">My Property</field>
|
||||
<field name="company_id" ref="base.main_company" />
|
||||
<field name="default_pricelist_id" ref="product.list0" />
|
||||
<field name="default_restriction_id" ref="main_pms_room_type_restriction" />
|
||||
<field
|
||||
name="default_availability_id"
|
||||
ref="main_pms_room_type_availability"
|
||||
/>
|
||||
<field name="street">Rua Street Demo, s/n</field>
|
||||
<field name="city">Commitsun city</field>
|
||||
<field name="country_id" ref="base.es" />
|
||||
|
||||
@@ -298,14 +298,17 @@
|
||||
</field>
|
||||
</record>
|
||||
<!-- Multi pms Demo -->
|
||||
<record id="demo_pms_room_type_restriction" model="pms.room.type.restriction">
|
||||
<field name="name">Restriction Plan Demo</field>
|
||||
<record id="demo_pms_room_type_availability" model="pms.room.type.availability">
|
||||
<field name="name">Availability Plan Demo</field>
|
||||
</record>
|
||||
<record id="demo_pms_property" model="pms.property">
|
||||
<field name="name">My pms Demo</field>
|
||||
<field name="company_id" ref="base.main_company" />
|
||||
<field name="default_pricelist_id" ref="product.list0" />
|
||||
<field name="default_restriction_id" ref="demo_pms_room_type_restriction" />
|
||||
<field
|
||||
name="default_availability_id"
|
||||
ref="demo_pms_room_type_availability"
|
||||
/>
|
||||
</record>
|
||||
<!-- pms.room.type -->
|
||||
<record id="demo_pms_room_type_0" model="pms.room.type">
|
||||
|
||||
@@ -24,8 +24,7 @@ from . import product_template
|
||||
from . import res_company
|
||||
from . import account_payment
|
||||
from . import pms_room_type_availability
|
||||
from . import pms_room_type_restriction
|
||||
from . import pms_room_type_restriction_item
|
||||
from . import pms_room_type_availability_rule
|
||||
from . import pms_reservation_line
|
||||
from . import pms_checkin_partner
|
||||
from . import product_pricelist
|
||||
|
||||
@@ -41,11 +41,11 @@ class PmsProperty(models.Model):
|
||||
required=True,
|
||||
help="The default pricelist used in this property.",
|
||||
)
|
||||
default_restriction_id = fields.Many2one(
|
||||
"pms.room.type.restriction",
|
||||
"Restriction Plan",
|
||||
default_availability_id = fields.Many2one(
|
||||
"pms.room.type.availability",
|
||||
"Availability Plan",
|
||||
required=True,
|
||||
help="The default restriction plan used in this property.",
|
||||
help="The default availability plan used in this property.",
|
||||
)
|
||||
default_arrival_hour = fields.Char(
|
||||
"Arrival Hour (GMT)", help="HH:mm Format", default="14:00"
|
||||
|
||||
@@ -521,7 +521,9 @@ class PmsReservation(models.Model):
|
||||
[("active", "=", True)]
|
||||
)
|
||||
return
|
||||
rooms_available = self.env["pms.room.type.restriction"].rooms_available(
|
||||
rooms_available = self.env[
|
||||
"pms.room.type.availability"
|
||||
].rooms_available(
|
||||
checkin=reservation.checkin,
|
||||
checkout=reservation.checkout,
|
||||
room_type_id=False, # Allow chosen any available room
|
||||
@@ -1101,7 +1103,7 @@ class PmsReservation(models.Model):
|
||||
}
|
||||
|
||||
def open_reservation_wizard(self):
|
||||
rooms_available = self.env["pms.room.type.restriction"].rooms_available(
|
||||
rooms_available = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=self.checkin,
|
||||
checkout=self.checkout,
|
||||
current_lines=self.reservation_line_ids.ids,
|
||||
@@ -1184,7 +1186,7 @@ class PmsReservation(models.Model):
|
||||
def _autoassign(self):
|
||||
self.ensure_one()
|
||||
room_chosen = False
|
||||
rooms_available = self.env["pms.room.type.restriction"].rooms_available(
|
||||
rooms_available = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=self.checkin,
|
||||
checkout=self.checkout,
|
||||
room_type_id=self.room_type_id.id or False,
|
||||
|
||||
@@ -108,7 +108,9 @@ class PmsReservationLine(models.Model):
|
||||
# select room_id regardless room_type_id selected on reservation
|
||||
free_room_select = True if reservation.preferred_room_id else False
|
||||
# we get the rooms available for the entire stay
|
||||
rooms_available = self.env["pms.room.type.restriction"].rooms_available(
|
||||
rooms_available = self.env[
|
||||
"pms.room.type.availability"
|
||||
].rooms_available(
|
||||
checkin=line.reservation_id.checkin,
|
||||
checkout=line.reservation_id.checkout,
|
||||
room_type_id=reservation.room_type_id.id
|
||||
@@ -139,7 +141,7 @@ class PmsReservationLine(models.Model):
|
||||
else:
|
||||
line.room_id = rooms_available[0]
|
||||
# check that the reservation cannot be allocated even by dividing it
|
||||
elif not self.env["pms.room.type.restriction"].splitted_availability(
|
||||
elif not self.env["pms.room.type.availability"].splitted_availability(
|
||||
checkin=line.reservation_id.checkin,
|
||||
checkout=line.reservation_id.checkout,
|
||||
room_type_id=line.reservation_id.room_type_id.id,
|
||||
@@ -233,7 +235,7 @@ class PmsReservationLine(models.Model):
|
||||
def _compute_impact_quota(self):
|
||||
for line in self:
|
||||
reservation = line.reservation_id
|
||||
line.impacts_quota = self.env["pms.room.type.restriction"].update_quota(
|
||||
line.impacts_quota = self.env["pms.room.type.availability"].update_quota(
|
||||
pricelist_id=reservation.pricelist_id,
|
||||
room_type_id=reservation.room_type_id,
|
||||
date=line.date,
|
||||
|
||||
@@ -1,92 +1,193 @@
|
||||
# Copyright 2017 Alexandre Díaz
|
||||
# Copyright 2017 Dario Lodeiros
|
||||
# Copyright 2018 Pablo Quesada
|
||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
||||
from datetime import timedelta
|
||||
import datetime
|
||||
|
||||
from odoo import api, fields, models
|
||||
|
||||
|
||||
class PmsRoomTypeAvailability(models.Model):
|
||||
"""The room type availability is used as a daily availability plan for room types
|
||||
and therefore is related only with one property."""
|
||||
|
||||
_name = "pms.room.type.availability"
|
||||
_description = "Availability"
|
||||
_inherit = "mail.thread"
|
||||
_description = "Reservation availability plan"
|
||||
|
||||
# Default methods
|
||||
@api.model
|
||||
def _default_max_avail(self):
|
||||
return self.room_type_id.default_max_avail
|
||||
|
||||
@api.model
|
||||
def _default_quota(self):
|
||||
return self.room_type_id.default_quota
|
||||
def _get_default_pms_property(self):
|
||||
return self.env.user.pms_property_id or None
|
||||
|
||||
# Fields declaration
|
||||
room_type_id = fields.Many2one(
|
||||
"pms.room.type", "Room Type", required=True, ondelete="cascade"
|
||||
)
|
||||
date = fields.Date(
|
||||
"Date",
|
||||
required=True,
|
||||
tracking=True,
|
||||
)
|
||||
quota = fields.Integer(
|
||||
"Quota",
|
||||
default=_default_quota,
|
||||
tracking=True,
|
||||
help="Generic Quota assigned.",
|
||||
)
|
||||
max_avail = fields.Integer(
|
||||
"Max. Availability",
|
||||
default=-1,
|
||||
readonly=True,
|
||||
tracking=True,
|
||||
help="Maximum simultaneous availability on own Booking Engine.",
|
||||
)
|
||||
no_web = fields.Boolean(
|
||||
"No Web",
|
||||
default=False,
|
||||
tracking=True,
|
||||
help="Set zero availability to the own Booking Engine "
|
||||
"even when the availability is positive,",
|
||||
name = fields.Char("Availability Plan Name", required=True)
|
||||
pms_property_id = fields.Many2one(
|
||||
comodel_name="pms.property",
|
||||
string="Property",
|
||||
ondelete="restrict",
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
(
|
||||
"unique_availability_room_type_rule_date",
|
||||
"unique(room_type_id, date)",
|
||||
"The availability rule for this date in this room type already exists, "
|
||||
"modify it instead of trying to create a new one",
|
||||
),
|
||||
]
|
||||
pms_pricelist_ids = fields.One2many(
|
||||
comodel_name="product.pricelist",
|
||||
inverse_name="availability_id",
|
||||
string="Pricelists",
|
||||
required=False,
|
||||
ondelete="restrict",
|
||||
)
|
||||
|
||||
item_ids = fields.One2many(
|
||||
comodel_name="pms.room.type.availability.rule",
|
||||
inverse_name="availability_id",
|
||||
string="Rule Items",
|
||||
copy=True,
|
||||
)
|
||||
|
||||
active = fields.Boolean(
|
||||
string="Active",
|
||||
default=True,
|
||||
help="If unchecked, it will allow you to hide the "
|
||||
"Availability plan without removing it.",
|
||||
)
|
||||
|
||||
# Business Methods
|
||||
@classmethod
|
||||
def any_rule_applies(cls, checkin, checkout, item):
|
||||
reservation_len = (checkout - checkin).days
|
||||
return any(
|
||||
[
|
||||
(0 < item.max_stay < reservation_len),
|
||||
(0 < item.min_stay > reservation_len),
|
||||
(0 < item.max_stay_arrival < reservation_len and checkin == item.date),
|
||||
(0 < item.min_stay_arrival > reservation_len and checkin == item.date),
|
||||
item.closed,
|
||||
(item.closed_arrival and checkin == item.date),
|
||||
(item.closed_departure and checkout == item.date),
|
||||
(item.quota == 0 or item.max_avail == 0),
|
||||
]
|
||||
)
|
||||
|
||||
@api.model
|
||||
def rooms_available(
|
||||
self, checkin, checkout, room_type_id=False, current_lines=False
|
||||
self,
|
||||
checkin,
|
||||
checkout,
|
||||
room_type_id=False,
|
||||
current_lines=False,
|
||||
pricelist=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
|
||||
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 []),
|
||||
]
|
||||
)
|
||||
free_rooms = free_rooms & rooms_linked
|
||||
.mapped("room_id.id")
|
||||
)
|
||||
|
||||
domain_rooms = [
|
||||
("id", "not in", rooms_not_avail if len(rooms_not_avail) > 0 else [])
|
||||
]
|
||||
domain_rules = [
|
||||
("date", ">=", checkin),
|
||||
("date", "<=", checkout),
|
||||
]
|
||||
|
||||
if room_type_id:
|
||||
domain_rooms.append(("room_type_id", "=", room_type_id))
|
||||
domain_rules.append(("room_type_id", "=", room_type_id))
|
||||
|
||||
free_rooms = self.env["pms.room"].search(domain_rooms)
|
||||
|
||||
if pricelist:
|
||||
domain_rules.append(("availability_id.pms_pricelist_ids", "=", pricelist))
|
||||
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 free_rooms.sorted(key=lambda r: r.sequence)
|
||||
|
||||
@api.model
|
||||
def _get_domain_reservations_occupation(self, dfrom, dto, current_lines=False):
|
||||
if current_lines and not isinstance(current_lines, list):
|
||||
current_lines = [current_lines]
|
||||
domain = [
|
||||
("date", ">=", dfrom),
|
||||
("date", "<=", dto),
|
||||
("occupies_availability", "=", True),
|
||||
("id", "not in", current_lines),
|
||||
]
|
||||
return domain
|
||||
def splitted_availability(
|
||||
self,
|
||||
checkin,
|
||||
checkout,
|
||||
room_type_id=False,
|
||||
current_lines=False,
|
||||
pricelist=False,
|
||||
):
|
||||
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=pricelist.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:
|
||||
rule = self.env["pms.room.type.availability.rule"].search(
|
||||
[
|
||||
("availability_id.pms_pricelist_ids", "=", pricelist_id.id),
|
||||
("room_type_id", "=", room_type_id.id),
|
||||
("date", "=", date),
|
||||
]
|
||||
)
|
||||
# applies a rule
|
||||
if rule:
|
||||
rule.ensure_one()
|
||||
if rule and rule.quota != -1 and rule.quota > 0:
|
||||
|
||||
# the line has no rule item applied before
|
||||
if not line.impacts_quota:
|
||||
rule.quota -= 1
|
||||
return rule.id
|
||||
|
||||
# the line has a rule item applied before
|
||||
elif line.impacts_quota != rule.id:
|
||||
|
||||
# decrement quota on current rule item
|
||||
rule.quota -= 1
|
||||
|
||||
# check old rule item
|
||||
old_rule = self.env["pms.room.type.availability.rule"].search(
|
||||
[("id", "=", line.impacts_quota)]
|
||||
)
|
||||
|
||||
# restore quota in old rule item
|
||||
if old_rule:
|
||||
old_rule.quota += 1
|
||||
|
||||
return rule.id
|
||||
|
||||
# in any case, check old rule item
|
||||
if line.impacts_quota:
|
||||
old_rule = self.env["pms.room.type.availability.rule"].search(
|
||||
[("id", "=", line.impacts_quota)]
|
||||
)
|
||||
# and restore quota in old rule item
|
||||
if old_rule:
|
||||
old_rule.quota += 1
|
||||
|
||||
return False
|
||||
|
||||
@@ -4,15 +4,15 @@ from odoo import _, api, fields, models
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class PmsRoomTypeRestrictionItem(models.Model):
|
||||
_name = "pms.room.type.restriction.item"
|
||||
_description = "Reservation restriction by day"
|
||||
class PmsRoomTypeAvailabilityRule(models.Model):
|
||||
_name = "pms.room.type.availability.rule"
|
||||
_description = "Reservation rule by day"
|
||||
|
||||
# Field Declarations
|
||||
|
||||
restriction_id = fields.Many2one(
|
||||
comodel_name="pms.room.type.restriction",
|
||||
string="Restriction Plan",
|
||||
availability_id = fields.Many2one(
|
||||
comodel_name="pms.room.type.availability",
|
||||
string="Availability Plan",
|
||||
ondelete="cascade",
|
||||
index=True,
|
||||
)
|
||||
@@ -71,8 +71,8 @@ class PmsRoomTypeRestrictionItem(models.Model):
|
||||
_sql_constraints = [
|
||||
(
|
||||
"room_type_registry_unique",
|
||||
"unique(restriction_id, room_type_id, date)",
|
||||
"Only can exists one restriction in the same \
|
||||
"unique(availability_id, room_type_id, date)",
|
||||
"Only can exists one availability rule in the same \
|
||||
day for the same room type!",
|
||||
)
|
||||
]
|
||||
@@ -1,195 +0,0 @@
|
||||
# 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
|
||||
|
||||
|
||||
class PmsRoomTypeRestriction(models.Model):
|
||||
"""The room type restriction is used as a daily restriction plan for room types
|
||||
and therefore is related only with one property."""
|
||||
|
||||
_name = "pms.room.type.restriction"
|
||||
_description = "Reservation restriction plan"
|
||||
|
||||
# Default methods
|
||||
@api.model
|
||||
def _get_default_pms_property(self):
|
||||
return self.env.user.pms_property_id or None
|
||||
|
||||
# Fields declaration
|
||||
name = fields.Char("Restriction Plan Name", required=True)
|
||||
pms_property_id = fields.Many2one(
|
||||
comodel_name="pms.property",
|
||||
string="Property",
|
||||
ondelete="restrict",
|
||||
)
|
||||
|
||||
pms_pricelist_ids = fields.One2many(
|
||||
comodel_name="product.pricelist",
|
||||
inverse_name="restriction_id",
|
||||
string="Pricelists",
|
||||
required=False,
|
||||
ondelete="restrict",
|
||||
)
|
||||
|
||||
item_ids = fields.One2many(
|
||||
comodel_name="pms.room.type.restriction.item",
|
||||
inverse_name="restriction_id",
|
||||
string="Restriction Items",
|
||||
copy=True,
|
||||
)
|
||||
|
||||
active = fields.Boolean(
|
||||
string="Active",
|
||||
default=True,
|
||||
help="If unchecked, it will allow you to hide the "
|
||||
"restriction plan without removing it.",
|
||||
)
|
||||
|
||||
# Business Methods
|
||||
@classmethod
|
||||
def any_restriction_applies(cls, checkin, checkout, item):
|
||||
reservation_len = (checkout - checkin).days
|
||||
return any(
|
||||
[
|
||||
(0 < item.max_stay < reservation_len),
|
||||
(0 < item.min_stay > reservation_len),
|
||||
(0 < item.max_stay_arrival < reservation_len and checkin == item.date),
|
||||
(0 < item.min_stay_arrival > reservation_len and checkin == item.date),
|
||||
item.closed,
|
||||
(item.closed_arrival and checkin == item.date),
|
||||
(item.closed_departure and checkout == item.date),
|
||||
(item.quota == 0 or item.max_avail == 0),
|
||||
]
|
||||
)
|
||||
|
||||
@api.model
|
||||
def rooms_available(
|
||||
self,
|
||||
checkin,
|
||||
checkout,
|
||||
room_type_id=False,
|
||||
current_lines=False,
|
||||
pricelist=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")
|
||||
)
|
||||
|
||||
domain_rooms = [
|
||||
("id", "not in", rooms_not_avail if len(rooms_not_avail) > 0 else [])
|
||||
]
|
||||
domain_restrictions = [
|
||||
("date", ">=", checkin),
|
||||
("date", "<=", checkout),
|
||||
]
|
||||
|
||||
if room_type_id:
|
||||
domain_rooms.append(("room_type_id", "=", room_type_id))
|
||||
domain_restrictions.append(("room_type_id", "=", room_type_id))
|
||||
|
||||
free_rooms = self.env["pms.room"].search(domain_rooms)
|
||||
|
||||
if pricelist:
|
||||
domain_restrictions.append(
|
||||
("restriction_id.pms_pricelist_ids", "=", pricelist)
|
||||
)
|
||||
restriction_items = self.env["pms.room.type.restriction.item"].search(
|
||||
domain_restrictions
|
||||
)
|
||||
|
||||
if len(restriction_items) > 0:
|
||||
room_types_to_remove = []
|
||||
for item in restriction_items:
|
||||
if self.any_restriction_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 free_rooms.sorted(key=lambda r: r.sequence)
|
||||
|
||||
@api.model
|
||||
def splitted_availability(
|
||||
self,
|
||||
checkin,
|
||||
checkout,
|
||||
room_type_id=False,
|
||||
current_lines=False,
|
||||
pricelist=False,
|
||||
):
|
||||
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=pricelist.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:
|
||||
restriction = self.env["pms.room.type.restriction.item"].search(
|
||||
[
|
||||
("restriction_id.pms_pricelist_ids", "=", pricelist_id.id),
|
||||
("room_type_id", "=", room_type_id.id),
|
||||
("date", "=", date),
|
||||
]
|
||||
)
|
||||
# applies a restriction
|
||||
if restriction:
|
||||
restriction.ensure_one()
|
||||
if restriction and restriction.quota != -1 and restriction.quota > 0:
|
||||
|
||||
# the line has no restriction item applied before
|
||||
if not line.impacts_quota:
|
||||
restriction.quota -= 1
|
||||
return restriction.id
|
||||
|
||||
# the line has a restriction item applied before
|
||||
elif line.impacts_quota != restriction.id:
|
||||
|
||||
# decrement quota on current restriction_item
|
||||
restriction.quota -= 1
|
||||
|
||||
# check old restricition item
|
||||
old_restriction = self.env[
|
||||
"pms.room.type.restriction.item"
|
||||
].search([("id", "=", line.impacts_quota)])
|
||||
|
||||
# restore quota in old restriction item
|
||||
if old_restriction:
|
||||
old_restriction.quota += 1
|
||||
|
||||
return restriction.id
|
||||
|
||||
# in any case, check old restricition item
|
||||
if line.impacts_quota:
|
||||
old_restriction = self.env["pms.room.type.restriction.item"].search(
|
||||
[("id", "=", line.impacts_quota)]
|
||||
)
|
||||
# and restore quota in old restriction item
|
||||
if old_restriction:
|
||||
old_restriction.quota += 1
|
||||
|
||||
return False
|
||||
@@ -22,9 +22,9 @@ class ProductPricelist(models.Model):
|
||||
[("daily", "Daily Plan")], string="Pricelist Type", default="daily"
|
||||
)
|
||||
|
||||
restriction_id = fields.Many2one(
|
||||
comodel_name="pms.room.type.restriction",
|
||||
string="restriction",
|
||||
availability_id = fields.Many2one(
|
||||
comodel_name="pms.room.type.availability",
|
||||
string="Availability Plan",
|
||||
ondelete="restrict",
|
||||
)
|
||||
|
||||
|
||||
@@ -2,4 +2,4 @@ This module is an all-in-one property management system (PMS) focused on medium-
|
||||
for managing every aspect of your property's daily operations.
|
||||
|
||||
You can manage hotel properties with multi-hotel and multi-company support, including your rooms inventory,
|
||||
reservations, check-in, daily reports, board services, rate and restriction plans among other hotel functionalities.
|
||||
reservations, check-in, daily reports, board services, rate and availability plans among other hotel functionalities.
|
||||
|
||||
@@ -3,7 +3,6 @@ user_access_pms_floor,user_access_pms_floor,model_pms_floor,pms.group_pms_user,1
|
||||
user_access_pms_amenity,user_access_pms_amenity,model_pms_amenity,pms.group_pms_user,1,0,0,0
|
||||
user_access_pms_amenity_type,user_access_pms_amenity_type,model_pms_amenity_type,pms.group_pms_user,1,0,0,0
|
||||
user_access_pms_service,user_access_pms_service,model_pms_service,pms.group_pms_user,1,1,1,1
|
||||
user_access_pms_room_type_restriction,user_access_pms_room_type_restriction,model_pms_room_type_restriction,pms.group_pms_user,1,0,0,0
|
||||
user_access_pms_reservation_line,user_access_pms_reservation_line,model_pms_reservation_line,pms.group_pms_user,1,1,1,1
|
||||
user_access_room_closure_reason,user_access_room_closure_reason,model_room_closure_reason,pms.group_pms_user,1,0,0,0
|
||||
user_access_pms_service_line,user_access_pms_service_line,model_pms_service_line,pms.group_pms_user,1,1,1,1
|
||||
@@ -12,7 +11,7 @@ user_access_pms_checkin_partner,user_access_pms_checkin_partner,model_pms_checki
|
||||
user_access_pms_room_type_class,user_access_pms_room_type_class,model_pms_room_type_class,pms.group_pms_user,1,0,0,0
|
||||
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_restriction_item,user_access_pms_room_type_restriction_item,model_pms_room_type_restriction_item,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_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
|
||||
@@ -29,7 +28,6 @@ manager_access_pms_floor,manager_access_pms_floor,model_pms_floor,pms.group_pms_
|
||||
manager_access_pms_amenity,manager_access_pms_amenity,model_pms_amenity,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_pms_amenity_type,manager_access_pms_amenity_type,model_pms_amenity_type,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_pms_service,manager_access_pms_service,model_pms_service,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_pms_room_type_restriction,manager_access_pms_room_type_restriction,model_pms_room_type_restriction,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_pms_reservation_line,manager_access_pms_reservation_line,model_pms_reservation_line,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_room_closure_reason,manager_access_room_closure_reason,model_room_closure_reason,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_pms_service_line,manager_access_pms_service_line,model_pms_service_line,pms.group_pms_manager,1,1,1,1
|
||||
@@ -38,7 +36,7 @@ manager_access_pms_checkin_partner,manager_access_pms_checkin_partner,model_pms_
|
||||
manager_access_pms_room_type_class,manager_access_pms_room_type_class,model_pms_room_type_class,pms.group_pms_manager,1,1,1,1
|
||||
manager_access_pms_room,manager_access_pms_room,model_pms_room,pms.group_pms_manager,1,1,1,1
|
||||
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_restriction_item,manager_access_pms_room_type_restriction_item,model_pms_room_type_restriction_item,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_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
|
||||
|
||||
|
@@ -371,7 +371,7 @@ ul.auto-toc {
|
||||
<p>This module is an all-in-one property management system (PMS) focused on medium-sized hotels
|
||||
for managing every aspect of your property’s daily operations.</p>
|
||||
<p>You can manage hotel properties with multi-hotel and multi-company support, including your rooms inventory,
|
||||
reservations, check-in, daily reports, board services, rate and restriction plans among other hotel functionalities.</p>
|
||||
reservations, check-in, daily reports, board services, rate and availability plans among other hotel functionalities.</p>
|
||||
<div class="admonition important">
|
||||
<p class="first admonition-title">Important</p>
|
||||
<p class="last">This is an alpha version, the data model and design can change at any time without warning.
|
||||
|
||||
@@ -25,4 +25,4 @@ from . import test_pms_pricelist_priority
|
||||
from . import test_pms_checkin_partner
|
||||
from . import test_pms_sale_channel
|
||||
from . import test_pms_folio
|
||||
from . import test_pms_room_type_restriction
|
||||
from . import test_pms_room_type_availability_rules
|
||||
|
||||
@@ -15,19 +15,19 @@ class TestPmsPricelistRules(common.TransactionCase):
|
||||
{"name": "Category1"}
|
||||
)
|
||||
|
||||
self.restriction = self.env["pms.room.type.restriction"].create(
|
||||
{"name": "Restriction1"}
|
||||
self.availability = self.env["pms.room.type.availability"].create(
|
||||
{"name": "Availability 1"}
|
||||
)
|
||||
|
||||
self.restriction2 = self.env["pms.room.type.restriction"].create(
|
||||
{"name": "Restriction2"}
|
||||
self.availability2 = self.env["pms.room.type.availability"].create(
|
||||
{"name": "Availability"}
|
||||
)
|
||||
self.property1 = self.env["pms.property"].create(
|
||||
{
|
||||
"name": "Property_1",
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
"default_pricelist_id": self.env.ref("product.list0").id,
|
||||
"default_restriction_id": self.restriction.id,
|
||||
"default_availability_id": self.availability.id,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ class TestPmsPricelistRules(common.TransactionCase):
|
||||
"name": "Property_2",
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
"default_pricelist_id": self.env.ref("product.list0").id,
|
||||
"default_restriction_id": self.restriction2.id,
|
||||
"default_availability_id": self.availability2.id,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ from .common import TestHotel
|
||||
@freeze_time("2012-01-14")
|
||||
class TestPmsReservations(TestHotel):
|
||||
def create_common_scenario(self):
|
||||
# create a room type restriction
|
||||
self.room_type_restriction = self.env["pms.room.type.restriction"].create(
|
||||
{"name": "Restriction plan for TEST"}
|
||||
# create a room type availability
|
||||
self.room_type_availability = self.env["pms.room.type.availability"].create(
|
||||
{"name": "Availability plan for TEST"}
|
||||
)
|
||||
|
||||
# create a property
|
||||
@@ -22,7 +22,7 @@ class TestPmsReservations(TestHotel):
|
||||
"name": "MY PMS TEST",
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
"default_pricelist_id": self.env.ref("product.list0").id,
|
||||
"default_restriction_id": self.room_type_restriction.id,
|
||||
"default_availability_id": self.room_type_availability.id,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from .common import TestHotel
|
||||
|
||||
|
||||
@freeze_time("1980-01-01")
|
||||
class TestPmsRoomTypeRestriction(TestHotel):
|
||||
class TestPmsRoomTypeAvailabilityRules(TestHotel):
|
||||
def create_common_scenario(self):
|
||||
# product.pricelist
|
||||
self.test_pricelist1 = self.env["product.pricelist"].create(
|
||||
@@ -18,10 +18,12 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
"name": "test pricelist 1",
|
||||
}
|
||||
)
|
||||
# pms.room.type.restriction
|
||||
self.test_room_type_restriction1 = self.env["pms.room.type.restriction"].create(
|
||||
# pms.room.type.availability
|
||||
self.test_room_type_availability1 = self.env[
|
||||
"pms.room.type.availability"
|
||||
].create(
|
||||
{
|
||||
"name": "Restriction plan for TEST",
|
||||
"name": "Availability plan for TEST",
|
||||
"pms_pricelist_ids": [(6, 0, [self.test_pricelist1.id])],
|
||||
}
|
||||
)
|
||||
@@ -31,7 +33,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
"name": "MY PMS TEST",
|
||||
"company_id": self.env.ref("base.main_company").id,
|
||||
"default_pricelist_id": self.test_pricelist1.id,
|
||||
"default_restriction_id": self.test_room_type_restriction1.id,
|
||||
"default_availability_id": self.test_room_type_availability1.id,
|
||||
}
|
||||
)
|
||||
# pms.room.type.class
|
||||
@@ -115,7 +117,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
@Skip
|
||||
def test_availability_rooms_all(self):
|
||||
# TEST CASE
|
||||
# get availability withouth restrictions
|
||||
# get availability withouth rules
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
@@ -127,7 +129,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
)
|
||||
|
||||
# ACT
|
||||
result = self.env["pms.room.type.restriction"].rooms_available(
|
||||
result = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=checkin,
|
||||
checkout=checkout,
|
||||
)
|
||||
@@ -136,13 +138,13 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
self.assertTrue(
|
||||
obtained,
|
||||
"Availability should contain the test rooms"
|
||||
"because there's no restriction for them.",
|
||||
"because there's no availability rules for them.",
|
||||
)
|
||||
|
||||
@Skip
|
||||
def test_availability_rooms_all_lines(self):
|
||||
# TEST CASE
|
||||
# get availability withouth restrictions
|
||||
# get availability withouth rules
|
||||
# given reservation lines to not consider
|
||||
|
||||
# ARRANGE
|
||||
@@ -161,7 +163,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
)
|
||||
|
||||
# ACT
|
||||
result = self.env["pms.room.type.restriction"].rooms_available(
|
||||
result = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=checkin,
|
||||
checkout=checkout,
|
||||
current_lines=test_reservation.reservation_line_ids.ids,
|
||||
@@ -171,13 +173,13 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
self.assertTrue(
|
||||
obtained,
|
||||
"Availability should contain the test rooms"
|
||||
"because there's no restriction for them.",
|
||||
"because there's no availability rules for them.",
|
||||
)
|
||||
|
||||
@Skip
|
||||
def test_availability_rooms_room_type(self):
|
||||
# TEST CASE
|
||||
# get availability withouth restrictions
|
||||
# get availability withouth rules
|
||||
# given a room type
|
||||
|
||||
# ARRANGE
|
||||
@@ -190,7 +192,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
)
|
||||
|
||||
# ACT
|
||||
result = self.env["pms.room.type.restriction"].rooms_available(
|
||||
result = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=fields.date.today(),
|
||||
checkout=(fields.datetime.today() + datetime.timedelta(days=4)).date(),
|
||||
room_type_id=self.test_room_type_double.id,
|
||||
@@ -201,30 +203,31 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
self.assertTrue(
|
||||
obtained,
|
||||
"Availability should contain the test rooms"
|
||||
"because there's no restriction for them.",
|
||||
"because there's no availability rules for them.",
|
||||
)
|
||||
|
||||
@Skip
|
||||
def test_availability_closed_no_room_type(self):
|
||||
# TEST CASE:
|
||||
# coverage for 2 points:
|
||||
# 1. without room type, restrictions associated with the pricelist are applied
|
||||
# 2. restriction rule "closed" is taken into account
|
||||
# 1. without room type, availability rules associated
|
||||
# with the pricelist are applied
|
||||
# 2. availability rule "closed" is taken into account
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
self.test_room_type_restriction1_item1 = self.env[
|
||||
"pms.room.type.restriction.item"
|
||||
self.test_room_type_availability1_item1 = self.env[
|
||||
"pms.room.type.availability.rule"
|
||||
].create(
|
||||
{
|
||||
"restriction_id": self.test_room_type_restriction1.id,
|
||||
"availability_id": self.test_room_type_availability1.id,
|
||||
"room_type_id": self.test_room_type_double.id,
|
||||
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
|
||||
"closed": True, # <- (1/2)
|
||||
}
|
||||
)
|
||||
# ACT
|
||||
result = self.env["pms.room.type.restriction"].rooms_available(
|
||||
result = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=fields.date.today(),
|
||||
checkout=(fields.datetime.today() + datetime.timedelta(days=4)).date(),
|
||||
# room_type_id=False, # <- (2/2)
|
||||
@@ -235,24 +238,24 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
self.test_room_type_double,
|
||||
result.mapped("room_type_id"),
|
||||
"Availability should not contain rooms of a type "
|
||||
"which its restriction rules applies",
|
||||
"which its availability rules applies",
|
||||
)
|
||||
|
||||
@Skip
|
||||
def test_availability_restrictions(self):
|
||||
def test_availability_rules(self):
|
||||
# TEST CASE
|
||||
# the availability should take into acount restriction rules:
|
||||
# the availability should take into acount availability rules:
|
||||
# closed_arrival, closed_departure, min_stay, max_stay,
|
||||
# min_stay_arrival, max_stay_arrival
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
|
||||
self.test_room_type_restriction1_item1 = self.env[
|
||||
"pms.room.type.restriction.item"
|
||||
self.test_room_type_availability1_item1 = self.env[
|
||||
"pms.room.type.availability.rule"
|
||||
].create(
|
||||
{
|
||||
"restriction_id": self.test_room_type_restriction1.id,
|
||||
"availability_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(),
|
||||
}
|
||||
@@ -364,9 +367,9 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
with self.subTest(k=test_case):
|
||||
|
||||
# ACT
|
||||
self.test_room_type_restriction1_item1.write(test_case)
|
||||
self.test_room_type_availability1_item1.write(test_case)
|
||||
|
||||
result = self.env["pms.room.type.restriction"].rooms_available(
|
||||
result = self.env["pms.room.type.availability"].rooms_available(
|
||||
checkin=checkin,
|
||||
checkout=checkout,
|
||||
room_type_id=self.test_room_type_double.id,
|
||||
@@ -378,23 +381,23 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
self.test_room_type_double,
|
||||
result.mapped("room_type_id"),
|
||||
"Availability should not contain rooms of a type "
|
||||
"which its restriction rules applies",
|
||||
"which its availability rules applies",
|
||||
)
|
||||
|
||||
@Skip
|
||||
@freeze_time("1980-11-01")
|
||||
def test_restriction_on_create_reservation(self):
|
||||
def test_rule_on_create_reservation(self):
|
||||
# TEST CASE
|
||||
# a restriction should be applied that would prevent the
|
||||
# an availability rule should be applied that would prevent the
|
||||
# creation of reservations
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
self.test_room_type_restriction1_item1 = self.env[
|
||||
"pms.room.type.restriction.item"
|
||||
self.test_room_type_availability1_item1 = self.env[
|
||||
"pms.room.type.availability.rule"
|
||||
].create(
|
||||
{
|
||||
"restriction_id": self.test_room_type_restriction1.id,
|
||||
"availability_id": self.test_room_type_availability1.id,
|
||||
"room_type_id": self.test_room_type_double.id,
|
||||
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
|
||||
"closed": True,
|
||||
@@ -407,7 +410,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
# ACT & ASSERT
|
||||
with self.assertRaises(
|
||||
ValidationError,
|
||||
msg="Restriction should be applied that would"
|
||||
msg="Availability rules should be applied that would"
|
||||
" prevent the creation of the reservation.",
|
||||
):
|
||||
self.env["pms.reservation"].create(
|
||||
@@ -423,18 +426,18 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
|
||||
@Skip
|
||||
@freeze_time("1980-11-01")
|
||||
def test_restriction_on_create_splitted_reservation(self):
|
||||
def test_rules_on_create_splitted_reservation(self):
|
||||
# TEST CASE
|
||||
# a restriction should be applied that would prevent the
|
||||
# an availability rule should be applied that would prevent the
|
||||
# creation of reservations including splitted reservations.
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
self.test_room_type_restriction1_item1 = self.env[
|
||||
"pms.room.type.restriction.item"
|
||||
self.test_room_type_availability1_item1 = self.env[
|
||||
"pms.room.type.availability.rule"
|
||||
].create(
|
||||
{
|
||||
"restriction_id": self.test_room_type_restriction1.id,
|
||||
"availability_id": self.test_room_type_availability1.id,
|
||||
"room_type_id": self.test_room_type_double.id,
|
||||
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
|
||||
"closed": True,
|
||||
@@ -469,7 +472,7 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
# ACT & ASSERT
|
||||
with self.assertRaises(
|
||||
ValidationError,
|
||||
msg="Restriction should be applied that would"
|
||||
msg="Availability rule should be applied that would"
|
||||
" prevent the creation of splitted reservation.",
|
||||
):
|
||||
self.env["pms.reservation"].create(
|
||||
@@ -485,19 +488,19 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
|
||||
@Skip
|
||||
@freeze_time("1980-11-01")
|
||||
def test_restriction_update_quota_on_create_reservation(self):
|
||||
def test_rule_update_quota_on_create_reservation(self):
|
||||
# TEST CASE
|
||||
# quota rule is changed after creating a reservation
|
||||
# with pricelist linked to a restriction_item that applies
|
||||
# with pricelist linked to a availability plan that applies
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
|
||||
self.test_room_type_restriction1_item1 = self.env[
|
||||
"pms.room.type.restriction.item"
|
||||
self.test_room_type_availability1_item1 = self.env[
|
||||
"pms.room.type.availability.rule"
|
||||
].create(
|
||||
{
|
||||
"restriction_id": self.test_room_type_restriction1.id,
|
||||
"availability_id": self.test_room_type_availability1.id,
|
||||
"room_type_id": self.test_room_type_double.id,
|
||||
"date": datetime.date.today(),
|
||||
"quota": 1,
|
||||
@@ -530,12 +533,12 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
)
|
||||
|
||||
@freeze_time("1980-11-01")
|
||||
def test_restriction_update_quota_on_update_reservation(self):
|
||||
def test_rule_update_quota_on_update_reservation(self):
|
||||
# TEST CASE
|
||||
# quota rule is restored after creating a reservation
|
||||
# with pricelist linked to a restriction_item that applies
|
||||
# with pricelist linked to a availability rule that applies
|
||||
# and then modify the pricelist of the reservation and
|
||||
# no restriction applies
|
||||
# no rules applies
|
||||
|
||||
# ARRANGE
|
||||
self.create_common_scenario()
|
||||
@@ -545,9 +548,9 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
"name": "test pricelist 2",
|
||||
}
|
||||
)
|
||||
restriction = self.env["pms.room.type.restriction.item"].create(
|
||||
rule = self.env["pms.room.type.availability.rule"].create(
|
||||
{
|
||||
"restriction_id": self.test_room_type_restriction1.id,
|
||||
"availability_id": self.test_room_type_availability1.id,
|
||||
"room_type_id": self.test_room_type_double.id,
|
||||
"date": datetime.date.today(),
|
||||
"quota": test_quota,
|
||||
@@ -569,6 +572,6 @@ class TestPmsRoomTypeRestriction(TestHotel):
|
||||
reservation.flush()
|
||||
self.assertEqual(
|
||||
test_quota,
|
||||
restriction.quota,
|
||||
rule.quota,
|
||||
"The quota should be restored after changing the reservation's pricelist",
|
||||
)
|
||||
@@ -21,10 +21,10 @@
|
||||
<group
|
||||
colspan="4"
|
||||
col="4"
|
||||
string="Price and Restriction Plans"
|
||||
string="Price and Availability Plans"
|
||||
>
|
||||
<field name="default_pricelist_id" required="True" />
|
||||
<field name="default_restriction_id" required="True" />
|
||||
<field name="default_availability_id" required="True" />
|
||||
</group>
|
||||
<group string="Timezone">
|
||||
<field name="tz" widget="timezone_mismatch" />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" ?>
|
||||
<odoo>
|
||||
<record id="room_type_restriction_item_view_form" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.restriction.item.form</field>
|
||||
<field name="model">pms.room.type.restriction.item</field>
|
||||
<record id="room_type_availability_rule_view_form" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.availability.rule.form</field>
|
||||
<field name="model">pms.room.type.availability.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Restrictions">
|
||||
<form string="Availability Plans">
|
||||
<group>
|
||||
<field name="room_type_id" required="True" />
|
||||
<field name="date" />
|
||||
@@ -31,11 +31,11 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="room_type_restriction_item_view_tree" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.restriction.item.tree</field>
|
||||
<field name="model">pms.room.type.restriction.item</field>
|
||||
<record id="room_type_availability_rule_view_tree" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.availability.rule.tree</field>
|
||||
<field name="model">pms.room.type.availability.rule</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Restrictions">
|
||||
<tree string="Availability rules">
|
||||
<field name="room_type_id" />
|
||||
<field name="date" />
|
||||
<field name="min_stay" />
|
||||
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" ?>
|
||||
<odoo>
|
||||
<record id="room_type_restriction_view_form" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.restriction.form</field>
|
||||
<field name="model">pms.room.type.restriction</field>
|
||||
<record id="room_type_availability_view_form" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.availability.form</field>
|
||||
<field name="model">pms.room.type.availability</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Restrictions">
|
||||
<form string="Rules">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
<button
|
||||
@@ -37,9 +37,9 @@
|
||||
options="{'no_create': True,'no_open': True}"
|
||||
/>
|
||||
</group>
|
||||
<separator string="Restriction Items" />
|
||||
<separator string="Availability Rules" />
|
||||
<field name="item_ids" nolabel="1">
|
||||
<tree string="Restriction Items">
|
||||
<tree string="Availability Rules">
|
||||
<field name="room_type_id" />
|
||||
<field name="date" />
|
||||
</tree>
|
||||
@@ -48,11 +48,11 @@
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
<record id="room_type_restriction_view_tree" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.restriction.tree</field>
|
||||
<field name="model">pms.room.type.restriction</field>
|
||||
<record id="room_type_availability_view_tree" model="ir.ui.view">
|
||||
<field name="name">pms.room.type.availability.tree</field>
|
||||
<field name="model">pms.room.type.availability</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Restrictions">
|
||||
<tree string="Availability Plans">
|
||||
<field name="name" />
|
||||
<field name="pms_property_id" />
|
||||
<field
|
||||
@@ -64,17 +64,17 @@
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
<!-- Action of reservation restriction -->
|
||||
<record model="ir.actions.act_window" id="room_type_restriction_action">
|
||||
<field name="name">Reservation restrictions</field>
|
||||
<field name="res_model">pms.room.type.restriction</field>
|
||||
<!-- Action of reservation availability plan-->
|
||||
<record model="ir.actions.act_window" id="room_type_availability_action">
|
||||
<field name="name">Reservation Availability Plans</field>
|
||||
<field name="res_model">pms.room.type.availability</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
<!-- MENUS -->
|
||||
<menuitem
|
||||
name="Restrictions"
|
||||
id="reservation_restriction_menu"
|
||||
action="room_type_restriction_action"
|
||||
name="Availability Plans"
|
||||
id="reservation_availability_rules_menu"
|
||||
action="room_type_availability_action"
|
||||
sequence="22"
|
||||
parent="pms.configuration_others"
|
||||
/>
|
||||
Reference in New Issue
Block a user