-
Notifications
You must be signed in to change notification settings - Fork 2.1k
[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
base: 18.0
Are you sure you want to change the base?
Conversation
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)
…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.
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 @shib-odoo
Some comments/questions
Thanks!!
estate/__init__.py
Outdated
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.
Missing blank line EOF needs to check other occurrences also
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.
Added blank line EOF in all the respective files.
estate/__manifest__.py
Outdated
'security/ir.model.access.csv', | ||
'views/estate_property_views.xml', | ||
'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.
estate/models/estate_property.py
Outdated
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 |
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 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
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.
Fix the imports where all the external libraries are on the top followed by the imports from odoo in all the files.
estate/models/estate_property.py
Outdated
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") |
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.
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
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.
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): |
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.
Need 2 blank lines before defining the class.
estate/models/estate_property.py
Outdated
|
||
|
||
def action_cancel(self): | ||
for prop in self: |
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.
Generally, we write `` `for record self``` because here self refers to a recordset.
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.
_sql_constraints = [ | ||
('check_offer_price_positive', 'CHECK(price > 0)', 'The offer price must be strictly positive.'), | ||
] | ||
@api.depends('create_date', 'validity') |
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.
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?
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.
_sql_constraints = [ | ||
("unique_name", "UNIQUE(name)", "Property type name must be unique."), | ||
] |
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 should be after the field definition.
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.
Move ' _sql_constraints' after all field definitions in all the model files
<list string="Estate offer list" | ||
editable="top" | ||
decoration-danger="status == 'refused'" | ||
decoration-success="status == 'accepted'"> |
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.
<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.
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.
Fixed indentation issue in all the xml files.
<group> | ||
<field name="name"/> | ||
<field name="tag_ids" | ||
widget="many2many_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.
indentation issue.
…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 \
This commit introduces several improvements across the Card and TodoList components to enhance reusability, interactivity, and UI consistency in the `awesome_owl` module. 1. Card Component: - Replaced static content with support for slots to allow arbitrary child components. - Added a toggle feature to show/hide card content using internal state. - Enhanced styling for better visual clarity, spacing, and Bootstrap integration. 2. Playground Template: - Updated the playground template to insert multiple cards with dynamic content, including embedded Counter components and summary sections. - Improved layout using Bootstrap utilities (`gap`, `d-flex`, column grids). - Replaced placeholder text with meaningful titles and added alert components for feedback. 3. TodoList Component: - Improved the styling of todo items using Bootstrap badges, spacing, muted text, and contextual coloring. - Refactored `removeTodoItem()` to use splice instead of replacing the array (which Owl does not track reactively), ensuring UI updates correctly. - Applied visual polish to headers, spacing, and input fields for a more polished experience. These changes are part of a broader effort to demonstrate advanced Owl component patterns, including slots, event communication, component state, and styling integration with Bootstrap.
This commit introduces several improvements across the Card and TodoList components to enhance reusability, interactivity, and UI consistency in the `awesome_owl` module. 1. Card Component: - Replaced static content with support for slots to allow arbitrary child components. - Added a toggle feature to show/hide card content using internal state. - Enhanced styling for better visual clarity, spacing, and Bootstrap integration. 2. Playground Template: - Updated the playground template to insert multiple cards with dynamic content, including embedded Counter components and summary sections. - Improved layout using Bootstrap utilities (`gap`, `d-flex`, column grids). - Replaced placeholder text with meaningful titles and added alert components for feedback. 3. TodoList Component: - Improved the styling of todo items using Bootstrap badges, spacing, muted text, and contextual coloring. - Refactored `removeTodoItem()` to use splice instead of replacing the array (which Owl does not track reactively), ensuring UI updates correctly. - Applied visual polish to headers, spacing, and input fields for a more polished experience. These changes are part of a broader effort to demonstrate advanced Owl component patterns, including slots, event communication, component state, and styling integration with Bootstrap.
This commit introduces several improvements across the Card and TodoList components to enhance reusability, interactivity, and UI consistency in the `awesome_owl` module. 1. Card Component: - Replaced static content with support for slots to allow arbitrary child components. - Added a toggle feature to show/hide card content using internal state. - Enhanced styling for better visual clarity, spacing, and Bootstrap integration. 2. Playground Template: - Updated the playground template to insert multiple cards with dynamic content, including embedded Counter components and summary sections. - Improved layout using Bootstrap utilities (`gap`, `d-flex`, column grids). - Replaced placeholder text with meaningful titles and added alert components for feedback. 3. TodoList Component: - Improved the styling of todo items using Bootstrap badges, spacing, muted text, and contextual coloring. - Refactored `removeTodoItem()` to use splice instead of replacing the array (which Owl does not track reactively), ensuring UI updates correctly. - Applied visual polish to headers, spacing, and input fields for a more polished experience. These changes are part of a broader effort to demonstrate advanced Owl component patterns, including slots, event communication, component state, and styling integration with Bootstrap.
- Switched from @api.model to @api.model_create_multi to support batch creation. - Added guard clauses for empty input and missing property_id. - Improved error handling using UserError and ValidationError where appropriate. - Validated offer price against current best price using property.best_price. - Prevented offers on sold, cancelled, or offer-accepted properties. - Ensured property state is updated to 'offer_received' only when needed. This improves code readability, consistency with Odoo standards, and prevents invalid offer creation scenarios.
Added explicit validation in `estate.property.offer.create` to raise ValidationError when an offer price is zero or negative. This ensures consistency with the SQL constraint and aligns with unit test expectations. Previously, invalid prices could trigger unrelated UserError messages (e.g., price not exceeding best price), causing tests to fail. Now, the error is caught early and clearly reported.
Added explicit validation in `estate.property.offer.create` to raise ValidationError when an offer price is zero or negative. This ensures consistency with the SQL constraint and aligns with unit test expectations. Previously, invalid prices could trigger unrelated UserError messages (e.g., price not exceeding best price), causing tests to fail. Now, the error is caught early and clearly reported.
Added explicit validation in `estate.property.offer.create` to raise ValidationError when an offer price is zero or negative. This ensures consistency with the SQL constraint and aligns with unit test expectations. Previously, invalid prices could trigger unrelated UserError messages (e.g., price not exceeding best price), causing tests to fail. Now, the error is caught early and clearly reported.
Added explicit validation in `estate.property.offer.create` to raise ValidationError when an offer price is zero or negative. This ensures consistency with the SQL constraint and aligns with unit test expectations. Previously, invalid prices could trigger unrelated UserError messages (e.g., price not exceeding best price), causing tests to fail. Now, the error is caught early and clearly reported.
This commit introduces a user-configurable settings dialog to the dashboard, allowing users to selectively show or hide dashboard items. Preferences are persisted using local storage for improved user experience. The dialog is built using OWL's Dialog component and includes improved close handling by passing an explicit `close` function via props, solving previous issues with `this.env.services.dialog.close`. Styling of the dashboard and individual items has been significantly enhanced: - Cards now feature consistent padding, elevation on hover, and responsive layout. - The `DashboardItem` component has flexible sizing and a modern hover animation. - `NumberCard` and other widgets have improved font scaling and alignment. The overall dashboard layout is now more responsive, adapting to smaller screen sizes with proper wrapping and spacing of cards. Also includes: - Button controls to open settings and navigate to leads/customers. - Proper use of `useState` to track selected items in the dialog. - Improved use of scoped props and default slot composition for better maintainability. This change improves both the usability and aesthetic quality of the dashboard, bringing it closer to a production-grade interface. task-101 (related to improving dashboard customizability and UX) Fixes odoo#42 (dialog not closing on apply)
This commit introduces a user-configurable settings dialog to the dashboard, allowing users to selectively show or hide dashboard items. Preferences are persisted using local storage for improved user experience. The dialog is built using OWL's Dialog component and includes improved close handling by passing an explicit `close` function via props, solving previous issues with `this.env.services.dialog.close`. Styling of the dashboard and individual items has been significantly enhanced: - Cards now feature consistent padding, elevation on hover, and responsive layout. - The `DashboardItem` component has flexible sizing and a modern hover animation. - `NumberCard` and other widgets have improved font scaling and alignment. The overall dashboard layout is now more responsive, adapting to smaller screen sizes with proper wrapping and spacing of cards. Also includes: - Button controls to open settings and navigate to leads/customers. - Proper use of `useState` to track selected items in the dialog. - Improved use of scoped props and default slot composition for better maintainability. This change improves both the usability and aesthetic quality of the dashboard, bringing it closer to a production-grade interface. task-101 (related to improving dashboard customizability and UX) Fixes odoo#42 (dialog not closing on apply)
…nvoice line This commit adds a computed 'Book Price' field on both sale order lines and customer invoice lines, allowing users to compare the price from the pricelist with any manually adjusted price. - Added a computed `book_price` field to `sale.order.line`, calculated based on the selected pricelist, product, quantity, and UoM. - Added a computed `book_price` field to `account.move.line` (invoice lines), fetched from the related sale order's pricelist. - Updated the sale order form view to display 'Book Price' on order lines. - Updated the customer invoice form view to display 'Book Price' on invoice lines, using `column_invisible` to restrict visibility to customer invoices only (`move_type == 'out_invoice'`). These changes help users analyze pricing transparency and identify discounts or overrides from the original pricelist.
-fixed styling issue of adding new line at the end of the file
The goal is to ensure that the book price: - Is correctly calculated based on the pricelist's discount formula. - Falls back to the list price if no pricelist is applied. - Is propagated from sale orders to customer invoice lines. - Is still computed but hidden in the UI for non-customer invoices. The tests cover sale order line creation with and without a pricelist, sale order confirmation and invoice generation, and behavior in refund scenarios. All tests are based on `TransactionCase` and are suitable for `post_install` execution. They help ensure the reliability of the custom `book_price` logic implemented in sale and account modules.
Fix the styling issue in the model files
Fix the styling issue in the model files
Core Functionality:
Technical Implementation:
Models:
Relationships:
Security:
UI/UX:
Business Logic:
task-001 (Chapter 1–7 Odoo 18 Developer Tutorial)