-
Notifications
You must be signed in to change notification settings - Fork 2.8k
[ADD] estate: add real estate module (framework 101 tutorial) #1077
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: 19.0
Are you sure you want to change the base?
Conversation
924f90b to
0af92ad
Compare
cab625c to
d8993d0
Compare
ushyme
left a comment
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.
Good work so far. I just have a few suggestions.
estate/__manifest__.py
Outdated
| 'name': 'Real Estate', | ||
| 'description': 'Real Estate Advertising', | ||
| # 'version': '1.0', | ||
| 'author': 'robal', |
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.
| 'author': 'robal', | |
| 'author': 'Odoo S.A.', |
As an Odoo employee, you are creating this module in the name of Odoo
estate/models/estate_property.py
Outdated
| name = fields.Char(string="Title", required=True) | ||
| description = fields.Text() | ||
| postcode = fields.Char() | ||
| date_availability = fields.Date(string="Available From", default=fields.Date.today() + relativedelta(months=3), copy=False) |
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.
| date_availability = fields.Date(string="Available From", default=fields.Date.today() + relativedelta(months=3), copy=False) | |
| date_availability = fields.Date(string="Available From", default=lambda self: fields.Date.context_today(self) + relativedelta(months=3), copy=False) |
date_availability's default was calculated only once at server launch. Wrapping it in a lambda fixes this by computing it dynamically for each new record. I also used fields.Date.context_today(self) for timezone correctness.
estate/models/estate_property.py
Outdated
| if record.state == "sold": | ||
| error_msg = "This property has already been sold." | ||
| raise UserError(error_msg) |
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.
| if record.state == "sold": | |
| error_msg = "This property has already been sold." | |
| raise UserError(error_msg) | |
| if record.state == "sold": | |
| continue |
In the action_ methods, it's slightly more user-friendly to silently ignore a button click if the record is already in the target state, rather than raising an error.
estate/models/estate_property.py
Outdated
| raise UserError(error_msg) | ||
|
|
||
| if record.state == "cancelled": | ||
| error_msg = "Cancelled properties cannot be sold." |
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.
| error_msg = "Cancelled properties cannot be sold." | |
| error_msg = record.env._("Cancelled properties cannot be sold.") |
User-facing strings in errors and constraints must be wrapped in record.env._() to be translatable.
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.
Is there a practical difference between using record.env._() and using _() imported with from odoo import _ or the one from self.env._() ?
| def _get_reference_date(offer: EstatePropertyOffer) -> date: | ||
| return fields.Date.today() if not offer.create_date else offer.create_date.date() |
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.
I don't know if this function is really helpful here. I think the code would overall be more readable if this logic was inlined directly in the compute/inverse method.
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.
Should I use context_today like in the other model ?
estate/models/estate_property.py
Outdated
| for record in self: | ||
| # Selling price is zero when no offer has been accepted | ||
| if not float_is_zero(record.selling_price, precision_digits=2) and float_compare(record.selling_price, 0.9 * record.expected_price, precision_digits=2) < 0: | ||
| raise ValidationError(_("A property's selling price cannot be lower that 90 percent of its expected price.")) |
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.
| raise ValidationError(_("A property's selling price cannot be lower that 90 percent of its expected price.")) | |
| raise ValidationError(_("A property's selling price cannot be lower than 90 percent of its expected price.")) |
small typo
estate/models/estate_property.py
Outdated
|
|
||
| # Methods that trigger on changes | ||
| @api.onchange("garden") | ||
| def _compute_garden_defaults(self) -> None: |
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.
| def _compute_garden_defaults(self) -> None: | |
| def _onchange_garden_defaults(self) -> None: |
This is an onchange, not a compute. Should be named _onchange_garden_defaults or _onchange_garden.
| Command.create({"name": percent_description, "quantity": 1, "price_unit": 0.06 * record.selling_price}), | ||
| Command.create({"name": admin_fee_description, "quantity": 1, "price_unit": 100.0}), | ||
| ], | ||
| } |
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/__manifest__.py
Outdated
| { | ||
| "name": "Real Estate", | ||
| "description": "Real Estate Advertising", | ||
| "author": "robal", |
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.
| "author": "robal", | |
| "author": "Odoo S.A.", |
As an employee, you work in the name of Odoo.
.gitignore
Outdated
|
|
||
| # VScode | ||
| .vscode/ |
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.
| # VScode | |
| .vscode/ |
This is personal configuration that shouldn't be pushed to the general codebase.
2fb7576 to
9dd3005
Compare
Framework 101 tutorial - add estate module - add estate_account module for integration with invoicing
440b49e to
6b2e660
Compare

No description provided.