Skip to content

Commit c011c65

Browse files
committed
[IMP] estate: add sql and python constraints to estate_property
1 parent fc150fb commit c011c65

File tree

7 files changed

+64
-38
lines changed

7 files changed

+64
-38
lines changed

estate/__manifest__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,5 @@
1212
],
1313
'installable': True,
1414
'application': True,
15-
'auto_install': False,
1615
'license': 'AGPL-3',
1716
}

estate/models/estate_property.py

Lines changed: 44 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,24 @@
1-
from odoo import api, fields, models
2-
from odoo.exceptions import UserError
31
from dateutil.relativedelta import relativedelta
2+
from odoo import api, fields, models
3+
from odoo.exceptions import UserError, ValidationError
4+
from odoo.tools.float_utils import float_compare, float_is_zero
45

56

67
class EstateProperty(models.Model):
78
_name = "estate.property"
8-
_description = "Estate Property discription"
9+
_description = "Estate property"
10+
_sql_constraints = [
11+
("check_expected_price", "CHECK(expected_price > 0)",
12+
"The expected price must be strictly positive"),
13+
("check_sell_price", "CHECK(selling_price > 0)",
14+
"The selling price of a property must be positive")
15+
]
916

1017
name = fields.Char('name', required=True)
1118
description = fields.Text('description')
1219
postcode = fields.Char('postcode')
13-
availability_date = fields.Date(
14-
'availabilty date', copy=False, default=fields.Date.today() + relativedelta(months=3))
20+
availability_date = fields.Date('availabilty date', copy=False,
21+
default=fields.Date.today() + relativedelta(months=3))
1522
expected_price = fields.Float('expected price', required=True)
1623
selling_price = fields.Float('selling price', readonly=True, copy=False)
1724
bedrooms = fields.Integer('bedrooms', default=2)
@@ -22,25 +29,31 @@ class EstateProperty(models.Model):
2229
garden_area = fields.Integer('garden area')
2330
garden_orientation = fields.Selection(
2431
string='Garden Orientation',
25-
selection=[('north', 'North'), ('south', 'South'),
26-
('east', 'East'), ('west', 'West')]
32+
selection=[
33+
('north', 'North'),
34+
('south', 'South'),
35+
('east', 'East'),
36+
('west', 'West')
37+
],
2738
)
2839
active = fields.Boolean('active', default=True)
2940
state = fields.Selection(
3041
string='State',
31-
selection=[('new', 'New'), ('offer_received', 'Offer Received'),
32-
('offer_accepted', 'Offer Acccepted'), ('sold', 'Sold'),
33-
('cancelled', 'Cancelled')],
34-
default="new"
42+
selection=[
43+
('new', 'New'),
44+
('offer_received', 'Offer Received'),
45+
('offer_accepted', 'Offer Acccepted'),
46+
('sold', 'Sold'),
47+
('cancelled', 'Cancelled')
48+
],
49+
default="new",
3550
)
36-
property_type_id = fields.Many2one(
37-
"estate.property.type", string="property type")
38-
user_id = fields.Many2one(
39-
"res.users", string="Salesperson", default=lambda self: self.env.user)
51+
property_type_id = fields.Many2one("estate.property.type", string="property type")
52+
user_id = fields.Many2one("res.users", string="Salesperson",
53+
default=lambda self: self.env.user)
4054
buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False)
4155
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
42-
offer_ids = fields.One2many(
43-
"estate.property.offer", "property_id", string="Offers")
56+
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
4457
total_area = fields.Integer(compute='_compute_total_area')
4558
best_offer = fields.Float(compute="_compute_best_offer")
4659

@@ -52,8 +65,7 @@ def _compute_total_area(self):
5265
@api.depends("offer_ids")
5366
def _compute_best_offer(self):
5467
for record in self:
55-
record.best_offer = max(record.offer_ids.mapped(
56-
"price")) if record.offer_ids else 0.0
68+
record.best_offer = max(record.offer_ids.mapped("price"), default=0.0)
5769

5870
@api.onchange("garden")
5971
def _onchange_garden(self):
@@ -65,17 +77,21 @@ def _onchange_garden(self):
6577
self.garden_orientation = None
6678

6779
def action_sell(self):
68-
for record in self:
69-
if record.state == "cancelled":
70-
raise UserError("You can't sell a cancelled property")
71-
record.state = "sold"
72-
80+
if "cancelled" in self.mapped('state'):
81+
raise UserError("You can't sell a cancelled property")
82+
self.state = "sold"
7383
return True
7484

7585
def action_cancel(self):
76-
for record in self:
77-
if record.state == "sold":
78-
raise UserError("You can't cancel a sold property")
79-
record.state = "cancelled"
86+
if "sold" in self.mapped('state'):
87+
raise UserError("You can't cancel a sold property")
88+
self.state = "Cancelled"
8089

8190
return True
91+
92+
@api.constrains("selling_price", "expected_price")
93+
def _check_selling_price(self):
94+
for record in self:
95+
if not float_is_zero(record.selling_price, 2) and \
96+
float_compare(record.selling_price, 0.9*record.expected_price, 2) < 0:
97+
raise ValidationError("The selling price has to be at least 90% of the expected price")

estate/models/estate_property_offer.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
1+
from dateutil.relativedelta import relativedelta
12
from odoo import api, models, fields
23
from odoo.exceptions import UserError
3-
from dateutil.relativedelta import relativedelta
44

55

66
class EstatePropertyOffer(models.Model):
77
_name = "estate.property.offer"
8-
_description = "Estate property offer description"
8+
_description = "Estate property offer"
9+
_sql_constraints = [
10+
("check_price", "CHECK(price > 0)","The offer price must be strictly positive")
11+
]
912

1013
price = fields.Float('price')
1114
status = fields.Selection(
1215
string='status',
13-
selection=[('accepted', 'Accepted'), ('refused', 'Refused')]
16+
selection=[
17+
('accepted', 'Accepted'),
18+
('refused', 'Refused')
19+
],
1420
)
1521
partner_id = fields.Many2one('res.partner', required=True)
1622
property_id = fields.Many2one('estate.property', required=True)
1723
validity = fields.Integer(default=7)
18-
date_deadline = fields.Date(
19-
compute="_compute_date_deadline", inverse="_inverse_date_deadline")
24+
date_deadline = fields.Date(compute="_compute_date_deadline", inverse="_inverse_date_deadline")
2025

2126
@api.depends("validity", "create_date")
2227
def _compute_date_deadline(self):

estate/models/estate_property_tag.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
class EstatePropertyTag(models.Model):
55
_name = "estate.property.tag"
6-
_description = "Estate property tag description"
6+
_description = "Estate property tag"
7+
_sql_constraints = [
8+
("check_unique_name", "UNIQUE(name)", "Property tag must be unqie")
9+
]
710

811
name = fields.Char('name', required=True)

estate/models/estate_property_type.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33

44
class EstatePropertyType(models.Model):
55
_name = "estate.property.type"
6-
_description = "Estate property type description"
6+
_description = "Estate property type"
7+
_sql_constraints = [
8+
("check_unique_name", "UNIQUE(name)","Property type name must be unqie")
9+
]
710

811
name = fields.Char('name', required=True)

estate/views/estate_property_type_views.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<field name="name">properties.view.type.form</field>
2020
<field name="model">estate.property.type</field>
2121
<field name="arch" type="xml">
22-
<form string="properties type from">
22+
<form string="properties type form">
2323
<sheet>
2424
<h1>
2525
<field name="name"/>

estate/views/estate_property_views.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@
8989
<field name="expected_price"/>
9090
<field name="selling_price"/>
9191
<field name="availability_date"/>
92-
<filter string="Available" name="state" domain="['|',('state','=','new'),('state','=','offer_received')]"/>
92+
<filter string="Available" name="state" domain="[('state','in',['new', 'offer_received'])]"/>
9393
<group expand="1" string="Group By">
9494
<filter string="Postcode" name="postcode" context="{'group_by':'postcode'}"/>
9595
</group>

0 commit comments

Comments
 (0)