Skip to content

Commit 99386a7

Browse files
author
Oussema Heni
committed
[IMP] real_estate: add action methods and models constraints
1 parent db55157 commit 99386a7

File tree

7 files changed

+162
-31
lines changed

7 files changed

+162
-31
lines changed

estate/models/estate_property.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,23 @@
11
from odoo import fields, models, api
2+
from odoo.exceptions import UserError, ValidationError
3+
from odoo.tools.float_utils import float_compare, float_is_zero
24
from datetime import timedelta
35

46

57
class EstateProperty(models.Model):
68
_name = "estate.property"
79
_description = "Estate property"
810

11+
_check_expected_price = models.Constraint(
12+
"CHECK(expected_price > 0)",
13+
"The expected price must be strictly positive.",
14+
)
15+
16+
_check_selling_price = models.Constraint(
17+
"CHECK(selling_price >= 0)",
18+
"The selling price must be positive.",
19+
)
20+
921
name = fields.Char('Name', required=True, default='My new house')
1022
description = fields.Text('Description')
1123
active = fields.Boolean(default=True)
@@ -115,3 +127,34 @@ def _inverse_date_deadline(self):
115127
record.validity = (
116128
record.date_deadline - record.create_date.date()
117129
).days
130+
131+
def action_cancel(self):
132+
for record in self:
133+
if record.state == "sold":
134+
raise UserError("A sold property cannot be cancelled.")
135+
record.state = "cancelled"
136+
return True
137+
138+
def action_sold(self):
139+
for record in self:
140+
if record.state == "cancelled":
141+
raise UserError("A cancelled property cannot be sold.")
142+
record.state = "sold"
143+
return True
144+
145+
@api.constrains("selling_price", "expected_price")
146+
def _check_selling_price(self):
147+
for record in self:
148+
if float_is_zero(record.selling_price, precision_rounding=0.01):
149+
continue
150+
151+
min_price = record.expected_price * 0.9
152+
153+
if float_compare(
154+
record.selling_price,
155+
min_price,
156+
precision_rounding=0.01
157+
) < 0:
158+
raise ValidationError(
159+
"The selling price cannot be lower than 90% of the expected price."
160+
)

estate/models/estate_property_offer.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@ class EstatePropertyOffer(models.Model):
66
_name = "estate.property.offer"
77
_description = "Estate Property Offer"
88

9+
_check_offer_price = models.Constraint(
10+
"CHECK(price > 0)",
11+
"The offer price must be strictly positive.",
12+
)
13+
914
price = fields.Float()
15+
1016
status = fields.Selection(
1117
[
1218
('accepted', 'Accepted'),
@@ -61,3 +67,22 @@ def _inverse_date_deadline(self):
6167
record.validity = (
6268
record.date_deadline - record.create_date.date()
6369
).days
70+
71+
def action_accept(self):
72+
for record in self:
73+
other_offers = record.property_id.offer_ids - record
74+
other_offers.write({"status": "refused"})
75+
76+
record.status = "accepted"
77+
78+
record.property_id.write({
79+
"buyer_id": record.partner_id.id,
80+
"selling_price": record.price,
81+
"state": "offer_accepted",
82+
})
83+
return True
84+
85+
def action_refuse(self):
86+
for record in self:
87+
record.status = "refused"
88+
return True

estate/models/estate_property_tag.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ class EstatePropertyTag(models.Model):
55
_name = "estate.property.tag"
66
_description = "Estate Property Tag"
77

8+
_unique_tag_name = models.Constraint(
9+
"UNIQUE(name)",
10+
"The property tag name must be unique.",
11+
)
12+
813
name = fields.Char(required=True)

estate/models/estate_property_type.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,9 @@ class EstatePropertyType(models.Model):
55
_name = "estate.property.type"
66
_description = "Estate property type"
77

8+
_unique_type_name = models.Constraint(
9+
"UNIQUE(name)",
10+
"The property type name must be unique.",
11+
)
12+
813
name = fields.Char('Name', required=True)

estate/security/ir.model.access.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
22
access_estate_property,access.estate.property,model_estate_property,base.group_user,1,1,1,1
33
access_estate_property_type,access.estate.property.type,model_estate_property_type,base.group_user,1,1,1,1
44
access_estate_property_tag,access.estate.property.tag,model_estate_property_tag,base.group_user,1,1,1,1
5-
access_estate_property_offer,estate.property.offer,model_estate_property_offer,,1,1,1,1
5+
access_estate_property_offer,estate.property.offer,model_estate_property_offer,base.group_user,1,1,1,1
Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,65 @@
11
<?xml version="1.0"?>
22
<odoo>
3-
<record id="view_estate_property_offer_tree" model="ir.ui.view">
4-
<field name="name">estate.property.offer.tree</field>
5-
<field name="model">estate.property.offer</field>
6-
<field name="arch" type="xml">
7-
<list>
8-
<field name="price"/>
9-
<field name="partner_id"/>
10-
<field name="status"/>
11-
<field name="validity"/>
12-
<field name="date_deadline"/>
13-
</list>
14-
</field>
15-
</record>
3+
<record id="view_estate_property_offer_tree" model="ir.ui.view">
4+
<field name="name">estate.property.offer.tree</field>
5+
<field name="model">estate.property.offer</field>
6+
<field name="arch" type="xml">
7+
<list>
8+
<field name="price" />
9+
<field name="partner_id" />
10+
<field name="status" />
11+
<field name="validity" />
12+
<button
13+
title="accept-btn"
14+
name="action_accept"
15+
type="object"
16+
icon="fa-check"
17+
/>
18+
<button
19+
title="refuse-btn"
20+
name="action_refuse"
21+
type="object"
22+
icon="fa-times"
23+
/>
24+
<field name="date_deadline" />
25+
</list>
26+
</field>
27+
</record>
1628

17-
<record id="view_estate_property_offer_form" model="ir.ui.view">
18-
<field name="name">estate.property.offer.form</field>
19-
<field name="model">estate.property.offer</field>
20-
<field name="arch" type="xml">
21-
<form>
22-
<sheet>
23-
<group>
24-
<field name="price"/>
25-
<field name="partner_id"/>
26-
<field name="validity"/>
27-
<field name="date_deadline"/>
28-
<field name="status"/>
29-
</group>
30-
</sheet>
31-
</form>
32-
</field>
33-
</record>
29+
<record id="view_estate_property_offer_form" model="ir.ui.view">
30+
<field name="name">estate.property.offer.form</field>
31+
<field name="model">estate.property.offer</field>
32+
<field name="arch" type="xml">
33+
<form>
34+
<header>
35+
<button
36+
name="action_accept"
37+
type="object"
38+
string="Accept"
39+
icon="fa-check"
40+
invisible="status == 'accepted'"
41+
title="accept-form-btn"
42+
/>
43+
44+
<button
45+
name="action_refuse"
46+
type="object"
47+
string="Refuse"
48+
icon="fa-times"
49+
invisible="status == 'refused'"
50+
title="reject-form-btn"
51+
/>
52+
</header>
53+
<sheet>
54+
<group>
55+
<field name="price" />
56+
<field name="partner_id" />
57+
<field name="validity" />
58+
<field name="date_deadline" />
59+
<field name="status" />
60+
</group>
61+
</sheet>
62+
</form>
63+
</field>
64+
</record>
3465
</odoo>

estate/views/estate_property_views.xml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,28 @@
2929
<field name="model">estate.property</field>
3030
<field name="arch" type="xml">
3131
<form string="Estate Property">
32+
<header>
33+
<button
34+
name="action_sold"
35+
type="object"
36+
string="Sold"
37+
class="btn-primary"
38+
invisible="state in ('sold', 'cancelled')"
39+
/>
40+
41+
<button
42+
name="action_cancel"
43+
type="object"
44+
string="Cancel"
45+
invisible="state in ('sold', 'cancelled')"
46+
/>
47+
48+
<field
49+
name="state"
50+
widget="statusbar"
51+
statusbar_visible="new,offer_received,offer_accepted,sold,cancelled"
52+
/>
53+
</header>
3254
<sheet>
3355
<div class="oe_title mb32">
3456
<h1>

0 commit comments

Comments
 (0)