diff --git a/pms/models/pms_amenity.py b/pms/models/pms_amenity.py index 5f4c37a1d..cda83cb73 100644 --- a/pms/models/pms_amenity.py +++ b/pms/models/pms_amenity.py @@ -12,9 +12,17 @@ class PmsRoomAmenity(models.Model): # Fields declaration name = fields.Char("Amenity Name", translate=True, required=True) pms_property_ids = fields.Many2many( - "pms.property", string="Properties", required=False, ondelete="restrict" + "pms.property", + string="Properties", + required=False, + ondelete="restrict", + ) + room_amenity_type_id = fields.Many2one( + "pms.amenity.type", + "Amenity Category", + domain="['|', ('pms_property_ids', '=', False),('pms_property_ids', 'in', " + "pms_property_ids)]", ) - room_amenity_type_id = fields.Many2one("pms.amenity.type", "Amenity Category") default_code = fields.Char("Internal Reference") active = fields.Boolean("Active", default=True) @@ -51,4 +59,4 @@ class PmsRoomAmenity(models.Model): if rec.pms_property_ids and rec.allowed_property_ids: for prop in rec.pms_property_ids: if prop not in rec.allowed_property_ids: - raise ValidationError(_("Property not allowed")) + raise ValidationError(_("Property not allowed in amenity type")) diff --git a/pms/models/pms_board_service_line.py b/pms/models/pms_board_service_line.py index 6fbba0ea3..58154dd4b 100644 --- a/pms/models/pms_board_service_line.py +++ b/pms/models/pms_board_service_line.py @@ -1,6 +1,7 @@ # Copyright 2017 Dario Lodeiros # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import api, fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class PmsBoardServiceLine(models.Model): @@ -29,3 +30,11 @@ class PmsBoardServiceLine(models.Model): def onchange_product_id(self): if self.product_id: self.update({"amount": self.product_id.list_price}) + + @api.constrains("pms_property_ids", "product_id") + def _check_property_integrity(self): + for record in self: + if record.pms_property_ids and record.product_id.pms_property_ids: + for pms_property in record.pms_property_ids: + if pms_property not in record.product_id.pms_property_ids: + raise ValidationError(_("Property not allowed in product")) diff --git a/pms/models/pms_board_service_room_type.py b/pms/models/pms_board_service_room_type.py index e5b029e8c..38219458a 100644 --- a/pms/models/pms_board_service_room_type.py +++ b/pms/models/pms_board_service_room_type.py @@ -1,7 +1,7 @@ # Copyright 2017 Dario # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from odoo import _, api, fields, models -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError class PmsBoardServiceRoomType(models.Model): @@ -34,26 +34,39 @@ class PmsBoardServiceRoomType(models.Model): ondelete="cascade", required=True, ) - pms_room_type_id = fields.Many2one( - "pms.room.type", - string="Room Type", - index=True, - ondelete="cascade", - required=True, - ) - pricelist_id = fields.Many2one( - "product.pricelist", string="Pricelist", required=False - ) - board_service_line_ids = fields.One2many( - "pms.board.service.room.type.line", "pms_board_service_room_type_id" - ) - # TODO:review relation with pricelist and properties pms_property_ids = fields.Many2many( "pms.property", string="Properties", required=False, ondelete="restrict", ) + pms_room_type_id = fields.Many2one( + "pms.room.type", + string="Room Type", + index=True, + ondelete="cascade", + required=True, + domain=[ + "|", + ("pms_property_ids", "=", False), + ("pms_property_ids", "in", pms_property_ids), + ], + ) + pricelist_id = fields.Many2one( + "product.pricelist", + string="Pricelist", + required=False, + domain=[ + "|", + ("pms_property_ids", "=", False), + ("pms_property_ids", "in", pms_property_ids), + ], + ) + board_service_line_ids = fields.One2many( + "pms.board.service.room.type.line", "pms_board_service_room_type_id" + ) + # TODO:review relation with pricelist and properties + price_type = fields.Selection( [("fixed", "Fixed"), ("percent", "Percent")], string="Type", @@ -130,6 +143,22 @@ class PmsBoardServiceRoomType(models.Model): ) ) + @api.constrains("pms_property_ids", "pms_room_type_ids") + def _check_room_type_property_integrity(self): + for record in self: + if record.pms_property_ids and record.pms_room_type_id.pms_property_ids: + for pms_property in record.pms_property_ids: + if pms_property not in record.pms_room_type_id.pms_property_ids: + raise ValidationError(_("Property not allowed in room type")) + + @api.constrains("pms_property_ids", "pricelist_id") + def _check_pricelist_property_integrity(self): + for record in self: + if record.pms_property_ids and record.pricelist_id: + for pms_property in record.pms_property_ids: + if pms_property not in record.pricelist_id.pms_property_ids: + raise ValidationError(_("Property not allowed in pricelist")) + # Action methods def open_board_lines_form(self): diff --git a/pms/models/pms_board_service_room_type_line.py b/pms/models/pms_board_service_room_type_line.py index 8e89e1551..53a0cbc16 100644 --- a/pms/models/pms_board_service_room_type_line.py +++ b/pms/models/pms_board_service_room_type_line.py @@ -1,6 +1,7 @@ # Copyright 2017 Dario Lodeiros # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import fields, models +from odoo import _, api, fields, models +from odoo.exceptions import ValidationError class PmsBoardServiceRoomTypeLine(models.Model): @@ -15,7 +16,23 @@ class PmsBoardServiceRoomTypeLine(models.Model): required=True, ) product_id = fields.Many2one( - "product.product", "Product", required=True, readonly=True + "product.product", + "Product", + required=True, + readonly=True, ) # TODO def default_amount "amount of service" amount = fields.Float("Amount", digits=("Product Price"), default=0.0) + + @api.constrains("pms_board_service_room_type_id", "product_id") + def _check_property_integrity(self): + for record in self: + if ( + record.pms_board_service_room_type_id.pms_property_ids + and record.product_id.pms_property_ids + ): + for ( + pms_property + ) in record.pms_board_service_room_type_id.pms_property_ids: + if pms_property not in record.product_id.pms_property_ids: + raise ValidationError(_("Property not allowed")) diff --git a/pms/models/pms_room.py b/pms/models/pms_room.py index 6d4b85f92..78e39a4fb 100644 --- a/pms/models/pms_room.py +++ b/pms/models/pms_room.py @@ -32,14 +32,29 @@ class PmsRoom(models.Model): "pms.property", required=True, ondelete="restrict", - default=lambda self: self.env.user.get_active_property_ids()[0], + default=lambda self: self.env.user.active_property_ids[0], ) room_type_id = fields.Many2one( - "pms.room.type", "Property Room Type", required=True, ondelete="restrict" + "pms.room.type", + "Property Room Type", + required=True, + ondelete="restrict", + domain=[ + "|", + ("pms_property_ids", "=", False), + (pms_property_id, "in", "pms_property_ids"), + ], ) shared_room_id = fields.Many2one("pms.shared.room", "Shared Room", default=False) floor_id = fields.Many2one( - "pms.floor", "Ubication", help="At which floor the room is located." + "pms.floor", + "Ubication", + help="At which floor the room is located.", + domain=[ + "|", + ("pms_property_ids", "=", False), + (pms_property_id, "in", "pms_property_ids"), + ], ) capacity = fields.Integer("Capacity") to_be_cleaned = fields.Boolean("To be Cleaned", default=False) @@ -111,7 +126,9 @@ class PmsRoom(models.Model): for rec in self: if rec.pms_property_id and rec.allowed_property_ids: if rec.pms_property_id.id not in rec.allowed_property_ids.ids: - raise ValidationError(_("Property not allowed")) + raise ValidationError( + _("Property not allowed in room type or in floor") + ) # Business methods diff --git a/pms/models/pms_room_type.py b/pms/models/pms_room_type.py index b46b4122e..124b0e72b 100644 --- a/pms/models/pms_room_type.py +++ b/pms/models/pms_room_type.py @@ -45,14 +45,32 @@ class PmsRoomType(models.Model): delegate=True, ondelete="cascade", ) - room_ids = fields.One2many("pms.room", "room_type_id", "Rooms") + room_ids = fields.One2many( + "pms.room", + "room_type_id", + "Rooms", + domain="[" + "'|', " + "('pms_property_id', '=', False), " + "('pms_property_id','in', pms_property_ids)" + "]", + ) class_id = fields.Many2one( "pms.room.type.class", "Property Type Class", required=True, + domain="[" + "'|', " + "('pms_property_ids', '=', False), " + "('pms_property_ids', 'in', pms_property_ids)" + "]", ) board_service_room_type_ids = fields.One2many( - "pms.board.service.room.type", "pms_room_type_id", string="Board Services" + "pms.board.service.room.type", + "pms_room_type_id", + string="Board Services", + domain="['|', ('pms_property_ids', '=', False), ('pms_property_ids', 'in', " + "pms_property_ids)]", ) room_amenity_ids = fields.Many2many( "pms.amenity", @@ -61,6 +79,11 @@ class PmsRoomType(models.Model): "amenity_ids", string="Room Type Amenities", help="List of Amenities.", + domain="[" + "'|', " + "('pms_property_ids', '=', False), " + "('pms_property_ids', 'in', pms_property_ids)" + "]", ) code_type = fields.Char( "Code", @@ -169,6 +192,37 @@ class PmsRoomType(models.Model): if other and other != rec: raise ValidationError(msg) + @api.constrains("room_amenity_ids", "pms_property_ids") + def _check_integrity_property_amenity(self): + for record in self: + if record.room_amenity_ids.pms_property_ids and record.pms_property_ids: + for pms_property in record.pms_property_ids: + if pms_property not in record.room_amenity_ids.pms_property_ids: + raise ValidationError(_("Property not allowed in amenity")) + + @api.constrains("room_ids", "pms_property_ids") + def _check_integrity_property_room(self): + for record in self: + if record.room_ids and record.pms_property_ids: + for room in record.room_ids: + if room.pms_property_id not in record.pms_property_ids: + raise ValidationError(_("Property not allowed in room")) + + @api.constrains("board_service_room_type_ids", "pms_property_ids") + def _check_integrity_property_board_service_room_type(self): + for record in self: + if record.board_service_room_type_ids and record.pms_property_ids: + for board_service_room_type in record.board_service_room_type_ids: + if board_service_room_type.pms_property_ids: + for pms_property in record.pms_property_ids: + if ( + pms_property + not in board_service_room_type.pms_property_ids + ): + raise ValidationError( + _("Property not allowed in board service room type") + ) + # ORM Overrides @api.model def create(self, vals): diff --git a/pms/models/product_pricelist.py b/pms/models/product_pricelist.py index aead05b70..97c38a9f8 100644 --- a/pms/models/product_pricelist.py +++ b/pms/models/product_pricelist.py @@ -21,7 +21,13 @@ class ProductPricelist(models.Model): "pms.property", string="Properties", required=False, ondelete="restrict" ) cancelation_rule_id = fields.Many2one( - "pms.cancelation.rule", string="Cancelation Policy" + "pms.cancelation.rule", + string="Cancelation Policy", + domain=[ + "|", + ("pms_property_ids", "=", False), + ("pms_property_ids", "in", pms_property_ids), + ], ) pricelist_type = fields.Selection( [("daily", "Daily Plan")], string="Pricelist Type", default="daily" @@ -34,6 +40,11 @@ class ProductPricelist(models.Model): comodel_name="pms.room.type.availability.plan", string="Availability Plan", ondelete="restrict", + domain=[ + "|", + ("pms_property_ids", "=", False), + ("pms_property_ids", "in", pms_property_ids), + ], ) # Constraints and onchanges @@ -161,4 +172,16 @@ class ProductPricelist(models.Model): if rec.pms_property_ids: for p in rec.pms_property_ids: if p.id not in rec.cancelation_rule_id.pms_property_ids.ids: - raise ValidationError(_("Property not allowed")) + raise ValidationError( + _("Property not allowed in cancelation rule") + ) + + @api.constrains("pms_property_ids", "availability_plan_id") + def _check_availability_plan_property_integrity(self): + for record in self: + if record.pms_property_ids and record.availability_plan_id.pms_property_ids: + for pms_property in record.pms_property_ids: + if pms_property not in record.availability_plan_id.pms_property_ids: + raise ValidationError( + _("Property not allowed availability plan") + ) diff --git a/pms/tests/__init__.py b/pms/tests/__init__.py index 7136aa1a6..a9fec7d89 100644 --- a/pms/tests/__init__.py +++ b/pms/tests/__init__.py @@ -33,4 +33,7 @@ from . import test_pms_wizard_folio from . import test_pms_res_users from . import test_pms_amenity from . import test_pms_room +from . import test_pms_board_service_line +from . import test_pms_board_service_room_type +from . import test_pms_board_service_room_type_line from . import test_pms_folio_invoice diff --git a/pms/tests/test_pms_board_service_line.py b/pms/tests/test_pms_board_service_line.py new file mode 100644 index 000000000..d16f2feec --- /dev/null +++ b/pms/tests/test_pms_board_service_line.py @@ -0,0 +1,46 @@ +from odoo.exceptions import ValidationError + +from .common import TestHotel + + +class TestPmsBoardService(TestHotel): + def test_property_integrity(self): + self.company1 = self.env["res.company"].create( + { + "name": "Pms_Company_Test", + } + ) + self.property1 = self.env["pms.property"].create( + { + "name": "Pms_property_test1", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.property2 = self.env["pms.property"].create( + { + "name": "Pms_property_test2", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.product = self.env["product.product"].create( + {"name": "Product", "pms_property_ids": self.property1} + ) + + self.board_service = self.env["pms.board.service"].create( + { + "name": "Board Service", + "price_type": "fixed", + } + ) + with self.assertRaises(ValidationError): + board_service_line = self.board_service_line = self.env[ + "pms.board.service.line" + ].create( + { + "product_id": self.product.id, + "pms_board_service_id": self.board_service.id, + } + ) + board_service_line.pms_property_ids = [self.property2.id] diff --git a/pms/tests/test_pms_board_service_room_type.py b/pms/tests/test_pms_board_service_room_type.py new file mode 100644 index 000000000..5bdaac266 --- /dev/null +++ b/pms/tests/test_pms_board_service_room_type.py @@ -0,0 +1,70 @@ +from odoo.exceptions import ValidationError + +from .common import TestHotel + + +class TestPmsBoardServiceRoomType(TestHotel): + def _create_common_scenario(self): + self.company1 = self.env["res.company"].create( + { + "name": "Pms_Company_Test", + } + ) + self.property1 = self.env["pms.property"].create( + { + "name": "Pms_property_test1", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.property2 = self.env["pms.property"].create( + { + "name": "Pms_property_test2", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.board_service = self.env["pms.board.service"].create( + {"name": "Board Service", "price_type": "fixed"} + ) + self.room_type_class = self.env["pms.room.type.class"].create( + {"name": "Room Type Class", "code_class": "SIN1"} + ) + self.room_type = self.env["pms.room.type"].create( + { + "name": "Room Type", + "code_type": "Type1", + "class_id": self.room_type_class.id, + } + ) + + def test_room_type_property_integrity(self): + self._create_common_scenario() + self.room_type.pms_property_ids = [self.property1.id] + with self.assertRaises(ValidationError): + self.board_service_room_type = self.env[ + "pms.board.service.room.type" + ].create( + { + "pms_board_service_id": self.board_service.id, + "pms_room_type_id": self.room_type.id, + "price_type": "fixed", + "pms_property_ids": self.property2, + } + ) + + def test_pricelist_property_integrity(self): + self._create_common_scenario() + self.pricelist = self.env["product.pricelist"].create( + {"name": "pricelist_1", "pms_property_ids": [self.property1.id]} + ) + with self.assertRaises(ValidationError): + self.env["pms.board.service.room.type"].create( + { + "pms_board_service_id": self.board_service.id, + "pms_room_type_id": self.room_type.id, + "price_type": "fixed", + "pricelist_id": self.pricelist.id, + "pms_property_ids": self.property2, + } + ) diff --git a/pms/tests/test_pms_board_service_room_type_line.py b/pms/tests/test_pms_board_service_room_type_line.py new file mode 100644 index 000000000..74fa31bf6 --- /dev/null +++ b/pms/tests/test_pms_board_service_room_type_line.py @@ -0,0 +1,63 @@ +from odoo.exceptions import ValidationError + +from .common import TestHotel + + +class TestPmsBoardServiceRoomTypeLine(TestHotel): + def test_check_product_property_integrity(self): + self.company1 = self.env["res.company"].create( + { + "name": "Pms_Company_Test", + } + ) + self.property1 = self.env["pms.property"].create( + { + "name": "Pms_property_test1", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.property2 = self.env["pms.property"].create( + { + "name": "Pms_property_test2", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.board_service = self.env["pms.board.service"].create( + {"name": "Board Service", "price_type": "fixed"} + ) + self.room_type_class = self.env["pms.room.type.class"].create( + { + "name": "Room Type Class", + "pms_property_ids": self.property1, + "code_class": "SIN1", + } + ) + self.room_type = self.env["pms.room.type"].create( + { + "name": "Room Type", + "code_type": "Type1", + "class_id": self.room_type_class.id, + } + ) + self.board_service_room_type = self.env["pms.board.service.room.type"].create( + { + "pms_board_service_id": self.board_service.id, + "pms_room_type_id": self.room_type.id, + "price_type": "fixed", + "pms_property_ids": self.property1, + } + ) + + self.product = self.env["product.product"].create( + {"name": "Product", "pms_property_ids": self.property2} + ) + + with self.assertRaises(ValidationError): + self.env["pms.board.service.room.type.line"].create( + { + "pms_board_service_room_type_id": self.board_service_room_type.id, + "product_id": self.product.id, + } + ) diff --git a/pms/tests/test_pms_pricelist.py b/pms/tests/test_pms_pricelist.py index 7f201405e..6139456ce 100644 --- a/pms/tests/test_pms_pricelist.py +++ b/pms/tests/test_pms_pricelist.py @@ -148,3 +148,17 @@ class TestPmsPricelist(common.TransactionCase): "cancelation_rule_id": self.cancelation_rule.id, } ) + + def test_availability_plan_property_integrity(self): + self.create_common_scenario() + self.availability_plan = self.env["pms.room.type.availability.plan"].create( + {"name": "Availability Plan", "pms_property_ids": [self.property1.id]} + ) + with self.assertRaises(ValidationError): + self.env["product.pricelist"].create( + { + "name": "Pricelist", + "pms_property_ids": [self.property2.id], + "availability_plan_id": self.availability_plan.id, + } + ) diff --git a/pms/tests/test_pms_room_type.py b/pms/tests/test_pms_room_type.py index f04696a94..5a0e65398 100644 --- a/pms/tests/test_pms_room_type.py +++ b/pms/tests/test_pms_room_type.py @@ -725,3 +725,85 @@ class TestRoomTypeCodePropertyUniqueness(TestRoomType): } ) r.pms_property_ids = [(4, self.p1.id)] + + def test_check_board_service_property_integrity(self): + self.company1 = self.env["res.company"].create( + { + "name": "Pms_Company_Test", + } + ) + self.property1 = self.env["pms.property"].create( + { + "name": "Pms_property_test1", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.property2 = self.env["pms.property"].create( + { + "name": "Pms_property_test2", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.room_type_class = self.env["pms.room.type.class"].create( + {"name": "Room Type Class", "code_class": "SIN1"} + ) + self.room_type = self.env["pms.room.type"].create( + { + "name": "Room Type", + "code_type": "Type1", + "pms_property_ids": self.property2, + "class_id": self.room_type_class.id, + } + ) + self.board_service = self.env["pms.board.service"].create( + {"name": "Board Service", "price_type": "fixed"} + ) + with self.assertRaises(ValidationError): + self.env["pms.board.service.room.type"].create( + { + "pms_board_service_id": self.board_service.id, + "pms_room_type_id": self.room_type.id, + "price_type": "fixed", + "pricelist_id": self.env.ref("product.list0").id, + "pms_property_ids": self.property2, + } + ) + + def test_check_amenities_property_integrity(self): + self.company1 = self.env["res.company"].create( + { + "name": "Pms_Company_Test", + } + ) + self.property1 = self.env["pms.property"].create( + { + "name": "Pms_property_test1", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.property2 = self.env["pms.property"].create( + { + "name": "Pms_property_test2", + "company_id": self.company1.id, + "default_pricelist_id": self.env.ref("product.list0").id, + } + ) + self.amenity = self.env["pms.amenity"].create( + {"name": "Amenity", "pms_property_ids": self.property1} + ) + self.room_type_class = self.env["pms.room.type.class"].create( + {"name": "Room Type Class", "code_class": "SIN1"} + ) + with self.assertRaises(ValidationError): + self.env["pms.room.type"].create( + { + "name": "Room Type", + "code_type": "Type1", + "class_id": self.room_type_class.id, + "pms_property_ids": [self.property2.id], + "room_amenity_ids": [self.amenity.id], + } + )