Skip to content

Commit 35ef67e

Browse files
committed
[ADD] estate: add buttons and logic to manage property and offer state changes
- Add 'Cancel' and 'Sold' buttons to estate.property - Add 'Accept' and 'Refuse' buttons to estate.property.offer - Prevent accepting more than one offer - Set selling price and buyer on offer acceptance - Prevent cancelling sold properties and vice versa
1 parent a5a04ae commit 35ef67e

9 files changed

+136
-81
lines changed

estate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from . import models
1+
from . import models

estate/__manifest__.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{
2-
'name': 'Real Estate',
3-
'category': 'Real Estate/Brokerage',
4-
'application': True,
5-
'installable': True,
6-
'depends': ['base'],
7-
'data': [
8-
'security/estate_security.xml',
9-
'security/ir.model.access.csv',
10-
'views/estate_property_offers_views.xml',
11-
'views/estate_property_tag_views.xml',
12-
'views/estate_property_type_views.xml',
13-
'views/estate_property_views.xml',
14-
'views/estate_menus.xml',
2+
"name": "Real Estate",
3+
"category": "Real Estate/Brokerage",
4+
"application": True,
5+
"installable": True,
6+
"depends": ["base"],
7+
"data": [
8+
"security/estate_security.xml",
9+
"security/ir.model.access.csv",
10+
"views/estate_property_offers_views.xml",
11+
"views/estate_property_tag_views.xml",
12+
"views/estate_property_type_views.xml",
13+
"views/estate_property_views.xml",
14+
"views/estate_menus.xml",
1515
],
16-
'license': 'LGPL-3',
16+
"license": "LGPL-3",
1717
}

estate/models/estate_property.py

Lines changed: 52 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,88 @@
1-
from odoo import api,fields, models
1+
from odoo import api, fields, models, exceptions
22

33

44
class EstateProperty(models.Model):
55
_name = "estate.property"
66
_description = "Estate Property"
77

8-
9-
108
name = fields.Char(required=True)
119
description = fields.Text()
1210
postcode = fields.Char()
13-
date_availaility = fields.Date(default=(fields.Date.add(fields.Date.today(), days=90)), copy=False)
14-
11+
date_availaility = fields.Date(
12+
default=(fields.Date.add(fields.Date.today(), days=90)), copy=False
13+
)
14+
1515
expected_price = fields.Float(required=True)
16-
selling_price = fields.Float(readonly = True,copy=False)
16+
selling_price = fields.Float(readonly=True, copy=False)
1717
bedrooms = fields.Integer(default=2)
1818
living_area = fields.Integer()
1919
facades = fields.Integer()
2020
garage = fields.Boolean()
2121
garden = fields.Boolean()
2222
garden_area = fields.Integer()
2323
garden_orientation = fields.Selection(
24-
string = 'Type',
25-
selection=[('North','north'),('South','south'),('East','east'),('West','west')],
26-
help="Type is used to know the direction of the Garden ")
27-
active = fields.Boolean(default = True)
28-
state = fields.Selection([ ('new', 'New'),
29-
('offer_received', 'Offer Received'),
30-
('offer_accepted', 'Offer Accepted'),
31-
('sold', 'Sold'),
32-
('cancelled', 'Cancelled'),],required=True, copy=False, default='new')
24+
string="Type",
25+
selection=[
26+
("North", "north"),
27+
("South", "south"),
28+
("East", "east"),
29+
("West", "west"),
30+
],
31+
help="Type is used to know the direction of the Garden ",
32+
)
33+
active = fields.Boolean(default=True)
34+
state = fields.Selection(
35+
[
36+
("new", "New"),
37+
("offer_received", "Offer Received"),
38+
("offer_accepted", "Offer Accepted"),
39+
("sold", "Sold"),
40+
("cancelled", "Cancelled"),
41+
],
42+
required=True,
43+
copy=False,
44+
default="new",
45+
)
3346
property_type = fields.Many2one("estate.property.type", string="Property Type")
34-
salesman = fields.Many2one("res.users", default = lambda self: self.env.user)
35-
buyer = fields.Many2one("res.partner", copy=False)
47+
salesman = fields.Many2one("res.users", default=lambda self: self.env.user)
48+
buyer = fields.Many2one("res.partner", readonly=True, copy=False)
3649
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
3750
offers_ids = fields.One2many("estate.property.offers", "property_id")
38-
total_area = fields.Integer(compute= "_compute_area")
51+
total_area = fields.Integer(compute="_compute_area")
3952
best_price = fields.Float(compute="_compute_bestprice")
4053

41-
#it's calculate the total area
42-
@api.depends('living_area','garden_area')
54+
# it's calculate the total area
55+
@api.depends("living_area", "garden_area")
4356
def _compute_area(self):
4457
for area in self:
4558
area.total_area = area.living_area + area.garden_area
4659

47-
#it's taking the best offer from among all
48-
@api.depends('offers_ids.price')
60+
# it's taking the best offer from among all
61+
@api.depends("offers_ids.price")
4962
def _compute_bestprice(self):
5063
for record in self:
51-
record.best_price = max(record.offers_ids.mapped('price'), default = 0)
52-
53-
#change the values on the basis of the garden True or False
54-
@api.onchange('garden')
64+
record.best_price = max(record.offers_ids.mapped("price"), default=0)
65+
66+
# change the values on the basis of the garden True or False
67+
@api.onchange("garden")
5568
def _onchnage_garden(self):
56-
if self.garden==True:
69+
if self.garden:
5770
self.garden_area = 10
5871
self.garden_orientation = "North"
5972
else:
6073
self.garden_area = 0
6174
self.garden_orientation = ""
6275

76+
def action_cancel(self):
77+
for record in self:
78+
if record.state != "sold":
79+
record.state = "cancelled"
80+
else:
81+
raise exceptions.UserError("A sold property cannot be cancelled")
6382

83+
def action_sold(self):
84+
for record in self:
85+
if record.state != "cancelled":
86+
record.state = "sold"
87+
else:
88+
raise exceptions.UserError("A cancelled property cannot be set as sold")
Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,57 @@
1-
from odoo import fields, models, api
1+
from odoo import fields, models, api, exceptions
22

33

44
class EstatePropertyOffer(models.Model):
55
_name = "estate.property.offers"
66
_description = "Estate Property Offer"
77

88
price = fields.Float()
9-
status = fields.Selection([("Accepted","accepted"),("refused","Refused")], copy=False)
9+
status = fields.Selection(
10+
[("Accepted", "accepted"), ("refused", "Refused")], copy=False
11+
)
1012
partner_id = fields.Many2one("res.partner", required=True)
1113
property_id = fields.Many2one("estate.property", required=True)
1214
validity = fields.Integer(default=7)
13-
date_deadline = fields.Date(compute = "_compute_deadline", inverse = "_inverse_deadline", store=True)
15+
date_deadline = fields.Date(
16+
compute="_compute_deadline", inverse="_inverse_deadline", store=True
17+
)
1418

15-
#date_deadline
16-
@api.depends("create_date","validity")
19+
# date_deadline
20+
@api.depends("create_date", "validity")
1721
def _compute_deadline(self):
1822
for record in self:
1923
if record.create_date:
20-
record.date_deadline = fields.Date.add(record.create_date, days=record.validity)
21-
#if user adding new data then their is no available of create_date then use today
24+
record.date_deadline = fields.Date.add(
25+
record.create_date, days=record.validity
26+
)
27+
# if user adding new data then their is no available of create_date then use today
2228
else:
23-
record.date_deadline = fields.Date.add(fields.Date.today(), days=record.validity)
24-
29+
record.date_deadline = fields.Date.add(
30+
fields.Date.today(), days=record.validity
31+
)
32+
2533
def _inverse_deadline(self):
2634
for record in self:
2735
if record.create_date:
28-
record.validity = (record.date_deadline - record.create_date.date()).days
36+
record.validity = (
37+
record.date_deadline - record.create_date.date()
38+
).days
2939
else:
30-
record.validity = (record.date_deadline - record.fields.Date.today()).days
40+
record.validity = (
41+
record.date_deadline - record.fields.Date.today()
42+
).days
3143

32-
33-
44+
def action_accepted(self):
45+
for record in self:
46+
#selling price is default 0 and field is readonly then when the selling_price 0 so their is no offer is accepted yet
47+
if record.property_id.selling_price == 0:
48+
record.status = "Accepted"
49+
record.property_id.selling_price = record.price
50+
record.property_id.buyer = record.partner_id
51+
record.property_id.state = "offer_accepted"
52+
else:
53+
raise exceptions.UserError("Already One Offer is Accepted")
54+
55+
def action_refused(self):
56+
for record in self:
57+
record.status = "refused"

estate/models/estate_property_tag.py

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

8-
name = fields.Char(required=True)
8+
name = fields.Char(required=True)

estate/models/estate_property_type.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
from odoo import fields,models
1+
from odoo import fields, models
2+
23

34
class EstatePropertyType(models.Model):
45
_name = "estate.property.type"
56
_description = "Property Type"
67

7-
name = fields.Char(required=True)
8+
name = fields.Char(required=True)

estate/views/estate_property_offers_views.xml

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@
1111
<field name="model">estate.property.offers</field>
1212
<field name="arch" type="xml">
1313
<list>
14-
<field name="partner_id"/>
15-
<field name="price"/>
16-
<field name="validity"/>
17-
<field name="date_deadline"/>
18-
<field name="status"/>
14+
<field name="partner_id" />
15+
<field name="price" />
16+
<field name="validity" />
17+
<field name="date_deadline" />
18+
<button name="action_accepted" type="object" string="Accepted" icon="fa-check" />
19+
<button name="action_refused" type="object" string="Refused" icon="fa-times" />
20+
<field name="status" />
1921
</list>
2022
</field>
2123
</record>
@@ -26,11 +28,10 @@
2628
<field name="arch" type="xml">
2729
<form>
2830
<group>
29-
<field name="partner_id"/>
30-
<field name="price"/>
31-
<field name="validity"/>
32-
<field name="date_deadline"/>
33-
<field name="status"/>
31+
<field name="partner_id" />
32+
<field name="price" />
33+
<field name="validity" />
34+
<field name="date_deadline" />
3435
</group>
3536
</form>
3637
</field>

estate/views/estate_property_views.xml

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<field name="selling_price" string="Selling Price" />
2020
<field name="date_availaility" string="Available From" />
2121
<field name="property_type" />
22-
<field name="tag_ids" widget="many2many_tags"/>
22+
<field name="tag_ids" widget="many2many_tags" />
2323
</list>
2424
</field>
2525
</record>
@@ -53,23 +53,27 @@
5353
<field name="model">estate.property</field>
5454
<field name="arch" type="xml">
5555
<form string="edit_form">
56+
<header>
57+
<button name="action_cancel" type="object" string="Cancel" />
58+
<button name="action_sold" type="object" string="Sold" />
59+
</header>
5660
<sheet>
57-
<group>
58-
<h1>
59-
<field name="name"></field>
60-
</h1>
61-
62-
<field name="tag_ids" widget="many2many_tags"/>
61+
<group>
62+
<h1>
63+
<field name="name"></field>
64+
</h1>
65+
66+
<field name="tag_ids" widget="many2many_tags" />
6367
</group>
6468
<group>
6569
<group>
66-
<field name="property_type"/>
70+
<field name="property_type" />
6771
<field name="postcode" />
6872
<field name="date_availaility" string="Available From" />
6973
</group>
7074
<group>
7175
<field name="expected_price" />
72-
<field name="best_price"/>
76+
<field name="best_price" />
7377
<field name="selling_price" />
7478
</group>
7579
</group>
@@ -84,13 +88,13 @@
8488
<field name="garden" />
8589
<field name="garden_area" string="Garden Area (sqm)" />
8690
<field name="garden_orientation" string="Garden Orientation" />
87-
<field name="active"/>
88-
<field name="state"/>
89-
<field name="total_area"/>
91+
<field name="active" />
92+
<field name="state" />
93+
<field name="total_area" />
9094
</group>
9195
</page>
9296
<page string="Offers">
93-
<field name="offers_ids"/>
97+
<field name="offers_ids" />
9498
</page>
9599
<page string="Other Info">
96100
<group>

git

Whitespace-only changes.

0 commit comments

Comments
 (0)