-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[ADD] estate: Created Estate Module #1049
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
base: 19.0
Are you sure you want to change the base?
Conversation
3a46ead to
949b655
Compare
96dc36b to
2b93d6f
Compare
There was a problem hiding this 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
estate/__manifest__.py
Outdated
| 'category': 'Sales/Real Estate', | ||
| 'installable': True, | ||
| 'auto_install': False, | ||
| 'description': """Description text""", |
There was a problem hiding this comment.
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.
estate/models/__init__.py
Outdated
| @@ -0,0 +1,4 @@ | |||
| from . import estate_property # noqa: F401 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| from . import estate_property # noqa: F401 | |
| from . import estate_property |
estate/models/estate_property.py
Outdated
| from odoo import models, fields | ||
| from dateutil.relativedelta import relativedelta | ||
| from datetime import date |
There was a problem hiding this comment.
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/models/estate_property.py
Outdated
| 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") |
There was a problem hiding this comment.
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") | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unneccary diff.
estate/models/estate_property_tag.py
Outdated
| _name = "estate.property.tag" | ||
| _description = "Real Estate Property Tag" | ||
|
|
||
| name = fields.Char(string="Name", required=True) |
There was a problem hiding this comment.
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.
estate/views/estate_menus.xml
Outdated
| @@ -0,0 +1,15 @@ | |||
| <!-- /home/odoo/odoo19/tutorials/estate/views/estate_menus.xml --> | |||
There was a problem hiding this comment.
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 --> | |||
There was a problem hiding this comment.
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 --> | |||
There was a problem hiding this comment.
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 --> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unneccary diff.
d2aa309 to
44f5059
Compare
|
Hello Sir, I’ve applied all your suggested changes and updated the commit messages. |
7e10da0 to
3609cce
Compare
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.
3609cce to
0d62e93
Compare
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
dc398ad to
dfc0ad5
Compare
bit-odoo
left a comment
There was a problem hiding this 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.""", |
There was a problem hiding this comment.
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)
| 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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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) |
There was a problem hiding this comment.
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)
| 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 |
There was a problem hiding this comment.
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")
| def action_set_sold(self): | ||
| for rec in self: | ||
| if rec.state == "cancelled": | ||
| raise UserError("Canceled properties cannot be sold.") | ||
| else: | ||
| rec.state = "sold" |
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
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.
| from dateutil.relativedelta import relativedelta | ||
| from odoo import models, fields, api | ||
| from odoo.exceptions import UserError |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| 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( |
There was a problem hiding this comment.
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.
| <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"/> |
There was a problem hiding this comment.
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.
| <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"/> |
There was a problem hiding this comment.
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.

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.