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 @@