Skip to content

Commit e6b35b9

Browse files
[CLN] estate{_account}: applied suggested review comments
1 parent 750a886 commit e6b35b9

File tree

11 files changed

+167
-125
lines changed

11 files changed

+167
-125
lines changed

estate/models/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from . import estate_property
2-
from . import estate_property_type
3-
from . import estate_property_tag
42
from . import estate_property_offer
3+
from . import estate_property_tag
4+
from . import estate_property_type
55
from . import res_users

estate/models/estate_property.py

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dateutil.relativedelta import relativedelta
2-
from odoo import api, models, fields
2+
3+
from odoo import api, fields, models
34
from odoo.exceptions import UserError
45
from odoo.tools.float_utils import float_compare, float_is_zero
56

@@ -12,7 +13,9 @@ class EstateProperty(models.Model):
1213
name = fields.Char(required=True)
1314
description = fields.Text()
1415
postcode = fields.Char()
15-
date_availability = fields.Date(copy=False, default=fields.Date.today() + relativedelta(months=+3))
16+
date_availability = fields.Date(
17+
copy=False, default=fields.Date.today() + relativedelta(months=+3)
18+
)
1619
expected_price = fields.Float(required=True, default=1)
1720
selling_price = fields.Float(readonly=True, copy=False)
1821
bedrooms = fields.Integer(default=2)
@@ -22,78 +25,91 @@ class EstateProperty(models.Model):
2225
garden = fields.Boolean()
2326
garden_area = fields.Integer()
2427
garden_orientation = fields.Selection(
25-
selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]
28+
selection=[
29+
("north", "North"),
30+
("south", "South"),
31+
("east", "East"),
32+
("west", "West"),
33+
]
2634
)
2735
active = fields.Boolean(default=True)
2836
state = fields.Selection(
2937
selection=[
30-
('new', 'New'),
31-
('offer_received', 'Offer Received'),
32-
('offer_accepted', 'Offer Accepted'),
33-
('sold', 'Sold'),
34-
('cancelled', 'Cancelled')
38+
("new", "New"),
39+
("offer_received", "Offer Received"),
40+
("offer_accepted", "Offer Accepted"),
41+
("sold", "Sold"),
42+
("cancelled", "Cancelled"),
3543
],
3644
required=True,
3745
copy=False,
38-
default='new'
46+
default="new",
3947
)
4048
property_type_id = fields.Many2one("estate.property.type", string="Property Type")
4149
buyer_id = fields.Many2one("res.partner", copy=False)
4250
salesperson_id = fields.Many2one("res.users", default=lambda self: self.env.user)
4351
property_tag_ids = fields.Many2many("estate.property.tag", string="Propert Tags")
44-
offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers")
45-
52+
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
4653
total_area = fields.Float(compute="_compute_total_area")
4754
best_price = fields.Float(compute="_compute_best_price")
48-
49-
_positive_expected_price = models.Constraint(
50-
'CHECK(expected_price > 0)',
51-
'The Expected Price of a Property must be strictly positive'
55+
_check_positive_expected_price = models.Constraint(
56+
"CHECK(expected_price > 0)",
57+
"The Expected Price of a Property must be strictly positive",
5258
)
53-
54-
_positive_selling_price = models.Constraint(
55-
'CHECK(selling_price > 0)',
56-
'The Selling Price of a Property must be strictly positive'
59+
_check_positive_selling_price = models.Constraint(
60+
"CHECK(selling_price > 0)",
61+
"The Selling Price of a Property must be strictly positive",
5762
)
5863

59-
@api.constrains('expected_price', 'selling_price')
64+
@api.constrains("expected_price", "selling_price")
6065
def _check_selling_price(self):
61-
for prop in self:
62-
percentage = prop.selling_price / prop.expected_price
63-
if not float_is_zero(prop.selling_price, precision_digits=2) \
64-
and float_compare(percentage, 0.9, precision_digits=2) == -1:
65-
raise UserError("selling price cannot be lower than 90% of the expected price")
66+
for property in self:
67+
percentage = property.selling_price / property.expected_price
68+
if (
69+
not float_is_zero(property.selling_price, precision_digits=2)
70+
and float_compare(percentage, 0.9, precision_digits=2) == -1
71+
):
72+
raise UserError(
73+
"selling price cannot be lower than 90% of the expected price"
74+
)
6675

67-
@api.depends('living_area', 'garden_area')
76+
@api.depends("living_area", "garden_area")
6877
def _compute_total_area(self):
69-
for prop in self:
70-
prop.total_area = prop.living_area + prop.garden_area
78+
self.ensure_one()
79+
for property in self:
80+
property.total_area = property.living_area + property.garden_area
7181

72-
@api.depends('offer_ids')
82+
@api.depends("offer_ids")
7383
def _compute_best_price(self):
74-
for prop in self:
75-
prop.best_price = max(prop.offer_ids.mapped('price') or [0])
84+
self.ensure_one()
85+
for property in self:
86+
property.best_price = max(property.offer_ids.mapped("price") or [0])
7687

77-
@api.onchange('garden')
88+
@api.onchange("garden")
7889
def _onchange_garden(self):
7990
self.garden_area = 10 if self.garden else 0
80-
self.garden_orientation = 'north' if self.garden else ''
91+
self.garden_orientation = "north" if self.garden else ""
8192

8293
@api.ondelete(at_uninstall=False)
8394
def _unlink_if_new_or_cancelled_state(self):
84-
if any(not (prop.state == 'new' or prop.state == 'cancelled') for prop in self):
95+
if any(
96+
not (property.state == "new" or property.state == "cancelled")
97+
for property in self
98+
):
8599
raise UserError("You can only delete new or cancelled properties")
86100

87101
def action_sold(self):
88-
for prop in self:
89-
if prop.state == "cancelled":
102+
self.ensure_one()
103+
for property in self:
104+
if property.state == "cancelled":
90105
raise UserError("You cannot sell a cancelled property")
91-
prop.state = "sold"
106+
property.state = "sold"
92107
return True
93108

94109
def action_cancel(self):
95-
for prop in self:
96-
if prop.state == "sold":
110+
self.ensure_one()
111+
for property in self:
112+
if property.state == "sold":
97113
raise UserError("You cannot cancel a sold property")
98-
prop.state = "cancelled"
114+
property.state = "cancelled"
99115
return True
Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from dateutil.relativedelta import relativedelta
2-
from odoo import api, models, fields
2+
3+
from odoo import api, fields, models
34
from odoo.exceptions import UserError
45

56

@@ -10,43 +11,56 @@ class EstatePropertyOffer(models.Model):
1011

1112
price = fields.Float()
1213
status = fields.Selection(
13-
selection=[('accepted', 'Accepted'), ('refused', 'Refused')],
14-
copy=False
14+
selection=[("accepted", "Accepted"), ("refused", "Refused")], copy=False
15+
)
16+
partner_id = fields.Many2one("res.partner", string="Partner", required=True)
17+
property_id = fields.Many2one(
18+
"estate.property", string="Property", required=True, ondelete="cascade"
1519
)
16-
partner_id = fields.Many2one('res.partner', string="Partner", required=True)
17-
property_id = fields.Many2one('estate.property', string="Property", required=True, ondelete="cascade")
1820
validity = fields.Integer(default=7)
19-
date_deadline = fields.Date(compute="_compute_date_deadline", inverse="_inverse_date_deadline")
21+
date_deadline = fields.Date(
22+
compute="_compute_date_deadline", inverse="_inverse_date_deadline"
23+
)
2024
property_state = fields.Selection(related="property_id.state")
21-
property_type_id = fields.Many2one(related="property_id.property_type_id", store=True)
22-
23-
_positive_offer_price = models.Constraint(
24-
'CHECK(price > 0)',
25-
'The Offer Price must be strictly positive'
25+
property_type_id = fields.Many2one(
26+
related="property_id.property_type_id", store=True
27+
)
28+
_check_positive_offer_price = models.Constraint(
29+
"CHECK(price > 0)", "The Offer Price must be strictly positive"
2630
)
2731

2832
@api.depends("validity", "create_date")
2933
def _compute_date_deadline(self):
34+
self.ensure_one()
3035
for offer in self:
31-
offer.date_deadline = (offer.create_date or fields.Date.today()) + relativedelta(days=+offer.validity)
36+
offer.date_deadline = (
37+
offer.create_date or fields.Date.today()
38+
) + relativedelta(days=+offer.validity)
3239

3340
def _inverse_date_deadline(self):
41+
self.ensure_one()
3442
for offer in self:
35-
offer.validity = (offer.date_deadline - (offer.create_date or fields.Date.today()).date()).days
43+
offer.validity = (
44+
offer.date_deadline - (offer.create_date or fields.Date.today()).date()
45+
).days
3646

3747
@api.model
38-
def create(self, vals):
39-
for offer in vals:
40-
prop = self.env['estate.property'].browse(offer['property_id'])
41-
prop.state = "offer_received"
42-
if offer['price'] < prop.best_price:
43-
raise UserError(f"The offer must be higher than {prop.best_price}")
44-
return super().create(vals)
45-
46-
def accept_offer(self):
48+
def create(self, vals_list):
49+
EstateProperties = self.env["estate.property"].with_prefetch(
50+
[vals["property_id"] for vals in vals_list]
51+
)
52+
for offer in vals_list:
53+
property = EstateProperties.browse(offer["property_id"])
54+
property.state = "offer_received"
55+
if offer["price"] < property.best_price:
56+
raise UserError(f"The offer must be higher than {property.best_price}")
57+
return super().create(vals_list)
58+
59+
def action_accept_offer(self):
60+
self.ensure_one()
4761
for offer in self:
48-
if offer.status == 'refused':
49-
raise UserError("You cann't accept a refused offer")
62+
if offer.status == "refused":
63+
raise UserError("You cannot accept a refused offer")
5064
if offer.property_id.buyer_id:
5165
raise UserError("Only one offer can be accepted")
5266
offer.property_id.buyer_id = offer.partner_id
@@ -55,9 +69,10 @@ def accept_offer(self):
5569
offer.status = "accepted"
5670
return True
5771

58-
def refuse_offer(self):
72+
def action_refuse_offer(self):
73+
self.ensure_one()
5974
for offer in self:
60-
if offer.status == 'accepted':
75+
if offer.status == "accepted":
6176
raise UserError("You cannot refuse an accepted offer")
6277
offer.status = "refused"
6378
return True
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import models, fields
1+
from odoo import fields, models
22

33

44
class EstatePropertyTag(models.Model):
@@ -8,8 +8,7 @@ class EstatePropertyTag(models.Model):
88

99
name = fields.Char(required=True)
1010
color = fields.Integer()
11-
12-
_unique_name = models.Constraint(
13-
'UNIQUE(name)',
14-
'The name must be unique',
11+
_check_unique_name = models.Constraint(
12+
"UNIQUE(name)",
13+
"The name must be unique",
1514
)

estate/models/estate_property_type.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import api, models, fields
1+
from odoo import api, fields, models
22

33

44
class EstatePropertyType(models.Model):
@@ -8,13 +8,16 @@ class EstatePropertyType(models.Model):
88

99
name = fields.Char(required=True)
1010
sequence = fields.Integer(default=1)
11-
estate_property_ids = fields.One2many("estate.property", "property_type_id", string="Properties")
12-
offer_ids = fields.One2many("estate.property.offer", "property_type_id", string="Offers")
11+
estate_property_ids = fields.One2many(
12+
"estate.property", "property_type_id", string="Properties"
13+
)
14+
offer_ids = fields.One2many(
15+
"estate.property.offer", "property_type_id", string="Offers"
16+
)
1317
offer_count = fields.Integer(compute="_compute_offer_count")
14-
15-
_unique_name = models.Constraint(
16-
'UNIQUE(name)',
17-
'The name must be unique',
18+
_check_unique_name = models.Constraint(
19+
"UNIQUE(name)",
20+
"The name must be unique",
1821
)
1922

2023
@api.depends("offer_ids")

estate/models/res_users.py

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1-
from odoo import models, fields
1+
from odoo import fields, models
22

33

44
class ResUsers(models.Model):
5-
_inherit = 'res.users'
6-
_description = 'user with properties model'
5+
_inherit = "res.users"
6+
_description = "user with properties model"
77

8-
property_ids = fields.One2many('estate.property', 'salesperson_id', string='Estate Properties',
9-
domain=['|', ('state', '=', 'new'), ('state', '=', 'offer_received')])
8+
property_ids = fields.One2many(
9+
"estate.property",
10+
"salesperson_id",
11+
string="Estate Properties",
12+
domain=[
13+
(
14+
"state",
15+
"in",
16+
["new", "offer_received"],
17+
),
18+
],
19+
)

estate/views/estate_menus.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,32 @@
44
id="estate_property_menu_root"
55
name="Real Estate"
66
/>
7-
87
<menuitem
98
id="estate_property_menu_advertisements"
109
name="Advertisements"
1110
parent="estate_property_menu_root"
1211
sequence="1"
1312
/>
14-
1513
<menuitem
1614
id="estate_property_menu_properties"
1715
name="Properties"
1816
parent="estate_property_menu_advertisements"
1917
action="estate_property_action"
2018
sequence="1"
2119
/>
22-
2320
<menuitem
2421
id="estate_property_menu_settings"
2522
name="Settings"
2623
parent="estate_property_menu_root"
2724
sequence="2"
2825
/>
29-
3026
<menuitem
3127
id="estate_property_menu_property_type"
3228
name="Property Types"
3329
parent="estate_property_menu_settings"
3430
action="estate_property_type_action"
3531
sequence="1"
3632
/>
37-
3833
<menuitem
3934
id="estate_property_menu_property_tag"
4035
name="Property Tags"

estate/views/estate_property_offer_views.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@
2828
<field name="partner_id" string="Partner"/>
2929
<field name="validity" string="Validity (days)"/>
3030
<field name="date_deadline" string="Deadline"/>
31-
<button name="accept_offer" type="object" icon="fa-check"
32-
invisible="not not status or property_state == 'offer_accepted' or property_state == 'sold' or property_state == 'cancelled'"/>
33-
<button name="refuse_offer" type="object" icon="fa-close"
34-
invisible="not not status or property_state == 'offer_accepted' or property_state == 'sold' or property_state == 'cancelled'"/>
31+
<button name="action_accept_offer" type="object" icon="fa-check"
32+
invisible="status or property_state in['offer_accepted', 'sold', 'cancelled']"/>
33+
<button name="action_refuse_offer" type="object" icon="fa-close"
34+
invisible="status or property_state in['offer_accepted', 'sold', 'cancelled']"/>
3535
<field name="property_type_id" string="Property Type"/>
3636
</list>
3737
</field>

0 commit comments

Comments
 (0)