diff --git a/pms/models/pms_folio.py b/pms/models/pms_folio.py
index d98193ae38..45cdf8cce7 100644
--- a/pms/models/pms_folio.py
+++ b/pms/models/pms_folio.py
@@ -791,7 +791,7 @@ def _compute_number_of_services(self):
def _compute_sale_line_ids(self):
for folio in self.filtered(lambda f: isinstance(f.id, int)):
sale_lines_vals = []
- if folio.reservation_type in ("normal", "staff"):
+ if folio.reservation_type in self._get_reservation_types_with_any_pricing():
sale_lines_vals_to_drop = []
seq = 0
for reservation in sorted(
@@ -802,7 +802,11 @@ def _compute_sale_line_ids(self):
# RESERVATION LINES
reservation_sale_lines = []
reservation_sale_lines_to_drop = []
- if reservation.reservation_line_ids:
+ if (
+ reservation.reservation_line_ids
+ and folio.reservation_type
+ in self._get_reservation_types_with_night_pricing()
+ ):
(
reservation_sale_lines,
reservation_sale_lines_to_drop,
@@ -817,7 +821,11 @@ def _compute_sale_line_ids(self):
# RESERVATION SERVICES
service_sale_lines = []
service_sale_lines_to_drop = []
- if reservation.service_ids:
+ if (
+ reservation.service_ids
+ and folio.reservation_type
+ in self._get_reservation_types_with_service_pricing()
+ ):
(
service_sale_lines,
service_sale_lines_to_drop,
@@ -861,7 +869,10 @@ def _compute_company_id(self):
def _compute_pricelist_id(self):
for folio in self:
is_new = not folio.pricelist_id or isinstance(folio.id, models.NewId)
- if folio.reservation_type == "out":
+ if (
+ folio.reservation_type
+ not in self._get_reservation_types_with_any_pricing()
+ ):
folio.pricelist_id = False
elif len(folio.reservation_ids.pricelist_id) == 1:
folio.pricelist_id = folio.reservation_ids.pricelist_id
@@ -1224,7 +1235,10 @@ def _compute_untaxed_amount_to_invoice(self):
)
def _compute_amount(self):
for record in self:
- if record.reservation_type == "out":
+ if (
+ record.reservation_type
+ not in self._get_reservation_types_with_any_pricing()
+ ):
record.amount_total = 0
vals = {
"payment_state": "nothing_to_pay",
@@ -2765,3 +2779,31 @@ def _get_portal_return_action(self):
when returning from customer portal."""
self.ensure_one()
return self.env.ref("pms.open_pms_folio1_form_tree_all")
+
+ def _get_reservation_types_with_night_pricing(self):
+ """
+ Returns reservation types that use night-based pricing
+ (e.g. per-night room price).
+ This method is meant to be extended by other modules.
+ """
+ return ("normal",)
+
+ def _get_reservation_types_with_service_pricing(self):
+ """
+ Returns reservation types that use the standard service pricing logic
+ (e.g. pms.service._get_price_unit_line).
+ This method is meant to be extended by other modules.
+ """
+ return ("normal", "staff")
+
+ def _get_reservation_types_with_any_pricing(self):
+ """
+ Returns reservation types that have any pricing rule.
+ (union of night-based and service-based types)
+ """
+ night = list(self._get_reservation_types_with_night_pricing())
+ service = list(self._get_reservation_types_with_service_pricing())
+
+ # Combine preserving order: night first, then service without duplicates
+ result = night + [t for t in service if t not in night]
+ return tuple(result)
diff --git a/pms/models/pms_service.py b/pms/models/pms_service.py
index 71c6fe833b..435d63c306 100644
--- a/pms/models/pms_service.py
+++ b/pms/models/pms_service.py
@@ -591,7 +591,11 @@ def _service_day_qty(self):
def _get_price_unit_line(self, date=False):
self.ensure_one()
- if self.reservation_id.reservation_type in ("normal", "staff"):
+ Folio = self.env["pms.folio"]
+ if (
+ self.reservation_id.reservation_type
+ in Folio._get_reservation_types_with_service_pricing()
+ ):
folio = self.folio_id
reservation = self.reservation_id
origin = reservation if reservation else folio
diff --git a/pms/tests/test_pms_folio_sale_line.py b/pms/tests/test_pms_folio_sale_line.py
index 5d0e26361e..7e1c21760a 100644
--- a/pms/tests/test_pms_folio_sale_line.py
+++ b/pms/tests/test_pms_folio_sale_line.py
@@ -1217,18 +1217,20 @@ def test_comp_fsl_fol_extra_services_two(self):
def test_no_sale_lines_staff_reservation(self):
"""
- Check that the sale_line_ids of a folio whose reservation
- is of type 'staff' are created with price 0.
+ Check that the folio sale lines linked to a staff reservation
+ are not created.
+
-----
A reservation is created with the reservation_type field
- with value 'staff'. Then it is verified that the
- sale_line_ids of the folio created with the creation of
- the reservation have price 0.
+ set to 'staff'. Then it is verified that the folio created
+ together with the reservation has no sale lines linked to
+ the reservation lines.
"""
# ARRANGE
self.partner1 = self.env["res.partner"].create({"name": "Alberto"})
- checkin = fields.date.today()
- checkout = fields.date.today() + datetime.timedelta(days=1)
+ checkin = fields.Date.today()
+ checkout = fields.Date.today() + datetime.timedelta(days=1)
+
# ACT
reservation = self.env["pms.reservation"].create(
{
@@ -1243,11 +1245,23 @@ def test_no_sale_lines_staff_reservation(self):
"adults": 1,
}
)
+
+ # Sale lines of this folio that are linked to any reservation line
+ # of this reservation. Adjust the field name if it is
+ # reservation_line_id instead of reservation_line_ids.
+ sale_lines_linked = reservation.folio_id.sale_line_ids.filtered(
+ lambda line: line.reservation_line_ids
+ and any(
+ rl in reservation.reservation_line_ids
+ for rl in line.reservation_line_ids
+ )
+ )
+
# ASSERT
- self.assertEqual(
- reservation.folio_id.sale_line_ids.mapped("price_unit")[0],
- 0,
- "Staff folio sale lines should have price 0",
+ self.assertFalse(
+ sale_lines_linked,
+ "Staff reservations should not create folio sale lines linked "
+ "to reservation lines.",
)
def test_no_sale_lines_out_reservation(self):
diff --git a/pms/views/pms_folio_views.xml b/pms/views/pms_folio_views.xml
index fd0f1da29a..28cab8cf61 100644
--- a/pms/views/pms_folio_views.xml
+++ b/pms/views/pms_folio_views.xml
@@ -331,7 +331,7 @@