1
- from odoo import api , fields , models
2
- from odoo .exceptions import UserError
3
1
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
4
5
5
6
6
7
class EstateProperty (models .Model ):
7
8
_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
+ ]
9
16
10
17
name = fields .Char ('name' , required = True )
11
18
description = fields .Text ('description' )
12
19
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 ))
15
22
expected_price = fields .Float ('expected price' , required = True )
16
23
selling_price = fields .Float ('selling price' , readonly = True , copy = False )
17
24
bedrooms = fields .Integer ('bedrooms' , default = 2 )
@@ -22,25 +29,31 @@ class EstateProperty(models.Model):
22
29
garden_area = fields .Integer ('garden area' )
23
30
garden_orientation = fields .Selection (
24
31
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
+ ],
27
38
)
28
39
active = fields .Boolean ('active' , default = True )
29
40
state = fields .Selection (
30
41
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" ,
35
50
)
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 )
40
54
buyer_id = fields .Many2one ("res.partner" , string = "Buyer" , copy = False )
41
55
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" )
44
57
total_area = fields .Integer (compute = '_compute_total_area' )
45
58
best_offer = fields .Float (compute = "_compute_best_offer" )
46
59
@@ -52,8 +65,7 @@ def _compute_total_area(self):
52
65
@api .depends ("offer_ids" )
53
66
def _compute_best_offer (self ):
54
67
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 )
57
69
58
70
@api .onchange ("garden" )
59
71
def _onchange_garden (self ):
@@ -65,17 +77,21 @@ def _onchange_garden(self):
65
77
self .garden_orientation = None
66
78
67
79
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"
73
83
return True
74
84
75
85
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"
80
89
81
90
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" )
0 commit comments