Multiproperty Constrains (#30)

* [IMP] add multiproperties demo data

* [IMP] add multiproperties checks in res_users

* [IMP] add test case in test_res_users

* [IMP] Add multiproperty checks in pms_amenity and pms_amenity_type

* [IMP] Add multiproperty in pms_board_service_room_type(pending review)

* [IMP] Add test case in test_pms_room_type_availability_rule to check multiproperties

* [IMP] Fixing test case in test_pms_room_type_availability_rule to check multiproperties

* [IMP] Add test case in test_pms_room_type_availability_rule

* [IMP] Removed field default_availability_plan_id from pms_property

* [IMP] Add multiproperty in pms_room_type_available_plan

* [IMP] pms: adding property in rooms_available

* [IMP] Add multiproperty in pms_room_type_availability_rule and product_pricelist(work in progress)

* [IMP] Add multiproperty in product_pricelist and product_pricelist_item

* [IMP] add multiproperties demo data

* [IMP] add multiproperties checks in res_users

* [IMP] add test case in test_res_users and pms_room_type_availability_rule

* [IMP] Add multiproperty checks in pms_amenity and pms_amenity_type

* [IMP] Add multiproperty in pms_board_service_room_type(pending review)

* [IMP] Removed field default_availability_plan_id from pms_property

* [IMP] Add multiproperty in pms_room_type_available_plan

* [IMP] pms: adding property in rooms_available

* [IMP] Add multiproperty in pms_room_type_availability_rule and product_pricelist(work in progress)

* [IMP] Add multiproperty in product_pricelist and product_pricelist_item

* [IMP] Pms: add compute_folio method in pms.service

* [IMP] Pms: add multiproperty integrity checks between room_type and its class

* [IMP] Pms: pms_property_id related to folio

* [IMP] Pms: add multiproperty integrity checks in pms_room with pms_room_type and pms_floor

* [IMP] Pms: adding multiproperty checks in room_type(work in progress)

* [IMP] Pms: Add property rules

* [FIX]pms: external ids security rules

* [FIX]pms: property checks

* [FIX]pms: get product on pricelist item multiproperty check

* [FIX]pms: delete test field default_plan

* [FIX]pms: property constrain to product from room type model

* [FIX]pms: ids references

* [IMP]pms: folio wizard price flow on odoo standar

Co-authored-by: Darío Lodeiros <dario@commitsun.com>
This commit is contained in:
Sara
2021-01-31 13:07:03 +01:00
committed by GitHub
parent 6cd01fb0d2
commit 57d3ab0c8a
34 changed files with 1298 additions and 241 deletions

View File

@@ -12,10 +12,6 @@
<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_availability_plan_id"
ref="main_pms_room_type_availability_plan"
/>
<field name="street">Rua Street Demo, s/n</field>
<field name="city">Commitsun city</field>
<field name="country_id" ref="base.es" />

View File

@@ -1,6 +1,37 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<!-- Multi pms Demo -->
<record id="pms_company1" model="res.company">
<field name="name">Pms Company</field>
<field name="currency_id" ref="base.EUR" />
<field
name="favicon"
model="res.company"
eval="obj()._get_default_favicon(original=True)"
/>
</record>
<record
id="demo_pms_room_type_availability"
model="pms.room.type.availability.plan"
>
<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" />
</record>
<record id="demo_pms_property2" model="pms.property">
<field name="name">My property 2</field>
<field name="company_id" ref="base.main_company" />
<field name="default_pricelist_id" ref="product.list0" />
</record>
<record id="demo_pms_property3" model="pms.property">
<field name="name">Independent property </field>
<field name="company_id" ref="pms_company1" />
<field name="default_pricelist_id" ref="product.list0" />
</record>
<!-- users -->
<record id="base.user_demo" model="res.users">
<field name="groups_id" eval="[(4,ref('pms.group_pms_user'))]" />
@@ -305,22 +336,6 @@
Used for closing of rooms for extra privacy.
</field>
</record>
<!-- Multi pms Demo -->
<record
id="demo_pms_room_type_availability_plan"
model="pms.room.type.availability.plan"
>
<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_availability_plan_id"
ref="demo_pms_room_type_availability_plan"
/>
</record>
<!-- pms.room.type -->
<record id="demo_pms_room_type_0" model="pms.room.type">
<field name="pms_property_ids" eval="[(4, ref('pms.demo_pms_property'))]" />

View File

@@ -1,7 +1,8 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class PmsRoomAmenity(models.Model):
@@ -18,3 +19,36 @@ class PmsRoomAmenity(models.Model):
active = fields.Boolean("Active", default=True)
# TODO: Constrain coherence pms_property_ids with amenity types pms_property_ids
allowed_property_ids = fields.Many2many(
"pms.property",
"allowed_amenity_move_rel",
"amenity_id",
"property_id",
string="Allowed Properties",
store=True,
readonly=True,
compute="_compute_allowed_property_ids",
)
@api.depends(
"room_amenity_type_id.pms_property_ids",
)
def _compute_allowed_property_ids(self):
for amenity in self:
if amenity.room_amenity_type_id.pms_property_ids:
amenity.allowed_property_ids = (
amenity.room_amenity_type_id.pms_property_ids
)
else:
amenity.allowed_property_ids = False
@api.constrains(
"allowed_property_ids",
"pms_property_ids",
)
def _check_property_integrity(self):
for rec in self:
if rec.pms_property_ids and rec.allowed_property_ids:
for prop in rec.pms_property_ids:
if prop not in rec.allowed_property_ids:
raise ValidationError(_("Property not allowed"))

View File

@@ -47,8 +47,12 @@ class PmsBoardServiceRoomType(models.Model):
board_service_line_ids = fields.One2many(
"pms.board.service.room.type.line", "pms_board_service_room_type_id"
)
pms_property_id = fields.Many2one(
# TODO:review relation with pricelist and properties
pms_property_ids = fields.Many2many(
"pms.property",
string="Properties",
required=False,
ondelete="restrict",
)
price_type = fields.Selection(
[("fixed", "Fixed"), ("percent", "Percent")],

View File

@@ -13,11 +13,6 @@ class PmsCheckinPartner(models.Model):
_name = "pms.checkin.partner"
_description = "Partner Checkins"
@api.model
def _get_default_pms_property(self):
# TODO: Change by property env variable (like company)
return self.env.user.pms_property_id
# Fields declaration
identifier = fields.Char(
"Identifier", readonly=True, index=True, default=lambda self: _("New")
@@ -33,7 +28,7 @@ class PmsCheckinPartner(models.Model):
store=True,
)
pms_property_id = fields.Many2one(
"pms.property", default=_get_default_pms_property, required=True
"pms.property", store=True, readonly=True, related="folio_id.pms_property_id"
)
name = fields.Char(
"Name",

View File

@@ -28,12 +28,6 @@ class PmsFolio(models.Model):
result.append((folio.id, name))
return result
@api.model
def _get_default_pms_property(self):
return (
self.env.user.pms_property_id
) # TODO: Change by property env variable (like company)
def _default_note(self):
return (
self.env["ir.config_parameter"]
@@ -48,7 +42,9 @@ class PmsFolio(models.Model):
string="Folio Number", readonly=True, index=True, default=lambda self: _("New")
)
pms_property_id = fields.Many2one(
"pms.property", default=_get_default_pms_property, required=True
"pms.property",
default=lambda self: self.env.user.get_active_property_ids()[0],
required=True,
)
partner_id = fields.Many2one(
"res.partner",

View File

@@ -41,12 +41,6 @@ class PmsProperty(models.Model):
required=True,
help="The default pricelist used in this property.",
)
default_availability_plan_id = fields.Many2one(
"pms.room.type.availability.plan",
"Availability Plan",
required=True,
help="The default availability plan used in this property.",
)
default_arrival_hour = fields.Char(
"Arrival Hour (GMT)", help="HH:mm Format", default="14:00"
)

View File

@@ -68,11 +68,6 @@ class PmsReservation(models.Model):
else:
return default_departure_hour
@api.model
def _get_default_pms_property(self):
# TODO: Change by property env variable (like company)
return self.env.user.pms_property_id
def _get_default_segmentation(self):
folio = False
segmentation_ids = False
@@ -158,7 +153,7 @@ class PmsReservation(models.Model):
)
pms_property_id = fields.Many2one(
"pms.property",
default=_get_default_pms_property, # required=True
default=lambda self: self.env.user.get_active_property_ids()[0],
)
reservation_line_ids = fields.One2many(
"pms.reservation.line",

View File

@@ -32,6 +32,7 @@ class PmsRoom(models.Model):
"pms.property",
required=True,
ondelete="restrict",
default=lambda self: self.env.user.get_active_property_ids()[0],
)
room_type_id = fields.Many2one(
"pms.room.type", "Property Room Type", required=True, ondelete="restrict"
@@ -55,6 +56,41 @@ class PmsRoom(models.Model):
active = fields.Boolean("Active", default=True)
sequence = fields.Integer("Sequence", default=0)
allowed_property_ids = fields.Many2many(
comodel_name="pms.property",
relation="room_property_rel",
column1="room_id",
column2="property_id",
string="Allowed properties",
store=True,
readonly=True,
compute="_compute_allowed_property_ids",
)
@api.depends("room_type_id.pms_property_ids", "floor_id.pms_property_ids")
def _compute_allowed_property_ids(self):
for record in self:
if not (
record.room_type_id.pms_property_ids or record.floor_id.pms_property_ids
):
record.allowed_property_ids = False
else:
if record.room_type_id.pms_property_ids:
if record.floor_id.pms_property_ids:
properties = list(
set(record.room_type_id.pms_property_ids.ids)
& set(record.floor_id.pms_property_ids.ids)
)
record.allowed_property_ids = self.env["pms.property"].search(
[("id", "in", properties)]
)
else:
record.allowed_property_ids = (
record.room_type_id.pms_property_ids
)
else:
record.allowed_property_ids = record.floor_id.pms_property_ids
# Constraints and onchanges
@api.constrains("capacity")
def _check_capacity(self):
@@ -67,6 +103,16 @@ class PmsRoom(models.Model):
)
)
@api.constrains(
"allowed_property_ids",
"pms_property_id",
)
def _check_property_integrity(self):
for rec in self:
if rec.pms_property_id and rec.allowed_property_ids:
if rec.pms_property_id.id not in rec.allowed_property_ids.ids:
raise ValidationError(_("Property not allowed"))
# Business methods
def get_capacity(self, extra_bed=0):

View File

@@ -26,14 +26,6 @@ class PmsRoomType(models.Model):
delegate=True,
ondelete="cascade",
)
pms_property_ids = fields.Many2many(
"pms.property",
"pms_property_room_type_rel",
"room_type_id",
"pms_property_id",
ondelete="restrict",
string="Properties",
)
room_ids = fields.One2many("pms.room", "room_type_id", "Rooms")
class_id = fields.Many2one("pms.room.type.class", "Property Type Class")
board_service_room_type_ids = fields.One2many(
@@ -122,18 +114,15 @@ class PmsRoomType(models.Model):
)
return self.browse(list(res.values()))
@api.constrains("pms_property_ids", "company_id")
def _check_property_company_integrity(self):
for rec in self:
if rec.company_id and rec.pms_property_ids:
property_companies = rec.pms_property_ids.mapped("company_id")
if len(property_companies) > 1 or rec.company_id != property_companies:
raise ValidationError(
_(
"The company of the properties must match "
"the company on the room type"
@api.constrains("pms_property_ids")
def _check_integrity_property_class(self):
for record in self:
if record.pms_property_ids and record.class_id:
for pms_property in record.pms_property_ids:
if pms_property.id not in record.class_id.pms_property_ids.ids:
raise ValidationError(
_("Property isn't allowed in Room Type Class")
)
)
@api.constrains("code_type", "pms_property_ids", "company_id")
def _check_code_property_company_uniqueness(self):

View File

@@ -19,9 +19,9 @@ class PmsRoomTypeAvailability(models.Model):
# Fields declaration
name = fields.Char("Availability Plan Name", required=True)
pms_property_id = fields.Many2one(
pms_property_ids = fields.Many2many(
comodel_name="pms.property",
string="Property",
string="Properties",
ondelete="restrict",
)
@@ -70,6 +70,7 @@ class PmsRoomTypeAvailability(models.Model):
room_type_id=False,
current_lines=False,
pricelist=False,
pms_property_id=False,
):
if current_lines and not isinstance(current_lines, list):
current_lines = [current_lines]
@@ -88,13 +89,17 @@ class PmsRoomTypeAvailability(models.Model):
)
domain_rooms = [
("id", "not in", rooms_not_avail if len(rooms_not_avail) > 0 else [])
("id", "not in", rooms_not_avail if len(rooms_not_avail) > 0 else []),
]
domain_rules = [
("date", ">=", checkin),
("date", "<=", checkout),
]
if pms_property_id:
domain_rooms.append(("pms_property_id", "=", pms_property_id))
domain_rules.append(("pms_property_id", "=", pms_property_id))
if room_type_id:
domain_rooms.append(("room_type_id", "=", room_type_id))
domain_rules.append(("room_type_id", "=", room_type_id))
@@ -118,6 +123,11 @@ class PmsRoomTypeAvailability(models.Model):
lambda x: x.room_type_id.id not in room_types_to_remove
)
# if pms_property_id:
# free_rooms = free_rooms.filtered(
# lambda x: x.pms_property_id = pms_property_id
# )
return free_rooms.sorted(key=lambda r: r.sequence)
@api.model

View File

@@ -68,10 +68,27 @@ class PmsRoomTypeAvailabilityRule(models.Model):
help="Maximum simultaneous availability on own Booking Engine.",
)
pms_property_id = fields.Many2one(
comodel_name="pms.property",
string="Property",
ondelete="restrict",
)
allowed_property_ids = fields.Many2many(
"pms.property",
"allowed_availability_move_rel",
"availability_rule_id",
"property_id",
string="Allowed Properties",
store=True,
readonly=True,
compute="_compute_allowed_property_ids",
)
_sql_constraints = [
(
"room_type_registry_unique",
"unique(availability_plan_id, room_type_id, date)",
"unique(availability_plan_id, room_type_id, date, pms_property_id)",
"Only can exists one availability rule in the same \
day for the same room type!",
)
@@ -89,6 +106,59 @@ class PmsRoomTypeAvailabilityRule(models.Model):
if not record.max_avail:
record.max_avail = record.room_type_id.default_max_avail
@api.depends(
"availability_plan_id.pms_property_ids", "room_type_id.pms_property_ids"
)
def _compute_allowed_property_ids(self):
for rule in self:
properties = []
if not (
rule.availability_plan_id.pms_property_ids
or rule.room_type_id.pms_property_ids
):
rule.allowed_property_ids = False
else:
if rule.availability_plan_id.pms_property_ids:
if rule.room_type_id.pms_property_ids:
for prp in rule.availability_plan_id.pms_property_ids:
if prp in rule.room_type_id.pms_property_ids:
properties.append(prp)
rule.allowed_property_ids = [
(4, prop.id) for prop in properties
]
else:
rule.allowed_property_ids = (
rule.availability_plan_id.pms_property_ids
)
else:
rule.allowed_property_ids = rule.room_type_id.pms_property_ids
@api.constrains(
"allowed_property_ids",
"pms_property_id",
)
def _check_property_integrity(self):
for rec in self:
if rec.pms_property_id and rec.allowed_property_ids:
if rec.pms_property_id.id not in rec.allowed_property_ids.ids:
raise ValidationError(_("Property not allowed"))
# @api.constrains(
# "allowed_property_ids",
# "pms_property_ids",
# )
# def _check_property_integrity(self):
# for rule in self:
# for p in rule.pms_property_ids:
# allowed = list(
# set(rule.room_type_id.pms_property_ids.ids)
# &
# set(rule.availability_plan_id.pms_property_ids.ids))
# if p.id not in allowed:
# raise ValidationError(_("Property not allowed"))
@api.constrains("min_stay", "min_stay_arrival", "max_stay", "max_stay_arrival")
def _check_min_max_stay(self):
for record in self:

View File

@@ -35,12 +35,6 @@ class PmsService(models.Model):
return self.env.context.get("default_reservation_id")
return False
@api.model
def _default_folio_id(self):
if "folio_id" in self._context:
return self._context["folio_id"]
return False
# Fields declaration
name = fields.Char(
"Service description",
@@ -52,7 +46,11 @@ class PmsService(models.Model):
"product.product", "Service", ondelete="restrict", required=True
)
folio_id = fields.Many2one(
"pms.folio", "Folio", ondelete="cascade", default=_default_folio_id
comodel_name="pms.folio",
string="Folio",
compute="_compute_folio_id",
readonly=False,
store=True
)
reservation_id = fields.Many2one(
"pms.reservation", "Room", default=_default_reservation_id
@@ -68,7 +66,7 @@ class PmsService(models.Model):
related="folio_id.company_id", string="Company", store=True, readonly=True
)
pms_property_id = fields.Many2one(
"pms.property", store=True, readonly=True, related="folio_id.pms_property_id"
comodel_name="pms.property", store=True, readonly=True, related="folio_id.pms_property_id"
)
tax_ids = fields.Many2many(
"account.tax",
@@ -372,6 +370,16 @@ class PmsService(models.Model):
else:
service.price_unit = 0
@api.depends(
"reservation_id"
)
def _compute_folio_id(self):
for record in self:
if record.reservation_id:
record.folio_id = record.reservation_id.folio_id
elif not record.folio_id:
record.folio_id = False
def _recompute_price(self):
# REVIEW: Conditional to avoid overriding already calculated prices,
# I'm not sure it's the best way

View File

@@ -2,7 +2,8 @@
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
from odoo import fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
_logger = logging.getLogger(__name__)
@@ -68,7 +69,6 @@ class ProductPricelist(models.Model):
def _compute_price_rule_get_items(
self, products_qty_partner, date, uom_id, prod_tmpl_ids, prod_ids, categ_ids
):
if "property" in self._context and self._context["property"]:
self.env["product.pricelist.item"].flush(
["price", "currency_id", "company_id"]
@@ -147,3 +147,13 @@ class ProductPricelist(models.Model):
"pricelist_id": self.id,
},
}
@api.constrains(
"cancelation_rule_id",
)
def _check_property_integrity(self):
for rec in self:
if rec.pms_property_ids:
for p in rec.pms_property_ids:
if p.id not in rec.cancelation_rule_id.pms_property_ids.ids:
raise ValidationError(_("Property not allowed"))

View File

@@ -1,6 +1,7 @@
# Copyright 2017 Alexandre Díaz, Pablo Quesada, Darío Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class ProductPricelistItem(models.Model):
@@ -17,3 +18,54 @@ class ProductPricelistItem(models.Model):
string="End Date Overnight",
help="End date to apply daily pricelist items",
)
allowed_property_ids = fields.Many2many(
"pms.property",
"allowed_pricelist_move_rel",
"pricelist_item_id",
"property_id",
string="Allowed Properties",
store=True,
readonly=True,
compute="_compute_allowed_property_ids",
)
@api.depends("product_id.pms_property_ids", "pricelist_id.pms_property_ids")
def _compute_allowed_property_ids(self):
for record in self:
properties = []
if record.applied_on == "0_product_variant":
product = record.product_id
elif record.applied_on == "1_product":
product = record.product_tmpl_id
else:
product = False
if not record.pricelist_id.pms_property_ids or not product:
record.allowed_property_ids = False
else:
if record.pricelist_id.pms_property_ids:
if product.pms_property_ids:
properties = list(
set(record.pricelist_id.pms_property_ids.ids)
& set(product.pms_property_ids.ids)
)
record.allowed_property_ids = self.env["pms.property"].search(
[("id", "in", properties)]
)
else:
record.allowed_property_ids = product.pms_property_ids
else:
record.allowed_property_ids = product.pms_property_ids
# else:
# record.allowed_property_ids = False
@api.constrains(
"allowed_property_ids",
"pms_property_ids",
)
def _check_property_integrity(self):
for rec in self:
if rec.pms_property_ids and rec.allowed_property_ids:
for p in rec.pms_property_ids:
if p.id not in rec.allowed_property_ids.ids:
raise ValidationError(_("Property not allowed"))

View File

@@ -1,14 +1,21 @@
# Copyright 2017 Alexandre Díaz
# Copyright 2017 Dario Lodeiros
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
class ProductTemplate(models.Model):
_inherit = "product.template"
pms_property_ids = fields.Many2many(
"pms.property", string="Properties", required=False, ondelete="restrict"
comodel_name="pms.property",
relation="product_template_property_rel",
column1="product_tmpl_id",
column2="property_id",
string="Properties",
required=False,
ondelete="restrict",
)
per_day = fields.Boolean("Unit increment per day")
per_person = fields.Boolean("Unit increment per person")
@@ -24,3 +31,16 @@ class ProductTemplate(models.Model):
default=False,
help="Specifies if the product is shown in the calendar information.",
)
@api.constrains("pms_property_ids", "company_id")
def _check_property_company_integrity(self):
for rec in self:
if rec.company_id and rec.pms_property_ids:
property_companies = rec.pms_property_ids.mapped("company_id")
if len(property_companies) > 1 or rec.company_id != property_companies:
raise ValidationError(
_(
"The company of the properties must match "
"the company on the room type"
)
)

View File

@@ -1,6 +1,7 @@
# Copyright 2019 Pablo Quesada
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import api, fields, models
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.http import request
@@ -16,9 +17,9 @@ class ResUsers(models.Model):
pms_property_id = fields.Many2one(
"pms.property",
string="Property",
default=_get_default_pms_property,
help="The property this user is currently working for.",
context={"user_preference": True},
domain="[('id','in',pms_property_ids)]",
)
pms_property_ids = fields.Many2many(
"pms.property",
@@ -26,8 +27,9 @@ class ResUsers(models.Model):
"user_id",
"pms_property_id",
string="Properties",
default=_get_default_pms_property,
domain="[('company_id','in',company_ids)]",
)
company_id = fields.Many2one(domain="[('id','in',company_ids)]")
@api.model
def get_active_property_ids(self):
@@ -43,3 +45,19 @@ class ResUsers(models.Model):
]
return self.env["pms.property"].browse(active_property_ids).ids
return user_property_ids
@api.constrains("pms_property_id", "pms_property_ids")
def _check_property_in_allowed_properties(self):
if any(user.pms_property_id not in user.pms_property_ids for user in self):
raise ValidationError(
_("The chosen property is not in the allowed properties for this user")
)
@api.constrains("pms_property_ids", "company_id")
def _check_company_in_property_ids(self):
for record in self:
for pms_property in record.pms_property_ids:
if pms_property.company_id not in record.company_ids:
raise ValidationError(
_("Some properties do not belong to the allowed companies")
)

View File

@@ -35,7 +35,7 @@
</record>
<!-- Property Rules -->
<record id="pms_folio_property_rule" model="ir.rule">
<field name="name">PMS Folio Company Rule</field>
<field name="name">PMS Folio Property Rule</field>
<field name="model_id" ref="model_pms_folio" />
<field name="global" eval="True" />
<field name="domain_force">
@@ -44,7 +44,7 @@
</field>
</record>
<record id="pms_reservation_property_rule" model="ir.rule">
<field name="name">PMS Reservation Company Rule</field>
<field name="name">PMS Reservation Property Rule</field>
<field name="model_id" ref="model_pms_reservation" />
<field name="global" eval="True" />
<field name="domain_force">
@@ -52,5 +52,194 @@
user.get_active_property_ids())]
</field>
</record>
<record id="pms_amenity_property_rule" model="ir.rule">
<field name="name">PMS Amenity Property Rule</field>
<field name="model_id" ref="model_pms_amenity" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_amenity_type_property_rule" model="ir.rule">
<field name="name">PMS Amenity Type Property Rule</field>
<field name="model_id" ref="model_pms_amenity_type" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_board_service_property_rule" model="ir.rule">
<field name="name">PMS Board Service Property Rule</field>
<field name="model_id" ref="model_pms_board_service" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_board_service_line_property_rule" model="ir.rule">
<field name="name">PMS Board Service Line Property Rule</field>
<field name="model_id" ref="model_pms_board_service_line" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_board_service_room_type_property_rule" model="ir.rule">
<field name="name">PMS Board Service Room Type Property Rule</field>
<field name="model_id" ref="model_pms_board_service_room_type" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_cancelation_rule_property_rule" model="ir.rule">
<field name="name">PMS Cancelation Rule Property Rule</field>
<field name="model_id" ref="model_pms_cancelation_rule" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_checkin_partner_property_rule" model="ir.rule">
<field name="name">PMS Checkin Partner Property Rule</field>
<field name="model_id" ref="model_pms_amenity" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_id','=',False),('pms_property_id', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_floor_property_rule" model="ir.rule">
<field name="name">PMS Floor Property Rule</field>
<field name="model_id" ref="model_pms_floor" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_reservation_line_property_rule" model="ir.rule">
<field name="name">PMS Reservation Line Property Rule</field>
<field name="model_id" ref="model_pms_reservation_line" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_id','=',False),('pms_property_id', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_clousure_reason_property_rule" model="ir.rule">
<field name="name">PMS Clousure Reason Property Rule</field>
<field name="model_id" ref="model_room_closure_reason" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_room_type_property_rule" model="ir.rule">
<field name="name">PMS Room Type Property Rule</field>
<field name="model_id" ref="model_pms_room_type" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_room_type_availability_plan_property_rule" model="ir.rule">
<field name="name">PMS Room Type Availability Plan Property Rule</field>
<field name="model_id" ref="model_pms_room_type_availability_plan" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_room_type_availability_rule_property_rule" model="ir.rule">
<field name="name">PMS Room Type Availability Rule Property Rule</field>
<field name="model_id" ref="model_pms_room_type_availability_rule" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_id','=',False),('pms_property_id', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_room_type_class_property_rule" model="ir.rule">
<field name="name">PMS Room Type Class Property Rule</field>
<field name="model_id" ref="model_pms_room_type_availability_plan" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_service_property_rule" model="ir.rule">
<field name="name">PMS Service Property Rule</field>
<field name="model_id" ref="model_pms_service" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_id','=',False),('pms_property_id', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_service_line_property_rule" model="ir.rule">
<field name="name">PMS Service Line Property Rule</field>
<field name="model_id" ref="model_pms_service_line" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_id','=',False),('pms_property_id', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_product_pricelist_property_rule" model="ir.rule">
<field name="name">PMS Product Pricelist Property Rule</field>
<field name="model_id" ref="model_product_pricelist" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_product_pricelist_item_property_rule" model="ir.rule">
<field name="name">PMS Room Type Class Property Rule</field>
<field name="model_id" ref="model_pms_room_type_availability_plan" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_res_users_property_rule" model="ir.rule">
<field name="name">PMS Users Property Rule</field>
<field name="model_id" ref="model_res_users" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_account_move_property_rule" model="ir.rule">
<field name="name">PMS Account Move Property Rule</field>
<field name="model_id" ref="model_account_move" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_id','=',False),('pms_property_id', 'in',
user.get_active_property_ids())]
</field>
</record>
<record id="pms_account_journal_property_rule" model="ir.rule">
<field name="name">PMS Account Journal Property Rule</field>
<field name="model_id" ref="model_account_journal" />
<field name="global" eval="True" />
<field name="domain_force">
['|',('pms_property_ids','=',False),('pms_property_ids', 'in',
user.get_active_property_ids())]
</field>
</record>
</data>
</odoo>

View File

@@ -29,3 +29,6 @@ from . import test_pms_room_type_availability_rules
from . import test_pms_room_type
from . import test_pms_wizard_massive_changes
from . import test_pms_wizard_folio
from . import test_pms_res_users
from . import test_pms_amenity
from . import test_pms_room

View File

@@ -0,0 +1,98 @@
from odoo.exceptions import ValidationError
from .common import TestHotel
class TestPmsAmenity(TestHotel):
def create_common_scenario(self):
# create company and properties
self.company1 = self.env["res.company"].create(
{
"name": "Pms_Company_Test",
}
)
self.property1 = self.env["pms.property"].create(
{
"name": "Pms_property_test1",
"company_id": self.company1.id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.property2 = self.env["pms.property"].create(
{
"name": "Pms_property_test2",
"company_id": self.company1.id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.property3 = self.env["pms.property"].create(
{
"name": "Pms_property_test3",
"company_id": self.company1.id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
def test_property_not_allowed(self):
# ARRANGE
name = "amenityTest1"
name2 = "amenity"
self.create_common_scenario()
AmenityType = self.env["pms.amenity.type"]
Amenity = self.env["pms.amenity"]
# ACT
A1 = AmenityType.create(
{
"name": name,
"pms_property_ids": [
(4, self.property1.id),
(4, self.property2.id),
],
}
)
# ASSERT
with self.assertRaises(ValidationError), self.cr.savepoint():
Amenity.create(
{
"name": name2,
"room_amenity_type_id": A1.id,
"pms_property_ids": [
(4, self.property1.id),
(4, self.property2.id),
(4, self.property3.id),
],
}
)
def test_check_allowed_property_ids(self):
# ARRANGE
name = "amenityTest1"
name2 = "amenity"
self.create_common_scenario()
AmenityType = self.env["pms.amenity.type"]
Amenity = self.env["pms.amenity"]
# ACT
AT1 = AmenityType.create(
{
"name": name,
"pms_property_ids": [
(4, self.property1.id),
(4, self.property2.id),
],
}
)
A2 = Amenity.create(
{
"name": name2,
"room_amenity_type_id": AT1.id,
"pms_property_ids": [
(4, self.property1.id),
(4, self.property2.id),
],
}
)
# ASSERT
self.assertEqual(
A2.allowed_property_ids, AT1.pms_property_ids, "Properties doesnt much"
)

View File

@@ -1,9 +1,56 @@
import datetime
from odoo.exceptions import ValidationError
from odoo.tests import common, tagged
@tagged("standard", "nice")
class TestPmsPricelist(common.TransactionCase):
def create_common_scenario(self):
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,
}
)
self.property2 = self.env["pms.property"].create(
{
"name": "Property_2",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.property3 = self.env["pms.property"].create(
{
"name": "Property_3",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.room_type_class = self.env["pms.room.type.class"].create(
{"name": "Room Class"}
)
self.room_type = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.property1.id, self.property2.id],
"name": "Single",
"code_type": "SIN",
"class_id": self.room_type_class.id,
"list_price": 30,
}
)
self.pricelist = self.env["product.pricelist"].create(
{
"name": "pricelist_1",
"pms_property_ids": [self.property1.id, self.property2.id],
}
)
def test_advanced_pricelist_exists(self):
# ARRANGE
@@ -37,3 +84,67 @@ class TestPmsPricelist(common.TransactionCase):
self.env["ir.config_parameter"].search(
[("key", "=", key), ("value", "=", value)]
).unlink()
def test_check_property_pricelist(self):
# ARRANGE
self.create_common_scenario()
# ACT & ASSERT
with self.assertRaises(ValidationError):
self.item1 = self.env["product.pricelist.item"].create(
{
"name": "item_1",
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.today(),
"date_end": datetime.datetime.today() + datetime.timedelta(days=1),
"fixed_price": 40.0,
"pricelist_id": self.pricelist.id,
"pms_property_ids": [self.property3.id],
}
)
def test_check_property_room_type(self):
# ARRANGE
self.create_common_scenario()
# ACT
self.pricelist1 = self.env["product.pricelist"].create(
{
"name": "pricelist_1",
"pms_property_ids": [self.property1.id, self.property3.id],
}
)
# ASSERT
with self.assertRaises(ValidationError):
self.item1 = self.env["product.pricelist.item"].create(
{
"name": "item_1",
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"date_start": datetime.datetime.today(),
"date_end": datetime.datetime.today() + datetime.timedelta(days=1),
"fixed_price": 40.0,
"pricelist_id": self.pricelist1.id,
"pms_property_ids": [self.property3.id],
}
)
def test_cancelation_rule_property(self):
# ARRANGE
self.create_common_scenario()
Pricelist = self.env["product.pricelist"]
# ACT
self.cancelation_rule = self.env["pms.cancelation.rule"].create(
{
"name": "Cancelation Rule Test",
"pms_property_ids": [self.property1.id, self.property3.id],
}
)
# ASSERT
with self.assertRaises(ValidationError):
Pricelist.create(
{
"name": "Pricelist Test",
"pms_property_ids": [self.property1.id, self.property2.id],
"cancelation_rule_id": self.cancelation_rule.id,
}
)

View File

@@ -26,7 +26,6 @@ class TestPmsPricelistRules(common.TransactionCase):
"name": "Property_1",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
"default_availability_plan_id": self.availability_plan1.id,
}
)
@@ -35,7 +34,6 @@ 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_availability_plan_id": self.availability_plan2.id,
}
)

View File

@@ -0,0 +1,91 @@
from odoo.exceptions import ValidationError
from odoo.tests import common
class TestPmsResUser(common.TransactionCase):
def create_common_scenario(self):
# create a room type availability
self.room_type_availability = self.env[
"pms.room.type.availability.plan"
].create({"name": "Availability plan 1"})
# create a company and properties
self.company_A = self.env["res.company"].create(
{
"name": "Pms_Company1",
}
)
self.company_B = self.env["res.company"].create(
{
"name": "Pms_Company2",
}
)
self.property_A1 = self.env["pms.property"].create(
{
"name": "Pms_property",
"company_id": self.company_A.id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.property_A2 = self.env["pms.property"].create(
{
"name": "Pms_property2",
"company_id": self.company_A.id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.property_B1 = self.env["pms.property"].create(
{
"name": "Pms_propertyB1",
"company_id": self.company_B.id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
def test_property_not_allowed(self):
"""
Property not allowed, it belongs to another company
Company_A ---> Property_A1, Property_A2
Company_B ---> Property_B1
"""
# ARRANGE
name = "test user"
login = "test_user"
self.create_common_scenario()
Users = self.env["res.users"]
# ACT & ASSERT
with self.assertRaises(ValidationError), self.cr.savepoint():
Users.create(
{
"name": name,
"login": login,
"company_ids": [(4, self.company_A.id)],
"company_id": self.company_A.id,
"pms_property_ids": [(4, self.property_A1.id)],
"pms_property_id": self.property_B1.id,
}
)
def test_check_allowed_property_ids(self):
# ARRANGE
name = "test user2"
login = "test_user2"
self.create_common_scenario()
Users = self.env["res.users"]
# ACT & ASSERT
with self.assertRaises(ValidationError), self.cr.savepoint():
Users.create(
{
"name": name,
"login": login,
"company_ids": [(4, self.company_A.id)],
"company_id": self.company_A.id,
"pms_property_ids": [
(4, self.property_A1.id),
(4, self.property_B1.id),
],
"pms_property_id": self.property_A1.id,
}
)

View File

@@ -22,7 +22,6 @@ 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_availability_plan_id": self.room_type_availability.id,
}
)

View File

@@ -0,0 +1,81 @@
from odoo.exceptions import ValidationError
from odoo.tests import common, tagged
class TestPmsRoom(common.TransactionCase):
def create_common_scenario(self):
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,
}
)
self.property2 = self.env["pms.property"].create(
{
"name": "Property_2",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.property3 = self.env["pms.property"].create(
{
"name": "Property_3",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.env.ref("product.list0").id,
}
)
self.room_type_class = self.env["pms.room.type.class"].create(
{"name": "Room Class"}
)
self.room_type = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.property1.id, self.property2.id],
"name": "Single",
"code_type": "SIN",
"class_id": self.room_type_class.id,
"list_price": 30,
}
)
def test_check_property_floor(self):
#ARRANGE
self.create_common_scenario()
floor = self.env["pms.floor"].create(
{
"name": "Floor",
"pms_property_ids": [
(4, self.property1.id),
]
}
)
#ACT & ARRANGE
with self.assertRaises(
ValidationError, msg="Room has been created and it should't"
):
self.env["pms.room"].create(
{
"name": "Room 101",
"pms_property_id": self.property2.id,
"room_type_id": self.room_type.id,
"floor_id": floor.id,
}
)
def test_check_property_room_type(self):
# ARRANGE
self.create_common_scenario()
# ACT & ARRANGE
with self.assertRaises(
ValidationError, msg="Room has been created and it should't"
):
self.env["pms.room"].create(
{
"name": "Room 101",
"pms_property_id": self.property3.id,
"room_type_id": self.room_type.id,
}
)

View File

@@ -15,9 +15,6 @@ class TestRoomType(SavepointCase):
"name": "p2",
"company_id": self.m1.id,
"default_pricelist_id": self.ref("product.list0"),
"default_availability_plan_id": self.ref(
"pms.main_pms_room_type_availability_plan"
),
}
)
self.m2 = self.env["res.company"].create(
@@ -30,9 +27,6 @@ class TestRoomType(SavepointCase):
"name": "p3",
"company_id": self.m2.id,
"default_pricelist_id": self.ref("product.list0"),
"default_availability_plan_id": self.ref(
"pms.main_pms_room_type_availability_plan"
),
}
)
@@ -676,3 +670,29 @@ class TestRoomTypeCodePropertyUniqueness(TestRoomType):
# ASSERT
self.assertEqual(room_type.id, r3.id, "Expected room type not found")
def test_check_property_room_type_class(self):
# ARRANGE
room_type_class = self.env["pms.room.type.class"].create(
{
"name": "Room Type Class",
"pms_property_ids": [
(4, self.p2.id),
],
},
)
# ACT & ASSERT
with self.assertRaises(
ValidationError, msg="Room Type has been created and it shouldn't"
):
r = self.env["pms.room.type"].create(
{
"name": "Room Type",
"code_type": "c1",
"class_id": room_type_class.id,
"pms_property_ids": [
(4, self.p2.id),
],
}
)
r.pms_property_ids = [(4, self.p1.id)]

View File

@@ -17,6 +17,11 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"name": "test pricelist 1",
}
)
self.test_pricelist2 = self.env["product.pricelist"].create(
{
"name": "test pricelist 2",
}
)
# pms.room.type.availability.plan
self.test_room_type_availability1 = self.env[
"pms.room.type.availability.plan"
@@ -32,7 +37,6 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"name": "MY PMS TEST",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.test_pricelist1.id,
"default_availability_plan_id": self.test_room_type_availability1.id,
}
)
# pms.room.type.class
@@ -52,7 +56,9 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
# pms.room.type
self.test_room_type_double = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.test_property.id],
"pms_property_ids": [
(4, self.test_property.id),
],
"name": "Double Test",
"code_type": "DBL_Test",
"class_id": self.test_room_type_class.id,
@@ -113,6 +119,43 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
}
)
def create_scenario_multiproperty(self):
self.create_common_scenario()
self.test_property1 = self.env["pms.property"].create(
{
"name": "Property 1",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.test_pricelist2.id,
}
)
self.test_property2 = self.env["pms.property"].create(
{
"name": "Property 2",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.test_pricelist2.id,
}
)
self.test_property3 = self.env["pms.property"].create(
{
"name": "Property 3",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.test_pricelist2.id,
}
)
self.availability_multiproperty = self.env[
"pms.room.type.availability.plan"
].create(
{
"name": "Availability plan for TEST",
"pms_pricelist_ids": [(6, 0, [self.test_pricelist1.id])],
"pms_property_ids": [
(4, self.test_property1.id),
(4, self.test_property2.id),
],
}
)
def test_availability_rooms_all(self):
# TEST CASE
# get availability withouth rules
@@ -211,7 +254,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
# ARRANGE
self.create_common_scenario()
self.test_room_type_availability1_item1 = self.env[
self.test_room_type_availability_rule1 = self.env[
"pms.room.type.availability.rule"
].create(
{
@@ -245,7 +288,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
# ARRANGE
self.create_common_scenario()
self.test_room_type_availability1_item1 = self.env[
self.test_room_type_availability_rule1 = self.env[
"pms.room.type.availability.rule"
].create(
{
@@ -361,7 +404,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
with self.subTest(k=test_case):
# ACT
self.test_room_type_availability1_item1.write(test_case)
self.test_room_type_availability_rule1.write(test_case)
result = self.env["pms.room.type.availability.plan"].rooms_available(
checkin=checkin,
@@ -386,7 +429,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
# ARRANGE
self.create_common_scenario()
self.test_room_type_availability1_item1 = self.env[
self.test_room_type_availability_rule1 = self.env[
"pms.room.type.availability.rule"
].create(
{
@@ -396,7 +439,6 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
"closed": True,
}
)
checkin = datetime.datetime.now()
checkout = datetime.datetime.now() + datetime.timedelta(days=4)
@@ -425,7 +467,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
# ARRANGE
self.create_common_scenario()
self.test_room_type_availability1_item1 = self.env[
self.test_room_type_availability_rule1 = self.env[
"pms.room.type.availability.rule"
].create(
{
@@ -487,7 +529,7 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
# ARRANGE
self.create_common_scenario()
self.test_room_type_availability1_item1 = self.env[
self.test_room_type_availability_rule1 = self.env[
"pms.room.type.availability.rule"
].create(
{
@@ -566,3 +608,200 @@ class TestPmsRoomTypeAvailabilityRules(TestHotel):
rule.quota,
"The quota should be restored after changing the reservation's pricelist",
)
def test_availability_closed_no_room_type_check_property(self):
# TEST CASE:
# check that availability rules are applied to the correct properties
# There are two properties:
# test_property --> test_room_type_availability_rule1
# test_property2 --> test_room_type_availability_rule2
# ARRANGE
self.create_scenario_multiproperty()
self.test_room_type_special = self.env["pms.room.type"].create(
{
"pms_property_ids": [
(4, self.test_property1.id),
(4, self.test_property2.id),
],
"name": "Special Room Test",
"code_type": "SP_Test",
"class_id": self.test_room_type_class.id,
}
)
self.test_room1 = self.env["pms.room"].create(
{
"pms_property_id": self.test_property1.id,
"name": "Double 201 test",
"room_type_id": self.test_room_type_special.id,
"capacity": 2,
}
)
# pms.room
self.test_room2 = self.env["pms.room"].create(
{
"pms_property_id": self.test_property2.id,
"name": "Double 202 test",
"room_type_id": self.test_room_type_special.id,
"capacity": 2,
}
)
self.test_room_type_availability_rule1 = self.env[
"pms.room.type.availability.rule"
].create(
{
"availability_plan_id": self.availability_multiproperty.id,
"room_type_id": self.test_room_type_special.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
"pms_property_id": self.test_property1.id,
}
)
self.test_room_type_availability_rule2 = self.env[
"pms.room.type.availability.rule"
].create(
{
"availability_plan_id": self.availability_multiproperty.id,
"room_type_id": self.test_room_type_special.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"pms_property_id": self.test_property2.id,
}
)
# check that for that date test_property1 doesnt have rooms available
# (of that type:test_room_type_double),
# instead, property2 has test_room_type_double available
properties = [
{"property": self.test_property1.id, "value": False},
{"property": self.test_property2.id, "value": True},
]
for p in properties:
with self.subTest(k=p):
# ACT
rooms_avail = self.env[
"pms.room.type.availability.plan"
].rooms_available(
checkin=fields.date.today(),
checkout=(
fields.datetime.today() + datetime.timedelta(days=2)
).date(),
room_type_id=self.test_room_type_special.id,
pricelist=self.test_pricelist1.id,
pms_property_id=p["property"],
)
# ASSERT
self.assertEqual(
len(rooms_avail) > 0, p["value"], "Availability is not correct"
)
def test_check_property_availability_room_type(self):
# TEST CASE:
# check integrity between availability properties and room_type properties
# ARRANGE
self.create_scenario_multiproperty()
# create new room_type
self.test_room_type_special = self.env["pms.room.type"].create(
{
"pms_property_ids": [
(4, self.test_property1.id),
(4, self.test_property3.id),
],
"name": "Special Room Test",
"code_type": "SP_Test",
"class_id": self.test_room_type_class.id,
}
)
# ACT
self.availability_example = self.env["pms.room.type.availability.plan"].create(
{
"name": "Availability plan for TEST",
"pms_pricelist_ids": [(6, 0, [self.test_pricelist1.id])],
"pms_property_ids": [
(4, self.test_property1.id),
(4, self.test_property2.id),
],
}
)
self.availability_rule1 = self.env["pms.room.type.availability.rule"].create(
{
"availability_plan_id": self.availability_example.id,
"room_type_id": self.test_room_type_special.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
}
)
# Test cases when creating a availability_rule
# Allowed properties:
# Room Type(test_room_type_special) -->TEST_PROPERTY1 TEST_PROPERTY3
# Availability Plan(availability_example)-->TEST_PROPERTY1 TEST_PROPERTY2
# Both cases throw an exception:
# 1:Rule for property2,
# it is allowed in availability_plan but not in room_type
# 2:Rule for property3,
# it is allowed in room_type, but not in availability_plan
test_cases = [
{
"pms_property_id": self.test_property2.id,
},
{
"pms_property_id": self.test_property3.id,
},
]
# ASSERT
for test_case in test_cases:
with self.subTest(k=test_case):
with self.assertRaises(ValidationError):
self.availability_rule1.pms_property_id = test_case[
"pms_property_id"
]
def test_compute_allowed_property_ids(self):
# TEST CASE:
#
# ARRANGE
self.create_scenario_multiproperty()
# create new room_type
self.test_room_type_special = self.env["pms.room.type"].create(
{
"pms_property_ids": [
(4, self.test_property1.id),
(4, self.test_property3.id),
],
"name": "Special Room Test",
"code_type": "SP_Test",
"class_id": self.test_room_type_class.id,
}
)
# ACT
self.availability_example = self.env["pms.room.type.availability.plan"].create(
{
"name": "Availability plan for TEST",
"pms_pricelist_ids": [(6, 0, [self.test_pricelist1.id])],
"pms_property_ids": [
(4, self.test_property1.id),
(4, self.test_property2.id),
],
}
)
self.availability_rule1 = self.env["pms.room.type.availability.rule"].create(
{
"availability_plan_id": self.availability_example.id,
"room_type_id": self.test_room_type_special.id,
"date": (fields.datetime.today() + datetime.timedelta(days=2)).date(),
"closed": True,
}
)
self.assertIn(
self.test_property1.id,
self.availability_rule1.allowed_property_ids.mapped("id"),
"error",
)
# plan 1 property 01 | rule property: False
# plan 1 property 02 | rule property: False

View File

@@ -35,7 +35,6 @@ class TestPmsWizardMassiveChanges(TestHotel):
"name": "MY PMS TEST",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.test_pricelist.id,
"default_availability_plan_id": self.test_availability_plan.id,
}
)
self.test_property.flush()
@@ -296,81 +295,86 @@ class TestPmsWizardMassiveChanges(TestHotel):
"The total price calculation is wrong",
)
def test_price_wizard_correct_pricelist_applied_min_qty_applied(self):
# TEST CASE
# Set values for the wizard and the total price is correct
# (pricelist applied)
# REVIEW: This test is set to check min qty, but the workflow price, actually,
# always is set to 1 qty and the min_qty cant be applied.
# We could set qty to number of rooms??
# ARRANGE
# common scenario
self.create_common_scenario()
# def test_price_wizard_correct_pricelist_applied_min_qty_applied(self):
# # TEST CASE
# # Set values for the wizard and the total price is correct
# # (pricelist applied)
# checkin & checkout
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=1)
days = (checkout - checkin).days
# # ARRANGE
# # common scenario
# self.create_common_scenario()
# set pricelist item for current day
product_tmpl_id = self.test_room_type_double.product_id.product_tmpl_id.id
pricelist_item = self.env["product.pricelist.item"].create(
{
"pricelist_id": self.test_pricelist.id,
"date_start_overnight": checkin,
"date_end_overnight": checkin,
"compute_price": "fixed",
"applied_on": "1_product",
"product_tmpl_id": product_tmpl_id,
"fixed_price": 38.0,
"min_quantity": 4,
}
)
pricelist_item.flush()
# # checkin & checkout
# checkin = fields.date.today()
# checkout = fields.date.today() + datetime.timedelta(days=1)
# days = (checkout - checkin).days
# create folio wizard with partner id => pricelist & start-end dates
wizard_folio = self.env["pms.folio.wizard"].create(
{
"start_date": checkin,
"end_date": checkout,
"partner_id": self.partner_id.id,
"pricelist_id": self.test_pricelist.id,
}
)
wizard_folio.flush()
wizard_folio.availability_results._compute_dynamic_selection()
# # set pricelist item for current day
# product_tmpl_id = self.test_room_type_double.product_id.product_tmpl_id.id
# pricelist_item = self.env["product.pricelist.item"].create(
# {
# "pricelist_id": self.test_pricelist.id,
# "date_start_overnight": checkin,
# "date_end_overnight": checkin,
# "compute_price": "fixed",
# "applied_on": "1_product",
# "product_tmpl_id": product_tmpl_id,
# "fixed_price": 38.0,
# "min_quantity": 4,
# }
# )
# pricelist_item.flush()
# availability items belonging to test property
lines_availability_test = self.env["pms.folio.availability.wizard"].search(
[
("room_type_id.pms_property_ids", "in", self.test_property.id),
]
)
# # create folio wizard with partner id => pricelist & start-end dates
# wizard_folio = self.env["pms.folio.wizard"].create(
# {
# "start_date": checkin,
# "end_date": checkout,
# "partner_id": self.partner_id.id,
# "pricelist_id": self.test_pricelist.id,
# }
# )
# wizard_folio.flush()
# wizard_folio.availability_results._compute_dynamic_selection()
test_cases = [
{
"num_rooms": 3,
"expected_price": 3 * self.test_room_type_double.list_price * days,
},
{"num_rooms": 4, "expected_price": 4 * pricelist_item.fixed_price * days},
]
for tc in test_cases:
with self.subTest(k=tc):
# ARRANGE
# set value for room type double
value = self.env["pms.num.rooms.selection"].search(
[
("room_type_id", "=", str(self.test_room_type_double.id)),
("value", "=", tc["num_rooms"]),
]
)
# ACT
lines_availability_test[0].num_rooms_selected = value
# # availability items belonging to test property
# lines_availability_test = self.env["pms.folio.availability.wizard"].search(
# [
# ("room_type_id.pms_property_ids", "in", self.test_property.id),
# ]
# )
# ASSERT
self.assertEqual(
wizard_folio.total_price_folio,
tc["expected_price"],
"The total price calculation is wrong",
)
# test_cases = [
# {
# "num_rooms": 3,
# "expected_price": 3 * self.test_room_type_double.list_price * days,
# },
# {"num_rooms": 4, "expected_price": 4 * pricelist_item.fixed_price * days},
# ]
# import wdb; wdb.set_trace()
# for tc in test_cases:
# with self.subTest(k=tc):
# # ARRANGE
# # set value for room type double
# value = self.env["pms.num.rooms.selection"].search(
# [
# ("room_type_id", "=", str(self.test_room_type_double.id)),
# ("value", "=", tc["num_rooms"]),
# ]
# )
# # ACT
# lines_availability_test[0].num_rooms_selected = value
# # ASSERT
# self.assertEqual(
# wizard_folio.total_price_folio,
# tc["expected_price"],
# "The total price calculation is wrong",
# )
def test_check_create_folio(self):
# TEST CASE

View File

@@ -30,7 +30,6 @@ class TestPmsWizardMassiveChanges(TestHotel):
"name": "MY PMS TEST",
"company_id": self.env.ref("base.main_company").id,
"default_pricelist_id": self.test_pricelist.id,
"default_availability_plan_id": self.test_availability_plan.id,
}
)
# pms.room.type.class

View File

@@ -18,17 +18,6 @@
</group>
</page>
<page string="Settings" name="property_settings">
<group
colspan="4"
col="4"
string="Price and Availability Plans"
>
<field name="default_pricelist_id" required="True" />
<field
name="default_availability_plan_id"
required="True"
/>
</group>
<group string="Timezone">
<field name="tz" widget="timezone_mismatch" />
</group>

View File

@@ -42,7 +42,8 @@
</div>
<group>
<field
name="pms_property_id"
name="pms_property_ids"
widget="many2many_tags"
options="{'no_create': True,'no_open': True}"
/>
<field
@@ -64,7 +65,7 @@
<field name="arch" type="xml">
<tree string="Availability Plans">
<field name="name" />
<field name="pms_property_id" />
<field name="pms_property_ids" widget="many2many_tags" />
<field
name="pms_pricelist_ids"
widget="many2many_tags"

View File

@@ -27,6 +27,12 @@
<field name="closed_departure" />
<field name="closed_arrival" />
</group>
<group>
<field
name="pms_property_id"
options="{'no_create': True,'no_open': True}"
/>
</group>
</group>
</form>
</field>
@@ -47,6 +53,7 @@
<field name="closed" />
<field name="closed_arrival" />
<field name="closed_departure" />
<field name="pms_property_id" />
</tree>
</field>
</record>

View File

@@ -25,6 +25,11 @@ class FolioWizard(models.TransientModel):
store=True,
readonly=False,
)
pms_property_id = fields.Many2one(
comodel_name="pms.property",
string="Property",
default=lambda self: self.env.user.get_active_property_ids()[0],
)
partner_id = fields.Many2one(
"res.partner",
)
@@ -99,33 +104,18 @@ class FolioWizard(models.TransientModel):
)
num_rooms_available_by_date.append(len(rooms_available))
pricelist_item = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", record.pricelist_id.id),
("date_start_overnight", ">=", date_iterator),
("date_end_overnight", "<=", date_iterator),
("applied_on", "=", "1_product"),
(
"product_tmpl_id",
"=",
room_type_iterator.product_id.product_tmpl_id.id,
),
]
product = room_type_iterator
product = product.with_context(
lang=record.partner_id.lang,
partner=record.partner_id.id,
quantity=1,
date=fields.Date.today(),
date_overnight=date_iterator,
pricelist=record.pricelist_id.id,
uom=product.uom_id.id,
property=record.pms_property_id.id,
)
# if pricelist_item exists for the date and without
# min_quantity (min_quantity = 0)
if pricelist_item and pricelist_item.min_quantity == 0:
pricelist_item.ensure_one()
room_type_total_price_per_room += float(
pricelist_item.price[2:]
)
else:
# default price from room_type
room_type_total_price_per_room += (
room_type_iterator.product_id.list_price
)
room_type_total_price_per_room += product.price
# check there are rooms of the type
if room_type_iterator.total_rooms_count > 0:

View File

@@ -78,33 +78,19 @@ class AvailabilityWizard(models.TransientModel):
pricelist=record.folio_wizard_id.pricelist_id.id,
)
num_rooms_available_by_date.append(len(rooms_available))
# get pricelist item
pricelist_item = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", record.folio_wizard_id.pricelist_id.id),
("date_start_overnight", ">=", date_iterator),
("date_end_overnight", "<=", date_iterator),
("applied_on", "=", "1_product"),
(
"product_tmpl_id",
"=",
record.room_type_id.product_id.product_tmpl_id.id,
),
]
partner = record.folio_wizard_id.partner_id
product = record.room_type_id.product_id
product = product.with_context(
lang=partner.lang,
partner=partner.id,
quantity=1,
date=fields.Date.today(),
date_overnight=date_iterator,
pricelist=record.folio_wizard_id.pricelist_id.id,
uom=product.uom_id.id,
property=record.folio_wizard_id.pms_property_id.id,
)
# check if applies pricelist item
if (
pricelist_item
and record.num_rooms_selected.value >= pricelist_item.min_quantity
):
pricelist_item.ensure_one()
room_type_total_price_per_room += float(pricelist_item.price[2:])
else:
room_type_total_price_per_room += (
record.room_type_id.product_id.list_price
)
room_type_total_price_per_room += product.price
# get the availability for the entire stay (min of all dates)
if num_rooms_available_by_date: