[IMP] pms: manage pricelist of board services

This commit is contained in:
miguelpadin
2021-06-03 00:21:27 +02:00
parent 18318dd86b
commit e8bb9fd0d0
10 changed files with 1688 additions and 167 deletions

View File

@@ -109,6 +109,15 @@ class PmsBoardServiceRoomType(models.Model):
total += service.amount
record.update({"amount": total})
def name_get(self):
res = []
for record in self:
name = "{} - {}".format(
record.pms_board_service_id.name, record.pms_room_type_id.name
)
res.append((record.id, name))
return res
@api.constrains("by_default")
def constrains_duplicated_board_defaul(self):
for record in self:

View File

@@ -544,10 +544,10 @@ class PmsService(models.Model):
board_service=board_room_type.id if board_room_type else False,
uom=self.product_id.uom_id.id,
fiscal_position=False,
property=self.pms_property_id.id,
property=self.reservation_id.pms_property_id.id,
)
if date:
product_context["date_overnight"] = date
product_context["consumption_date"] = date
if reservation and self.is_board_service:
product_context["board_service"] = reservation.board_service_room_id.id
product = self.product_id.with_context(product_context)

View File

@@ -69,6 +69,7 @@ class ProductPricelist(models.Model):
def _compute_price_rule_get_items(
self, products_qty_partner, date, uom_id, prod_tmpl_ids, prod_ids, categ_ids
):
board_service = True if self._context.get("board_service") else False
if (
"property" in self._context
and self._context["property"]
@@ -84,8 +85,6 @@ class ProductPricelist(models.Model):
ON item.pricelist_id = cab.product_pricelist_id
LEFT JOIN product_pricelist_item_pms_property_rel lin
ON item.id = lin.product_pricelist_item_id
LEFT JOIN board_service_pricelist_item_rel board
ON item.id = board.pricelist_item_id
WHERE (lin.pms_property_id = %s OR lin.pms_property_id IS NULL)
AND (cab.pms_property_id = %s OR cab.pms_property_id IS NULL)
AND (item.product_tmpl_id IS NULL
@@ -119,8 +118,6 @@ class ProductPricelist(models.Model):
prod_tmpl_ids,
prod_ids,
categ_ids,
# on_board_service_bool,
# board_service_id,
self.id,
date,
date,
@@ -131,6 +128,13 @@ class ProductPricelist(models.Model):
item_ids = [x[0] for x in self.env.cr.fetchall()]
items = self.env["product.pricelist.item"].browse(item_ids)
if board_service:
items = items.filtered(
lambda x: x.board_service_room_type_id.id
== self._context.get("board_service")
)
else:
items = items.filtered(lambda x: not x.board_service_room_type_id.id)
else:
items = super(ProductPricelist, self)._compute_price_rule_get_items(
products_qty_partner, date, uom_id, prod_tmpl_ids, prod_ids, categ_ids

View File

@@ -1,6 +1,6 @@
# 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
class ProductPricelistItem(models.Model):
@@ -26,18 +26,10 @@ class ProductPricelistItem(models.Model):
string="End Date Overnight",
help="End date to apply daily pricelist items",
)
on_board_service = fields.Boolean(
string="On Board Service",
help="Those included in Board Services",
)
board_service_room_type_ids = fields.Many2many(
string="Board Services",
help="""Specify a Board services on Room Types.""",
board_service_room_type_id = fields.Many2one(
string="Board Service",
help="Specify a Board services on Room Types.",
comodel_name="pms.board.service.room.type",
relation="board_service_pricelist_item_rel",
column1="pricelist_item_id",
column2="board_service_id",
ondelete="cascade",
check_pms_properties=True,
)
pricelist_id = fields.Many2one(
@@ -55,3 +47,68 @@ class ProductPricelistItem(models.Model):
help="Product template associated with the item",
check_pms_properties=True,
)
allowed_board_service_product_ids = fields.Many2many(
string="Allowed board service products",
comodel_name="product.product",
store=True,
readonly=False,
compute="_compute_allowed_board_service_product_ids",
)
allowed_board_service_room_type_ids = fields.Many2many(
string="Allowed board service room types",
comodel_name="pms.board.service.room.type",
store=True,
readonly=False,
compute="_compute_allowed_board_service_room_type_ids",
)
@api.depends("board_service_room_type_id")
def _compute_allowed_board_service_product_ids(self):
for record in self:
domain = []
if record.board_service_room_type_id:
domain.append(
(
"id",
"in",
record.board_service_room_type_id.board_service_line_ids.mapped(
"product_id"
).ids,
)
)
allowed_board_service_product_ids = self.env["product.product"].search(
domain
)
record.allowed_board_service_product_ids = allowed_board_service_product_ids
@api.depends("product_id")
def _compute_allowed_board_service_room_type_ids(self):
for record in self:
allowed_board_service_room_type_ids = []
all_board_service_room_type_ids = self.env[
"pms.board.service.room.type"
].search([])
if record.product_id:
for board_service_room_type_id in all_board_service_room_type_ids:
if (
record.product_id
in board_service_room_type_id.board_service_line_ids.mapped(
"product_id"
)
):
allowed_board_service_room_type_ids.append(
board_service_room_type_id.id
)
else:
allowed_board_service_room_type_ids = (
all_board_service_room_type_ids.ids
)
domain = []
if allowed_board_service_room_type_ids:
domain.append(("id", "in", allowed_board_service_room_type_ids))
record.allowed_board_service_room_type_ids = (
self.env["pms.board.service.room.type"].search(domain)
if domain
else False
)

View File

@@ -2,6 +2,7 @@ import datetime
from freezegun import freeze_time
from odoo import fields
from odoo.exceptions import UserError, ValidationError
from odoo.tests import common, tagged
@@ -81,12 +82,51 @@ class TestPmsPricelist(common.SavepointCase):
}
)
# pms.room
self.room1 = self.env["pms.room"].create(
{
"pms_property_id": self.property1.id,
"name": "Single 101",
"room_type_id": self.room_type.id,
"capacity": 2,
}
)
self.pricelist = self.env["product.pricelist"].create(
{
"name": "pricelist_1",
"pms_property_ids": [self.property1.id, self.property2.id],
}
)
# product.product 1
self.test_service_breakfast = self.env["product.product"].create(
{"name": "Test Breakfast"}
)
# pms.board.service
self.test_board_service_only_breakfast = self.env["pms.board.service"].create(
{
"name": "Test Only Breakfast",
"default_code": "CB1",
}
)
# pms.board.service.line
self.board_service_line_single_1 = self.env["pms.board.service.line"].create(
{
"product_id": self.test_service_breakfast.id,
"pms_board_service_id": self.test_board_service_only_breakfast.id,
}
)
# pms.board.service.room.type
self.test_board_service_single = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.room_type.id,
"pms_board_service_id": self.test_board_service_only_breakfast.id,
}
)
self.partner1 = self.env["res.partner"].create({"name": "Carles"})
def test_advanced_pricelist_exists(self):
@@ -200,6 +240,555 @@ class TestPmsPricelist(common.SavepointCase):
}
)
# board services pricelist items
def test_board_service_pricelist_item_apply_sale_dates(self):
# TEST CASE
# Pricelist item is created to apply on board services at SALE date.
# The reservation created take into account the board service
# pricelist item created previously according to the SALE date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"board_service_room_type_id": self.test_board_service_single.id,
"fixed_price": expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"board_service_room_id": self.test_board_service_single.id,
}
)
# ASSERT
self.assertEqual(
reservation_created.service_ids.price_subtotal,
expected_price,
"The reservation created should take into account the board service"
" pricelist item created previously according to the SALE date.",
)
def test_board_service_pricelist_item_not_apply_sale_dates(self):
# TEST CASE
# Pricelist item is created to apply on board services at SALE date.
# The reservation created DONT take into account the board service pricelist
# item created previously according to the SALE date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=1)
date_to = fields.date.today() + datetime.timedelta(days=1)
not_expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"board_service_room_type_id": self.test_board_service_single.id,
"fixed_price": not_expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"board_service_room_id": self.test_board_service_single.id,
}
)
# ASSERT
self.assertNotEqual(
reservation_created.service_ids.price_subtotal,
not_expected_price,
"The reservation created shouldnt take into account the board service pricelist"
" item created previously according to the SALE date.",
)
def test_board_service_pricelist_item_apply_overnight_dates(self):
# TEST CASE
# Pricelist item is created to apply on board services
# at CONSUMPTION date.
# The reservation created take into account the board service
# pricelist item created previously according to the CONSUMPTION date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=1)
date_to = fields.date.today() + datetime.timedelta(days=1)
expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start_overnight": date_from,
"date_end_overnight": date_to,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"board_service_room_type_id": self.test_board_service_single.id,
"fixed_price": expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"board_service_room_id": self.test_board_service_single.id,
}
)
# ASSERT
self.assertEqual(
reservation_created.service_ids.price_subtotal,
expected_price,
"The reservation created should take into account the board service"
" pricelist item created previously according to the CONSUMPTION date.",
)
def test_board_service_pricelist_item_not_apply_overnight_dates(self):
# TEST CASE
# Pricelist item is created to apply on board services
# at CONSUMPTION date.
# The reservation created DONT take into account the board service
# pricelist item created previously according to the CONSUMPTION date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=2)
date_to = fields.date.today() + datetime.timedelta(days=2)
not_expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"board_service_room_type_id": self.test_board_service_single.id,
"fixed_price": not_expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"board_service_room_id": self.test_board_service_single.id,
}
)
# ASSERT
self.assertNotEqual(
reservation_created.service_ids.price_subtotal,
not_expected_price,
"The reservation created shouldnt take into account the board service"
" pricelist item created previously according to the CONSUMPTION date.",
)
# room types pricelist items
def test_room_type_pricelist_item_apply_sale_dates(self):
# TEST CASE
# Pricelist item is created to apply on room types
# at SALE date.
# The reservation created take into account the room type
# pricelist item created previously according to the SALE date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
}
)
# ASSERT
self.assertEqual(
reservation_created.price_subtotal,
expected_price,
"The reservation created should take into account the room type"
" pricelist item created previously according to the SALE date.",
)
def test_room_type_pricelist_item_not_apply_sale_dates(self):
# TEST CASE
# Pricelist item is created to apply on room types
# at SALE date.
# The reservation created DONT take into account the room type
# pricelist item created previously according to the SALE date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=1)
date_to = fields.date.today() + datetime.timedelta(days=1)
not_expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": not_expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
}
)
# ASSERT
self.assertNotEqual(
reservation_created.price_subtotal,
not_expected_price,
"The reservation created shouldnt take into account the room type"
" pricelist item created previously according to the SALE date.",
)
def test_room_type_pricelist_item_apply_overnight_dates(self):
# TEST CASE
# Pricelist item is created to apply on room types
# at CONSUMPTION date.
# The reservation created take into account the room type
# pricelist item created previously according to the CONSUMPTION date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=1)
date_to = fields.date.today() + datetime.timedelta(days=1)
expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start_overnight": date_from,
"date_end_overnight": date_to,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
}
)
# ASSERT
self.assertEqual(
reservation_created.price_subtotal,
expected_price,
"The reservation created should take into account the room type"
" pricelist item created previously according to the CONSUMPTION date.",
)
def test_room_type_pricelist_item_not_apply_overnight_dates(self):
# TEST CASE
# Pricelist item is created to apply on room types
# at CONSUMPTION date.
# The reservation created DONT take into account the room type
# pricelist item created previously according to the CONSUMPTION date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=2)
date_to = fields.date.today() + datetime.timedelta(days=2)
not_expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.room_type.product_id.id,
"fixed_price": not_expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
}
)
# ASSERT
self.assertNotEqual(
reservation_created.price_subtotal,
not_expected_price,
"The reservation created shouldnt take into account the room type"
" pricelist item created previously according to the CONSUMPTION date.",
)
# services pricelist items
def test_service_pricelist_item_apply_sale_dates(self):
# TEST CASE
# Pricelist item is created to apply on services at SALE date.
# The reservation created take into account the service
# pricelist item created previously according to the SALE date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"fixed_price": expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"service_ids": [(0, 0, {"product_id": self.test_service_breakfast.id})],
}
)
# ASSERT
self.assertEqual(
reservation_created.service_ids.price_subtotal,
expected_price,
"The reservation created should take into account the service"
" pricelist item created previously according to the SALE date.",
)
def test_service_pricelist_item_not_apply_sale_dates(self):
# TEST CASE
# Pricelist item is created to apply on services at SALE date.
# The reservation created DONT take into account the service pricelist
# item created previously according to the SALE date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=1)
date_to = fields.date.today() + datetime.timedelta(days=1)
not_expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"fixed_price": not_expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"service_ids": [(0, 0, {"product_id": self.test_service_breakfast.id})],
}
)
# ASSERT
self.assertNotEqual(
reservation_created.service_ids.price_subtotal,
not_expected_price,
"The reservation created shouldnt take into account the service pricelist"
" item created previously according to the SALE date.",
)
def test_service_pricelist_item_apply_overnight_dates(self):
# TEST CASE
# Pricelist item is created to apply on services at CONSUMPTION date.
# The reservation created take into account the service
# pricelist item created previously according to the CONSUMPTION date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=1)
date_to = fields.date.today() + datetime.timedelta(days=1)
expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start_overnight": date_from,
"date_end_overnight": date_to,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"fixed_price": expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now() + datetime.timedelta(days=1),
"checkout": datetime.datetime.now() + datetime.timedelta(days=2),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"service_ids": [(0, 0, {"product_id": self.test_service_breakfast.id})],
}
)
# ASSERT
self.assertEqual(
reservation_created.service_ids.price_subtotal,
expected_price,
"The reservation created should take into account the service"
" pricelist item created previously according to the CONSUMPTION date.",
)
def test_service_pricelist_item_not_apply_overnight_dates(self):
# TEST CASE
# Pricelist item is created to apply on services at CONSUMPTION date.
# The reservation created DONT take into account the service pricelist
# item created previously according to the CONSUMPTION date.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today() + datetime.timedelta(days=2)
date_to = fields.date.today() + datetime.timedelta(days=2)
not_expected_price = 1000.0
vals = {
"pricelist_id": self.pricelist.id,
"date_start": datetime.datetime.combine(
date_from, datetime.datetime.min.time()
),
"date_end": datetime.datetime.combine(
date_to, datetime.datetime.max.time()
),
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": self.test_service_breakfast.id,
"fixed_price": not_expected_price,
"pms_property_ids": [self.property1.id],
}
self.env["product.pricelist.item"].create(vals)
# ACT
reservation_created = self.env["pms.reservation"].create(
{
"partner_id": self.partner1.id,
"checkin": datetime.datetime.now(),
"checkout": datetime.datetime.now() + datetime.timedelta(days=1),
"preferred_room_id": self.room1.id,
"pms_property_id": self.property1.id,
"pricelist_id": self.pricelist.id,
"service_ids": [(0, 0, {"product_id": self.test_service_breakfast.id})],
}
)
# ASSERT
self.assertNotEqual(
reservation_created.service_ids.price_subtotal,
not_expected_price,
"The reservation created shouldnt take into account the service pricelist "
"item created previously according to the CONSUMPTION date.",
)
@freeze_time("2000-01-01")
def test_pricelist_daily_failed(self):
self.create_common_scenario()

View File

@@ -61,7 +61,6 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
self.test_room_type_class = self.env["pms.room.type.class"].create(
{"name": "Room", "default_code": "ROOM"}
)
# pms.room.type
self.test_room_type_single = self.env["pms.room.type"].create(
{
@@ -71,7 +70,6 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
"class_id": self.test_room_type_class.id,
}
)
# pms.room.type
self.test_room_type_double = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.test_property.id],
@@ -81,6 +79,62 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
}
)
# pms.board.service
self.test_board_service_only_breakfast = self.env["pms.board.service"].create(
{
"name": "Test Only Breakfast",
"default_code": "CB1",
}
)
self.test_board_service_half_board = self.env["pms.board.service"].create(
{
"name": "Test Half Board",
"default_code": "CB2",
}
)
# product.product 1
self.test_service_breakfast = self.env["product.product"].create(
{"name": "Test Breakfast"}
)
self.test_service_dinner = self.env["product.product"].create(
{"name": "Test Dinner"}
)
self.test_service_spa = self.env["product.product"].create({"name": "Test Spa"})
# pms.board.service.room.type
self.test_board_service_single = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.test_room_type_single.id,
"pms_board_service_id": self.test_board_service_only_breakfast.id,
}
)
self.test_board_service_double = self.env["pms.board.service.room.type"].create(
{
"pms_room_type_id": self.test_room_type_double.id,
"pms_board_service_id": self.test_board_service_half_board.id,
}
)
# pms.board.service.line
self.board_service_line_single_1 = self.env["pms.board.service.line"].create(
{
"product_id": self.test_service_breakfast.id,
"pms_board_service_id": self.test_board_service_only_breakfast.id,
}
)
self.board_service_line_double_1 = self.env["pms.board.service.line"].create(
{
"product_id": self.test_service_breakfast.id,
"pms_board_service_id": self.test_board_service_half_board.id,
}
)
self.board_service_line_double_2 = self.board_service_line = self.env[
"pms.board.service.line"
].create(
{
"product_id": self.test_service_dinner.id,
"pms_board_service_id": self.test_board_service_half_board.id,
}
)
# MASSIVE CHANGE WIZARD TESTS ON AVAILABILITY RULES
@freeze_time("1980-12-01")
@@ -498,7 +552,7 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
}
)
wizard = self.env["pms.massive.changes.wizard"].create(
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"availability_plan_ids": [
@@ -522,7 +576,7 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
self.test_availability_plan.id,
self.test_availability_plan_2.id,
]
for avail_plan_id in wizard["availability_plan_ids"].ids:
for avail_plan_id in wizard_result["availability_plan_ids"].ids:
with self.subTest(k=avail_plan_id):
self.assertIn(
avail_plan_id,
@@ -541,7 +595,7 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
}
)
wizard = self.env["pms.massive.changes.wizard"].create(
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [
@@ -555,18 +609,18 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
)
pricelist_ids = [self.test_pricelist.id, self.test_pricelist_2.id]
for pricelist_id in wizard["pricelist_ids"].ids:
for pricelist_id in wizard_result["pricelist_ids"].ids:
with self.subTest(k=pricelist_id):
self.assertIn(
pricelist_id, pricelist_ids, "Pricelist has not been write "
)
@freeze_time("2025-02-01")
def test_several_room_types(self):
def test_several_room_types_pricelist(self):
self.create_common_scenario()
date_from = fields.date.today()
date_to = date_from + datetime.timedelta(days=6)
wizard = self.env["pms.massive.changes.wizard"].create(
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
@@ -584,8 +638,341 @@ class TestPmsWizardMassiveChanges(common.SavepointCase):
)
room_type_ids = [self.test_room_type_double.id, self.test_room_type_double.id]
for room_type_id in wizard["room_type_ids"].ids:
for room_type_id in wizard_result["room_type_ids"].ids:
with self.subTest(k=room_type_id):
self.assertIn(
room_type_id, room_type_ids, "Room type has not been write "
)
@freeze_time("2025-02-01")
def test_several_room_types_availability_plan(self):
self.create_common_scenario()
date_from = fields.date.today()
date_to = date_from + datetime.timedelta(days=6)
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "availability_plan",
"availability_plan_ids": [(6, 0, [self.test_availability_plan.id])],
"room_type_ids": [
(
6,
0,
[self.test_room_type_double.id, self.test_room_type_double.id],
)
],
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
}
)
room_type_ids = [self.test_room_type_double.id, self.test_room_type_double.id]
for room_type_id in wizard_result["room_type_ids"].ids:
with self.subTest(k=room_type_id):
self.assertIn(
room_type_id, room_type_ids, "Room type has not been write "
)
@freeze_time("2025-02-01")
def test_one_board_service_room_type_no_board_service(self):
# TEST CASE
# Call to wizard with one board service room type and no
# board service.
# The wizard must create as many pricelist items as there
# are services on the given board service.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
"apply_pricelists_on": "board_services",
"board_service_room_type_ids": [
(
6,
0,
[self.test_board_service_single.id],
)
],
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
"date_types": "consumption_dates",
}
)
# ACT
wizard_result.apply_massive_changes()
items_created = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", self.test_pricelist.id),
("pms_property_ids", "=", self.test_property.id),
("product_id", "=", self.board_service_line_single_1.product_id.id),
]
)
# ASSERT
self.assertIn(
self.test_service_breakfast,
items_created.mapped("product_id"),
"The wizard must create as many pricelist items as there "
"are services on the given board service.",
)
@freeze_time("2025-02-01")
def test_one_board_service_room_type_with_board_service(self):
# TEST CASE
# Call to wizard with one board service room type and
# board service.
# The wizard must create one pricelist items with
# the board service given.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
"apply_pricelists_on": "board_services",
"board_service_room_type_ids": [
(
6,
0,
[self.test_board_service_single.id],
)
],
"board_service": self.board_service_line_single_1.product_id.id,
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
"date_types": "consumption_dates",
}
)
# ACT
wizard_result.apply_massive_changes()
items_created = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", self.test_pricelist.id),
("pms_property_ids", "=", self.test_property.id),
("product_id", "=", self.board_service_line_single_1.product_id.id),
]
)
# ASSERT
self.assertIn(
self.test_service_breakfast,
items_created.mapped("product_id"),
"The wizard must create one pricelist items with "
" the board service given.",
)
@freeze_time("2025-02-01")
def test_several_board_service_room_type_no_board_service(self):
# TEST CASE
# Call to wizard with several board service room type and no
# board service.
# The wizard must create as many pricelist items as there
# are services on the given board services.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
product_ids_expected = (
self.test_board_service_double.pms_board_service_id.board_service_line_ids.mapped(
"product_id"
).ids
+ self.test_board_service_single.pms_board_service_id.board_service_line_ids.mapped(
"product_id"
).ids
)
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
"apply_pricelists_on": "board_services",
"board_service_room_type_ids": [
(
6,
0,
[
self.test_board_service_single.id,
self.test_board_service_double.id,
],
)
],
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
"date_types": "consumption_dates",
}
)
# ACT
wizard_result.apply_massive_changes()
items_created = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", self.test_pricelist.id),
("pms_property_ids", "=", self.test_property.id),
("product_id", "in", product_ids_expected),
]
)
# ASSERT
self.assertEqual(
set(product_ids_expected),
set(items_created.mapped("product_id").ids),
"The wizard should create as many pricelist items as there"
" are services on the given board services.",
)
@freeze_time("2025-02-01")
def test_several_board_service_room_type_with_board_service(self):
# TEST CASE
# Call to wizard with several board service room types and
# board service.
# The wizard must create as many pricelist items as there
# are services on the given board services.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
board_service_id_double = self.test_board_service_double.pms_board_service_id
board_service_id_single = self.test_board_service_single.pms_board_service_id
product_ids_expected = list(
set(board_service_id_double.board_service_line_ids.mapped("product_id").ids)
& set(
board_service_id_single.board_service_line_ids.mapped("product_id").ids
)
)
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
"apply_pricelists_on": "board_services",
"board_service_room_type_ids": [
(
6,
0,
[
self.test_board_service_single.id,
self.test_board_service_double.id,
],
)
],
"board_service": self.test_service_breakfast.id,
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
"date_types": "consumption_dates",
}
)
# ACT
wizard_result.apply_massive_changes()
items_created = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", self.test_pricelist.id),
("pms_property_ids", "=", self.test_property.id),
("product_id", "in", product_ids_expected),
]
)
# ASSERT
self.assertEqual(
set(product_ids_expected),
set(items_created.mapped("product_id").ids),
"The wizard should create as many pricelist items as there"
" are services on the given board services.",
)
@freeze_time("2025-02-01")
def test_service(self):
# TEST CASE
# Call to wizard with one service (product_id)
# The wizard must create one pricelist items with
# the given service (product_id).
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
"apply_pricelists_on": "service",
"service": self.test_service_spa.id,
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
"date_types": "consumption_dates",
}
)
# ACT
wizard_result.apply_massive_changes()
items_created = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", self.test_pricelist.id),
("pms_property_ids", "=", self.test_property.id),
("product_id", "=", self.test_service_spa.id),
]
)
# ASSERT
self.assertIn(
self.test_service_spa.id,
items_created.mapped("product_id").ids,
"The wizard should create one pricelist items with"
" the given service (product_id).",
)
@freeze_time("2025-02-01")
def test_sale_dates(self):
# TEST CASE
# Call to wizard with one service (product_id)
# and dates of SALE
# The wizard must create one pricelist items with
# the given service (product_id) and dates of SALE.
# ARRANGE
self.create_common_scenario()
date_from = fields.date.today()
date_to = fields.date.today()
wizard_result = self.env["pms.massive.changes.wizard"].create(
{
"massive_changes_on": "pricelist",
"pricelist_ids": [(6, 0, [self.test_pricelist.id])],
"apply_pricelists_on": "service",
"service": self.test_service_spa.id,
"pms_property_ids": [self.test_property.id],
"start_date": date_from,
"end_date": date_to,
"date_types": "sale_dates",
}
)
# ACT
wizard_result.apply_massive_changes()
items_created = self.env["product.pricelist.item"].search(
[
("pricelist_id", "=", self.test_pricelist.id),
("pms_property_ids", "=", self.test_property.id),
("product_id", "=", self.test_service_spa.id),
]
)
expected_dates = [
datetime.datetime.combine(date_from, datetime.datetime.min.time()),
datetime.datetime.combine(date_to, datetime.datetime.max.time()),
]
# ASSERT
self.assertEqual(
expected_dates,
items_created.mapped("date_start") + items_created.mapped("date_end"),
"The wizard should create one pricelist items with"
" the given service (product_id) and dates of sale.",
)

View File

@@ -5,13 +5,15 @@
<field name="inherit_id" ref="product.product_pricelist_item_form_view" />
<field name="arch" type="xml">
<xpath expr="//field[@name='applied_on']" position="before">
<field name="on_board_service" />
<field name="allowed_board_service_product_ids" invisible="1" />
<field name="allowed_board_service_room_type_ids" invisible="1" />
<field
name="board_service_room_type_ids"
widget="many2many_tags"
name="board_service_room_type_id"
options="{'no_create': True,'no_open': True}"
attrs="{'invisible': [('on_board_service','=',False)]}"
domain="[('id', 'in',allowed_board_service_room_type_ids)]"
/>
</xpath>
<xpath expr="//field[@name='min_quantity']" position="before">
<field
@@ -24,17 +26,26 @@
<field name="date_start_overnight" />
<field name="date_end_overnight" />
</xpath>
<xpath expr="//field[@name='product_id']" position="attributes">
<attribute
name="domain"
>[('id', 'in',allowed_board_service_product_ids)]</attribute>
</xpath>
</field>
</record>
<record id="product_pricelist_item_view_tree" model="ir.ui.view">
<field name="model">product.pricelist.item</field>
<field name="arch" type="xml">
<tree>
<field name="pricelist_id" />
<field string="Applicable on" name="name" />
<field name="date_start_overnight" />
<field name="date_end_overnight" />
<field name="price" />
<field name="pricelist_id" />
<field string="Applicable on" name="name" />
<field name="board_service_room_type_id" />
<field string="Sale Date Start" name="date_start" />
<field string="Sale Date End" name="date_end" />
<field name="date_start_overnight" />
<field name="date_end_overnight" />
<field name="price" />
<field name="pms_property_ids" widget="many2many_tags" />
</tree>
</field>
</record>

View File

@@ -29,6 +29,18 @@
</xpath>
<xpath
expr="//field[@name='item_ids']/tree/field[@name='name']"
position="after"
>
<field
name="board_service_room_type_id"
options="{'no_create': True, 'no_open': True}"
/>
</xpath>
<xpath expr="//widget[@name='web_ribbon']" position="after">
<div class="oe_button_box " name="button_box">
<button

View File

@@ -17,6 +17,7 @@ class AvailabilityWizard(models.TransientModel):
self.env.user.get_active_property_ids()[0]
),
check_pms_properties=True,
required=True,
)
massive_changes_on = fields.Selection(
string="On",
@@ -25,17 +26,17 @@ class AvailabilityWizard(models.TransientModel):
("availability_plan", "Availability Plan"),
],
default=lambda self: "availability_plan"
if self._context.get("availability_plan_ids")
if self._context.get("availability_plan_id")
else "pricelist"
if self._context.get("pricelist_ids")
if self._context.get("pricelist_id")
else "availability_plan",
required=True,
)
availability_plan_ids = fields.Many2many(
comodel_name="pms.availability.plan",
string="Availability Plan to apply massive changes",
check_pms_properties=True,
# can be setted by context from availability plan detail
)
pricelist_ids = fields.Many2many(
@@ -57,11 +58,65 @@ class AvailabilityWizard(models.TransientModel):
required=True,
)
apply_pricelists_on = fields.Selection(
string="Apply pricelists on",
selection=[
("room_types", "Room Types"),
("board_services", "Board Services"),
("service", "Service"),
],
default="room_types",
)
room_type_ids = fields.Many2many(
comodel_name="pms.room.type",
string="Room Type",
check_pms_properties=True,
compute="_compute_room_type_ids",
readonly=False,
store=True,
)
board_service_room_type_ids = fields.Many2many(
string="Room type's board services",
comodel_name="pms.board.service.room.type",
check_pms_properties=True,
compute="_compute_board_service_room_type_ids",
readonly=False,
store=True,
)
board_service = fields.Many2one(
string="Board service",
comodel_name="product.product",
check_pms_properties=True,
domain="[('id', 'in',allowed_board_services)]",
)
allowed_board_services = fields.Many2many(
string="Allowed services",
comodel_name="product.product",
compute="_compute_allowed_board_services",
readonly=False,
store=True,
)
service = fields.Many2one(
string="Service",
comodel_name="product.product",
check_pms_properties=True,
compute="_compute_service",
readonly=False,
store=True,
)
date_types = fields.Selection(
string="Date types",
selection=[
("sale_dates", "Sale Dates"),
("consumption_dates", "Consumption Dates"),
],
default="consumption_dates",
)
price = fields.Float(string="Price")
min_quantity = fields.Float(string="Min. Quantity")
@@ -216,10 +271,10 @@ class AvailabilityWizard(models.TransientModel):
)
def _default_avail_readonly(self):
return True if self._context.get("availability_plan_ids") else False
return True if self._context.get("availability_plan_id") else False
def _default_pricelist_readonly(self):
return True if self._context.get("pricelist_ids") else False
return True if self._context.get("pricelist_id") else False
@api.depends("massive_changes_on")
def _compute_allowed_pricelist_ids(self):
@@ -230,6 +285,99 @@ class AvailabilityWizard(models.TransientModel):
]
)
@api.depends("apply_pricelists_on")
def _compute_room_type_ids(self):
for record in self:
if (
record.apply_pricelists_on == "board_services"
or record.apply_pricelists_on == "service"
):
record.room_type_ids = False
@api.depends("apply_pricelists_on", "board_service")
def _compute_board_service_room_type_ids(self):
for record in self:
if (
record.apply_pricelists_on == "room_types"
or record.apply_pricelists_on == "service"
):
record.board_service_room_type_ids = False
record.board_service = False
else:
if not record.board_service_room_type_ids:
allowed_board_service_room_type_ids = []
all_board_service_room_type_ids = self.env[
"pms.board.service.room.type"
].search([])
if record.board_service:
for (
board_service_room_type_id
) in all_board_service_room_type_ids:
if (
record.board_service
in board_service_room_type_id.board_service_line_ids.mapped(
"product_id"
)
):
allowed_board_service_room_type_ids.append(
board_service_room_type_id.id
)
else:
allowed_board_service_room_type_ids = (
all_board_service_room_type_ids.ids
)
domain = []
if allowed_board_service_room_type_ids:
domain.append(("id", "in", allowed_board_service_room_type_ids))
record.board_service_room_type_ids = (
self.env["pms.board.service.room.type"].search(domain)
if domain
else False
)
@api.depends("apply_pricelists_on")
def _compute_service(self):
for record in self:
if (
record.apply_pricelists_on == "board_services"
or record.apply_pricelists_on == "room_types"
):
record.service = False
@api.depends("board_service_room_type_ids")
def _compute_allowed_board_services(self):
for record in self:
if not record.board_service_room_type_ids:
record.allowed_board_services = (
self.env["pms.board.service.room.type"]
.search([])
.board_service_line_ids.mapped("product_id")
)
else:
product_ids = []
for bs_room_type_id in record.board_service_room_type_ids:
tmp_list = bs_room_type_id.board_service_line_ids.mapped(
"product_id"
).ids
product_ids = (
tmp_list
if not product_ids
else product_ids
if record.board_service_room_type_ids
else list(set(tmp_list) & set(product_ids))
)
record.allowed_board_services = self.env["product.product"].search(
[
(
"id",
"in",
product_ids,
)
]
)
@api.depends(
"start_date",
"end_date",
@@ -265,10 +413,10 @@ class AvailabilityWizard(models.TransientModel):
def _compute_rules_to_overwrite(self):
for record in self:
if not record.availability_plan_ids and self._context.get(
"availability_plan_ids"
"availability_plan_id"
):
record.availability_plan_ids = [
(4, self._context.get("availability_plan_ids"))
(4, self._context.get("availability_plan_id"))
]
record.massive_changes_on = "availability_plan"
@@ -321,6 +469,11 @@ class AvailabilityWizard(models.TransientModel):
"start_date",
"end_date",
"room_type_ids",
"board_service_room_type_ids",
"board_service",
"service",
"apply_pricelists_on",
"date_types",
"apply_on_monday",
"apply_on_tuesday",
"apply_on_wednesday",
@@ -330,14 +483,20 @@ class AvailabilityWizard(models.TransientModel):
"apply_on_sunday",
"apply_on_all_week",
"pricelist_ids",
"pms_property_ids",
)
def _compute_pricelist_items_to_overwrite(self):
for record in self:
if not record.pricelist_ids and self._context.get("pricelist_ids"):
record.pricelist_ids = [(4, self._context.get("pricelist_ids"))]
if not record.pricelist_ids and self._context.get("pricelist_id"):
record.pricelist_ids = [(4, self._context.get("pricelist_id"))]
record.massive_changes_on = "pricelist"
if record.pricelist_ids:
if (
record.pricelist_ids
and record.start_date
and record.end_date
and record.pms_property_ids
):
domain = [
("pricelist_id", "in", record.pricelist_ids.ids),
"|",
@@ -345,18 +504,37 @@ class AvailabilityWizard(models.TransientModel):
("pms_property_ids", "in", record.pms_property_ids.ids),
]
if record.start_date:
domain.append(("date_start_overnight", ">=", record.start_date))
if record.end_date:
domain.append(("date_end_overnight", "<=", record.end_date))
if record.room_type_ids:
room_type_ids = record.room_type_ids.ids
product_ids = (
self.env["pms.room.type"]
.search([("id", "in", room_type_ids)])
.mapped("product_id")
.ids
if record.date_types == "sale_dates":
domain.append(
(
"date_start",
">=",
datetime.datetime.combine(
record.start_date, datetime.datetime.min.time()
),
)
)
domain.append(
(
"date_start",
"<=",
datetime.datetime.combine(
record.end_date, datetime.datetime.max.time()
),
)
)
elif record.date_types == "consumption_dates":
domain.append(("date_start_overnight", ">=", record.start_date))
domain.append(("date_end_overnight", "<=", record.end_date))
product_ids = self.generate_product_ids_to_filter(
record.apply_pricelists_on,
record.room_type_ids,
record.board_service_room_type_ids,
record.board_service,
record.service,
)
if product_ids:
domain.append(
(
"product_id",
@@ -364,6 +542,14 @@ class AvailabilityWizard(models.TransientModel):
product_ids,
)
)
if record.board_service_room_type_ids:
domain.append(
(
"board_service_room_type_id",
"in",
record.board_service_room_type_ids.ids,
)
)
week_days_to_apply = (
record.apply_on_monday,
record.apply_on_tuesday,
@@ -381,11 +567,20 @@ class AvailabilityWizard(models.TransientModel):
and record.start_date
and record.end_date
):
record.pricelist_items_to_overwrite = items.filtered(
lambda x: week_days_to_apply[
x.date_end_overnight.timetuple()[6]
]
)
items_filtered = False
if record.date_types == "consumption_dates":
items_filtered = items.filtered(
lambda x: x.date_end_overnight
and week_days_to_apply[
x.date_end_overnight.timetuple()[6]
]
)
elif record.date_types == "sale_dates":
items_filtered = items.filtered(
lambda x: x.date_end
and week_days_to_apply[x.date_end.date().timetuple()[6]]
)
record.pricelist_items_to_overwrite = items_filtered
else:
record.pricelist_items_to_overwrite = items
else:
@@ -440,6 +635,247 @@ class AvailabilityWizard(models.TransientModel):
)
return domain_overwrite
@api.model
def generate_product_ids_to_filter(
self,
apply_pricelists_on,
room_type_ids,
board_service_room_type_ids,
board_service,
service,
):
product_ids = False
all_room_type_ids = self.env["pms.room.type"].search([]).ids
if apply_pricelists_on == "room_types":
room_type_ids = room_type_ids.ids
if not room_type_ids:
room_type_ids = all_room_type_ids
product_ids = (
self.env["pms.room.type"]
.search([("id", "in", room_type_ids)])
.mapped("product_id")
.ids
)
elif apply_pricelists_on == "board_services":
if board_service:
product_ids = [board_service.id]
elif not board_service_room_type_ids and not board_service:
product_ids = (
self.env["pms.board.service.room.type"]
.search([])
.board_service_line_ids.mapped("product_id")
.ids
)
else:
bsrti = board_service_room_type_ids
product_ids = bsrti.board_service_line_ids.mapped("product_id").ids
elif apply_pricelists_on == "service":
domain = []
product_ids_board_services = (
self.env["pms.board.service.room.type"]
.search([])
.board_service_line_ids.mapped("product_id")
.ids
)
if product_ids_board_services:
domain.append(("id", "not in", product_ids_board_services))
if service:
domain.append(("id", "=", service.id))
product_ids = self.env["product.product"].search(domain).ids
return product_ids
@api.model
def generate_dates_vals(
self,
date_types,
vals,
date,
):
if date_types == "sale_dates":
vals["date_start"] = datetime.datetime.combine(
date, datetime.datetime.min.time()
)
vals["date_end"] = datetime.datetime.combine(
date, datetime.datetime.max.time()
)
else:
vals["date_start_overnight"] = date
vals["date_end_overnight"] = date
return vals
@api.model
def create_pricelists_items_room_types(
self,
room_types,
pricelist_ids,
price,
min_quantity,
pms_property,
date,
date_types,
):
new_items = []
for room_type in room_types:
for pricelist in pricelist_ids:
vals = {
"pricelist_id": pricelist.id,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": room_type.product_id.id,
"fixed_price": price,
"min_quantity": min_quantity,
"pms_property_ids": [pms_property.id],
}
vals = self.generate_dates_vals(date_types, vals, date)
pricelist_item = self.env["product.pricelist.item"].create(vals)
new_items.append(pricelist_item.id)
return new_items
@api.model
def create_pricelists_items_board_services(
self,
board_service_room_type_ids,
pricelist_ids,
board_service,
price,
min_quantity,
pms_property,
date_types,
date,
):
new_items = []
for bs_room_type in board_service_room_type_ids:
for pricelist in pricelist_ids:
if board_service:
vals = {
"pricelist_id": pricelist.id,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": board_service.id,
"board_service_room_type_id": bs_room_type.id,
"fixed_price": price,
"min_quantity": min_quantity,
"pms_property_ids": [pms_property.id],
}
vals = self.generate_dates_vals(date_types, vals, date)
pricelist_item = self.env["product.pricelist.item"].create(vals)
new_items.append(pricelist_item.id)
else:
for (
board_service_line
) in bs_room_type.pms_board_service_id.board_service_line_ids:
vals = {
"pricelist_id": pricelist.id,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": board_service_line.product_id.id,
"board_service_room_type_id": bs_room_type.id,
"fixed_price": price,
"min_quantity": min_quantity,
"pms_property_ids": [pms_property.id],
}
vals = self.generate_dates_vals(date_types, vals, date)
pricelist_item = self.env["product.pricelist.item"].create(vals)
new_items.append(pricelist_item.id)
return new_items
@api.model
def create_availability_plans_rules(
self,
room_types,
availability_plan_ids,
min_stay,
apply_min_stay,
min_stay_arrival,
apply_min_stay_arrival,
max_stay,
apply_max_stay,
max_stay_arrival,
apply_max_stay_arrival,
quota,
apply_quota,
max_avail,
apply_max_avail,
closed,
apply_closed,
closed_arrival,
apply_closed_arrival,
closed_departure,
apply_closed_departure,
date,
rules_to_overwrite,
pms_property,
):
new_items = []
for room_type in room_types:
for avail_plan_id in availability_plan_ids:
vals = {}
vals.update({"min_stay": min_stay} if apply_min_stay else {})
vals.update(
{"min_stay_arrival": min_stay_arrival}
if apply_min_stay_arrival
else {}
)
vals.update({"max_stay": max_stay} if apply_max_stay else {})
vals.update(
{"max_stay_arrival": max_stay_arrival}
if apply_max_stay_arrival
else {}
)
vals.update({"quota": quota} if apply_quota else {})
vals.update({"max_avail": max_avail} if apply_max_avail else {})
vals.update({"closed": closed} if apply_closed else {})
vals.update(
{"closed_arrival": closed_arrival} if apply_closed_arrival else {}
)
vals.update(
{"closed_departure": closed_departure}
if apply_closed_departure
else {}
)
if date in rules_to_overwrite.mapped(
"date"
) and room_type in rules_to_overwrite.mapped("room_type_id"):
overwrite = rules_to_overwrite.search(
[
("room_type_id", "=", room_type.id),
("date", "=", date),
]
)
overwrite.write(vals)
new_items.append(overwrite.id)
else:
plan_rule = self.env["pms.availability.plan.rule"].create(
{
"availability_plan_id": avail_plan_id.id,
"date": date,
"room_type_id": room_type.id,
"quota": quota,
"max_avail": max_avail,
"min_stay": min_stay,
"min_stay_arrival": min_stay_arrival,
"max_stay": max_stay,
"max_stay_arrival": max_stay_arrival,
"closed": closed,
"closed_arrival": closed_arrival,
"closed_departure": closed_departure,
"pms_property_id": pms_property.id,
}
)
new_items.append(plan_rule.id)
return new_items
def apply_massive_changes(self):
for record in self:
@@ -477,112 +913,90 @@ class AvailabilityWizard(models.TransientModel):
)
else:
room_types = record.room_type_ids
for pms_property in record.pms_property_ids:
for room_type in room_types:
if record.massive_changes_on == "pricelist":
for pricelist in record.pricelist_ids:
if (
record.massive_changes_on == "pricelist"
and record.apply_pricelists_on == "room_types"
):
new_items = self.create_pricelists_items_room_types(
room_types,
record.pricelist_ids,
record.price,
record.min_quantity,
pms_property,
date,
record.date_types,
)
items = items + new_items if new_items else items
elif (
record.massive_changes_on == "pricelist"
and record.apply_pricelists_on == "board_services"
):
new_items = self.create_pricelists_items_board_services(
record.board_service_room_type_ids,
record.pricelist_ids,
record.board_service,
record.price,
record.min_quantity,
pms_property,
record.date_types,
date,
)
items = items + new_items if new_items else items
elif (
record.massive_changes_on == "pricelist"
and record.apply_pricelists_on == "service"
):
for pricelist in record.pricelist_ids:
if record.service:
vals = {
"pricelist_id": pricelist.id,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": record.service.id,
"fixed_price": record.price,
"min_quantity": record.min_quantity,
"pms_property_ids": [pms_property.id],
}
vals = self.generate_dates_vals(
record.date_types, vals, date
)
pricelist_item = self.env[
"product.pricelist.item"
].create(
{
"pricelist_id": pricelist.id,
"date_start_overnight": date,
"date_end_overnight": date,
"compute_price": "fixed",
"applied_on": "0_product_variant",
"product_id": room_type.product_id.id,
"fixed_price": record.price,
"min_quantity": record.min_quantity,
"pms_property_ids": [pms_property.id],
}
)
].create(vals)
items.append(pricelist_item.id)
else:
for avail_plan_id in record.availability_plan_ids:
vals = {}
vals.update(
{"min_stay": record.min_stay}
if record.apply_min_stay
else {}
)
vals.update(
{"min_stay_arrival": record.min_stay_arrival}
if record.apply_min_stay_arrival
else {}
)
vals.update(
{"max_stay": record.max_stay}
if record.apply_max_stay
else {}
)
elif record.massive_changes_on == "availability_plan":
vals.update(
{"max_stay_arrival": record.max_stay_arrival}
if record.apply_max_stay_arrival
else {}
)
vals.update(
{"quota": record.quota}
if record.apply_quota
else {}
)
vals.update(
{"max_avail": record.max_avail}
if record.apply_max_avail
else {}
)
vals.update(
{"closed": record.closed}
if record.apply_closed
else {}
)
vals.update(
{"closed_arrival": record.closed_arrival}
if record.apply_closed_arrival
else {}
)
vals.update(
{"closed_departure": record.closed_departure}
if record.apply_closed_departure
else {}
)
if date in record.rules_to_overwrite.mapped(
"date"
) and room_type in record.rules_to_overwrite.mapped(
"room_type_id"
):
overwrite = record.rules_to_overwrite.search(
[
("room_type_id", "=", room_type.id),
("date", "=", date),
]
)
overwrite.write(vals)
items.append(overwrite.id)
else:
plan_rule = self.env[
"pms.availability.plan.rule"
].create(
{
"availability_plan_id": avail_plan_id.id,
"date": date,
"room_type_id": room_type.id,
"quota": record.quota,
"max_avail": record.max_avail,
"min_stay": record.min_stay,
"min_stay_arrival": record.min_stay_arrival,
"max_stay": record.max_stay,
"max_stay_arrival": record.max_stay_arrival,
"closed": record.closed,
"closed_arrival": record.closed_arrival,
"closed_departure": record.closed_departure,
"pms_property_id": pms_property.id,
}
)
items.append(plan_rule.id)
action = {}
new_items = self.create_availability_plans_rules(
room_types,
record.availability_plan_ids,
record.min_stay,
record.apply_min_stay,
record.min_stay_arrival,
record.apply_min_stay_arrival,
record.max_stay,
record.apply_max_stay,
record.max_stay_arrival,
record.apply_max_stay_arrival,
record.quota,
record.apply_quota,
record.max_avail,
record.apply_max_avail,
record.closed,
record.apply_closed,
record.closed_arrival,
record.apply_closed_arrival,
record.closed_departure,
record.apply_closed_departure,
date,
record.rules_to_overwrite,
pms_property,
)
items = items + new_items if new_items else items
if (
record.massive_changes_on == "pricelist"
and not record.pricelist_readonly
@@ -590,6 +1004,8 @@ class AvailabilityWizard(models.TransientModel):
action = {
"view": self.env.ref("pms.product_pricelist_item_action2").read()[0]
}
action["view"]["domain"] = [("id", "in", items)]
return action["view"]
if (
record.massive_changes_on == "availability_plan"
@@ -600,5 +1016,5 @@ class AvailabilityWizard(models.TransientModel):
"pms.availability_plan_rule_view_tree_action"
).read()[0]
}
action["view"]["domain"] = [("id", "in", items)]
return action["view"]
action["view"]["domain"] = [("id", "in", items)]
return action["view"]

View File

@@ -9,9 +9,10 @@
<field name="massive_changes_on" invisible="1" />
<field name="avail_readonly" invisible="1" />
<field name="pricelist_readonly" invisible="1" />
<field name="allowed_board_services" invisible="1" />
</group>
<div class="row">
<div class="col-6">
<div class="col-5">
<group>
<field
name="start_date"
@@ -27,9 +28,14 @@
name="massive_changes_on"
attrs="{'invisible':['|', ('avail_readonly','=',True), ('pricelist_readonly', '=', True)]}"
/>
<field
name="apply_pricelists_on"
widget="radio"
attrs="{'invisible':[('massive_changes_on','!=','pricelist')]}"
/>
</group>
</div>
<div class="col-6">
<div class="col-7">
<group class="">
<field name="pms_property_ids" widget="many2many_tags" />
<field
@@ -59,6 +65,31 @@
default_focus="1"
widget="many2many_tags"
options="{'no_create': True,'no_open': True}"
attrs="{'invisible':[('apply_pricelists_on','!=','room_types'),('massive_changes_on', '=','pricelist')],'required': []}"
/>
<field
name="board_service_room_type_ids"
widget="many2many_tags"
options="{'no_create': True,'no_open': True}"
attrs="{'invisible':['|', ('apply_pricelists_on','!=','board_services'),('massive_changes_on', '=','availability_plan')],
'required': [('apply_pricelists_on','=','board_services')]}"
/>
<field
name="board_service"
options="{'no_create': True,'no_open': True}"
attrs="{'invisible':['|', ('apply_pricelists_on','!=','board_services'),('massive_changes_on', '=','availability_plan')],
'required': [('apply_pricelists_on','=','board_services')]}"
/>
<field
name="service"
options="{'no_create': True,'no_open': True}"
attrs="{'invisible':['|', ('apply_pricelists_on','!=','service'),('massive_changes_on', '=','availability_plan')]}"
/>
<field
name="date_types"
widget="radio"
options="{'no_create': True,'no_open': True}"
attrs="{'invisible':[('massive_changes_on', '=','availability_plan')]}"
/>
</group>
@@ -421,6 +452,7 @@
name="closed_departure"
attrs="{'column_invisible':[('parent.apply_closed_departure', '==', False)]}"
/>
<field name="pms_property_id" />
</tree>
</field>
<field
@@ -431,9 +463,13 @@
<tree>
<field name="pricelist_id" />
<field string="Applicable on" name="name" />
<field name="board_service_room_type_id" />
<field string="Sale Date Start" name="date_start" />
<field string="Sale Date End" name="date_end" />
<field name="date_start_overnight" />
<field name="date_end_overnight" />
<field name="price" />
<field name="pms_property_ids" widget="many2many_tags" />
</tree>
</field>
<footer>