Skip to content

Conversation

@snrav-odoo
Copy link

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

Added Estate Module for Managing Real Estate Properties

  • This PR adds a new Estate Management Module that allows users to create, manage, buy, and sell real estate properties. It includes property workflows, offer handling, validations, and data integrity rules.

  • To provide a structured and reliable system for managing real estate operations within Odoo, ensuring clean workflows and preventing invalid or inconsistent data through proper constraints and validations.

Changes made :

  • Added new estate module with full property management features.
  • Created models: estate.property, estate.property.offer, estate.property.type.
  • Implemented workflow: new → offer received → offer accepted → sold.
  • Added UserError validations for invalid operations.
  • Added SQL & Python constraints (price validation, offer price > 0, selling price rules).
  • Added views, menus, actions, and access control rules.

@robodoo
Copy link

robodoo commented Dec 4, 2025

Pull request status dashboard

@snrav-odoo snrav-odoo force-pushed the 19.0-tutorial-snrav branch 4 times, most recently from bfd9b9d to ebbd036 Compare December 9, 2025 06:06
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 @snrav-odoo

You did a great 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

Thanks

Comment on lines 1 to 2
from odoo import models, api, fields
from dateutil.relativedelta import relativedelta
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 odoo import models, api, fields
from dateutil.relativedelta import relativedelta
from dateutil.relativedelta import relativedelta
from odoo import models, api, fields

Comment on lines 25 to 28
('north', 'North'),
('south', 'South'),
('east', 'East'),
('west', 'West'),
Copy link

Choose a reason for hiding this comment

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

Please follow the same quote throughout the file.

tag_ids = fields.Many2many("estate.property.tag", string="Property Tags")
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offer")
total_area = fields.Integer(compute="_compute_area")
best_price = fields.Integer(compute="_compute_highest")
Copy link

Choose a reason for hiding this comment

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

I think it is good practice to declare a compute method name similar to the field name so others can easily identifity it. But it's my personal opinion 😅

Comment on lines 1 to 2
from odoo import models, api, fields
from dateutil.relativedelta import relativedelta
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.

estate.access_estate_property,"access_estate_property",estate.model_estate_property,base.group_user,1,1,1,1
estate.access_estate_property_type,"access_estate_property_type",estate.model_estate_property_type,base.group_user,1,1,1,1
estate.access_estate_property_tag,"access_estate_property_tag",estate.model_estate_property_tag,base.group_user,1,1,1,1
estate.access_estate_property_offer,"access_estate_property_offer",estate.model_estate_property_offer,base.group_user,1,1,1,1 No newline at end of file
Copy link

Choose a reason for hiding this comment

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

There should be one empty line at the EOF.

</list>
</field>
</record>
</odoo> No newline at end of file
Copy link

Choose a reason for hiding this comment

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

There should be one empty line at the EOF.

</list>
</field>
</record>
</odoo> No newline at end of file
Copy link

Choose a reason for hiding this comment

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

There should be one empty line at the EOF.

<?xml version="1.0"?>
<odoo>

<record id="estate_property_list_view" model="ir.ui.view">
Copy link

Choose a reason for hiding this comment

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

Indentation issues.

</record>


<record id="estate_property_form_view" model="ir.ui.view">
Copy link

Choose a reason for hiding this comment

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

Indentation issue.

Comment on lines 44 to 62
<page string="Description">
<group>
<group>
<field name="description"/>
<field name="bedrooms"/>
<field name="living_area" string="Living Area(sqm)"/>
<field name="facades"/>
<field name="garage"/>
<field name="garden"/>
<field name="garden_area" string="Garden Area(sqm)"/>
<field name="garden_orientation"/>
<field name="total_area" string="Total Area(sqm)"/>
</group>
<group>
<field name="active"/>
<field name="state"/>
</group>
</group>
</page>
Copy link

Choose a reason for hiding this comment

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

Same Indentation issue.

@snrav-odoo snrav-odoo force-pushed the 19.0-tutorial-snrav branch 9 times, most recently from 2a1bee5 to b2a440b Compare December 10, 2025 12:58
Created the necessary __init__.py and __manifest__.py files
to initialize the estate application.
Introduces the basic scaffolding for the new real estate module.
• Creates the module initialization files (__init__).
• Adds the first 'estate.property' model definition.
• Includes the initial set of base fields for the model.

These changes set up the foundational structure of the estate module, enabling
future development of property management features.
- Added a security CSV file in the `security` folder.
- Granted users access to the `estate.property` model.

These changes ensure that only authorized users can access and manage estate
properties, improving data security and compliance with access control rules.
• Added Real Estate menu structure and linked property action.
• Created window action for `estate.property`.
• Loaded property views and menu XML in manifest.

These changes provide users with a navigation structure and actions to access
property records efficiently, improving usability and making the estate module
functional from the UI.
* Added estate property form view.
* Added estate property list view.
* Added search view with filter and group_by options.

These changes provide the basic UI for managing estate properties, allowing users
to create, view, and search properties efficiently.
* Added estate_property_offer model with required fields.
* Added estate_property_tag model with required fields.
* Added estate_property_type model with required fields.
* Implemented relations between models (Many2one, One2many, Many2many).
* Created corresponding views for offers, tags, and property types.
* Added access rights for new models.
- Compute total_area and best_price in estate.property
- Compute validity date for offers with inverse method
- Set default garden area and orientation using onchange
- Chapter 8
Link business logic to UI buttons.
Prevent cancelled properties from being sold.
Prevent sold properties from being cancelled.
Add ‘Accept’ and ‘Refuse’ buttons for offers.
Update buyer and selling price automatically.
Ensure consistent workflow and reduce errors.
@snrav-odoo snrav-odoo force-pushed the 19.0-tutorial-snrav branch 2 times, most recently from 73d9430 to 1918b5f Compare December 11, 2025 05:26
- Added SQL constraints:
  * Expected price must be strictly positive.
  * Selling price must be positive.
  * Offer price must be strictly positive.
  * Property tag name must be unique.
  * Property type name must be unique.

- Added Python constraint:
  * Ensure the selling price cannot be lower than 90% of the expected price
    (except when selling price is zero before offer validation).
@snrav-odoo
Copy link
Author

Hello @bit-odoo sir,

Thanks for the review.
I have made the changes suggested by you. Kindly have a look into it.

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, Nice progress!
I have made some suggestions.

And can you please update PR title.


class EstateProperty(models.Model):
_name = "estate.property"
_description = "Real Estate Property"

Choose a reason for hiding this comment

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

Should be one line empty after it.

Comment on lines +9 to +14
_check_expected_price = models.Constraint(
"CHECK(expected_price > 0)", "Expected price must be strictly positive."
)
_check_selling_price = models.Constraint(
"CHECK(selling_price >= 0)", "Selling price must be positive."
)

Choose a reason for hiding this comment

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

It is good if we can declare it after the field declaration. You can refer odoo codebase.

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

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, api, fields, exceptions
from odoo.exceptions import ValidationError
from dateutil.relativedelta import relativedelta
from odoo import models, api, fields, exceptions
from odoo.exceptions import ValidationError

string="Status",
default="new",
)
active = fields.Boolean(default=False)

Choose a reason for hiding this comment

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

Why default False?

)
tag_ids = fields.Many2many("estate.property.tag", string="Property Tags")
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offer")
total_area = fields.Integer(compute="_total_area")

Choose a reason for hiding this comment

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

It is good that we can start the compute method with _compute_fieldname.So others can easily identify by the name.

</field>
</record>

<record id="action_estate_offer_view_form" model="ir.ui.view">

Choose a reason for hiding this comment

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

Indentation issue.Should be one tab.

Comment on lines +8 to +14
<field name="name" string="Title" />
<field name="postcode" />
<field name="bedrooms" />
<field name="living_area" string="Living Area (sqm)" />
<field name="expected_price" />
<field name="selling_price" />
<field name="date_availability" string="Available From" />

Choose a reason for hiding this comment

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

Indentation issue.

</group>
</group>
<notebook>
<page string="Description">

Choose a reason for hiding this comment

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

Indentation issue.should be one tab.

</page>
<page string="Information">
<group>
<field name="salesperson" />

Choose a reason for hiding this comment

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

Indentation issue.should be one tab.

Comment on lines +98 to +103
<field name="name">Estate Property</field>
<field name="res_model">estate.property</field>
<field name="view_mode">list,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">Create your Properties here !</p>
</field>

Choose a reason for hiding this comment

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

same.

@snrav-odoo snrav-odoo changed the title 19.0 tutorial snrav [ADD] estate: Added the 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.

3 participants