Skip to content

Commit 5e07a63

Browse files
committed
[IMP] real_estate: restrict record access and define initial module data
- Applied record rules and security groups to restrict user access based on roles. - Users can only view or modify records they are permitted to. - Defined initial data (user roles, property types, permissions) for consistent module setup.
1 parent 14dd401 commit 5e07a63

21 files changed

+212
-107
lines changed

awesome_gallery/views/views.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
<field name="res_model">res.partner</field>
77
<field name="view_mode">kanban,tree,form,activity</field>
88
<field name="search_view_id" ref="base.view_res_partner_filter"/>
9-
<field name="context">{'default_is_company': True}</field>
109
<field name="help" type="html">
1110
<p class="o_view_nocontent_smiling_face">
1211
Create a Contact in your address book

estate_account/models/estate_property.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ class EstateProperty(models.Model):
66
_inherit = "estate.property"
77

88
def action_sold(self):
9-
journal = self.env['account.journal'].search([
9+
self.check_access_rights('write')
10+
self.check_access_rule('write')
11+
journal = self.env['account.journal'].sudo().search([
1012
('type', '=', 'sale'),
1113
], limit=1)
1214

@@ -37,7 +39,5 @@ def action_sold(self):
3739
}),
3840
],
3941
}
40-
41-
self.env['account.move'].create(invoice_vals)
42-
42+
self.env['account.move'].sudo().create(invoice_vals)
4343
return super().action_sold()

real_estate/__manifest__.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
{
2-
'name': "RealEstate",
2+
'name': "Real Estate",
33
'version': '1.0',
44
'author': "prbo",
55
'license': 'LGPL-3',
6-
'category': 'Real Estate',
6+
'category': 'Real Estate/Brokerage',
77
'sequence': 1,
88
'application': True,
99
'depends': ['base'],
1010
'data': [
11+
'security/estate_security.xml',
1112
'security/ir.model.access.csv',
13+
'security/estate_property_rules.xml',
14+
'data/estate.property.type.csv',
1215
'views/estate_property_offer_view.xml',
1316
'views/estate_property_type_view.xml',
1417
'views/estate_property_views.xml',
1518
'views/estate_property_tag_view.xml',
16-
'views/estate_menus.xml',
1719
'views/res_users_views.xml',
20+
'views/estate_menus.xml',
21+
],
22+
'demo': [
23+
'demo/demo_data.xml',
1824
],
1925
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
id,name
2+
estate_property_type_residential,Residential
3+
estate_property_type_commercial,Commercial
4+
estate_property_type_industrial,Industrial
5+
estate_property_type_land,Land

real_estate/data/ir.model.access.csv

Lines changed: 0 additions & 2 deletions
This file was deleted.

real_estate/demo/demo_data.xml

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<odoo>
2+
<record id="estate_demo_property" model="estate.property">
3+
<field name="name">Big Villa</field>
4+
<field name="description">A nice and big villa</field>
5+
<field name="expected_price">97000</field>
6+
<field name="selling_price">97000</field>
7+
<field name="bedrooms">6</field>
8+
<field name="living_area">100</field>
9+
<field name="facades">4</field>
10+
<field name="garage">True</field>
11+
<field name="garden">True</field>
12+
<field name="garden_area">100000</field>
13+
<field name="garden_orientation">south</field>
14+
<field name="postcode">12345</field>
15+
<field name="date_availability">2020-02-02</field>
16+
<field name="state">new</field>
17+
<field name="property_type" ref="estate_property_type_residential" />
18+
</record>
19+
<record id="estate_demo_property_2" model="estate.property">
20+
<field name="name">Trailer home</field>
21+
<field name="description">Home in a trailer park</field>
22+
<field name="expected_price">1000</field>
23+
<field name="selling_price">1000</field>
24+
<field name="bedrooms">1</field>
25+
<field name="living_area">10</field>
26+
<field name="facades">4</field>
27+
<field name="garage">False</field>
28+
<field name="garden">False</field>
29+
<field name="postcode">54321</field>
30+
<field name="date_availability">1970-01-01</field>
31+
<field name="state">cancelled</field>
32+
<field name="property_type" ref="estate_property_type_residential" />
33+
</record>
34+
<record id="offer_azure_accepted" model="estate.property.offer">
35+
<field name="partner_id" ref="base.res_partner_1" />
36+
<field name="property_id" ref="estate_demo_property" />
37+
<field name="price">90000</field>
38+
<field name="validity">14</field>
39+
<field name="date_deadline" eval="(datetime.now() + timedelta(days=14)).date().isoformat()" />
40+
</record>
41+
<record id="offer_azure_rejected" model="estate.property.offer">
42+
<field name="partner_id" ref="base.res_partner_1" />
43+
<field name="property_id" ref="estate_demo_property" />
44+
<field name="price">1500000</field>
45+
<field name="validity">14</field>
46+
<field name="date_deadline" eval="(datetime.now() + timedelta(days=14)).date().isoformat()" />
47+
</record>
48+
<record id="offer_deco_rejected" model="estate.property.offer">
49+
<field name="partner_id" ref="base.res_partner_2" />
50+
<field name="property_id" ref="estate_demo_property" />
51+
<field name="price">1500001</field>
52+
<field name="validity">14</field>
53+
<field name="date_deadline" eval="(datetime.now() + timedelta(days=14)).date().isoformat()" />
54+
</record>
55+
<function model="estate.property.offer" name="action_accept">
56+
<value eval="[ref('offer_azure_accepted')]" />
57+
</function>
58+
<function model="estate.property.offer" name="action_refuse">
59+
<value eval="[ref('offer_azure_rejected')]" />
60+
</function>
61+
<function model="estate.property.offer" name="action_refuse">
62+
<value eval="[ref('offer_deco_rejected')]" />
63+
</function>
64+
<record id="demo_property_modern_apartment" model="estate.property">
65+
<field name="name">Modern Apartment</field>
66+
<field name="expected_price">100000</field>
67+
<field name="description">Stylish and modern 2BHK in the city center.</field>
68+
<field name="date_availability">2024-06-10</field>
69+
<field name="postcode">12345</field>
70+
<field name="selling_price">99000</field>
71+
<field name="state">new</field>
72+
<field name="bedrooms">2</field>
73+
<field name="living_area">950</field>
74+
<field name="facades">2</field>
75+
<field name="garage" eval="True"/>
76+
<field name="garden" eval="True"/>
77+
<field name="garden_area">200</field>
78+
<field name="property_type" ref="estate_property_type_residential"/>
79+
<field name="offer_ids" eval="[
80+
Command.create({
81+
'partner_id': ref('base.res_partner_1'),
82+
'price': 100000,
83+
'validity': 14,
84+
}),
85+
Command.create({
86+
'partner_id': ref('base.res_partner_2'),
87+
'price': 200000,
88+
'validity': 14,
89+
})
90+
]"/>
91+
</record>
92+
</odoo>

real_estate/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# license: LGPL-3
12
from . import estate_property
23
from . import estate_property_type
34
from . import estate_property_tag

real_estate/models/estate_property.py

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ class EstateProperty(models.Model):
88
_name = "estate.property"
99
_description = "Test Model"
1010
_order = "id desc"
11-
1211
name = fields.Char(required=True)
1312
description = fields.Text()
1413
postcode = fields.Char()
@@ -20,15 +19,13 @@ class EstateProperty(models.Model):
2019
expected_price = fields.Float(required=True)
2120
selling_price = fields.Float(readonly=True, copy=False)
2221
best_price = fields.Float(compute="_compute_best_price")
23-
24-
bedrooms = fields.Integer(default=2)
25-
facades = fields.Integer()
26-
garage = fields.Boolean()
27-
garden = fields.Boolean()
28-
living_area = fields.Float()
29-
garden_area = fields.Float()
22+
bedrooms = fields.Integer(string="Bedrooms", default=2)
23+
facades = fields.Integer(string="Facades")
24+
garage = fields.Boolean(string="Garage")
25+
garden = fields.Boolean(string="Garden")
26+
living_area = fields.Float(string="Living Area (m²)")
27+
garden_area = fields.Float(string="Garden Area (m²)")
3028
total_area = fields.Float(compute="_compute_total_area")
31-
3229
garden_orientation = fields.Selection(
3330
string='Garden Orientation',
3431
selection=[
@@ -39,7 +36,6 @@ class EstateProperty(models.Model):
3936
],
4037
help="Direction of the garden"
4138
)
42-
4339
active = fields.Boolean(default=True)
4440
state = fields.Selection(
4541
selection=[
@@ -53,17 +49,21 @@ class EstateProperty(models.Model):
5349
copy=False,
5450
default='new'
5551
)
56-
5752
property_type = fields.Many2one("estate.property.type", string="Property Type")
5853
buyer = fields.Many2one("res.partner", string="Buyer", copy=False)
5954
seller = fields.Many2one("res.users", string="Salesperson", default=lambda self: self.env.user)
6055
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
6156
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
62-
6357
_sql_constraints = [
6458
('check_expected_price_positive', 'CHECK(expected_price > 0)', 'Expected price must be strictly positive.'),
6559
('check_selling_price_positive', 'CHECK(selling_price >= 0)', 'Selling price must be zero or positive.')
6660
]
61+
company_id = fields.Many2one(
62+
'res.company',
63+
string='Company',
64+
required=True,
65+
default=lambda self: self.env.company
66+
)
6767

6868
@api.depends("living_area", "garden_area")
6969
def _compute_total_area(self):
@@ -91,14 +91,12 @@ def action_sold(self):
9191
if not record.buyer:
9292
raise UserError("Please assign a buyer before marking the property as sold.")
9393
record.state = 'sold'
94-
return True
9594

9695
def action_cancel(self):
9796
for record in self:
9897
if record.state in ['sold', 'cancelled']:
9998
raise UserError("You cannot cancel a sold or already cancelled property.")
10099
record.state = 'cancelled'
101-
return True
102100

103101
@api.constrains('selling_price', 'expected_price')
104102
def _check_selling_price_margin(self):

real_estate/models/estate_property_offer.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ class EstatePropertyOffer(models.Model):
77
_name = "estate.property.offer"
88
_description = "Property Offer"
99
_order = "price desc"
10-
1110
price = fields.Float(required=True)
1211
status = fields.Selection([
1312
('accepted', 'Accepted'),
@@ -24,14 +23,8 @@ class EstatePropertyOffer(models.Model):
2423
store=True,
2524
string="Property Type"
2625
)
27-
28-
validity = fields.Integer(default=7)
29-
date_deadline = fields.Date(
30-
compute="_compute_date_deadline",
31-
inverse="_inverse_date_deadline",
32-
store=True
33-
)
34-
26+
validity = fields.Integer(string="Validity (days)", default=7)
27+
date_deadline = fields.Date(string="Deadline Date", compute="_compute_date_deadline", inverse="_inverse_date_deadline", store=True)
3528
_sql_constraints = [
3629
('check_offer_price_positive', 'CHECK(price > 0)', 'Offer price must be strictly positive.')
3730
]
@@ -55,7 +48,6 @@ def action_accept(self):
5548
record.property_id.selling_price = record.price
5649
record.property_id.buyer = record.partner_id
5750
record.property_id.state = 'offer_accepted'
58-
5951
other_offers = self.search([
6052
('property_id', '=', record.property_id.id),
6153
('id', '!=', record.id)
@@ -69,10 +61,13 @@ def action_refuse(self):
6961

7062
@api.model_create_multi
7163
def create(self, vals_list):
64+
property_ids = list({vals['property_id'] for vals in vals_list if 'property_id' in vals})
65+
property_records = self.env['estate.property'].browse(property_ids)
66+
property_map = {prop.id: prop for prop in property_records}
7267
for vals in vals_list:
7368
property_id = vals.get('property_id')
74-
if property_id:
75-
property_rec = self.env['estate.property'].browse(property_id)
69+
property_rec = property_map.get(property_id)
70+
if property_rec:
7671
existing_offers = property_rec.offer_ids.filtered(
7772
lambda o: o.price >= vals.get('price', 0)
7873
)

real_estate/models/estate_property_tag.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,9 @@ class EstatePropertyTag(models.Model):
55
_name = "estate.property.tag"
66
_description = "Property Tag"
77
_order = "name"
8-
98
name = fields.Char(required=True)
109
color = fields.Integer(string="Color")
11-
sequence = fields.Integer(string="10")
12-
10+
sequence = fields.Integer(string="sequence", default="10")
1311
_sql_constraints = [
1412
('unique_tag_name', 'UNIQUE(name)', 'Tag name must be unique.')
1513
]

0 commit comments

Comments
 (0)