[ADD] estate : real estate module implementation#1232
Conversation
…tion - Configured manifest with required metadata and dependencies. - It covers chapter- 2 and 3 task - Added the required fields.
- Completed Ch 4 task for Access Rights
a0a9563 to
4fe99f0
Compare
- Created an action - Define main menu and submenus - Add views to manifest 'data' list - Completed Ch 5 Action and Menu part
- Added is_active and state fields in form - Added fields in list view - Improved and adjusted fields in Form View - Completed Ch 5 and Ch 6 List and Form Views
4fe99f0 to
b8bc03e
Compare
26c6c8b to
92ab5a6
Compare
bit-odoo
left a comment
There was a problem hiding this comment.
Hello
Can you please update your pr description?
Thanks
| def action_property_sold(self): | ||
| for record in self: | ||
| if record.state == "cancelled": | ||
| raise UserError("Cancelled property cannot be set as sold.") |
There was a problem hiding this comment.
It's good to make the error message translatable.
raise UserError(_("Cancelled property cannot be set as sold."))
| @api.depends('visit_ids') | ||
| def _compute_issue_count(self): | ||
| for record in self: | ||
| record.issue_count = len(record.issue_ids) |
| <field name="arch" type="xml"> | ||
| <form> | ||
| <header> | ||
| <button name="action_rainbow_man" string="Sold" class="btn-primary" type="object" invisible="state != 'offer_accepted'"/> |
There was a problem hiding this comment.
The name is not aligned with the string.
|
|
||
| def action_accepted(self): | ||
| for offer in self.property_id.offer_ids: | ||
| if offer.status == "accepted": |
There was a problem hiding this comment.
You already made the button invisible. No need for this condition.
| <field name="property_type_id"/> | ||
| <field name="validity" width="100"/> | ||
| <field name="date_deadline"/> | ||
| <button name="action_accepted" type="object" string="Accept" icon="fa-check" invisible="status != False"/> |
There was a problem hiding this comment.
| <button name="action_accepted" type="object" string="Accept" icon="fa-check" invisible="status != False"/> | |
| <button name="action_offer_accepted" type="object" string="Accept" icon="fa-check" invisible="status != False"/> |
| <field name="validity" width="100"/> | ||
| <field name="date_deadline"/> | ||
| <button name="action_accepted" type="object" string="Accept" icon="fa-check" invisible="status != False"/> | ||
| <button name="action_refused" type="object" string="Refuse" icon="fa-times" invisible="status != False"/> |
There was a problem hiding this comment.
| <button name="action_refused" type="object" string="Refuse" icon="fa-times" invisible="status != False"/> | |
| <button name="action_offer_refused" type="object" string="Refuse" icon="fa-times" invisible="status != False"/> |
| <field name="property_type_id"/> | ||
| <field name="property_tags_ids" widget="many2many_tags" options="{'color_field': 'color'}" width="300"/> | ||
| <field name="bedrooms"/> | ||
| <field name="living_area"/> |
There was a problem hiding this comment.
No need to display too many fields. You can make these fields optional.
92ab5a6 to
27f6eb8
Compare
| if (this.props.onincrement) { | ||
| this.props.onincrement(); |
There was a problem hiding this comment.
can you please enable linter -> ./addons/web/tooling/enable.sh
| <TodoList/> | ||
| </div> | ||
| </t> | ||
|
|
| const ref = useRef(refName); | ||
|
|
||
| onMounted(() => { | ||
| ref.el.focus(); |
|
|
||
| for record in self: | ||
| record.issue_count = data.get(record, 0) | ||
| # record.issue_count = len(record.issue_ids) |
| "The selling price cannot be lower than 90% of the expected price." | ||
| )) | ||
|
|
||
| def action_property_sold(self): |
There was a problem hiding this comment.
Can you please followe this documentation?
https://www.odoo.com/documentation/19.0/contributing/development/coding_guidelines.html#symbols-and-conventions
| for offer in property_id.offer_ids: | ||
| if current_price < offer.price: | ||
| raise UserError(_("Offer Price cannot be less than previous offer prices")) | ||
|
|
| raise UserError(_("Offer Price cannot be less than previous offer prices")) | ||
|
|
||
| offers = super().create(vals_list) | ||
|
|
| for offer in offers: | ||
| if offer.property_id.state == 'new': | ||
| offer.property_id.state = 'offer_received' | ||
|
|
- Implemented search view - Added property types, tags, and offers models - Linked properties with buyer, salesperson, types, tags, and offers - Completed Ch 6 and Ch 7.
- Added Best Offer and Total Area fields in property form view - Covers 2 tasks of chapter 8.
…nction - Added Validity and date_deadline fields with inverse function - Implemented onchange logic for garden_area and garden_orientation - Suggested fixes implemented - Covers last 2 tasks of chapter 8.
- Added sold and cancelled action buttons for state transition - Prevent invalid transitions between 'sold' and 'cancelled' states
- Introduce Accept and Refuse buttons for property offers - Assign buyer and selling price to property on acceptance - Restrict multiple offers from being accepted for the same property - Chapter 9 Completed.
- Ensure positive property and offer prices - Ensure unique property tag and type names - Chapter 10 task 1 completed.
- Adds constraint using float_compare, ignores zero selling price. - Chapter 10 completed.
- Added inline list view for property types - Implemented statusbar widget for property state - Defined default ordering on models - Added conditional visibility and readonly attributes - Enhanced list views with decorations and optional fields - Introduced stat button on property type to access related offers - Added related field and computed offer count for property types - Chapter 11 completed
- Extended CRUD methods for offer validation, state update - Added constraints to prevent invalid operations (state and offer price check) - Inherited res.users to add property_ids relation - Implemented view inheritance to display properties in user form - Completed chapter 12
- Integrated account module to create invoices from sold properties - Reused account.move for financial operations - Enhanced kanban view using QWeb templating - Implemented conditional UI logic with t-if and raw values - Chapter 13 and 14 completed.
- Added visit scheduling with list, form, and calendar views - Added constraint to prevent overlapping visits within the same property - Automatically create calendar events on visit creation - Added issue reporting with list and form views - Completed Group Tasks.
- Added chatter and activities - Implemented logic to reject all other offers when one is accepted - Added “Accept Best Offer” action to simplify offer selection - Added rainbow animation when a property is marked as sold - Display sold ribbon in form and kanban views - Updated kanban default grouping to state and disabled record drag - Made “Sold” and “Accept Best Offer” buttons conditional primary actions
…ard) - Create Counter component with increment action - Introduce TodoList component to manage todos - Add dynamic todo creation - Implement toggle functionality for todo completion - Add conditional styling based on state - Implement delete functionality for removing todos - Refactor Card to use slots and add toggle-able content.
5de64f4 to
5fa3a74
Compare
This commit implements the Awesome Dashboard as part of learning Owl. The main goal was to understand how frontend dashboard is built using Owl instead of using xml for standard list/form/kanban views as these are not suitable when we want to display mixed information like KPIs, charts and quick actions in one place, so a custom dashboard is needed. Explored how components, services and hooks are used together. The dashboard is split into smaller parts so it is easier to follow and not everything is in a single file. Also added the option to add/remove dashboard items. This was mainly to understand how state is handled on the client side.
044aca1 to
73e5118
Compare
bit-odoo
left a comment
There was a problem hiding this comment.
Hello,
Nice work,
Added some comments. Can you please look into it?
Thanks
| super().action_property_sold() | ||
|
|
||
| self.env['account.move'].create([{ | ||
| 'partner_id': self.salesperson_id.id, |
There was a problem hiding this comment.
partner_id expects res_partner but salesperson_id is a res_users id.
I think generally it can be buyers, not salespeople.
|
|
||
| _unique_type_name = models.Constraint('UNIQUE(name)', "Type name must be unique") | ||
|
|
||
| @api.depends('offer_count') |
There was a problem hiding this comment.
The compute field should not depend on itself.
| @api.depends('offer_count') | |
| @api.depends('offer_ids') |
| else: | ||
| record.best_price = 0.0 | ||
|
|
||
| @api.depends('visit_ids') |
There was a problem hiding this comment.
| @api.depends('visit_ids') | |
| @api.depends('issue_ids') |
| <header> | ||
| <button name="action_set_sold_rainbow_man" string="Sold" class="btn-primary" type="object" invisible="state != 'offer_accepted'"/> | ||
| <button name="action_property_cancelled" string="Cancel" type="object" invisible="state in ('sold', 'cancelled')"/> | ||
| <button name="action_accept_best_offer" string="Accept Best Offer" type="object" class="btn-primary" invisible="offer_ids.length < 1"/> |
There was a problem hiding this comment.
| <button name="action_accept_best_offer" string="Accept Best Offer" type="object" class="btn-primary" invisible="offer_ids.length < 1"/> | |
| <button name="action_accept_best_offer" string="Accept Best Offer" type="object" class="btn-primary" invisible="not offer_ids"/> |

Implementation of Real Estate Advertisement Module & Web Dashboard (Owl)
Real Estate Module
Owl (Web Framework)
Previous closed PR - #1193