diff --git a/pms/tests/test_pms_wizard_massive_changes.py b/pms/tests/test_pms_wizard_massive_changes.py index dc81206df..6cab0afca 100644 --- a/pms/tests/test_pms_wizard_massive_changes.py +++ b/pms/tests/test_pms_wizard_massive_changes.py @@ -99,10 +99,12 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "availability_plan", - "availability_plan_id": self.test_availability_plan.id, + "availability_plan_ids": [ + (6, 0, [self.test_availability_plan.id]) + ], "start_date": fields.date.today(), "end_date": fields.date.today() + datetime.timedelta(days=days), - "room_type_id": self.test_room_type_double.id, + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "pms_property_ids": [self.test_property.id], } ).apply_massive_changes() @@ -137,7 +139,7 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "availability_plan", - "availability_plan_id": self.test_availability_plan.id, + "availability_plan_ids": [(6, 0, [self.test_availability_plan.id])], "start_date": date_from, "end_date": date_to, "pms_property_ids": [self.test_property.id], @@ -164,10 +166,10 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): vals = { "massive_changes_on": "availability_plan", - "availability_plan_id": self.test_availability_plan.id, + "availability_plan_ids": [(6, 0, [self.test_availability_plan.id])], "start_date": date_from, "end_date": date_to, - "room_type_id": self.test_room_type_double.id, + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "quota": 50, "max_avail": 5, "min_stay": 10, @@ -185,10 +187,10 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): # ASSERT del vals["massive_changes_on"] - del vals["availability_plan_id"] + del vals["availability_plan_ids"] del vals["start_date"] del vals["end_date"] - del vals["room_type_id"] + del vals["room_type_ids"] del vals["pms_property_ids"] for key in vals: with self.subTest(k=key): @@ -221,8 +223,8 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): wizard = self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "availability_plan", - "availability_plan_id": self.test_availability_plan.id, - "room_type_id": self.test_room_type_double.id, + "availability_plan_ids": [(6, 0, [self.test_availability_plan.id])], + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "start_date": date_from, "end_date": date_to, "pms_property_ids": [self.test_property.id], @@ -276,10 +278,10 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): ) vals_wizard = { "massive_changes_on": "availability_plan", - "availability_plan_id": self.test_availability_plan.id, + "availability_plan_ids": [(6, 0, [self.test_availability_plan.id])], "start_date": date, "end_date": date, - "room_type_id": self.test_room_type_double.id, + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "apply_max_avail": True, "max_avail": 2, "pms_property_ids": [self.test_property.id], @@ -318,10 +320,10 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "pricelist", - "pricelist_id": self.test_pricelist.id, + "pricelist_ids": [(6, 0, [self.test_pricelist.id])], "start_date": fields.date.today(), "end_date": fields.date.today() + datetime.timedelta(days=days), - "room_type_id": self.test_room_type_double.id, + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "pms_property_ids": [self.test_property.id], } ).apply_massive_changes() @@ -359,7 +361,7 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "pricelist", - "pricelist_id": self.test_pricelist.id, + "pricelist_ids": [(6, 0, [self.test_pricelist.id])], "start_date": date_from, "end_date": date_to, "pms_property_ids": [self.test_property.id], @@ -402,10 +404,10 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "pricelist", - "pricelist_id": self.test_pricelist.id, + "pricelist_ids": [(6, 0, [self.test_pricelist.id])], "start_date": date_from, "end_date": date_to, - "room_type_id": self.test_room_type_double.id, + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "price": price, "min_quantity": min_quantity, "pms_property_ids": [self.test_property.id], @@ -446,8 +448,8 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): wizard = self.env["pms.massive.changes.wizard"].create( { "massive_changes_on": "pricelist", - "pricelist_id": self.test_pricelist.id, - "room_type_id": self.test_room_type_double.id, + "pricelist_ids": [(6, 0, [self.test_pricelist.id])], + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], "start_date": date_from, "end_date": date_to, "pms_property_ids": [self.test_property.id], @@ -483,3 +485,107 @@ class TestPmsWizardMassiveChanges(common.SavepointCase): and test_case[index], "Rule not created on correct day of week", ) + + @freeze_time("2025-12-01") + def test_several_availability_plan(self): + self.create_common_scenario() + date_from = fields.date.today() + date_to = date_from + datetime.timedelta(days=6) + self.test_availability_plan_2 = self.env["pms.availability.plan"].create( + { + "name": "Second availability plan for TEST", + "pms_pricelist_ids": [(6, 0, [self.test_pricelist.id])], + } + ) + + wizard = self.env["pms.massive.changes.wizard"].create( + { + "massive_changes_on": "pricelist", + "availability_plan_ids": [ + ( + 6, + 0, + [ + self.test_availability_plan.id, + self.test_availability_plan_2.id, + ], + ) + ], + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], + "pms_property_ids": [self.test_property.id], + "start_date": date_from, + "end_date": date_to, + } + ) + + availability_plan_ids = [ + self.test_availability_plan.id, + self.test_availability_plan_2.id, + ] + for avail_plan_id in wizard["availability_plan_ids"].ids: + with self.subTest(k=avail_plan_id): + self.assertIn( + avail_plan_id, + availability_plan_ids, + "Availability plan has not been write ", + ) + + @freeze_time("2025-01-01") + def test_several_pricelists(self): + self.create_common_scenario() + date_from = fields.date.today() + date_to = date_from + datetime.timedelta(days=6) + self.test_pricelist_2 = self.env["product.pricelist"].create( + { + "name": "test pricelist 2", + } + ) + + wizard = self.env["pms.massive.changes.wizard"].create( + { + "massive_changes_on": "pricelist", + "pricelist_ids": [ + (6, 0, [self.test_pricelist.id, self.test_pricelist_2.id]) + ], + "room_type_ids": [(6, 0, [self.test_room_type_double.id])], + "pms_property_ids": [self.test_property.id], + "start_date": date_from, + "end_date": date_to, + } + ) + + pricelist_ids = [self.test_pricelist.id, self.test_pricelist_2.id] + for pricelist_id in wizard["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): + 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( + { + "massive_changes_on": "pricelist", + "pricelist_ids": [(6, 0, [self.test_pricelist.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["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 " + ) diff --git a/pms/views/pms_availability_plan_rule_views.xml b/pms/views/pms_availability_plan_rule_views.xml index c0e4fa2ec..3b133bb7f 100644 --- a/pms/views/pms_availability_plan_rule_views.xml +++ b/pms/views/pms_availability_plan_rule_views.xml @@ -42,6 +42,7 @@ pms.availability.plan.rule + @@ -57,4 +58,12 @@ + + Availability Plan Rules + ir.actions.act_window + pms.availability.plan.rule + {'group_by':'availability_plan_id'} + + tree + diff --git a/pms/views/product_pricelist_item_views.xml b/pms/views/product_pricelist_item_views.xml index c2a231799..0226574f2 100644 --- a/pms/views/product_pricelist_item_views.xml +++ b/pms/views/product_pricelist_item_views.xml @@ -26,4 +26,25 @@ + + product.pricelist.item + + + + + + + + + + + + + Pricelists Items + ir.actions.act_window + product.pricelist.item + {'group_by':'pricelist_id'} + + tree + diff --git a/pms/wizards/wizard_massive_changes.py b/pms/wizards/wizard_massive_changes.py index 3750fd328..5c1453070 100644 --- a/pms/wizards/wizard_massive_changes.py +++ b/pms/wizards/wizard_massive_changes.py @@ -24,18 +24,23 @@ class AvailabilityWizard(models.TransientModel): ("pricelist", "Pricelist"), ("availability_plan", "Availability Plan"), ], - required=True, - default="availability_plan", + default=lambda self: "availability_plan" + if self._context.get("availability_plan_ids") + else "pricelist" + if self._context.get("pricelist_ids") + else "availability_plan", ) - availability_plan_id = fields.Many2one( - string="Availability Plan to apply massive changes", + + 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_id = fields.Many2one( - string="Pricelist to apply massive changes", + + pricelist_ids = fields.Many2many( comodel_name="product.pricelist", + string="Pricelist to apply massive changes", check_pms_properties=True, ) allowed_pricelist_ids = fields.One2many( @@ -51,9 +56,10 @@ class AvailabilityWizard(models.TransientModel): string="To", required=True, ) - room_type_id = fields.Many2one( - string="Room Type", + + room_type_ids = fields.Many2many( comodel_name="pms.room.type", + string="Room Type", check_pms_properties=True, ) price = fields.Float(string="Price") @@ -210,10 +216,10 @@ class AvailabilityWizard(models.TransientModel): ) def _default_avail_readonly(self): - return True if self._context.get("availability_plan_id") else False + return True if self._context.get("availability_plan_ids") else False def _default_pricelist_readonly(self): - return True if self._context.get("pricelist_id") else False + return True if self._context.get("pricelist_ids") else False @api.depends("massive_changes_on") def _compute_allowed_pricelist_ids(self): @@ -227,7 +233,7 @@ class AvailabilityWizard(models.TransientModel): @api.depends( "start_date", "end_date", - "room_type_id", + "room_type_ids", "apply_on_monday", "apply_on_tuesday", "apply_on_wednesday", @@ -236,7 +242,7 @@ class AvailabilityWizard(models.TransientModel): "apply_on_saturday", "apply_on_sunday", "apply_on_all_week", - "availability_plan_id", + "availability_plan_ids", "apply_quota", "apply_max_avail", "apply_min_stay", @@ -258,20 +264,21 @@ class AvailabilityWizard(models.TransientModel): ) def _compute_rules_to_overwrite(self): for record in self: - - if not record.availability_plan_id and self._context.get( - "availability_plan_id" + if not record.availability_plan_ids and self._context.get( + "availability_plan_ids" ): - record.availability_plan_id = self._context.get("availability_plan_id") + record.availability_plan_ids = [ + (4, self._context.get("availability_plan_ids")) + ] record.massive_changes_on = "availability_plan" - if record.availability_plan_id: + if record.availability_plan_ids: domain = [ - ("availability_plan_id", "=", record.availability_plan_id.id), + ("availability_plan_id", "in", record.availability_plan_ids.ids), ] - if record.room_type_id: - domain.append(("room_type_id", "=", record.room_type_id.id)) + if record.room_type_ids: + domain.append(("room_type_id", "in", record.room_type_ids.ids)) if record.start_date: domain.append(("date", ">=", record.start_date)) if record.end_date: @@ -284,7 +291,6 @@ class AvailabilityWizard(models.TransientModel): else: domain_overwrite = expression.OR(domain_overwrite) domain.extend(domain_overwrite) - week_days_to_apply = ( record.apply_on_monday, record.apply_on_tuesday, @@ -314,7 +320,7 @@ class AvailabilityWizard(models.TransientModel): @api.depends( "start_date", "end_date", - "room_type_id", + "room_type_ids", "apply_on_monday", "apply_on_tuesday", "apply_on_wednesday", @@ -323,18 +329,17 @@ class AvailabilityWizard(models.TransientModel): "apply_on_saturday", "apply_on_sunday", "apply_on_all_week", - "pricelist_id", + "pricelist_ids", ) def _compute_pricelist_items_to_overwrite(self): for record in self: - - if not record.pricelist_id and self._context.get("pricelist_id"): - record.pricelist_id = self._context.get("pricelist_id") + if not record.pricelist_ids and self._context.get("pricelist_ids"): + record.pricelist_ids = [(4, self._context.get("pricelist_ids"))] record.massive_changes_on = "pricelist" - if record.pricelist_id: + if record.pricelist_ids: domain = [ - ("pricelist_id", "=", record.pricelist_id.id), + ("pricelist_id", "in", record.pricelist_ids.ids), "|", ("pms_property_ids", "=", False), ("pms_property_ids", "in", record.pms_property_ids.ids), @@ -344,16 +349,21 @@ class AvailabilityWizard(models.TransientModel): domain.append(("date_start_overnight", ">=", record.start_date)) if record.end_date: domain.append(("date_end_overnight", "<=", record.end_date)) - - if record.room_type_id: + 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 + ) domain.append( ( - "product_tmpl_id", - "=", - record.room_type_id.product_id.product_tmpl_id.id, + "product_id", + "in", + product_ids, ) ) - week_days_to_apply = ( record.apply_on_monday, record.apply_on_tuesday, @@ -445,6 +455,7 @@ class AvailabilityWizard(models.TransientModel): ) # dates between start and end (both included) + items = [] for date in [ record.start_date + datetime.timedelta(days=x) for x in range(0, (record.end_date - record.start_date).days + 1) @@ -456,7 +467,7 @@ class AvailabilityWizard(models.TransientModel): ): continue - if not record.room_type_id: + if not record.room_type_ids: room_types = self.env["pms.room.type"].search( [ "|", @@ -465,119 +476,129 @@ class AvailabilityWizard(models.TransientModel): ] ) else: - room_types = [record.room_type_id] - for room_type in room_types: - for pms_property in record.pms_property_ids: + 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": - - self.env["product.pricelist.item"].create( - { - "pricelist_id": record.pricelist_id.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], - } - ) - else: - avail_plan_id = record.availability_plan_id.id - 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 {} - ) - - 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) - else: - self.env["pms.availability.plan.rule"].create( + for pricelist in record.pricelist_ids: + pricelist_item = self.env[ + "product.pricelist.item" + ].create( { - "availability_plan_id": avail_plan_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, + "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], } ) + 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 {} + ) + + 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 = {} if ( record.massive_changes_on == "pricelist" and not record.pricelist_readonly ): - action = self.env.ref("product.product_pricelist_action2").read()[0] - action["views"] = [ - (self.env.ref("pms.product_pricelist_view_form").id, "form") - ] - action["res_id"] = record.pricelist_id.id - return action + action = { + "view": self.env.ref("pms.product_pricelist_item_action2").read()[0] + } + if ( record.massive_changes_on == "availability_plan" and not record.avail_readonly ): - action = self.env.ref("pms.availability_action").read()[0] - action["views"] = [ - (self.env.ref("pms.availability_view_form").id, "form") - ] - action["res_id"] = record.availability_plan_id.id - return action + action = { + "view": self.env.ref( + "pms.availability_plan_rule_view_tree_action" + ).read()[0] + } + action["view"]["domain"] = [("id", "in", items)] + return action["view"] diff --git a/pms/wizards/wizard_massive_changes.xml b/pms/wizards/wizard_massive_changes.xml index 420c9434e..e0652d335 100644 --- a/pms/wizards/wizard_massive_changes.xml +++ b/pms/wizards/wizard_massive_changes.xml @@ -33,9 +33,11 @@ - +