diff --git a/estate.zip b/estate.zip new file mode 100644 index 0000000000..5446237138 Binary files /dev/null and b/estate.zip differ diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ab40a80f40..bddb9a613a 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -8,11 +8,16 @@ 'data': [ 'security/ir.model.access.csv', 'views/estate_property_views.xml', - 'views/estate_property_type_views.xml', 'views/estate_property_tag_views.xml', 'views/estate_property_offer_views.xml', + 'views/estate_property_type_views.xml', 'views/estate_menus.xml', - 'views/res_users_views.xml' + 'views/res_users_views.xml', + ], + 'demo': [ + 'demo/estate.property.type.csv', + 'demo/estate_property.xml', + 'demo/estate_property_offer.xml' ], 'installable': True, 'application': True, diff --git a/estate/demo/estate.property.type.csv b/estate/demo/estate.property.type.csv new file mode 100644 index 0000000000..17f4695bb6 --- /dev/null +++ b/estate/demo/estate.property.type.csv @@ -0,0 +1,5 @@ +"id","name" +"data_property_type_residential","Residential" +"data_property_type_commerial","Commerial" +"data_property_type_industrial","Industrial" +"data_property_type_land","Land" diff --git a/estate/demo/estate_property.xml b/estate/demo/estate_property.xml new file mode 100644 index 0000000000..71d03835de --- /dev/null +++ b/estate/demo/estate_property.xml @@ -0,0 +1,57 @@ + + + Big Villa + A nice and big villa + 12345 + + 1600000 + 6 + 100 + 4 + True + True + 100000 + south + + + + + Trailer home + cancelled + Home in a trailer park + 54321 + + 100000 + 1 + 10 + 4 + + + + + Tutorial House + offer_received + X2many tutorial + 13579 + + 123456 + 2 + 30 + 4 + + + + + \ No newline at end of file diff --git a/estate/demo/estate_property_offer.xml b/estate/demo/estate_property_offer.xml new file mode 100644 index 0000000000..87c01d263e --- /dev/null +++ b/estate/demo/estate_property_offer.xml @@ -0,0 +1,29 @@ + + + + + 10000 + 14 + + + + + + + 1500000 + 14 + + + + + + + 1500001 + 14 + + + + + + + diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index a816fd33d3..6971e731d1 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -57,19 +57,21 @@ def _compute_best_price(self): record.state = 'offer_received' @api.onchange("garden") - def _onchange_partner_id(self): + def _onchange_garden(self): for record in self: if record.garden: record.garden_area = 10 record.garden_orientation = 'north' else: - record.garden_area = None - record.garden_orientation = None + record.garden_area = 0 + record.garden_orientation = False def action_property_sold(self): for record in self: if record.state == 'cancelled': raise UserError("Cancelled properties cannot be sold.") + elif record.state != 'offer_accepted': + raise UserError("You cannot sell a property without an accepted offer.") else: record.state = 'sold' return True @@ -92,6 +94,6 @@ def _check_selling_price(self): def unlink_if_new_or_cancelled(self): for record in self: if record.state not in ('new', 'cancelled'): - raise UserError("Only new and cancelled properties can be sold.") + raise UserError("Only new and cancelled properties can be deleted.") if record.offer_ids: record.offer_ids.unlink() diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 8df062241a..3334e5a0ce 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -55,6 +55,9 @@ def action_offer_refuse(self): @api.model_create_multi def create(self, vals_list): for vals in vals_list: + property = self.env['estate.property'].browse(vals.get('property_id')) + if property.state in ('sold', 'cancelled'): + raise UserError(f"Cannot create an offer in a {property.state} property.") price = vals.get('price') estate_property = self.env['estate.property'].browse(vals.get('property_id')) if estate_property.best_price and price <= estate_property.best_price: diff --git a/estate/tests/__init__.py b/estate/tests/__init__.py new file mode 100644 index 0000000000..576617cccf --- /dev/null +++ b/estate/tests/__init__.py @@ -0,0 +1 @@ +from . import test_estate_property diff --git a/estate/tests/test_estate_property.py b/estate/tests/test_estate_property.py new file mode 100644 index 0000000000..75692d1295 --- /dev/null +++ b/estate/tests/test_estate_property.py @@ -0,0 +1,90 @@ +from odoo.tests.common import TransactionCase +from odoo.exceptions import UserError +from odoo.tests import Form, tagged +from odoo import Command + + +@tagged('post_install', '-at_install') +class EstateTestCase(TransactionCase): + + @classmethod + def setUpClass(cls): + # add env on cls and many other things + super().setUpClass() + + cls.property = cls.env['estate.property'].create([{'name': 'test_house'}]) + cls.partner = cls.env['res.partner'].create([{ + 'name': 'test_person', + }]) + + def test_creation_area(self): + """Test that the total_area is computed like it should.""" + self.property.living_area = 20 + self.property.garden = True + self.property.garden_area = 15 + + self.assertEqual(self.property.total_area, 35) + + def test_action_sell_without_accepted_offer(self): + """Test that everything behaves like it should when selling an invalid property.""" + + self.assertEqual(self.property.state, 'new') + + with self.assertRaises(UserError): + self.property.action_property_sold() + + def test_action_sell_with_accepted_offer(self): + """Test that everything behaves like it should when selling a valid property.""" + + self.property.offer_ids.create({ + 'property_id': self.property.id, + 'partner_id': self.partner.id, + 'price': 124, + 'validity': 14, + }) + self.property.offer_ids.action_offer_accept() + self.property.action_property_sold() + + self.assertRecordValues(self.property, [ + {'state': 'sold'}, + ]) + + def test_creation_offer_for_sold_property(self): + """Test that everything behaves like it should when property is sold.""" + + self.property.write({'offer_ids': [Command.create({ + 'partner_id': self.partner.id, + 'price': 124, + 'validity': 14, + })]}) + self.property.offer_ids.action_offer_accept() + self.property.action_property_sold() + + with self.assertRaises(UserError): + self.property.offer_ids.create({ + 'property_id': self.property.id, + 'partner_id': self.partner.id, + 'price': 130, + 'validity': 14, + }) + + def test_enable_garden(self): + """Test that default values are assigned to garden area and orientation when garden is enabled""" + + form = Form(self.env['estate.property']) + form.garden = True + + self.assertEqual(form.garden_area, 10) + self.assertEqual(form.garden_orientation, 'north') + + def test_disable_garden(self): + """Test that values are removed from garden area and orientation when garden is disabled""" + + form = Form(self.env['estate.property']) + form.garden = True + form.garden_area = 15 + form.garden_orientation = 'south' + form.garden = False + + self.assertEqual(form.garden_area, 0) + self.assertEqual(form.garden_orientation, False)