Skip to content

Technical Training (Ahnae)#1247

Open
ahmedamein100 wants to merge 35 commits intoodoo:masterfrom
odoo-dev:19.0-tutorials-ahnae
Open

Technical Training (Ahnae)#1247
ahmedamein100 wants to merge 35 commits intoodoo:masterfrom
odoo-dev:19.0-tutorials-ahnae

Conversation

@ahmedamein100
Copy link
Copy Markdown

  • created empty Estate module
  • update it's manifest to make it an app
  • created model files and write down the required fields
  • fix PR errors

omarait-mlouk and others added 3 commits October 3, 2025 11:20
The carousel template file was loaded too late in the manifest data
sequence, causing a ParseError when new_page_templates tried to
reference it.

closes odoo#988

X-original-commit: 34d70b5
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
Some imports are missing in the manifest causing some warnings and
the css doesn't load properly.
Fix was fixed in the master branch, backporting it in 19.0
for the onboarding classes that always happen in the lastest stable.

task-none

Part-of: odoo#1037
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
`json` routes were deprecated to `jsonrpc` in 19.0, let's
get rid of the warning to avoid confusion for the newdoos.

task-none

closes odoo#1037

Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
@robodoo
Copy link
Copy Markdown

robodoo commented Apr 22, 2026

Pull request status dashboard

ahmedamein100 and others added 6 commits April 22, 2026 14:06
The goal of this commit is to provide the initial user interface and
core field behaviors for the Real Estate module.

- UI: Added window action and a three-level menu hierarchy to allow
  users to navigate to property records.
- Data Integrity: Set 'selling_price' to read-only and prevented
  copying of 'date_availability' to ensure fresh data on duplication.
- Automation: Implemented a 3-month default for 'date_availability'
  using a dynamic lambda to handle the 'today' calculation at runtime.
- Management: Added 'active' (archiving) and 'state' (workflow) fields
  to support record lifecycle management.
Base users were able to unlink records although they're just plebs.
Copy link
Copy Markdown

@vandroogenbd vandroogenbd left a comment

Choose a reason for hiding this comment

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

Just some small comments 🙂

Be careful that I might have made a contribution to your PR 🫣

Comment thread estate/models/estate_property.py Outdated
Comment on lines +6 to +8
_description = "Estate Property Model"

name = fields.Char(required=True)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Good practice to separate attributes from fields 👍

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I am sorry but isn't it separated with line number 7?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Exactly, hence the 👍

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

ahhh okay hehe

Comment thread estate/models/estate_property.py Outdated
garden_orientation = fields.Selection(
string='Type',
selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Indentation is off here

Comment thread estate/models/estate_property.py Outdated
garden_area = fields.Integer()
garden_orientation = fields.Selection(
string='Type',
selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It is good practice to end argument lines with a ,. This way, if someone later adds a line, they don't have to add the coma so the line stays unchanged, this keeps the git history cleaner!

Comment thread estate/models/estate_property.py Outdated
Comment on lines +25 to +36
state = fields.Selection(
selection=[
('new', 'New'),
('offer_received', 'Offer Received'),
('offer_accepted', 'Offer Accepted'),
('sold', 'Sold'),
('canceled', 'Cancelled'),
],
required=True,
copy=False,
default='new',
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You might want to re-indent this block

Comment thread estate/security/ir.model.access.csv Outdated
@@ -0,0 +1,2 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,0 No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Comment thread estate/models/estate_property.py Outdated


class EstatePropertytModel(models.Model):
_name = "estate_property"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

By convention, we separate words with . in model names

word.word => model name
word_word => python variable (snake case)
wordWord => js variable (camel case)

Comment thread estate/__manifest__.py Outdated
'depends': ['base'],
'category': 'Tutorials',
'application': True,
'data': ['security/ir.model.access.csv', 'views/estate_property_views.xml', 'views/estate_menus.xml'],
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Same idea as the comment about the ,, if you break this into multiple lines it makes it so later commits don't mess with git-blaming when adding dependencies

Implement the property list, form, and search views, while
correcting technical naming and styling issues.

- Add list view for property overview
- Add form view with sheet layout, groups, and notebook
- Add search view with 'Available' filter and 'Postcode' grouping
- Correct model name to 'estate.property' and fix field indentation
- Create estate.property.type, estate.property.tag, and estate.property.offer models.
- Add Many2one relationships for property type, salesperson (res.users), and buyer (res.partner).
- Add Many2many relationship for property tags with many2many_tags widget.
- Add One2many relationship for property offers.
- Update views to include new relational fields and notebook pages.
- Add security access rights for all new models.
- Add 'total_area' as a sum of living and garden area.
- Add 'best_price' to track the highest offer using mapped().
- Add 'date_deadline' and 'validity' to offers with an inverse
  function to allow bi-directional updates.
- Implement an onchange to automatically set garden area and
  orientation when the garden checkbox is toggled.
- Add 'Sold' and 'Cancel' buttons to property form with UserError
  constraints to prevent invalid state transitions.
- Add 'Accept' and 'Refuse' buttons to property offers with icons.
- Implement logic to automatically set the property buyer and
  selling price when an offer is accepted.
- Add validation to ensure only one offer can be accepted per
  property.
- Add SQL constraints to ensure expected_price and offer price are
  strictly positive, and selling_price is positive.
- Add unique SQL constraints on property tag and type names.
- Add Python @api.constrains on the property model to ensure the
  selling price is at least 90% of the expected price.
- Use float_is_zero and float_compare to handle decimal precision
  safely in price validation.
- Add list view decorations based on property and offer states.
- Implement 'editable="bottom"' for offer and tag list views.
- Make 'date_availability' an optional hidden field in list view.
- Add 'filter_domain' to living area search for >= filtering.
- Implement 'search_default_available' in the window action.
- Add a stat button on property types to view related offers.
- Define 'property_type_id' as a stored related field on offers.
- Remove trailing whitespaces in property and offer models.
- Remove 'print' statement in property type compute method.
- Fix blank lines containing whitespace.
- Clean up formatting in ValidationErrors and related fields.
- Prevent deletion of properties unless state is 'New' or 'Cancelled'
  using '@api.ondelete'.
- Override 'create' in estate.property.offer to validate offer price
  against 'best_price' and update property state to 'Offer Received'.
- Extend 'res.users' model with a 'property_ids' One2many field.
- Add a filtered notebook page to the Users form view to display
  assigned available properties.
vandroogenbd and others added 5 commits April 28, 2026 15:33
This commit is here to introduce the testing framework of Odoo. Try running the
tests using `--test-tags :TestEstateProperty`.

Doc:
https://www.odoo.com/documentation/18.0/developer/reference/backend/testing.html?highlight=tests#invocation

The tests were made such that the first one should work but the second one
should fail. Your job is to ensure both tests pass in the end. You should update
the behaviour of the appropriate models.

If you want, you can also add a small test of your own to get a feel for it.
- Inherit estate.property in a new estate_account module.
- Override 'action_sold' to automate invoice creation.
- Implement 'account.move' generation with specific lines:
    - 6% commission on property selling price.
    - 100.00 fixed administrative fees.
- Use 'Command.create' for One2many invoice line handling.
- Update 'action_accept_offer' to prevent accepting offers below
  expected price for south-facing properties with gardens.
- Remove unused imports (float_compare, float_is_zero, fields).
- Fix 'Too many blank lines' (E303) in res_users and estate_property.
- Add missing newlines at end of files (W292) in multiple __init__ files.
- Clean up estate_account model imports.
- Create property kanban view with 'default_group_by' on state.
- Disable manual record relocation using 'records_draggable="0"'.
- Add conditional display logic using 't-if' for:
    - 'best_price' (shown only when offers are received).
    - 'selling_price' (shown only when an offer is accepted).
- Include 'expected_price' and 'tag_ids' in the card template.
Copy link
Copy Markdown

@vandroogenbd vandroogenbd left a comment

Choose a reason for hiding this comment

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

Make sure to remove the extra files you pushed. Also, you pushed changes to modules outside of estate and estate_account, can you remove those as well?

Once you're done with that you can squash your commits for estate 🙂

Comment thread .vscode/launch.json
@@ -0,0 +1,56 @@
{
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

You should configure your global .gitignore to make sure such files don't get pushed to your PRs 😉

Comment thread estate/models/estate_property.py Outdated
Comment on lines +1 to +2
from odoo import api, fields, models, exceptions
from odoo.exceptions import ValidationError, UserError
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Please respect alphabetical order for imports

Comment on lines +23 to +31
garden_orientation = fields.Selection(
string='Type',
selection=[
('north', 'North'),
('south', 'South'),
('east', 'East'),
('west', 'West'),
]
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Indentation

Suggested change
garden_orientation = fields.Selection(
string='Type',
selection=[
('north', 'North'),
('south', 'South'),
('east', 'East'),
('west', 'West'),
]
)
garden_orientation = fields.Selection(
string='Type',
selection=[
('north', 'North'),
('south', 'South'),
('east', 'East'),
('west', 'West'),
],
)

]
)
active = fields.Boolean(default=True)
state = fields.Selection(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Indentation here as well

"estate.property.type",
string="Tag",
)
salesperson_id = fields.Many2one(
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Indentation

</list>
</field>
</record>
</odoo> No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Missing empty line at end of file 😉

@@ -0,0 +1,51 @@
<odoo>
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Overall indentation of the file is off + missing empty line at end

<field name="view_mode">list,form,kanban</field>
<field name="context">{'search_default_available': True}</field>
</record>
<record id="estate_property_view_list" model="ir.ui.view">
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Separate <record> blocks with empty lines to make it easier to read please.

Comment thread estate/__manifest__.py Outdated
@@ -0,0 +1,20 @@
{
'name': "Estate",
'version': '1.0',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Version should match the Odoo version, this way Odoo will not allow the module to be installed in other versions.

Suggested change
'version': '1.0',
'version': '19.0.0.1.0',

Comment thread estate_account/__manifest__.py Outdated
@@ -0,0 +1,13 @@
{
'name': "Estate Account",
'version': '1.0',
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Same here

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.

5 participants