Skip to content

Conversation

@rugot-odoo
Copy link

Complete Chapters 1–6 of Odoo tutorial

  • Architecture Overview
  • Create new application
  • Define models and basic fields
  • Security access rules
  • Add menus and actions
  • UI elements (list, form, search views)

@robodoo
Copy link

robodoo commented Jan 1, 2026

Pull request status dashboard

@rugot-odoo rugot-odoo marked this pull request as draft January 1, 2026 09:13
@mash-odoo
Copy link

Hello @rugot-odoo
For this PR, we only need the changes related to the real_estate module.
Could you please remove the extra files (like .idea and other unrelated diffs) and keep the commit limited to the module scope?

1. Architecture Overview
2. Create new application
3. Define models and basic fields
4. Security access rules
5. Add menus and actions
6. UI elements (list, form, search views)

[ADD] real_estate: complete Chapters 1–6 of Odoo tutorial

1. Architecture Overview
2. Create new application
3. Define models and basic fields
4. Security access rules
5. Add menus and actions
6. UI elements (list, form, search views)

[ADD] real_estate: complete Chapters 1–6 of Odoo tutorial

1. Architecture Overview
2. Create new application
3. Define models and basic fields
4. Security access rules
5. Add menus and actions
6. UI elements (list, form, search views)

[FIX] real_estate: delete idea folder
@rugot-odoo rugot-odoo force-pushed the 19.0-tutorial-rugot branch from fab8839 to 19545d8 Compare January 1, 2026 09:52
@rugot-odoo
Copy link
Author

Hello @mash-odoo
I’ve cleaned up the PR by removing all unrelated files (including .idea)

…onships

Implement the property offers and tags model
- Connected offers and tags with the main model
- Completed relational field concepts as per the document
…onships

Implement the property offers and tags model
- Connected offers and tags with the main model
- Completed relational field concepts as per the document
@rugot-odoo rugot-odoo changed the title 19.0 tutorial rugot [ADD] real_estate: Create New Module Jan 2, 2026
Copy link

@mash-odoo mash-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 @rugot-odoo,
Good Work on the PR.
Please view my comments and apply the changes wherever needed.

@@ -0,0 +1,114 @@
<odoo>
<data>

Choose a reason for hiding this comment

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

I noticed the <data> tag here, what was the reason for adding it?

Copy link
Author

Choose a reason for hiding this comment

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

Here, the tag is not required. However, it is useful when we want to control updates for a specific block of code. By using the tag with the noupdate attribute, we can prevent Odoo from updating that particular data during module upgrades or not

- Implemented @api.onchange methods
- Added @api.depends for computed fields
- Defined ondelete behavior to handle related record deletion safely
…onships

Implement the property offers and tags model
- Connected offers and tags with the main model
- Completed relational field concepts as per the document
- Implemented @api.onchange methods
- Added @api.depends for computed fields
- Defined ondelete behavior to handle related record deletion safely
- Completed Unit 9 actions and business logic
- Added property type field
@rugot-odoo rugot-odoo force-pushed the 19.0-tutorial-rugot branch 2 times, most recently from bd2ac7b to 2b5dd2e Compare January 7, 2026 15:48
- Added SQL constraints for data integrity
- Implemented Python constraints
- Configured statusbar widget in form views
- Added inline list views for One2many fields
@rugot-odoo rugot-odoo force-pushed the 19.0-tutorial-rugot branch from 2b5dd2e to fedc96f Compare January 7, 2026 16:21
Copy link

@mash-odoo mash-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,
Good going on the PR,
Here are a few suggestions..

class="btn-secondary"
/>
<field name="stage" widget="statusbar"
options="{'clickable': False}"

Choose a reason for hiding this comment

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

What if this option is not written?

Copy link
Author

Choose a reason for hiding this comment

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

The statusbar is read-only by default, so it is not clickable even if the option is omitted.
The clickable: False is added only for clarity, is not strictly required
If we want users to change the state manually from the UI, we can explicitly enable it using clickable: 1.

string='Properties'
)
_unique_type_name = models.Constraint(
'UNIQUE(name)',

Choose a reason for hiding this comment

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

Will this work for all the cases or is there any drawback?

Copy link
Author

@rugot-odoo rugot-odoo Jan 9, 2026

Choose a reason for hiding this comment

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

This will work, but there is one drawback.
The UNIQUE(name) constraint is case-sensitive, so values like "House" and "house" would still be allowed.

<field name="date_availability"/>
<field name="living_area"/>
<field name="garden_area"/>
<field name="total_area" readonly="1"/>

Choose a reason for hiding this comment

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

Do you think readonly is required here?

Copy link
Author

Choose a reason for hiding this comment

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

No, The attribute was added by mistake.
total_area is a computed field, which is already read-only by default.

Comment on lines +97 to +102
@api.ondelete(at_uninstall=False)
def _unlink_if_accepted_offer(self):
for record in self:
for offer in record.offer_ids:
if offer.status == 'accepted':
raise UserError("Can't delete an active record!")

Choose a reason for hiding this comment

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

Can you optimize this?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, this can be optimized.
Instead of looping through all offers, we can directly filter the related recordset using filtered_domain.

@api.ondelete(at_uninstall=False)
def _unlink_if_accepted_offer(self):
if self.offer_ids.filtered_domain([('status', '=', 'accepted')]):
raise UserError("Can't delete an active record!")

Comment on lines +112 to +115
domain="['|','&amp;',('garden_orientation', '=' , 'north'),
('garden_orientation', '=' , 'south'),
('name', '=' , 'test')]"
/>

Choose a reason for hiding this comment

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

As garden_orientation is a selection field, this AND condition won’t ever match.
Should this be an OR?

Copy link
Author

Choose a reason for hiding this comment

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

Got it.
The & was added for testing; this should be an OR condition.
You’re right, since garden_orientation is a selection field, it can’t be both values at the same time.

Comment on lines +43 to +61
def action_accept(self):
# accepted_offer = self.search([
# ('property_id', '=', self.property_id.id),
# ('status', '=', 'accepted')
# ], limit=1)
# accepted_offer = self.property_id.offer_ids.filtered(
# lambda o: o.status == 'accepted'
# )
accepted_offer = self.property_id.offer_ids.filtered_domain([
('status', '=', 'accepted')
])
if accepted_offer:
raise UserError(
"Only one offer can be accepted for a property."
)
self.status = 'accepted'
self.property_id.selling_price = self.price
self.property_id.stage = 'sold'
self.property_id.buyer_id = self.partner_id.id

Choose a reason for hiding this comment

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

Can try to make this more optimized?

Copy link
Author

Choose a reason for hiding this comment

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

Yes, this can be optimized.
Instead of assigning each field individually, we can update the related property in a single write() call.

self.property_id.write({
'selling_price': self.price,
'stage': 'sold',
'buyer_id': self.partner_id.id,
})

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