Skip to content

Commit 4538aa3

Browse files
committed
[IMP] estate: revised security, learned new - website, controller, wizards
Revised security concept and solved one error occured while installing demo data in estate_account module. After that started new topic wizard which allow buyer to add same offers to many peoperties at once. taken refrece of codebase , docs and chatgpt and completed Learned controllers which opens end points for website to comunicate with modules. created endpoints and controller for active property page and property page (to display all metadata of property). Added new field to estate.property updated views and form to set image for properties. displayed image on website too. Updated demo data as per new fields, topics and verified everything by creating new database.
1 parent 51f40b8 commit 4538aa3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+599
-119
lines changed

estate/__init__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
from . import models
1+
from . import models
2+
from . import controllers
3+
from . import wizards

estate/__manifest__.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,33 @@
22
"version": "1.0",
33
"name": "Real Estate",
44
"category": "Real Estate/Brokerage",
5-
"depends": ["base"],
5+
"depends": ["base", "website", "mail"],
66
"author": "djip-odoo",
77
"description": """
88
part of technical training
99
""",
1010
"data": [
11-
# security
1211
"security/security.xml",
1312
"security/ir.model.access.csv",
14-
# reports
1513
"report/paperformat.xml",
1614
"report/company_details_templates.xml",
1715
"report/estate_property_offers_templates.xml",
1816
"report/res_users_reports.xml",
1917
"report/res_users_templates.xml",
2018
"report/estate_property_reports.xml",
2119
"report/estate_property_templates.xml",
22-
# views
20+
"wizards/wizard_add_offers.xml",
2321
"views/actions_menu_and_button.xml",
2422
"views/menu_views.xml",
2523
"views/estate_property_views.xml",
2624
"views/estate_property_type_views.xml",
2725
"views/estate_property_tag_views.xml",
2826
"views/estate_property_offer_views.xml",
2927
"views/res_users_views.xml",
28+
"views/website_menu.xml",
29+
"views/website_properties_templates.xml",
30+
"views/website_property_page_template.xml",
31+
"views/website_contact_form_template.xml",
3032
],
3133
"demo": [
3234
"demo/demo_res_company.xml",

estate/controllers/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from . import main
2+
from . import postreq

estate/controllers/main.py

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
from odoo.http import Controller, request, route
2+
3+
4+
class EstatePropertyControllers(Controller):
5+
@route("/active_properties", auth="public", website=True)
6+
def list_active_properties(self, page=1):
7+
page = int(page)
8+
limit = 3
9+
offset = (page - 1) * limit
10+
11+
properties = (
12+
request.env["estate.property"]
13+
.sudo()
14+
.search_read(
15+
[
16+
"&",
17+
("active", "=", True),
18+
("state", "in", ["new", "offer_received"]),
19+
],
20+
fields=["name", "expected_price", "description"],
21+
limit=limit,
22+
offset=offset,
23+
)
24+
)
25+
total_properties = (
26+
request.env["estate.property"]
27+
.sudo()
28+
.search_count(
29+
["&", ("active", "=", True), ("state", "in", ["new", "offer_received"])]
30+
)
31+
)
32+
total_pages = (total_properties + limit - 1) // limit
33+
34+
return request.render(
35+
"estate.property_list_template",
36+
{
37+
"properties": properties,
38+
"current_page": page,
39+
"total_pages": total_pages,
40+
},
41+
)
42+
43+
@route("/property/<int:property_id>", auth="public", website=True)
44+
def property_detail(self, property_id, **kw):
45+
property = request.env["estate.property"].sudo().browse(property_id)
46+
if property.exists():
47+
# print("*-*-" * 100)
48+
# print(property.image)
49+
return request.render(
50+
"estate.property_detail_template", {"property": property}
51+
)
52+
else:
53+
return request.not_found()
54+
55+
# Route for logged-in users
56+
@route("/private_page", auth="user")
57+
def private_page(self):
58+
"""
59+
Route accessible only to logged-in users.
60+
- Authentication is required.
61+
- Useful for internal interfaces or APIs where user identification is necessary.
62+
"""
63+
return """
64+
<h1>Private Page</h1>
65+
<p>This page is for logged-in users only.</p>
66+
<p>Authentication is required to access this route.</p>
67+
<p>It is commonly used for internal user interfaces or secure APIs.</p>
68+
"""
69+
70+
# Route with no authentication or session required
71+
@route("/none_type", auth="none", methods=["GET"], csrf=False)
72+
def api_data(self):
73+
return """
74+
Stateless API route with no authentication or session.
75+
<p><i><b>- Auth type: 'none' (no user/session context).</p></i></b>
76+
<p><i><b>- CSRF disabled for this route.</p></i></b>
77+
<p><i><b>- Suitable for integration scenarios requiring lightweight stateless operations.</p></i></b>
78+
"""
79+
80+
# Route accessible only to administrators
81+
@route("/admin_page", auth="admin")
82+
def admin_page(self):
83+
"""
84+
Route accessible only to administrators.
85+
- Auth type: 'admin'.
86+
- Suitable for pages or actions restricted to users with admin rights.
87+
"""
88+
return """
89+
<h1>Admin Page</h1>
90+
<p>This page is restricted to administrators only.</p>
91+
<p>It is used for critical or sensitive backend operations.</p>
92+
"""
93+
94+
# Route for portal users with website context
95+
@route("/portal_users", auth="portal", website=True)
96+
def my_orders(self):
97+
"""
98+
Route for portal users with website context.
99+
- Auth type: 'portal' (only users with portal access can view).
100+
- Includes website context for frontend integration.
101+
- Common use case: showing customer-specific data like orders or invoices.
102+
"""
103+
return """
104+
<h1>Portal Users Page</h1>
105+
<p>This page is only accessible to portal users (e.g., customers or suppliers).</p>
106+
<p>It is integrated with the website module for a frontend display.</p>
107+
"""

estate/controllers/postreq.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
from odoo import http
2+
from odoo.http import request, route
3+
import json
4+
5+
6+
class WebsiteContactForm(http.Controller):
7+
8+
@http.route("/website/contact_form", auth="public", website=True)
9+
def contact_form(self):
10+
# Render the contact form template
11+
return request.render("estate.contact_form_template")
12+
13+
@route(
14+
"/website/contact_form_submit",
15+
auth="user",
16+
methods=["POST"],
17+
type="http",
18+
website=True,
19+
)
20+
def submit_contact_form(self, **post):
21+
name = post.get("name")
22+
email = post.get("email")
23+
24+
request.env["res.partner"].sudo().create({"name": name, "email": email})
25+
26+
return request.render("estate.thank_you")
27+
28+
@http.route(
29+
"/ext_website/contact_form/submit",
30+
auth="public",
31+
methods=["POST"],
32+
type="json",
33+
website=True,
34+
csrf=False,
35+
cors="*",
36+
)
37+
def submit_contact_form_ext(self, **post):
38+
print("post:", post)
39+
if not post:
40+
try:
41+
post = json.loads(request.httprequest.data.decode("utf-8"))
42+
except Exception as e:
43+
_logger.error(f"Fallback JSON Parsing Error: {e}")
44+
return {"error": "Invalid request format"}
45+
46+
name = post.get("name")
47+
email = post.get("email")
48+
49+
# Debugging - check the received data
50+
print(f"Received data: {name}, {email}")
51+
52+
if name and email:
53+
# Create a new partner record with the provided data
54+
partner = (
55+
request.env["res.partner"].sudo().create({"name": name, "email": email})
56+
)
57+
return "Partner created successfully!"
58+
else:
59+
return "Error: Please provide both name and email."

estate/demo/estate.property.tags.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
"tag_green","Green","7"
99
"tag_waterfront","Waterfront","8"
1010
"tag_mountain_view","Mountain View","9"
11-
"tag_city_center","City Center","10"
11+
"tag_city_center","City Center","10"

estate/demo/estate.property.types.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
"estate_property_type_land","Land","3"
55
"estate_property_type_industrial","Industrial","4"
66
"estate_property_type_villa","Villa","5"
7-
"estate_property_type_apartment","Apartment","6"
7+
"estate_property_type_apartment","Apartment","6"

estate/demo/estate_property_demo.xml

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
<field name="company_id" ref="base.main_company" />
1919
<field name="garden_orientation">south</field>
2020
<field name="property_type_id" ref="estate_property_type_villa" />
21+
<field name="image" type="base64" file="estate/static/images/img_9.jpeg" />
2122
</record>
2223

2324
<record id="estate_property_trailer_home" model="estate.property">
@@ -38,6 +39,7 @@
3839
<field name="company_id" ref="base.main_company" />
3940
<field name="garden_orientation" />
4041
<field name="property_type_id" ref="estate_property_type_apartment" />
42+
<field name="image" type="base64" file="estate/static/images/img_8.jpeg" />
4143
</record>
4244

4345
<record id="estate_property_my_home" model="estate.property">
@@ -51,8 +53,8 @@
5153
<field name="bedrooms">15</field>
5254
<field name="living_area">10000</field>
5355
<field name="facades">4</field>
54-
<field name="user_id" ref="estate.estate_agent_user_1" />
55-
<field name="company_id" ref="base.main_company" />
56+
<field name="user_id" ref="estate.estate_agent_user_2" />
57+
<field name="company_id" ref="estate_company_2" />
5658
<field name="garage">False</field>
5759
<field name="garden">False</field>
5860
<field name="garden_area">0</field>
@@ -78,6 +80,7 @@
7880
})
7981
]"
8082
/>
83+
<field name="image" type="base64" file="estate/static/images/img_7.jpeg" />
8184
</record>
8285

8386

@@ -101,6 +104,7 @@
101104
<field name="property_type_id" ref="estate_property_type_villa" />
102105
<field name="tag_ids"
103106
eval="[(6, 0, [ref('tag_modern'), ref('tag_luxury'), ref('tag_spacious')])]" />
107+
<field name="image" type="base64" file="estate/static/images/img_6.jpg" />
104108
</record>
105109

106110
<record id="estate_property_commercial_office" model="estate.property">
@@ -122,6 +126,7 @@
122126
<field name="garden_orientation" />
123127
<field name="property_type_id" ref="estate_property_type_commercial" />
124128
<field name="tag_ids" eval="[(6, 0, [ref('tag_city_center'), ref('tag_spacious')])]" />
129+
<field name="image" type="base64" file="estate/static/images/img_5.jpeg" />
125130
</record>
126131

127132
<record id="estate_property_residential_apartment" model="estate.property">
@@ -160,6 +165,7 @@
160165
]"
161166
/>
162167
<field name="tag_ids" eval="[(6, 0, [ref('tag_modern'), ref('tag_economical')])]" />
168+
<field name="image" type="base64" file="estate/static/images/img_4.jpeg" />
163169
</record>
164170

165171
<record id="estate_property_land_for_sale" model="estate.property">
@@ -173,20 +179,21 @@
173179
<field name="bedrooms">0</field>
174180
<field name="living_area">0</field>
175181
<field name="facades">4</field>
176-
<field name="user_id" ref="estate.estate_agent_user_2" />
177-
<field name="company_id" ref="estate_company_2" />
182+
<field name="user_id" ref="estate.estate_agent_user_1" />
183+
<field name="company_id" ref="base.main_company" />
178184
<field name="partner_id" ref="base.res_partner_18" />
179185
<field name="garage">False</field>
180186
<field name="garden">False</field>
181187
<field name="garden_area">0</field>
182188
<field name="garden_orientation" />
183189
<field name="property_type_id" ref="estate_property_type_land" />
184190
<field name="tag_ids" eval="[(6, 0, [ref('tag_green'), ref('tag_waterfront')])]" />
191+
<field name="image" type="base64" file="estate/static/images/img_1.jpeg" />
185192
</record>
186193

187194
<record id="estate_property_industrial_warehouse" model="estate.property">
188195
<field name="name">Industrial Warehouse</field>
189-
<field name="state">sold</field>
196+
<field name="state">offer_received</field>
190197
<field name="description">An industrial warehouse with large storage capacity.</field>
191198
<field name="postcode">98765</field>
192199
<field name="date_availability">2024-04-10</field>
@@ -204,6 +211,7 @@
204211
<field name="garden_orientation" />
205212
<field name="property_type_id" ref="estate_property_type_industrial" />
206213
<field name="tag_ids" eval="[(6, 0, [ref('tag_spacious')])]" />
214+
<field name="image" type="base64" file="estate/static/images/img_2.jpeg" />
207215
</record>
208216

209217
<record id="estate_property_luxury_mountain_view_villa" model="estate.property">
@@ -219,14 +227,14 @@
219227
<field name="facades">5</field>
220228
<field name="garage">True</field>
221229
<field name="active">false</field>
222-
<field name="user_id" ref="estate.estate_agent_user_2" />
223-
<field name="company_id" ref="estate_company_2" />
230+
<field name="user_id" ref="estate.estate_agent_user_1" />
231+
<field name="company_id" ref="base.main_company" />
224232
<field name="partner_id" ref="base.res_partner_4" />
225233
<field name="garden_area">2000</field>
226234
<field name="garden_orientation">west</field>
227235
<field name="property_type_id" ref="estate_property_type_villa" />
228236
<field name="tag_ids" eval="[(6, 0, [ref('tag_luxury'), ref('tag_mountain_view')])]" />
237+
<field name="image" type="base64" file="estate/static/images/img_3.jpeg" />
229238
</record>
230239
</data>
231240
</odoo>
232-

estate/demo/estate_property_offers_demo.xml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
eval="(datetime.now() + timedelta(days=20)).strftime('%Y-%m-%d')" />
3434
</record>
3535
<record id="offer_1_modern_villa" model="estate.property.offers">
36-
<field name="price">25000000</field>
36+
<field name="price">25000000</field>
3737
<field name="partner_id" ref="base.res_partner_1" />
3838
<field name="property_id" ref="estate_property_modern_villa" />
3939
<field name="validity">30</field>
@@ -92,14 +92,12 @@
9292
</record>
9393
<record id="offer_1_industrial_warehouse" model="estate.property.offers">
9494
<field name="price">10550000</field>
95-
<field name="status">accepted</field>
9695
<field name="partner_id" ref="base.res_partner_12" />
9796
<field name="property_id" ref="estate_property_industrial_warehouse" />
9897
<field name="validity">30</field>
9998
</record>
10099
<record id="offer_2_industrial_warehouse" model="estate.property.offers">
101100
<field name="price">11050000</field>
102-
<field name="status">refused</field>
103101
<field name="partner_id" ref="base.res_partner_3" />
104102
<field name="property_id" ref="estate_property_industrial_warehouse" />
105103
<field name="validity">15</field>
@@ -119,4 +117,4 @@
119117
<field name="validity">30</field>
120118
</record>
121119
</data>
122-
</odoo>
120+
</odoo>

estate/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
from . import estate_property
33
from . import estate_property_type
44
from . import estate_property_tag
5-
from . import res_users
5+
from . import res_users

0 commit comments

Comments
 (0)