Skip to content

[ADD] estate: Real Estate Property Management Module #889

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 9 commits into
base: 18.0
Choose a base branch
from

Conversation

aarp-odoo
Copy link

@aarp-odoo aarp-odoo commented Jul 24, 2025

This PR introduces significant updates and improvements to the Estate module, designed to manage properties, offers, property types, property tags, and invoices.

Features

  • Property Management
    Enables adding, editing, and listing of properties with enhanced state management, including new buttons for Cancel, Sold, and statusbar improvements.

  • Property Types and Tags
    Allows defining property types and tags with support for unique naming, color coding, sequence ordering, and inline views to improve usability.

  • Offer Management
    Manages offers received for properties, including Accept and Refuse actions. Accepted offers automatically update the property’s buyer and selling price.

  • Invoice Management
    Introduces a new module estate_account that extends estate.property by overriding the action_mark_sold method to automatically create invoice upon sale of a property.

  • Business Logic Improvements
    Enforces data integrity with SQL and Python constraints (e.g., positive expected price, selling price limits, uniqueness constraints, and offer price validations).
    Also prevents deletion of properties that are not in allowable states.

  • UI/UX Improvements
    Improved default ordering across models, added default filters, status widgets, and stat buttons to improve navigation and data visibility.

Technical Features

  • Code Quality and Maintenance
    - Reformatted code according to Odoo coding guidelines.
    - Added docstring for easy understanding of what method's functionality.
    - Replaced deprecated @api.model with @api.model_create_multi in create method.

  • Manifest Improvements
    - Added license field to __manifest__.py files in both estate and estate_account modules to avoid warnings.

  • Views and XML files
    - Resolved XML ID error during build by correctly the writing the id for and name for res_users_views.xml

@robodoo
Copy link

robodoo commented Jul 24, 2025

Pull request status dashboard

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.

Comment on lines 8 to 59
<field name="name"/>
<field name="description"/>
<field name="postcode"/>
<field name="date_availability"/>
<field name="expected_price"/>
<field name="selling_price"/>
<field name="bedrooms"/>
<field name="living_area"/>
<field name="facades"/>
<field name="garage"/>
<field name="garden"/>
<field name="garden_area"/>
<field name="garden_orientation"/>
<field name="state"/>

Choose a reason for hiding this comment

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

No need to display every field in list view. We can display only those are important fields and other fields we can add in optional.

@@ -0,0 +1,42 @@
from odoo import fields, models
from dateutil.relativedelta import relativedelta

Choose a reason for hiding this comment

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

'description': """Real Estate Application.""",
'summary': """Real Estate Application for beginner.""",
'depends': ['base'],
'author': "Aaryan Parpyani (aarp)",

Choose a reason for hiding this comment

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

You can follow the same quote through the file.

<menuitem id="test_first_level_menu" name="Advertisements" parent="test_menu_root"/>
<menuitem id="test_model_menu_action" name="Estate Property" parent="test_first_level_menu" action="estate_property"/>
</data>
</odoo>

Choose a reason for hiding this comment

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

Should be an empty line at the end of the file.

@aarp-odoo aarp-odoo changed the title [ADD] training: chapter 1-6 [ADD] estate: Real Estate Property Management Module Jul 28, 2025
@aarp-odoo aarp-odoo force-pushed the 18.0-tutorials-aarp branch 4 times, most recently from 0c71271 to 86e3c19 Compare July 28, 2025 13:22
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, could you please also improve your previous commit message according to the guidelines.

@@ -0,0 +1,127 @@
List of relations

Choose a reason for hiding this comment

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

unnecessary file.

Comment on lines 116 to 118
offer.property_id.selling_price = offer.price
offer.property_id.buyer_id = offer.partner_id
offer.property_id.state = 'offer_accepted'

Choose a reason for hiding this comment

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

you can use .write().

UserError: If the property is already marked as 'sold'.
"""
for offer in self:
if offer.property_id.state == 'sold':

Choose a reason for hiding this comment

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

Only one offer can be accepted.



class EstatePropertyType(models.Model):
# === Pricvate attributes ===

Choose a reason for hiding this comment

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

typo mistake.

<field name="price"/>
<field name="validity"/>
<field name="date_deadline"/>
<!-- <field name="status"/> -->

Choose a reason for hiding this comment

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

Dead code.you can remove it.

Comment on lines 109 to 112
- If garden is enables, defaults:
- garden_area = 10
- garden_orientation = 'north'
- If disabled, both are cleared.

Choose a reason for hiding this comment

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

Comments should be added to complex code to ensure it is easily understood by others.Here i think it's not require.same for other functions too.

… relational mapping.

Key changes include:

- Defined core model (estate.property)
- Created `__init__.py` and `__manifest__.py`
- Added name and required dependencies of our module in `__manifest__.py`
- Added field declarations for estate.property

This commit lays the foundation for a functional real estate management system in Odoo.
…ld declarations.

- Added `__manifest__.py` with module metadata.
- Created the `models` directory and added `__init__.py` to register models.
- Implemented the basic `estate.property` model with fields such as:
  - name, description, postcode
  - expected_price, selling_price
  - bedrooms, living_area, facades, garage
  - garden, garden_area, garden_orientation, date_availability

This serves as the foundational structure for the Real Estate application as part of the Odoo tutorials.
…security rules

Key changes include:

- Defined core models (estate.property, estate.property.type, estate.property.tag).
- Added fields declarations for estate.property, estate.property.type and estate.property.tag.
- Set up basic security access and created model-specific access control CSV.
- Configured menus, actions, and views (list, form, search).
- Linked tags and property types using relational fields.
- Applied domain filters and default values for a cleaner UI.
…doo guidelines

This commit resolves multiple formatting and linting issues to align with Odoo's official coding guidelines:
- Added missing newline at end of files (`__init__.py`, `__manifest__.py`, `estate_property.py`).
- Removed unused import `timedelta` from `datetime`.
- Added an extra blank line before class definition `EstateProperty` in file `estate_property.py`.
- Removed trailing whitespace from lines 5 and 17 in `estate_property.py`.
- Ensured proper indentation and closing bracket formatting.

These improvements enhance code readability, maintainability, and compliance with Odoo community standards.
@aarp-odoo aarp-odoo force-pushed the 18.0-tutorials-aarp branch from 86e3c19 to d8b1825 Compare July 29, 2025 10:07
…oice on property sold, do code cleanup.

This commit improves the usability of the Real Estate module by:
- Making list views for Offers and Tags editable for quick updates.
- Adding row coloring: refused offers appear red, accepted ones green, and the status column has been removed for visual clarity.
- Enabling the ‘Available’ filter by default in property list action to surface active listings.
- Modifying the living_area search input to include properties with an area greater than or equal to the entered value.
- Introducing a stat button on the property type form that shows the number of linked offers.
- Introduced kanban view for the properties that are on sale, grouped by property type.

When a property is marked as sold, automatically create a draft customer invoice containing:
- Selling price of the property.
- 6% commission on the propertly selling price.
- Flat $100 Administrative fees.

Refactored `estate` module:
- Resolved linting and indentation error.
- Corrected XML ID and name for xml files according to Odoo coding guidelines.
- Replaced deprecated 'kanban-box' with 'card' template.
- Deleted unnecessary files.
- Removed unnecessary docstrings and code comments.
- Implemented the logic, that if one offer is accepted for the property then others are automatically marked as refused.
- Replaced direct field assignments with `write()` method for multiple fields.
- Corrected typo errors in the files.
- Removed dead code that wasn't necessary.
@aarp-odoo aarp-odoo force-pushed the 18.0-tutorials-aarp branch from d8b1825 to 0f74440 Compare July 29, 2025 10:36
…n playground.

- Created `Counter` component in playground.
- Extracted `Counter` component from playground into Counter component.
- Added `<Counter/>`in template of playground to add two counters.
- Created a card component and used t-esc and t-out directives to demonstrate the difference between escaped and safe HTML content using the markup     function.
- Added props validation to the card component
- Implemented parent-child communication using a callback prop (onChange) from the Counter component to the Playground component, updating and displaying the sum in local state whenever counters are incremented.
- Built a TodoList with hardcoded todos using useState, rendered each using the TodoItem component with t-foreach, and added prop validation for todo.
- Updated TodoItem to conditionally apply Bootstrap classes (text-muted, text-decoration-line-through) using t-att-class based on the todo's completion status.
- Enabled dynamic todo creation: replaced hardcoded todos with useState([]), added input field for user to enter a task.
- Implemented addTask method to add new todos on Enter key (with unique ID and empty check).
…list and improve UI for task view.

- Focus input field on mount in TodoList component using useAutoFocus() method.
- Add checkbox to TodoItem with toggleState callback to update isCompleted status on change
- Add removeTodo callback to TodoItem and trigger it via click on remove icon, to delete the task.
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, i have added some suggestion.

onMounted(() => {
inputRef.el?.focus();
})
}
Copy link

Choose a reason for hiding this comment

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

Should be one empty line at the end of the file.

default='new'
)

# Many2one fields
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 add this comment and space.

salesman_id = fields.Many2one('res.users', string='Salesman', default=lambda self: self.env.user)
buyer_id = fields.Many2one('res.partner', string='Buyer', copy=False)

# Many2many fields
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 write this comment

# Many2many fields
tag_ids = fields.Many2many('estate.property.tag', string='Tags')

# One2many fields
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 add this comment and space.

garden_area = fields.Integer()
active = fields.Boolean(default=True)

# Selection fields
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 add this comment and space.

# ----------------------
def action_mark_sold(self):
for record in self:
if record.state == 'cancelled':
Copy link

Choose a reason for hiding this comment

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

Offer should also be available for the marked property state sold.



class EstatePropertyOffer(models.Model):
# === Private attributes ===
Copy link

Choose a reason for hiding this comment

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

Same as for the previous file, there is no need to write this type of comment.

('unique_tag_name', 'UNIQUE(name)', 'Tag name must be unique.'),
]

# === Fields declaration ===
Copy link

Choose a reason for hiding this comment

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

Same as for the previous file, there is no need to write this type of comment.



class EstatePropertyType(models.Model):
# === Private attributes ===
Copy link

Choose a reason for hiding this comment

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

Same as for the previous file, there is no need to write this type of comment.

from odoo import fields, models


class EstatePropertyType(models.Model):
Copy link

Choose a reason for hiding this comment

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

Class name should be EstatePropertyTag instead of EstatePropertyType.

…ers exist, remove unnecessary comments and fix linting.

- Added logic to check if any offers are present before marking the property as sold.
- Added logic to check if one of the offers is accepted before marking property as sold
- Removed unnecessary comments from files.
- Fixed linting issues from `utils.js`
…minimize card content using toggle button. create dashboard using layout component.

- Transform the Card component to use a default slot instead of a content prop, include multiple cards with arbitrary content (e.g., Counter), and enforce prop validation for the title.
- Add toggle functionality to the Card component using a boolean state, conditionally render its content with t-if, and include a header button to switch between open and closed states.
- Imported layout component in dashboard and added dashboard.scss to create a basic dasboard view.
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