From 71de7ebdfb007b6c98242788b580da84260713a0 Mon Sep 17 00:00:00 2001 From: DarioLodeiros Date: Sun, 31 May 2026 11:41:47 +0200 Subject: [PATCH] [IMP] pms: add active field to board service Allow archiving board service regimes that are no longer commercialised (seasonal packages, retired group rates, board services that have been replaced) without affecting historical reservations or invoices that reference them. The active flag lives on pms.board.service as the source of truth and its write override propagates archive/restore down to: - pms.board.service.line (composition of the regime) - pms.board.service.room.type (per-room-type assignment) - pms.board.service.room.type.line (composition at room-type level) Each model also exposes its own active field so individual rows can be toggled independently when needed (e.g. retire a regime only for a specific room type). UI: - pms.board.service and pms.board.service.room.type forms gain the standard "Archived" ribbon. - pms.board.service form has a dedicated search view with an "Archived" filter, wired to the configuration menu. Historical pms.reservation.board_service_room_id references remain intact since the rows are archived rather than deleted; the regime simply stops appearing in selection dropdowns for new operations. Added a regression test in tests/test_pms_board_service.py covering the forward and reverse propagation of the active flag. --- pms/models/pms_board_service.py | 17 +++++ pms/models/pms_board_service_line.py | 4 + pms/models/pms_board_service_room_type.py | 25 +++++-- .../pms_board_service_room_type_line.py | 4 + pms/tests/test_pms_board_service.py | 74 +++++++++++++++++++ .../pms_board_service_room_type_views.xml | 43 ++++++----- pms/views/pms_board_service_views.xml | 63 +++++++++++----- 7 files changed, 187 insertions(+), 43 deletions(-) diff --git a/pms/models/pms_board_service.py b/pms/models/pms_board_service.py index b90a57a76f..7632e2d1b3 100644 --- a/pms/models/pms_board_service.py +++ b/pms/models/pms_board_service.py @@ -58,6 +58,23 @@ class PmsBoardService(models.Model): show_detail_report = fields.Boolean( help="True if you want that board service detail to be shown on the report", ) + active = fields.Boolean( + default=True, + help="If unchecked, this board service will be archived and hidden from " + "selections without affecting historical records that reference it.", + ) + + def write(self, vals): + res = super().write(vals) + if "active" in vals: + new_state = vals["active"] + self.with_context(active_test=False).mapped("board_service_line_ids").write( + {"active": new_state} + ) + self.with_context(active_test=False).mapped( + "pms_board_service_room_type_ids" + ).write({"active": new_state}) + return res @api.depends("board_service_line_ids.amount") def _compute_board_amount(self): diff --git a/pms/models/pms_board_service_line.py b/pms/models/pms_board_service_line.py index 7e314c68a4..93bf46bc16 100644 --- a/pms/models/pms_board_service_line.py +++ b/pms/models/pms_board_service_line.py @@ -50,6 +50,10 @@ class PmsBoardServiceLine(models.Model): help="Apply service to children", default=False, ) + active = fields.Boolean( + default=True, + help="Lines of an archived board service are archived as well.", + ) def _get_default_price(self): if self.product_id: diff --git a/pms/models/pms_board_service_room_type.py b/pms/models/pms_board_service_room_type.py index 8556c3e692..1e2d4a088f 100644 --- a/pms/models/pms_board_service_room_type.py +++ b/pms/models/pms_board_service_room_type.py @@ -64,6 +64,24 @@ class PmsBoardServiceRoomType(models.Model): help="Pricelists where this Board Service is available", comodel_name="product.pricelist", ) + active = fields.Boolean( + default=True, + help="If unchecked, this board service room type assignment will be " + "archived and hidden from selections without affecting historical " + "reservations that reference it.", + ) + + def write(self, vals): + if "pms_board_service_id" in vals and "board_service_line_ids" not in vals: + vals.update( + self.prepare_board_service_reservation_ids(vals["pms_board_service_id"]) + ) + res = super().write(vals) + if "active" in vals: + self.with_context(active_test=False).mapped("board_service_line_ids").write( + {"active": vals["active"]} + ) + return res @api.depends("board_service_line_ids.amount") def _compute_board_amount(self): @@ -136,13 +154,6 @@ def create(self, vals_list): ) return super().create(vals_list) - def write(self, vals): - if "pms_board_service_id" in vals and "board_service_line_ids" not in vals: - vals.update( - self.prepare_board_service_reservation_ids(vals["pms_board_service_id"]) - ) - return super().write(vals) - @api.model def prepare_board_service_reservation_ids(self, board_service_id): """ diff --git a/pms/models/pms_board_service_room_type_line.py b/pms/models/pms_board_service_room_type_line.py index 28b4a3818b..c203db5c47 100644 --- a/pms/models/pms_board_service_room_type_line.py +++ b/pms/models/pms_board_service_room_type_line.py @@ -48,6 +48,10 @@ class PmsBoardServiceRoomTypeLine(models.Model): help="Apply service to children", default=False, ) + active = fields.Boolean( + default=True, + help="Lines of an archived board service room type are archived as well.", + ) def _default_amount(self): return self.product_id.list_price diff --git a/pms/tests/test_pms_board_service.py b/pms/tests/test_pms_board_service.py index 43cf24839c..7e85814781 100644 --- a/pms/tests/test_pms_board_service.py +++ b/pms/tests/test_pms_board_service.py @@ -409,3 +409,77 @@ def test_search_bs_code_no_properties(self): board_service2.id, "Expected board service not found", ) + + def test_archive_board_service_propagates_to_children(self): + """ + Archiving a board service must cascade ``active=False`` to its + lines and to its room-type assignments (and their lines), so that + the archived regime fully disappears from operative selections + while historical references remain in place. + + PRE: - board_service bs1 is active + - bs1 has one line (bsl) + - bs1 has one room-type assignment (bsrt) with one line (bsrtl) + ACT: - bs1.active = False + POST: - bsl.active == False + - bsrt.active == False + - bsrtl.active == False + - reactivating bs1 propagates back to all descendants + """ + # ARRANGE + product = self.env["product.product"].create( + {"name": "Bs Product", "is_pms_available": True} + ) + room_type = self.env["pms.room.type"].create( + { + "pms_property_ids": [(6, 0, [self.pms_property1.id])], + "name": "Room Type Archive Test", + "default_code": "RTAT", + "class_id": self.room_type_class1.id, + "list_price": 30.0, + } + ) + board_service = self.env["pms.board.service"].create( + { + "name": "Bs Archive Test", + "default_code": "BSAT", + "pms_property_ids": [(6, 0, [self.pms_property1.id])], + "board_service_line_ids": [ + (0, 0, {"product_id": product.id, "adults": True}), + ], + } + ) + bsrt = self.env["pms.board.service.room.type"].create( + { + "pms_board_service_id": board_service.id, + "pms_room_type_id": room_type.id, + "pms_property_id": self.pms_property1.id, + } + ) + + # ACT — archive + board_service.active = False + + # ASSERT — propagation downwards + bs_line = board_service.with_context(active_test=False).board_service_line_ids + bsrt_line = bsrt.with_context(active_test=False).board_service_line_ids + self.assertFalse(bs_line.active, "Board service line was not archived") + self.assertFalse( + bsrt.with_context(active_test=False).active, + "Board service room type was not archived", + ) + self.assertFalse( + bsrt_line.active, + "Board service room type line was not archived", + ) + + # ACT — reactivate + board_service.with_context(active_test=False).active = True + + # ASSERT — propagation back + self.assertTrue(bs_line.active, "Board service line was not reactivated") + self.assertTrue(bsrt.active, "Board service room type was not reactivated") + self.assertTrue( + bsrt_line.active, + "Board service room type line was not reactivated", + ) diff --git a/pms/views/pms_board_service_room_type_views.xml b/pms/views/pms_board_service_room_type_views.xml index 741ccf691a..745efc1552 100644 --- a/pms/views/pms_board_service_room_type_views.xml +++ b/pms/views/pms_board_service_room_type_views.xml @@ -5,23 +5,32 @@ pms.board.service.room.type
- - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +
diff --git a/pms/views/pms_board_service_views.xml b/pms/views/pms_board_service_views.xml index 3447c420a0..82754734fe 100644 --- a/pms/views/pms_board_service_views.xml +++ b/pms/views/pms_board_service_views.xml @@ -5,26 +5,35 @@ pms.board.service
- - - - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + +
@@ -41,10 +50,26 @@
+ + pms.board.service.search + pms.board.service + + + + + + + + Board Services pms.board.service tree,form +