Skip to content

Commit 824ce8f

Browse files
committed
[IMP] estate: Added Inheritance to module and created estate account module
Applied model and view inheritance patterns to extend core functionality Enabled interactions between modules for enhanced business workflows Updated business logic to support new integration features
1 parent c67201f commit 824ce8f

15 files changed

+170
-76
lines changed

awesome_gallery/models/ir_action.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ class ActWindowView(models.Model):
77

88
view_mode = fields.Selection(selection_add=[
99
('gallery', "Awesome Gallery")
10-
], ondelete={'gallery': 'cascade'})
10+
], ondelete={'gallery': 'cascade'})

estate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from . import models
1+
from . import models

estate/__manifest__.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
{
2-
'name':"Real Estate",
3-
'summary':"This is real estate module",
4-
'category':"Tutorials",
5-
'description':"This is real estate module",
6-
'author':"Dhruvrajsinh Zala (zadh)",
2+
'name': "Real Estate",
3+
'summary': "This is real estate module",
4+
'category': "Tutorials",
5+
'description': "This is real estate module",
6+
'author': "Dhruvrajsinh Zala (zadh)",
77
'installable': True,
88
'application': True,
9-
'data':['security/ir.model.access.csv', 'views/estate_property_offers.xml',
10-
'views/estate_property_views.xml',
11-
'views/estate_menus.xml',
12-
'views/estate_property_type_views.xml','views/estate_property_tags.xml']
13-
}
9+
'data': ['security/ir.model.access.csv', 'views/estate_property_views.xml', 'views/estate_property_offers.xml', 'views/estate_property_type_views.xml', 'views/estate_property_tags.xml', 'views/res_users_views.xml', 'views/estate_menus.xml'],
10+
'license': 'AGPL-3'
11+
}

estate/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from . import esatate_property_type
33
from . import estate_property_tags
44
from . import estate_property_offer
5+
from . import inherited_res_users
Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
from odoo import models,fields,api
2-
1+
from odoo import models, fields, api
32

43
class EstatePropertyTyeps(models.Model):
5-
_name="estate.property.types"
6-
_description="Types of Estate Property"
7-
_order="sequence,name"
84

9-
_unique_type_name = models.Constraint('UNIQUE(name)','Property type name must be unique.')
105

11-
name=fields.Char(required=True)
12-
property_ids=fields.One2many('estate.property','property_type_id',string="Properties")
6+
_name = "estate.property.types"
7+
_description = "Types of Estate Property"
8+
_order = "sequence, name"
9+
10+
_sql_constraints = [('_unique_type_name', 'UNIQUE(name)', 'Property type name must be unique.')]
11+
12+
name = fields.Char(required=True)
13+
property_ids = fields.One2many('estate.property', 'property_type_id', string="Properties")
1314
sequence = fields.Integer(default=1)
1415

1516
offer_ids = fields.One2many(
@@ -18,7 +19,6 @@ class EstatePropertyTyeps(models.Model):
1819
string="Offers"
1920
)
2021

21-
2222
offer_count = fields.Integer(
2323
string="Offer Count",
2424
compute='_compute_offer_count',
@@ -28,4 +28,4 @@ class EstatePropertyTyeps(models.Model):
2828
@api.depends('offer_ids')
2929
def _compute_offer_count(self):
3030
for record in self:
31-
record.offer_count = len(record.offer_ids)
31+
record.offer_count = len(record.offer_ids)

estate/models/estate_property.py

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,37 @@
11
from dateutil.relativedelta import relativedelta
2-
from odoo import models,fields,api,_
3-
from odoo.tools.float_utils import float_compare,float_is_zero
4-
from odoo.exceptions import UserError,ValidationError
2+
from odoo import models, fields, api, _
3+
from odoo.tools.float_utils import float_compare, float_is_zero
4+
from odoo.exceptions import UserError, ValidationError
55

66
class EstateProperty(models.Model):
7+
8+
79
_name = 'estate.property'
810
_description = 'Real Estate Property'
911
_order = 'id desc'
1012

13+
_sql_constraints = [('_check_expected_price', 'CHECK(expected_price > 0)', 'The expected price must be positive.'), ('_check_selling_price', 'CHECK(selling_price >= 0)', 'The selling price must be positive.')]
1114

12-
_check_expected_price = models.Constraint('CHECK(expected_price > 0)','The expected price must be positive.')
13-
_check_selling_price = models.Constraint('CHECK(selling_price >= 0)','The selling price must be positive.')
14-
15-
name = fields.Char(required=True,string="Title")
15+
name = fields.Char(required=True, string="Title")
1616
description = fields.Text()
1717
postcode = fields.Char()
1818
date_availability = fields.Date(
19-
default=lambda self: fields.Date.today() + relativedelta(months=3),
20-
copy=False,string="Available From")
19+
default=lambda self: fields.Date.today() + relativedelta(months=3), copy=False, string="Available From")
2120
expected_price = fields.Float(required=True)
22-
selling_price = fields.Float(readonly=True,copy=False)
21+
selling_price = fields.Float(readonly=True, copy=False)
2322
bedrooms = fields.Integer(default=2)
2423
living_area = fields.Integer(string="Living Area (sqm)")
25-
total_area = fields.Float(compute='_compute_total_area',store=True)
24+
total_area = fields.Float(compute='_compute_total_area', store=True)
2625
facades = fields.Integer()
27-
garage = fields.Boolean()
26+
garage = fields.Boolean()
2827
garden = fields.Boolean()
2928
garden_area = fields.Integer(string="Garden Area (sqm)")
3029
active = fields.Boolean(default=True)
3130
garden_orientation = fields.Selection([
32-
('north','North'),
33-
('south','South'),
34-
('east','East'),
35-
('west','West')
31+
('north', 'North'),
32+
('south', 'South'),
33+
('east', 'East'),
34+
('west', 'West')
3635
],string="Garden Orientation")
3736
state = fields.Selection(
3837
[
@@ -54,21 +53,27 @@ class EstateProperty(models.Model):
5453
salesperson_id = fields.Many2one(
5554
"res.users", string="Salesperson", default=lambda self: self.env.user
5655
)
57-
tag_ids = fields.Many2many('estate.property.tags',string="Tags")
56+
tag_ids = fields.Many2many('estate.property.tags', string="Tags")
5857

59-
offer_ids = fields.One2many('estate.property.offer','property_id',string="Offers")
58+
offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers")
6059

61-
best_price = fields.Float(compute='_get_best_offer_price',store=True)
60+
best_price = fields.Float(compute='_get_best_offer_price', store=True)
6261

63-
@api.depends("living_area","garden_area")
62+
@api.ondelete(at_uninstall=False)
63+
def _unlink_except_state_new_or_cancelled(self):
64+
for record in self:
65+
if record.state not in ['new', 'cancelled']:
66+
raise UserError(_("You can only delete properties in 'New' or 'Cancelled' state."))
67+
68+
@api.depends("living_area", "garden_area")
6469
def _compute_total_area(self):
6570
for record in self:
6671
record.total_area = record.living_area + record.garden_area
6772

6873
@api.depends('offer_ids.price')
6974
def _get_best_offer_price(self):
7075
for record in self:
71-
prices=record.offer_ids.mapped('price')
76+
prices = record.offer_ids.mapped('price')
7277
record.best_price = max(prices) if prices else 0.0
7378

7479
@api.onchange('garden')
@@ -83,28 +88,23 @@ def _onchange_garden(self):
8388

8489
def action_set_state_sold(self):
8590
for record in self:
86-
if(record.state == 'cancelled'):
91+
if record.state == 'cancelled':
8792
raise UserError(_("Cancelled property cannot be sold."))
8893
else:
8994
record.state = 'sold'
9095
return True
9196

9297
def action_set_state_cancel(self):
9398
for record in self:
94-
if(record.state == 'sold'):
99+
if record.state == 'sold':
95100
raise UserError(_("Sold property cannot be cancelled."))
96101
else:
97102
record.state = 'cancelled'
98103
return True
99104

100-
@api.constrains('selling_price','expected_price')
105+
@api.constrains('selling_price', 'expected_price')
101106
def _check_selling_price(self):
102107
for record in self:
103-
if not float_is_zero(record.selling_price,precision_digits=2):
104-
if float_compare(
105-
record.selling_price,
106-
record.expected_price * 0.9,
107-
precision_digits=2) < 0 :
108-
raise ValidationError(_("The selling price cannot be lower than 90% of the expected price"))
109-
110-
108+
if not float_is_zero(record.selling_price, precision_digits=2):
109+
if float_compare(record.selling_price, record.expected_price * 0.9, precision_digits=2) < 0 :
110+
raise ValidationError(_("The selling price cannot be lower than 90% of the expected price"))

estate/models/estate_property_offer.py

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,56 @@
1-
from odoo import fields,models,api,_
1+
from odoo import fields, models, api, _
22
from odoo.exceptions import UserError
3-
from datetime import timedelta,datetime
3+
from datetime import timedelta, datetime
44

55
class EstatePropertyOffer(models.Model):
6-
_name="estate.property.offer"
7-
_description="Offers of Estate Property"
8-
_order = 'price desc'
96

10-
_check_offer_price = models.Constraint('CHECK(price > 0)','The Offer price must be positive.')
7+
_name = "estate.property.offer"
8+
_description = "Offers of Estate Property"
9+
_order = 'price desc'
10+
_sql_constraints = [('_check_offer_price', 'CHECK(price > 0)', 'The Offer price must be positive.')]
1111

1212
price = fields.Float()
13-
status = fields.Selection([('accepted','Accepted'),('refused','Refused')],copy=False)
14-
partner_id = fields.Many2one('res.partner',string="Partner",required=True)
15-
property_id = fields.Many2one('estate.property',string="Property",required=True)
13+
status = fields.Selection([('accepted', 'Accepted'), ('refused', 'Refused')], copy=False)
14+
partner_id = fields.Many2one('res.partner', string="Partner", required=True)
15+
property_id = fields.Many2one('estate.property', string="Property", required=True)
1616
property_type_id = fields.Many2one(
1717
'estate.property.types',
1818
related="property_id.property_type_id",
1919
string="Property Type",
2020
required=True)
21-
2221
validity = fields.Integer(default=7)
23-
date_deadline = fields.Date(compute="_compute_deadline",inverse="_inverse_deadline",store=True)
22+
date_deadline = fields.Date(compute="_compute_deadline", inverse="_inverse_deadline", store=True)
23+
24+
@api.model_create_multi
25+
def create(self, vals):
26+
27+
for val in vals:
28+
property_id = val['property_id']
29+
offer_price = val['price']
30+
is_state_new = self.env['estate.property'].browse(property_id).state == 'new'
31+
32+
result = self.read_group(
33+
domain=[('property_id','=',property_id)],
34+
fields=['price:max'],
35+
groupby=[]
36+
)
37+
38+
max_price = result[0]['price'] if result else 0
39+
40+
if max_price >= offer_price:
41+
raise UserError(_("You cannot create an offer with a lower or equal amount than an existing offer for this property."))
42+
43+
if is_state_new:
44+
self.env['estate.property'].browse(property_id).state = 'offer_received'
45+
46+
return super().create(vals)
47+
2448
@api.depends('validity')
2549
def _compute_deadline(self):
2650
for record in self:
2751
create_date = record.create_date or datetime.now()
2852
record.date_deadline = create_date + timedelta(days=record.validity)
53+
2954
def _inverse_deadline(self):
3055
for record in self:
3156
create_date = record.create_date or datetime.now()
@@ -36,19 +61,19 @@ def _inverse_deadline(self):
3661
def action_accept_offer(self):
3762
for record in self:
3863
existing = self.search([
39-
('property_id','=',record.property_id.id),
40-
('status','=','accepted')
64+
('property_id', '=', record.property_id.id),
65+
('status', '=', 'accepted')
4166
])
4267
if existing:
4368
raise UserError(_("Another offer has been already accepted."))
4469
record.status = "accepted"
4570
record.property_id.state = "offer_accepted"
4671
record.property_id.selling_price = record.price
4772
record.property_id.buyer_id = record.partner_id.id
73+
4874
def action_refuse_offer(self):
4975
for record in self:
50-
if(record.status == 'accepted'):
76+
if record.status == 'accepted':
5177
raise UserError(_("Accepted Offer cannot be Refused"))
5278
else:
5379
record.status = "refused"
54-

estate/models/estate_property_tags.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
from odoo import fields,models
1+
from odoo import fields, models
22

33
class EstatePropertyTags(models.Model):
4-
_name="estate.property.tags"
5-
_description="Estate Property Tags"
4+
5+
6+
_name = "estate.property.tags"
7+
_description = "Estate Property Tags"
68
_order = "name"
79

8-
_unique_tag_name = models.Constraint('UNIQUE(name)','Tag name must be unique.')
10+
_sql_constraints = [('_unique_tag_name', 'UNIQUE(name)', 'Tag name must be unique.')]
911

10-
name=fields.Char(required=True)
11-
color=fields.Integer(default=3)
12+
name = fields.Char(required=True)
13+
color = fields.Integer(default=3)

estate/models/inherited_res_users.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from odoo import models, fields
2+
3+
class InheritedResUsers(models.Model):
4+
5+
_inherit = 'res.users'
6+
7+
property_ids = fields.One2many('estate.property',
8+
'salesperson_id',
9+
string='Available Properties',
10+
domain=[('state','in',['new','offer_received'])])

estate/security/ir.model.access.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
2-
estate.access_estate_property,access_estate_property,estate.model_estate_property,,1,1,1,1
2+
estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1
33
estate.access_estate_property_types,access_estate_property_types,estate.model_estate_property_types,base.group_user,1,1,1,1
44
estate.access_estate_property_tags,access_estate_property_tags,estate.model_estate_property_tags,base.group_user,1,1,1,1
55
estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1

0 commit comments

Comments
 (0)