Skip to content

Conversation

@haman-odoo
Copy link

@haman-odoo haman-odoo commented Dec 4, 2025

This Real Estate module to sell and manage properties from a single place.
It includes property listings, price offers, buyers, agents, tags and property types, all connected together with
features like best-offer calculation, availability, total area and dashboards.

@robodoo
Copy link

robodoo commented Dec 4, 2025

Pull request status dashboard

@haman-odoo haman-odoo force-pushed the 19.0-real-estate-tutorial-haman branch from 3a46ead to 949b655 Compare December 5, 2025 06:55
@haman-odoo haman-odoo force-pushed the 19.0-real-estate-tutorial-haman branch 10 times, most recently from 96dc36b to 2b93d6f Compare December 9, 2025 06:12
Copy link

@bit-odoo bit-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello @haman-odoo
You did a good job 👏

I have added some suggestions. And can you please improve your commit message, and pr message, and title regarding these guidelines - https://www.odoo.com/documentation/19.0/contributing/development/git_guidelines.html

One more thing, writing a comment is a good idea. But i think it is good only if our code is complex or doing some magic things, etc.

Thanks

'category': 'Sales/Real Estate',
'installable': True,
'auto_install': False,
'description': """Description text""",
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can add description after the name so others can read it easily.

@@ -0,0 +1,4 @@
from . import estate_property # noqa: F401
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from . import estate_property # noqa: F401
from . import estate_property

Comment on lines 1 to 3
from odoo import models, fields
from dateutil.relativedelta import relativedelta
from datetime import date
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First, we can import external libraries.

Comment on lines 10 to 27
name = fields.Char(string="Property Title", required=True)
description = fields.Text(string="Description")
postcode = fields.Char(string="Postcode")
date_availability = fields.Date(
string="Available From",
default=lambda sself: date.today() + relativedelta(months=3),
copy=False
)
expected_price = fields.Float(string="Expected Price", required=True)
selling_price = fields.Float(
string="Selling Price",
readonly=True,
copy=False
)

bedrooms = fields.Integer(string="Bedrooms", default=2)
living_area = fields.Integer(string="Living Area (sqm)")
facades = fields.Integer(string="Number of Facades")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to declare a string if it is the same as the field name because Odoo can generate a string.

_description = "Real Estate Property Offer"

price = fields.Float(string="Price")

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unneccary diff.

_name = "estate.property.tag"
_description = "Real Estate Property Tag"

name = fields.Char(string="Name", required=True)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, no need to write a string.

@@ -0,0 +1,15 @@
<!-- /home/odoo/odoo19/tutorials/estate/views/estate_menus.xml -->
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unneccary diff.

@@ -0,0 +1,32 @@
<!-- /home/odoo/odoo19/tutorials/estate/views/estate_property_offer_views.xml -->
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unneccary diff.

@@ -0,0 +1,9 @@
<!-- /home/odoo/odoo19/tutorials/estate/views/estate_property_type_views.xml -->
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unneccary diff.

@@ -0,0 +1,124 @@
<!-- /home/odoo/odoo19/tutorials/estate/views/estate_property_views.xml -->
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unneccary diff.

@haman-odoo haman-odoo force-pushed the 19.0-real-estate-tutorial-haman branch 3 times, most recently from d2aa309 to 44f5059 Compare December 9, 2025 11:25
@haman-odoo
Copy link
Author

Hello Sir, I’ve applied all your suggested changes and updated the commit messages.

@haman-odoo haman-odoo force-pushed the 19.0-real-estate-tutorial-haman branch from 7e10da0 to 3609cce Compare December 10, 2025 07:28
Created the initial structure for the Estate module:

- Added __init__.py file to initialize the module.
- Added __manifest__.py file with basic module metadata like:
  - name
  - version
  - depends
  - data
  - description
Chapter 3 : Added EstateProperty model with core fields.
Updated __init__.py files to load new models.
Chapter 4 : Added ir.model.access.csv file for defining EstateProperty access rules.
Granted basic read, write, create, and delete permissions to internal users.
Updated __manifest__.py to load the security access file.
Chapter 5 : Added EstateProperty list and form views to display and manage properties.
Created ir.actions.act_window action to open EstateProperty records.
Added Real Estate main menu, submenu, and Properties menu item linked to the action.
chapter 6 : Created list, form, and search views for the estate.property model.
Added menu items and actions to open the property views in the Real Estate module.
Created new model estate.property.type and added its list & form views, menu, and access rights.
Chapter 7 : Added Many2many - tag_ids field for assigning multiple tags to a property.
Added Many2one - salesperson_id, buyer_id, property_type_id fields.
Added One2many - offer_ids field to show multiple offers linked to one property.
…den fields

Chapter 8 : Added compute, inverse, and onchange methods for dynamic field updates.
Implemented automatic offer price, total area, and deadline calculations.
Added Tag and Offer models with validity and date deadline logic.
@haman-odoo haman-odoo force-pushed the 19.0-real-estate-tutorial-haman branch from 3609cce to 0d62e93 Compare December 11, 2025 05:50
Chapter 9 : Added Sold/Cancel buttons on properties.
Added Accept/Refuse buttons on offers.
Set selling price and buyer when an offer is accepted.
Chapter 10 : Added SQL constraints:
  - expected price must be strictly positive
  - selling price must be positive
  - offer price must be strictly positive
  - property type and tag names must be unique
Added a Python constraint to prevent selling prices lower than 90% of the expected price
@haman-odoo haman-odoo force-pushed the 19.0-real-estate-tutorial-haman branch from dc398ad to dfc0ad5 Compare December 11, 2025 09:10
Copy link

@bit-odoo bit-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello, Good Job!
I have made some suggestions.

Can you please update PR title?

'category': 'Sales/Real Estate',
'installable': True,
'auto_install': False,
'description': """Real estate management tutorial module with properties, offers, types and tags.""",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please adapt this -> #1049 (comment)

Comment on lines +1 to +5
from dateutil.relativedelta import relativedelta
from datetime import date
from odoo import models, fields, api
from odoo.exceptions import UserError,ValidationError
from odoo.tools.float_utils import float_compare, float_is_zero

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from dateutil.relativedelta import relativedelta
from datetime import date
from odoo import models, fields, api
from odoo.exceptions import UserError,ValidationError
from odoo.tools.float_utils import float_compare, float_is_zero
from dateutil.relativedelta import relativedelta
from datetime import date
from odoo import models, fields, api
from odoo.exceptions import UserError,ValidationError
from odoo.tools.float_utils import float_compare, float_is_zero

default=lambda sself: date.today() + relativedelta(months=3),
copy=False
)
expected_price = fields.Float(string="Expected Price", required=True)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow this -> #1049 (comment)

Comment on lines +104 to +110
def action_cancel(self):
for rec in self:
if rec.state == "sold":
raise UserError("Sold properties cannot be cancelled.")
else:
rec.state = "cancelled"
return True

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think action_cancel_property will be good.

It's good to make the error message translatable.
raise exceptions.UserError(_("Sold properties cannot be cancelled."))

We can use filtered() here.

if self.filtered(lamda x: x.state=="sold")

Comment on lines +112 to +117
def action_set_sold(self):
for rec in self:
if rec.state == "cancelled":
raise UserError("Canceled properties cannot be sold.")
else:
rec.state = "sold"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

if rec.selling_price == 0:
return False
if float_compare(rec.selling_price, rec.expected_price * 0.9, precision_digits=2) < 0:
raise ValidationError(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, it should be translatable.

Comment on lines +1 to +3
from dateutil.relativedelta import relativedelta
from odoo import models, fields, api
from odoo.exceptions import UserError

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
from dateutil.relativedelta import relativedelta
from odoo import models, fields, api
from odoo.exceptions import UserError
from dateutil.relativedelta import relativedelta
from odoo import models, fields, api
from odoo.exceptions import UserError

offer.status = 'refused'
return True

_offer_price = models.Constraint(

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is good to declare constraint after the immediate declaration of all fields.

Comment on lines +2 to +15
<menuitem id="menu_estate_root" name="Real Estate"/>
<menuitem id="menu_estate_advertisements" name="Advertisements" parent="menu_estate_root" sequence="10"/>
<menuitem id="menu_estate_properties" name="Properties" parent="menu_estate_advertisements" action="action_estate_property" sequence="10"/>

<menuitem id="menu_estate_settings" name="Settings" parent="menu_estate_root" sequence="20"/>

<menuitem id="menu_estate_property_types" name="Property Types"
parent="menu_estate_settings"
action="action_estate_property_type"
sequence="10"/>

<menuitem id="menu_estate_property_tags" name="Property Tags"
parent="menu_estate_settings"
action="action_estate_property_tag"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation issue and empty line before . if you want to leave an empty line, then you should follow the same for others too.

Comment on lines +13 to +20
<field name="name"/>
<field name="property_type_id"/>
<field name="postcode"/>
<field name="expected_price"/>
<field name="selling_price"/>
<field name="bedrooms"/>
<field name="living_area"/>
<field name="date_availability"/>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except name,selling_price,expected_price,date_availability we can make other fields optional.

@haman-odoo haman-odoo changed the title 19.0 real estate tutorial haman [ADD] estate: Created Estate Module Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants