8000 [ADD] estate: implement core real estate property management module by shib-odoo · Pull Request #758 · odoo/tutorials · GitHub
[go: up one dir, main page]

Skip to content

[ADD] estate: implement core real estate property management module #758

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

shib-odoo
Copy link

Core Functionality:

  • Created base models for property listings with fields for pricing, descriptions , and status tracking
  • Implemented property type categorization (House, Apartment etc.)
  • Added tagging system for property characteristics (Cozy, Renovated etc.)
  • Developed offer management system to track buyer proposals

Technical Implementation:

  1. Models:

    • estate.property (main listing model)
    • estate.property.type (categorization)
    • estate.property.tag (characteristics)
    • estate.property.offer (purchase offers)
  2. Relationships:

    • Many2one: Property → Type, Buyer, Salesperson
    • Many2many: Property ↔ Tags
    • One2many: Property → Offers
  3. Security:

    • Configured access rights for all models
    • Set appropriate permissions for CRUD operations
  4. UI/UX:

    • Custom list view with key property attributes
    • Detailed form view with tabbed interface
    • Advanced search with filters and grouping
    • Intuitive menu structure
  5. Business Logic:

    • Default values (salesperson = current user)
    • Field constraints (read-only selling price)
    • Non-copyable fields (availability date)

task-001 (Chapter 1–7 Odoo 18 Developer Tutorial)

Core Functionality:
- Created base models for property listings with fields for pricing, descriptions
 , and status tracking
- Implemented property type categorization (House, Apartment etc.)
- Added tagging system for property characteristics (Cozy, Renovated etc.)
- Developed offer management system to track buyer proposals

Technical Implementation:
1. Models:
   - estate.property (main listing model)
   - estate.property.type (categorization)
   - estate.property.tag (characteristics)
   - estate.property.offer (purchase offers)

2. Relationships:
   - Many2one: Property → Type, Buyer, Salesperson
   - Many2many: Property ↔ Tags
   - One2many: Property → Offers

3. Security:
   - Configured access rights for all models
   - Set appropriate permissions for CRUD operations

4. UI/UX:
   - Custom list view with key property attributes
   - Detailed form view with tabbed interface
   - Advanced search with filters and grouping
   - Intuitive menu structure

5. Business Logic:
   - Default values (salesperson = current user)
   - Field constraints (read-only selling price)
   - Non-copyable fields (availability date)

task-001 (Chapter 1–7 Odoo 18 Developer Tutorial)
@robodoo
Copy link
robodoo commented May 7, 2025

Pull request status dashboard

shib-odoo added 2 commits May 8, 2025 18:31
…arameter

SQL Constraints:

- Add CHECK(expected_price > 0) to ensure strictly positive expected prices.

- Add CHECK(selling_price >= 0) for non-negative selling prices.

-  Ensure price > 0 for offers via SQL constraint.

- Enforce unique names for property tags and types with UNIQUE(name).

Python Constraint:

- Add @api.constrains to validate selling price ≥ 90% of expected price.

Fixes:

- Correct typo in selling_price field parameter (readOnly → readonly).

- Cleanup existing invalid data (e.g., non-positive prices) to apply constraints.
- Fix: Replace active_id with id in estate.property.type stat button context to
   resolve access rights error.

- Add: Inline list view for properties linked to types in estate.property.type
   form.

- Add: Stat button on property type form to view linked offers.
Copy link
@adsh-odoo adsh-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 @shib-odoo
Some comments/questions
Thanks!!

Choose a reason for hiding this comment

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

Missing blank line EOF needs to check other occurrences also

Copy link
Author

Choose a reason for hiding this comment

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

Added blank line EOF in all the respective files.

'security/ir.model.access.csv',
'views/estate_property_views.xml',
'views/estate_menus.xml',

Choose a reason for hiding this comment

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

Suggested change

Comment on lines 1 to 5
from odoo import api,models, fields
from dateutil.relativedelta import relativedelta
from odoo.exceptions import UserError
from odoo.exceptions import ValidationError
from odoo.tools 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 odoo import api,models, fields
from dateutil.relativedelta import relativedelta
from odoo.exceptions import UserError
from odoo.exceptions import ValidationError
from odoo.tools import float_compare, float_is_zero
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_compare, float_is_zero

Generally we follow a convention where we imports the external libraries first and then we make the imports from odoo.
https://www.odoo.com/documentation/18.0/contributing/development/coding_guidelines.html#imports

Copy link
Author

Choose a reason for hiding this comment

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

Fix the imports where all the external libraries are on the top followed by the imports from odoo in all the files.

Comment on lines 33 to 78
name = fields.Char(required=True) # Required field
description = fields.Text()
postcode = fields.Char()
date_availability = fields.Date( default=lambda self: fields.Date.today() + relativedelta(months=3),copy=False)
expected_price = fields.Float(required=True) # Required field
selling_price = fields.Float(readonly=True,copy=False)
bedrooms = fields.Integer(default=2)
living_area = fields.Integer()
facades = fields.Integer()
garage = fields.Boolean()
garden = fields.Boolean()
garden_area = fields.Integer()
garden_orientation = fields.Selection(
selection=[
('North', 'North'),
('South', 'South'),
('East', 'East'),
('West', 'West'),
],
)
active = fields.Boolean(default=True),
state = fields.Selection(
selection=[
('new', 'New'),
('offer_received', 'Offer Received'),
('offer_accepted', 'Offer Accepted'),
('sold', 'Sold'),
('cancelled', 'Cancelled'),
],
required=True,
default='new',
copy=False
)
property_type_id = fields.Many2one("estate.property.type", string="Property Type")
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False)
salesperson_id = fields.Many2one(
"res.users",
string="Salesperson",
default=lambda self: self.env.user, # Default to current user
)
tag_ids = fields.Many2many("estate.property.tag", string="Tags")

# Add to EstateProperty class
total_area = fields.Float(compute="_compute_total_area", string="Total Area")
best_price = fields.Float(compute="_compute_best_price", string="Best Offer")

Choose a reason for hiding this comment

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

Field definition should be above followed by the business logic as per our coding guidelines. it may change in certain cases for special methods. Hint: refer codebase

Copy link
Author

Choose a reason for hiding this comment

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

Change file structure by moving field definitions on top then compute methods and last is the business logic.

from odoo.exceptions import UserError
from odoo.exceptions import ValidationError
from odoo.tools import float_compare, float_is_zero
class EstateProperty(models.Model):

Choose a reason for hiding this comment

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

Need 2 blank lines before defining the class.



def action_cancel(self):
for prop in self:

Choose a reason for hiding this comment

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

Generally, we write `` `for record self``` because here self refers to a recordset.

Copy link
Author

Choose a reason for hiding this comment

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

image
Change naming convention that improves clarity and readability in codebase by changing "for prop in self" to "for record in self"

_sql_constraints = [
('check_offer_price_positive', 'CHECK(price > 0)', 'The offer price must be strictly positive.'),
]
@api.depends('create_date', 'validity')
Copy link
@adsh-odoo adsh-odoo May 12, 2025

Choose a reason for hiding this comment

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

We can remove create_date from depends as it will never change after record creation, and at the time of record default value for validity is there, so it will serve our purpose. Can you give it a try?

Copy link
Author

Choose a reason for hiding this comment

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

image
After updating the dependency from 'create_date' to 'validity', the recomputation still works correctly. I’ve verified this through UI testing.

Comment on lines 6 to 8
_sql_constraints = [
("unique_name", "UNIQUE(name)", "Property type name must be unique."),
]

Choose a reason for hiding this comment

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

It should be after the field definition.

Copy link
Author

Choose a reason for hiding this comment

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

Move ' _sql_constraints' after all field definitions in all the model files

Comment on lines 13 to 16
<list string="Estate offer list"
editable="top"
decoration-danger="status == 'refused'"
< 628C span class="blob-code-inner blob-code-marker-addition"> decoration-success="status == 'accepted'">

Choose a reason for hiding this comment

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

Suggested change
<list string="Estate offer list"
editable="top"
decoration-danger="status == 'refused'"
decoration-success="status == 'accepted'">
<list string="Estate offer list"
editable="top"
decoration-danger="status == 'refused'"
decoration-success="status == 'accepted'">

Need to check the indenation in other places also.

Copy link
Author

Choose a reason for hiding this comment

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

Fixed indentation issue in all the xml files.

<group>
<field name="name"/>
<field name="tag_ids"
widget="many2many_tags"

Choose a reason for hiding this comment

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

indentation issue.

shib-odoo added 6 commits May 12, 2025 15:50
…ency

- Replaced `for prop in self` with `for record in self` across methods for
  clarity, since `self` is a recordset.
- Moved `_sql_constraints` definitions below field declarations in all models,
  per community conventions.
- Removed `create_date` from @api.depends in `_compute_date_deadline` since
   it doesn't change after record creation.
- Fixed indentation issues in all the xml files for better readability of codebase.
- Fixed the suggested whitespace and newline style issues in all the files
   suggested by Github checklist
- Fix minor issues related to github style checklist
- Fix minor issues related to github style checklist
…with offers

- Added two demo properties: 'Big Villa' and 'Trailer home', including full
  field population.
- Created associated property offers for these demo properties using existing
    partners.
- Demonstrated inline offer creation using Command.create for a new property.
- Ensured property type is set to 'Residential' for all demo properties.
- Set offer statuses explicitly (accepted/refused) for demo evaluation.
- Created controllers with /properties and /properties/<int:property_id> routes
   to render the properties
-  Added wizard  in my module making it compatible with selecting one or more
   properties at a time and making an offer on it.
- Build report pdf to download the report of the offers for perticular property
\
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
0