8000 [ADD] estate: initial Real Estate module with models, views, and rela… by raaa-odoo · Pull Request #757 · odoo/tutorials · GitHub
[go: up one dir, main page]

Skip to content

[ADD] estate: initial Real Estate module with models, views, and rela… #757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 15 commits into
base: 18.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
[IMP] estate: add chatter, demo data, access rules, and PDF report
Enhance the estate module with collaborative features, realistic demo
content, fine-grained access control, and printable PDF output to
support real-world usage, development, and testing.

- Enabled chatter by adding `mail.thread` and `mail.activity.mixin` to property
and offer models for tracking and communication.
- Added a demo data file to preload properties, offers, and users for
 development and testing.
- Implemented access control using mixins and record rules to restrict
read/write/delete permissions based on ownership and roles.
- Introduced a QWeb PDF report for properties with a print button to export
 property data as a downloadable document.

Improves module functionality, security, and usability for real-world use and
testing.
  • Loading branch information
raaa-odoo committed May 29, 2025
commit d52e2a399c6b10f647fa1f5051f16b28e68f1c3b
14 changes: 11 additions & 3 deletions estate/__manifest__.py
8000
Original file line number Diff line number Diff line change
@@ -1,20 +1,28 @@
{
'name': 'Real Estate',
'version': '1.0',
'depends': ['base', 'sale', 'mail'],
'depends': ['base', 'mail'],
'author': 'Rajeev Aanjana',
'category': 'Real Estate',
'category': 'Real Estate/Brokerage',
'description': 'A module for managing real estate properties',
'application': True,
'data': [
'security/security.xml',
'security/ir.model.access.csv',
'views/estate_property_views.xml',
'views/estate_property_offer_views.xml',
'views/estate_property_type_views.xml',
'views/estate_property_tag_views.xml',
'views/res_users_views.xml',
'views/estate_menus.xml',
# 'data/master_data.xml',
'data/estate_property_demo.xml',
'report/estate_property_templates.xml',
'report/estate_property_reports.xml',
],
# 'demo': [
# 'demo/demo_data.xml',
# ],
'license': 'LGPL-3',
'application': True,
'installable': True,
}
125 changes: 125 additions & 0 deletions estate/data/estate_property_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<odoo noupdate="1">
<record id="property_type_residential" model="estate.property.type">
<field name="name">Residential</field>
</record>
<record id="property_type_commercial" model="estate.property.type">
<field name="name">Commercial</field>
</record>
<record id="property_type_industrial" model="estate.property.type">
<field name="name">Industrial</field>
</record>
<record id="property_type_land" model="estate.property.type">
<field name="name">Land</field>
</record>



<record id="villa" model="estate.property">
<field name="name">Big Villa</field>
<field name="state">new</field>
<field name="description">A nice and big villa</field>
<field name="postcode">12345</field>
<field name="date_availability">2020-02-02</field>
<field name="expected_price">1600000</field>
<field name="bedrooms">6</field>
<field name="living_area">100</field>
<field name="facades">4</field>
<field name="garage">True</field>
<field name="garden">True</field>
<field name="garden_area">100000</field>
<field name="garden_orientation">south</field>
<field name="property_type_id" ref="property_type_residential"/>
</record>


<record id="offer_azure_villa_1" model="estate.property.offer">
<field name="offer_price">10000</field>
<field name="validity">14</field>
<field name="partner_id" ref="base.res_partner_12"/>
<field name="property_id" ref="villa"/>
</record>

<record id="offer_azure_villa_2" model="estate.property.offer">
<field name="offer_price">1500000</field>
<field name="validity">14</field>
<field name="partner_id" ref="base.res_partner_12"/>
<field name="property_id" ref="villa"/>
</record>

<record id="offer_deco_villa" model="estate.property.offer">
<field name="offer_price">1500001</field>
<field name="validity">14</field>
<field name="partner_id" ref="base.res_partner_2"/>
<field name="property_id" ref="villa"/>
</record>

<record id="trailer" model="estate.property">
<field name="name">Trailer Home</field>
<field name="state">canceled</field>
<field name="description">Home in a trailer park</field>
<field name="postcode">54321</field>
<field name="date_availability">1970-01-01</field>
<field name="expected_price">100000</field>
<field name="selling_price">120000</field>
<field name="bedrooms">1</field>
<field name="living_area">10</field>
<field name="facades">4</field>
<field name="garage">False</field>
<field name="garden">True</field>
<field name="property_type_id" ref="property_type_residential"/>
</record>

<record id="space_ship" model="estate.property">
<field name="name">International Space Station</field>
<field name="state">new</field>
<field name="description">Aliens sometimes come visit</field>
<field name="postcode">12345</field>
<field name="date_availability">2030-12-31</field>
<field name="expected_price">45890000</field>
<field name="property_type_id" ref="property_type_industrial"/>
</record>

<record id="cabin" model="estate.property">
<field name="name">Cozy Cabin</field>
<field name="state">new</field>
<field name="description">Small cabin by lake</field>
<field name="postcode">10000</field>
<field name="date_availability">2020-01-01</field>
<field name="expected_price">80000</field>
<field name="bedrooms">1</field>
<field name="living_area">10</field>
<field name="facades">4</field>
<field name="garage">False</field>
<field name="garden">True</field>
<field name="property_type_id" ref="property_type_residential"/>
</record>

<record id="offer_cabin_1" model="estate.property.offer">
<field name="offer_price">60000</field>
<field name="validity">14</field>
<field name="partner_id" ref="base.res_partner_12"/>
<field name="property_id" ref="cabin"/>
</record>

<record id="offer_cabin_2" model="estate.property.offer">
<field name="offer_price">75000</field>
<field name="validity">14</field>
<field name="partner_id" ref="base.res_partner_12"/>
<field name="property_id" ref="cabin"/>
</record>


<function model="estate.property.offer" name="action_accept">
<value eval="[ref('offer_deco_villa')]"/>
</function>

<function model="estate.property.offer" name="action_refuse">
<value eval="[ref('offer_azure_villa_1'), ref('offer_azure_villa_2')]"/>
</function>

<function model="estate.property" name="action_set_sold">
<value eval="[ref('villa')]"/>
</function>


</odoo>
14 changes: 14 additions & 0 deletions estate/data/master_data.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<odoo noupdate="1">
<record id="property_type_residential" model="estate.property.type">
<field name="name">Residential</field>
</record>
<record id="property_type_commercial" model="estate.property.type">
<field name="name">Commercial</field>
</record>
<record id="property_type_industrial" model="estate.property.type">
<field name="name">Industrial</field>
</record>
<record id="property_type_land" model="estate.property.type">
<field name="name">Land</field>
</record>
</odoo>
25 changes: 21 additions & 4 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class EstateProperty(models.Model):
_name = "estate.property"
_description = "Real Estate Property"
_order = "id desc"
_inherit = ["mail.thread"]
_inherit = ['mail.thread', 'mail.activity.mixin']
# Basic Fields
name = fields.Char(string="Name", required=True)
description = fields.Text(string="Description")
Expand Down Expand Up @@ -63,6 +63,12 @@ class EstateProperty(models.Model):
)
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
total_area = fields.Float(string='Total Area (sqm)', compute='_compute_total_area', store=True, help='Sum of living area and garden area')
company_id = fields.Many2one(
'res.company',
string='Company',
required=True,
default=lambda self: self.env.company
)
# SQL Constraints
_sql_constraints = [
(
Expand All @@ -82,7 +88,7 @@ class EstateProperty(models.Model):
),
]
# Computed Fields & Onchange

@api.depends("living_area", "garden_area")
def _compute_total_area(self):
for record in self:
Expand All @@ -102,8 +108,8 @@ def _onchange_garden(self):
record.garden_orientation = 'north'
else:
record.garden_area = 0
record.garden_orientation = ''
record.garden_orientation = False

# Add Action Logic of "Cancel" & "Sold"
def action_set_sold(self):
for record in self:
Expand Down Expand Up @@ -139,3 +145,14 @@ def _check_state_before_delete(self):
for record in self:
if record.state not in ('new', 'canceled'):
raise UserError("You can only delete properties in 'New' or 'canceled' state.")

def action_sold(self):
# Check the user has write access to the properties
self.check_access_rights('write')
self.check_access_rule('write')

# Create invoice with sudo to bypass access rights
invoice = self.env['account.move'].sudo().create({
# ... invoice creation data ...
})
return super().action_sold()
12 changes: 8 additions & 4 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from odoo import models, fields, api
from odoo.exceptions import UserError, ValidationError
from datetime import timedelta

from odoo import api, models, fields
from odoo.exceptions import UserError, ValidationError


class EstatePropertyOffer(models.Model):
_name = "estate.property.offer"
Expand All @@ -21,7 +22,6 @@ class EstatePropertyOffer(models.Model):
string="Date Deadline",
compute="_compute_date_deadline",
inverse="_inverse_date_deadline",
store=True,
)
property_type_id = fields.Many2one(
related="property_id.property_type_id", store=True
Expand Down Expand Up @@ -53,8 +53,11 @@ def action_accept(self):
raise UserError(
"You cannot accept an offer for a sold or cancelled property."
)
if record.property_id.offer_ids.filtered(lambda o: o.status == "accepted"):
# if record.property_id.offer_ids.filtered(lambda o: o.status == "accepted"):
# raise UserError("An offer has already been accepted for this property.")
if record.property_id.state == 'offer_accepted':
raise UserError("An offer has already been accepted for this property.")

record.status = "accepted"
record.property_id.buyer_id = record.partner_id
record.property_id.selling_price = record.offer_price
Expand Down Expand Up @@ -88,5 +91,6 @@ def create(self, offers):
"The offer price must be higher than the current best price."
)
curr_max_price = max(curr_max_price, offer["offer_price"])

estate.state = "offer_received"
return super().create(offers)
8 changes: 4 additions & 4 deletions estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from odoo import fields, api, models
from odoo import api, fields, models


class EstatePropertyType(models.Model):
_name = "estate.property.type"
_description = "Real Estate Property Type"
_order = "sequence, name"

sequence = fields.Integer(string="Sequence")
# Basic Fields
name = fields.Char(required=True)
Expand All @@ -23,8 +23,8 @@ class EstatePropertyType(models.Model):
_sql_constraints = [
('unique_type_name', 'UNIQUE(name)', 'The property type name must be unique.'),
]

@api.depends("property_ids.offer_ids")
def _compute_offer_count(self):
for prop_type in self:
prop_type.offer_count = len(prop_type.mapped("property_ids.offer_ids"))
prop_type.offer_count = len(prop_type.mapped("property_ids.offer_ids"))
21 changes: 21 additions & 0 deletions estate/report/estate_property_reports.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<odoo>
<record id="report_estate_property_offers" model="ir.actions.report">
<field name="name">Estate Property Offers Report</field>
<field name="model">estate.property</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">estate.estate_property_report_offers</field>
<field name="print_report_name">'Property Offer Report - %s' % object.name</field>
<field name="paperformat_id" ref="base.paperformat_euro"/>
<field name="binding_model_id" ref="estate.model_estate_property"/>
</record>

<record id="report_res_users_properties" model="ir.actions.report">
<field name="name">Salesperson Properties Report</field>
<field name="model">res.users</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">estate.res_users_report_properties</field>
<field name="print_report_name">'Salesperson Properties Report - %s' % object.name</field>
<field name="paperformat_id" ref="base.paperformat_euro"/>
<field name="binding_model_id" ref="base.model_res_users"/>
</record>
</odoo>
Loading
0