1
- from odoo import models , fields
2
-
1
+ from odoo import api ,models , fields
2
+ from datetime import date
3
+ from dateutil .relativedelta import relativedelta
4
+ from odoo .exceptions import UserError ,ValidationError
5
+ from odoo .tools .float_utils import float_compare
3
6
4
7
class EstateProperty (models .Model ):
5
- _name = "estate.property"
8
+ _name = "estate.property"
6
9
_description = "Real Estate Property"
7
10
8
- name = fields .Char ("Estate Name" , required = True , translate = True )
9
- price = fields .Integer ("Estate Price" , default = 0 )
11
+ name = fields .Char ("Estate Name" , required = True ,)
12
+ description = fields .Text ("Description" ,)
13
+ postcode = fields .Char ("Postalcode" )
14
+ date_availability = fields .Date ('Date Availability' , default = lambda self : date .today () + relativedelta (months = 3 ))
15
+ expected_price = fields .Float ('Expected Price' , required = True )
16
+ selling_price = fields .Float ('Selling Price' , readonly = True )
17
+ bedrooms = fields .Integer ("Bedrooms" , default = 2 )
18
+ living_area = fields .Integer ("Living Area (sqm)" )
19
+ facades = fields .Boolean ("Facades" )
20
+ garage = fields .Boolean ("Garage" )
21
+ garden = fields .Boolean ("Garden" )
22
+ garden_area = fields .Integer ("Garden Area (sqm)" )
23
+ garden_orientation = fields .Selection ( selection = [
24
+ ('north' ,'NORTH' ),
25
+ ('south' ,'SOUTH' ),
26
+ ('west' ,'WEST' ),
27
+ ('east' ,'EAST' ),
28
+ ])
29
+ active = fields .Boolean ("Active" , default = True )
30
+ state = fields .Selection (selection = [
31
+ ('new' ,'NEW' ),
32
+ ('offer_received' ,'OFFER RECEIVED' ),
33
+ ('offer_accepted' ,'OFFER ACCEPTED' ),
34
+ ('sold' ,'SOLD' ),
35
+ ('cancelled' ,'CANCELLED' ),
36
+ ], default = 'new' )
37
+ property_type_id = fields .Many2one ('estate.property.type' , string = 'Real Estate Type' )
38
+ buyer_id = fields .Many2one ('res.partner' , string = 'Buyer' ,)
39
+ salesperson_id = fields .Many2one ('res.partner' , string = 'Salesperson' , default = lambda self : self .env .user )
40
+ tag_ids = fields .Many2many ('estate.property.tag' , string = 'Real Estate Tag' )
41
+ offer_ids = fields .One2many ('estate.property.offer' , inverse_name = 'property_id' )
42
+ total_area = fields .Float ('Total Area (sqm)' , compute = '_compute_total_area' , readonly = True )
43
+ best_offer = fields .Float ('Best Offer' , compute = '_compute_best_offer' , readonly = True )
44
+ type_id = fields .Many2one ('estate.property.type' )
45
+ _order = 'id desc'
46
+
47
+ _sql_constraints = [
48
+ ('expected_price' , 'CHECK(expected_price > 0)' ,
49
+ 'The expected price should be strictly grater than 0.' ),
50
+ ('selling_price' , 'CHECK(selling_price > 0)' ,
51
+ 'The selling price should be strictly grater than 0.' ),
52
+ ]
53
+
54
+
55
+ def action_open_offers (self ):
56
+ self .ensure_one ()
57
+ return {
58
+ 'name' : 'Property Offer' ,
59
+ 'views' : [(self .env .ref ('estate.estate_property_offer_view_list' ).id , 'list' )],
60
+ 'type' : 'ir.actions.act_window' ,
61
+ 'domain' : [('id' , 'in' , self .offer_ids .ids )],
62
+ 'res_model' : 'estate.property.offer' ,
63
+ }
64
+
65
+ @api .ondelete (at_uninstall = False )
66
+ def on_delete (self , vals_list ):
67
+ for val in vals_list :
68
+ if val and val ['state' ] == 'new' or val ['state' ] == 'cancelled' :
69
+ raise UserError ('You can not delete a new or cancelled property' )
70
+
71
+
72
+ @api .constrains ('expected_price' ,'selling_price' )
73
+ def _check_expected_price (self ):
74
+ for record in self :
75
+ if float_compare (record .expected_price * 0.9 , record .selling_price , 3 ) == 1 and record .selling_price != 0 :
76
+ raise ValidationError (f"The selling price must be at least the 90% of the expected price." )
77
+
78
+
79
+ def action_cancel (self ):
80
+ if self .state != 'cancelled' :
81
+ self .state = 'cancelled'
82
+
83
+ def action_sold (self ):
84
+ if self .state == 'cencelled' :
85
+ raise UserError ("You can't sold an estate marked as CANCELLED" )
86
+ self .state = 'sold'
87
+
88
+
89
+ @api .depends ("living_area" , "garden_area" )
90
+ def _compute_total_area (self ):
91
+ for record in self :
92
+ record .total_area = record .living_area + (record .garden_area or 0 )
93
+
94
+ @api .depends ("offer_ids.price" )
95
+ def _compute_best_offer (self ):
96
+ for record in self :
97
+ if record .offer_ids :
98
+ record .best_offer = max (offer .price for offer in record .offer_ids )
99
+ else :
100
+ record .best_offer = 0 # Set to 0 if no offers are present
101
+
102
+ @api .onchange ("garden" )
103
+ def _onchange_garden (self ):
104
+ if self .garden :
105
+ self .garden_area = 10
106
+ self .garden_orientation = 'north'
107
+ else :
108
+ self .garden_area = 0 # Set to 0 when garden is False
109
+ self .garden_orientation = None
110
+
111
+
0 commit comments