Skip to content

Commit 919f6ba

Browse files
committed
[IMP] real_estate: added test cases for offer validation and garden toggle
- Prevented new offers from being submitted on properties that are already sold. - Fixed the garden toggle so that when it’s unchecked, related fields like area and orientation are cleared. - Added test cases to verify offer restrictions and garden field behavior.
1 parent 483f43f commit 919f6ba

File tree

6 files changed

+86
-18
lines changed

6 files changed

+86
-18
lines changed

estate_account/models/estate_property.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ class EstateProperty(models.Model):
66
_inherit = "estate.property"
77

88
def action_sold(self):
9-
self.check_access_rights('write')
10-
self.check_access_rule('write')
9+
self.check_access('write')
1110
journal = self.env['account.journal'].sudo().search([
1211
('type', '=', 'sale'),
1312
], limit=1)

real_estate/demo/demo_data.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
<record id="offer_azure_accepted" model="estate.property.offer">
3535
<field name="partner_id" ref="base.res_partner_1" />
3636
<field name="property_id" ref="estate_demo_property" />
37-
<field name="price">90000</field>
37+
<field name="price">98000</field>
3838
<field name="validity">14</field>
3939
<field name="date_deadline" eval="(datetime.now() + timedelta(days=14)).date().isoformat()" />
4040
</record>

real_estate/models/estate_property.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,14 @@ def _onchange_garden(self):
8585
self.garden_orientation = False
8686

8787
def action_sold(self):
88+
self.check_access('write')
8889
for record in self:
89-
if record.state in ['sold', 'cancelled']:
90-
raise UserError("You cannot sell a cancelled or already sold property.")
91-
if not record.buyer:
92-
raise UserError("Please assign a buyer before marking the property as sold.")
90+
if record.state == 'cancelled':
91+
raise UserError("Cancelled properties cannot be sold.")
92+
if record.state == 'sold':
93+
raise UserError("The property is already sold.")
94+
if not record.offer_ids.filtered(lambda o: o.status == 'accepted'):
95+
raise UserError("You cannot sell a property without an accepted offer.")
9396
record.state = 'sold'
9497

9598
def action_cancel(self):

real_estate/models/estate_property_offer.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,19 @@ def action_refuse(self):
6161

6262
@api.model_create_multi
6363
def create(self, vals_list):
64-
property_ids = list({vals['property_id'] for vals in vals_list if 'property_id' in vals})
65-
property_records = self.env['estate.property'].browse(property_ids)
66-
property_map = {prop.id: prop for prop in property_records}
6764
for vals in vals_list:
65+
price = vals.get('price')
6866
property_id = vals.get('property_id')
69-
property_rec = property_map.get(property_id)
70-
if property_rec:
71-
existing_offers = property_rec.offer_ids.filtered(
72-
lambda o: o.price >= vals.get('price', 0)
73-
)
74-
if existing_offers:
75-
raise ValidationError("You cannot create an offer lower than or equal to an existing one.")
76-
property_rec.state = 'offer_received'
67+
if not property_id:
68+
raise ValidationError("Property ID must be provided.")
69+
property_obj = self.env['estate.property'].browse(property_id)
70+
71+
if property_obj.state == 'sold':
72+
raise UserError("Cannot create offer for a sold property.")
73+
existing_offers = property_obj.offer_ids.filtered(
74+
lambda o: o.price is not None and price is not None and o.price >= price
75+
)
76+
if existing_offers:
77+
raise ValidationError("You cannot create an offer with a lower or equal price than existing offers.")
78+
property_obj.state = 'offer_received'
7779
return super().create(vals_list)

real_estate/tests/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from . import test_estate_offer
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
from odoo.tests.common import TransactionCase
2+
from odoo.tests import Form
3+
from odoo.exceptions import UserError
4+
from odoo.tests import tagged
5+
6+
7+
@tagged('post_install', '-at_install')
8+
class TestEstatePropertyLogic(TransactionCase):
9+
10+
def setUp(self):
11+
super().setUp()
12+
Property = self.env['estate.property']
13+
Offer = self.env['estate.property.offer']
14+
self.partner = self.env['res.partner'].create({
15+
'name': 'Test Buyer',
16+
'email': '[email protected]'
17+
})
18+
self.property = Property.create({
19+
'name': 'Test Property',
20+
'state': 'new',
21+
'expected_price': 150000,
22+
'garden': True,
23+
'garden_area': 100,
24+
'garden_orientation': 'north',
25+
})
26+
self.offer = Offer.create({
27+
'property_id': self.property.id,
28+
'partner_id': self.partner.id,
29+
'price': 160000,
30+
})
31+
32+
def test_cannot_create_offer_on_sold_property(self):
33+
self.property.state = 'sold'
34+
with self.assertRaises(UserError):
35+
self.env['estate.property.offer'].create({
36+
'property_id': self.property.id,
37+
'partner_id': self.partner.id,
38+
'price': 170000
39+
})
40+
41+
def test_cannot_sell_property_without_accepted_offer(self):
42+
self.property.offer_ids.unlink()
43+
with self.assertRaises(UserError):
44+
self.property.action_sold()
45+
46+
def test_can_sell_property_with_accepted_offer(self):
47+
self.offer.action_accept()
48+
self.property.action_sold()
49+
self.assertEqual(self.property.selling_price, self.offer.price)
50+
self.assertEqual(self.property.buyer, self.partner)
51+
52+
def test_reset_garden_fields_when_unchecked(self):
53+
form = Form(self.env['estate.property'])
54+
form.name = 'Garden Test'
55+
form.garden = True
56+
form.expected_price = 15000
57+
form.garden_area = 50
58+
form.garden_orientation = 'east'
59+
prop = form.save()
60+
prop.garden = False
61+
prop._onchange_garden()
62+
self.assertEqual(prop.garden_area, 0)
63+
self.assertFalse(prop.garden_orientation)

0 commit comments

Comments
 (0)