Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions pms/models/pms_folio.py
Original file line number Diff line number Diff line change
Expand Up @@ -894,13 +894,21 @@ def _compute_pricelist_id(self):
folio.pricelist_id = False
elif len(folio.reservation_ids.pricelist_id) == 1:
folio.pricelist_id = folio.reservation_ids.pricelist_id
elif is_new and folio.agency_id and folio.agency_id.apply_pricelist:
elif (
is_new
and folio.agency_id
and folio.agency_id.apply_pricelist
and folio.agency_id.property_product_pricelist._is_pms_usable(
folio.pms_property_id
)
):
folio.pricelist_id = folio.agency_id.property_product_pricelist
elif (
is_new
and folio.partner_id
and folio.partner_id.property_product_pricelist
and folio.partner_id.property_product_pricelist.is_pms_available
and folio.partner_id.property_product_pricelist._is_pms_usable(
folio.pms_property_id
)
):
folio.pricelist_id = folio.partner_id.property_product_pricelist
elif not folio.pricelist_id:
Expand Down
10 changes: 7 additions & 3 deletions pms/models/pms_reservation.py
Original file line number Diff line number Diff line change
Expand Up @@ -992,17 +992,21 @@ def _compute_pricelist_id(self):
is_new
and reservation.agency_id
and reservation.agency_id.apply_pricelist
and reservation.agency_id.property_product_pricelist._is_pms_usable(
reservation.pms_property_id
)
):
reservation.pricelist_id = (
reservation.agency_id.property_product_pricelist
)
# only change de pricelist if the reservation is not yet saved
# and the partner has a pricelist default
# and the partner has a pricelist default usable in its property
elif (
is_new
and reservation.partner_id
and reservation.partner_id.property_product_pricelist
and reservation.partner_id.property_product_pricelist.is_pms_available
and reservation.partner_id.property_product_pricelist._is_pms_usable(
reservation.pms_property_id
)
):
reservation.pricelist_id = (
reservation.partner_id.property_product_pricelist
Expand Down
17 changes: 17 additions & 0 deletions pms/models/product_pricelist.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,23 @@ def _compute_price_rule(self, products, qty, uom=None, date=False, **kwargs):

return results

def _is_pms_usable(self, pms_property):
"""Return whether the pricelist can be used in the given property.

It must be available in the PMS and not restricted to other
properties. Without a property (e.g. not chosen yet in a form)
only the PMS availability is checked. An empty recordset is
never usable.
"""
return bool(
self.is_pms_available
and (
not pms_property
or not self.pms_property_ids
or pms_property in self.pms_property_ids
)
)

@api.constrains("is_pms_available", "availability_plan_id")
def _check_is_pms_available(self):
for record in self:
Expand Down
58 changes: 58 additions & 0 deletions pms/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,61 @@ def setUpClass(cls):
if not pricelist.availability_plan_id:
pricelist.availability_plan_id = cls.availability_plan1.id
pricelist.is_pms_available = True

def create_pricelist_by_property_scenario(self):
"""
- create pms_property2 in company1, with room_type_property2
and one room of it
- create pricelist_property1 and pricelist_property2, each one
restricted to its property; pricelist_property2 is the default
pricelist of pms_property2
- create partner_pricelist_property1 with pricelist_property1
as its pricelist
"""
self.pms_property2 = self.env["pms.property"].create(
{
"name": "Property 2",
"company_id": self.company1.id,
"default_pricelist_id": self.pricelist1.id,
}
)
self.pricelist_property1 = self.env["product.pricelist"].create(
{
"name": "Pricelist Property 1",
"is_pms_available": True,
"availability_plan_id": self.availability_plan1.id,
"pms_property_ids": [(6, 0, [self.pms_property1.id])],
}
)
self.pricelist_property2 = self.env["product.pricelist"].create(
{
"name": "Pricelist Property 2",
"is_pms_available": True,
"availability_plan_id": self.availability_plan1.id,
"pms_property_ids": [(6, 0, [self.pms_property2.id])],
}
)
self.pms_property2.default_pricelist_id = self.pricelist_property2
self.partner_pricelist_property1 = self.env["res.partner"].create(
{
"name": "Partner Pricelist Property 1",
"property_product_pricelist": self.pricelist_property1.id,
}
)
self.room_type_property2 = self.env["pms.room.type"].create(
{
"pms_property_ids": [self.pms_property2.id],
"name": "Double Property 2",
"default_code": "DBL_P2",
"class_id": self.room_type_class1.id,
"list_price": 25,
}
)
self.env["pms.room"].create(
{
"pms_property_id": self.pms_property2.id,
"name": "Double 201",
"room_type_id": self.room_type_property2.id,
"capacity": 2,
}
)
25 changes: 25 additions & 0 deletions pms/tests/test_pms_booking_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,31 @@ def _test_board_service_discount(self):
"The discount is not correctly established",
)

def test_partner_pricelist_from_another_property(self):
"""
Check that the booking engine does not propose the partner
pricelist when that pricelist is restricted to another property.
-------------
Open the booking engine in pms_property2 for a partner whose
pricelist only belongs to pms_property1. The proposed pricelist
must be the default pricelist of pms_property2.
"""
self.create_pricelist_by_property_scenario()
booking_engine = self.env["pms.booking.engine"].create(
{
"start_date": fields.date.today(),
"end_date": fields.date.today() + datetime.timedelta(days=1),
"partner_id": self.partner_pricelist_property1.id,
"pms_property_id": self.pms_property2.id,
"channel_type_id": self.sale_channel_direct1.id,
}
)
self.assertEqual(
booking_engine.pricelist_id,
self.pricelist_property2,
"The booking engine proposed a pricelist of another property",
)

def _test_adding_board_services_are_saved_on_lines(self):
checkin = fields.date.today()
checkout = fields.date.today() + datetime.timedelta(days=1)
Expand Down
56 changes: 56 additions & 0 deletions pms/tests/test_pms_folio.py
Original file line number Diff line number Diff line change
Expand Up @@ -1550,3 +1550,59 @@ def test_pms_folio_priority_fiscal_position_property(self):
"The fiscal_position_id of the folio was not set "
"correctly from the property",
)

def test_folio_partner_pricelist_from_another_property(self):
"""
Check that a new folio does not take the partner pricelist
when that pricelist is restricted to another property.
-------------
Create a folio without reservations in pms_property2 for a
partner whose pricelist only belongs to pms_property1. The
folio must be created with the default pricelist of
pms_property2 instead of failing on the property check.
"""
self.create_pricelist_by_property_scenario()
folio = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property2.id,
"partner_id": self.partner_pricelist_property1.id,
}
)
self.assertEqual(
folio.pricelist_id,
self.pricelist_property2,
"The folio took a partner pricelist of another property",
)

def test_folio_partner_pricelist_from_same_property(self):
"""
Check that a new folio still takes the partner pricelist
when that pricelist belongs to the folio property.
"""
self.create_pricelist_by_property_scenario()
folio = self.env["pms.folio"].create(
{
"pms_property_id": self.pms_property1.id,
"partner_id": self.partner_pricelist_property1.id,
}
)
self.assertEqual(
folio.pricelist_id,
self.pricelist_property1,
"The folio did not take the partner pricelist",
)

def test_folio_form_partner_pricelist_before_property(self):
"""
Check that the folio form keeps the partner pricelist restricted
to a property when the partner is chosen before that property.
"""
self.create_pricelist_by_property_scenario()
folio_form = Form(self.env["pms.folio"])
folio_form.partner_id = self.partner_pricelist_property1
folio_form.pms_property_id = self.pms_property1
self.assertEqual(
folio_form.pricelist_id,
self.pricelist_property1,
"The folio form lost the partner pricelist",
)
80 changes: 80 additions & 0 deletions pms/tests/test_pms_reservation.py
Original file line number Diff line number Diff line change
Expand Up @@ -1206,6 +1206,86 @@ def test_agency_pricelist(self):
"Rervation pricelist doesn't match with Agency pricelist",
)

def test_partner_pricelist_from_another_property(self):
"""
Check that a reservation does not take the partner pricelist
when that pricelist is restricted to another property.
-------------
Create a reservation without pricelist in pms_property2 for a
partner whose pricelist only belongs to pms_property1. The
reservation and its folio must take the default pricelist of
pms_property2 instead of failing on the property check.
"""
self.create_pricelist_by_property_scenario()
reservation = self.env["pms.reservation"].create(
{
"pms_property_id": self.pms_property2.id,
"checkin": fields.date.today() + datetime.timedelta(days=150),
"checkout": fields.date.today() + datetime.timedelta(days=152),
"partner_id": self.partner_pricelist_property1.id,
"room_type_id": self.room_type_property2.id,
"sale_channel_origin_id": self.sale_channel_direct.id,
}
)
self.assertEqual(
reservation.pricelist_id,
self.pricelist_property2,
"The reservation took a partner pricelist of another property",
)
self.assertEqual(
reservation.folio_id.pricelist_id,
self.pricelist_property2,
"The folio took a partner pricelist of another property",
)

def test_agency_pricelist_from_another_property(self):
"""
Check that a reservation does not take the agency pricelist
when that pricelist is restricted to another property.
-------------
Create a reservation without partner in pms_property2 for an
agency that applies its pricelist, which only belongs to
pms_property1. The reservation and its folio must take the
default pricelist of pms_property2 instead of failing on the
property check.
"""
self.create_pricelist_by_property_scenario()
sale_channel1 = self.env["pms.sale.channel"].create(
{
"name": "Test Indirect",
"channel_type": "indirect",
}
)
agency = self.env["res.partner"].create(
{
"firstname": "partner1",
"is_agency": True,
"sale_channel_id": sale_channel1.id,
"apply_pricelist": True,
"property_product_pricelist": self.pricelist_property1.id,
}
)
reservation = self.env["pms.reservation"].create(
{
"pms_property_id": self.pms_property2.id,
"checkin": fields.date.today() + datetime.timedelta(days=150),
"checkout": fields.date.today() + datetime.timedelta(days=152),
"agency_id": agency.id,
"room_type_id": self.room_type_property2.id,
"sale_channel_origin_id": self.sale_channel_direct.id,
}
)
self.assertEqual(
reservation.pricelist_id,
self.pricelist_property2,
"The reservation took an agency pricelist of another property",
)
self.assertEqual(
reservation.folio_id.pricelist_id,
self.pricelist_property2,
"The folio took an agency pricelist of another property",
)

def test_compute_access_url(self):
"""
Check that the access_url field of the reservation is
Expand Down
6 changes: 4 additions & 2 deletions pms/wizards/pms_booking_engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,10 @@ def _compute_pricelist_id(self):
for record in self:
record.pricelist_id = (
record.partner_id.property_product_pricelist.id
if record.partner_id.property_product_pricelist.is_pms_available
else self.pms_property_id.default_pricelist_id.id
if record.partner_id.property_product_pricelist._is_pms_usable(
record.pms_property_id
)
else record.pms_property_id.default_pricelist_id.id
)

@api.depends("agency_id")
Expand Down
Loading