1- from odoo import models , fields
21from dateutil .relativedelta import relativedelta
2+ from odoo import models , fields , api
3+ from odoo .exceptions import UserError , ValidationError
4+ from odoo .tools .float_utils import float_compare , float_is_zero
35
46
57class EstateProperty (models .Model ):
@@ -9,15 +11,18 @@ class EstateProperty(models.Model):
911 name = fields .Char (required = True )
1012 description = fields .Text ()
1113 postcode = fields .Char ()
12- date_availability = fields .Date ("Availability Date" , default = fields .Date .today () + relativedelta (months = 3 ))
14+ date_availability = fields .Date (
15+ "Availability Date" ,
16+ default = lambda self : fields .Date .today () + relativedelta (months = 3 )
17+ )
1318 expected_price = fields .Float ("Expected Price" , required = True )
1419 selling_price = fields .Float ("Selling Price" , readonly = True )
1520 bedrooms = fields .Integer (default = 2 )
16- living_area = fields .Integer ("Living Area(sqm)" )
21+ living_area = fields .Integer ("Living Area (sqm)" )
1722 facades = fields .Integer ()
1823 garage = fields .Boolean ()
1924 garden = fields .Boolean ()
20- garden_area = fields .Integer ("Garden Area(sqm)" )
25+ garden_area = fields .Integer ("Garden Area (sqm)" )
2126 garden_orientation = fields .Selection (
2227 selection = [
2328 ("north" , "North" ),
@@ -41,9 +46,81 @@ class EstateProperty(models.Model):
4146 default = "new" ,
4247 )
4348 active = fields .Boolean (default = True )
44- property_type_id = fields .Many2one ("estate.property.type" , string = "Property Type" )
45- buyer_id = fields .Many2one ("res.partner" , string = "Buyer" , copy = False )
46- salesperson_id = fields .Many2one (
47- "res.users" , string = "Salesperson" )
49+ property_type_id = fields .Many2one ("estate.property.type" , "Property Type" )
50+ buyer_id = fields .Many2one ("res.partner" , "Buyer" , copy = False )
51+ salesperson_id = fields .Many2one ("res.users" , string = "Salesperson" )
4852 tag_ids = fields .Many2many ("estate.property.tag" , string = "Tags" )
4953 offer_ids = fields .One2many ("estate.property.offer" , "property_id" , string = "Offers" )
54+ total_area = fields .Integer ("Total Area (sqm)" , compute = "_compute_total_area" )
55+ best_price = fields .Float ("Best Offer" , compute = "_compute_best_price" )
56+
57+ @api .depends ("living_area" , "garden_area" )
58+ def _compute_total_area (self ):
59+ for record in self :
60+ record .total_area = (record .living_area or 0 ) + (record .garden_area or 0 )
61+
62+ @api .depends ("offer_ids.price" )
63+ def _compute_best_price (self ):
64+ for record in self :
65+ record .best_price = max (record .offer_ids .mapped ("price" ) or [0 ])
66+
67+ @api .onchange ("garden" )
68+ def _onchange_garden (self ):
69+ for record in self :
70+ if record .garden :
71+ if record .garden_area == 10 :
72+ record .garden_orientation = "north"
73+ elif record .garden_area == 20 :
74+ record .garden_orientation = "south"
75+ elif record .garden_area == 30 :
76+ record .garden_orientation = "east"
77+ elif record .garden_area == 40 :
78+ record .garden_orientation = "west"
79+ else :
80+ record .garden_area = 0
81+ record .garden_orientation = False
82+ else :
83+ record .garden_area = 0
84+ record .garden_orientation = False
85+
86+ def action_cancel (self ):
87+ for record in self :
88+ if record .state == "sold" :
89+ raise UserError ("A sold property cannot be cancelled" )
90+ record .state = "cancelled"
91+
92+ def action_sold (self ):
93+ for record in self :
94+ if record .state == "cancelled" :
95+ raise UserError ("A cancelled property cannot be set as sold" )
96+ record .state = "sold"
97+
98+ _sql_constraints = [
99+ (
100+ "check_expected_price" ,
101+ "CHECK(expected_price > 0)" ,
102+ "The expected price must be strictly positive." ,
103+ ),
104+ (
105+ "check_selling_price_positive" ,
106+ "CHECK(selling_price >= 0)" ,
107+ "The selling price must be positive." ,
108+ ),
109+ ]
110+
111+ @api .constrains ("selling_price" , "expected_price" )
112+ def _check_selling_price_ratio (self ):
113+ for record in self :
114+ if not float_is_zero (record .selling_price , precision_digits = 2 ):
115+ if (
116+ float_compare (
117+ record .selling_price ,
118+ record .expected_price * 0.9 ,
119+ precision_digits = 2 ,
120+ )
121+ < 0
122+ ):
123+ raise ValidationError (
124+ "The selling price cannot be lower than 90% of the expected price."
125+ )
126+
0 commit comments