-
Notifications
You must be signed in to change notification settings - Fork 2.6k
JEDEL Onboarding #998
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?
JEDEL Onboarding #998
Conversation
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.
Small comments :)
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 here !
I see that your runbot is red because of style, so you may fix that.
Also be mindful about the naming of files/xmlids: https://www.odoo.com/documentation/19.0/contributing/development/coding_guidelines.html#xml-ids-and-naming
| @api.constrains('expected_price', 'selling_price') | ||
| def _check_selling_price(self): | ||
| for record in self: | ||
| if not float_is_zero(record.selling_price, precision_digits=3): | ||
| if float_compare(record.selling_price, record.expected_price*0.9, precision_digits=3) < 0: | ||
| raise UserError(r"The selling price must be at least 90% of the 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.
Be careful about model attribute order: https://www.odoo.com/documentation/19.0/contributing/development/coding_guidelines.html#symbols-and-conventions
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.
Still
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 understand the change I have to make
estate/security/ir.model.access.csv
Outdated
| estate.access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 | ||
| estate.access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 | ||
| estate.access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 | ||
| estate.access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 No newline at end of file |
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 newline
| <field name="bedrooms"/> | ||
| <field name="living_area" string="Living Area (sqm)"/> | ||
| <field name="facades"/> | ||
| <filter string="Available" name="available" domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]"/> |
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.
| <filter string="Available" name="available" domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]"/> | |
| <filter string="Available" name="available" domain="[('state', 'in', ('new', 'offer_received'))]"/> |
Simpler way when comparing the same variable :)
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.
Very good work !
Still a few things to fix left from yesterday's pass :)
estate/models/estate_property.py
Outdated
|
|
||
| class EstateProperty(models.Model): | ||
| _name = "estate.property" | ||
| _description = "Property for the Real Estate app" |
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.
| _description = "Property for the Real Estate app" | |
| _description = "Estate Property" |
_description contains a short human-readable name for the model
| @api.constrains('expected_price', 'selling_price') | ||
| def _check_selling_price(self): | ||
| for record in self: | ||
| if not float_is_zero(record.selling_price, precision_digits=3): | ||
| if float_compare(record.selling_price, record.expected_price*0.9, precision_digits=3) < 0: | ||
| raise UserError(r"The selling price must be at least 90% of the 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.
Still
| if len(offers) > 0: | ||
| if val['price'] < max(offers.mapped('price')): | ||
| raise UserError("You cannot create an offer with a lower amount than an existing 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.
| if len(offers) > 0: | |
| if val['price'] < max(offers.mapped('price')): | |
| raise UserError("You cannot create an offer with a lower amount than an existing offer !") | |
| if offers and val['price'] < max(offers.mapped('price')): | |
| raise UserError("You cannot create an offer with a lower amount than an existing offer !") |
Cleaner that way :)If you have an empty recordset, it will automatically be cast to 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.
Very good overall.
Could you just squash so that you have 1 commit per chapter ?
| @@ -0,0 +1,3 @@ | |||
| { | |||
| "files.insertFinalNewline": true | |||
| } No newline at end of file | |||
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.
Ironically, this is missing the newline :x
| @api.ondelete(at_uninstall=False) | ||
| def _unlike_if_stats_new_or_cancelled(self): | ||
| for record in self: | ||
| if record.state in ('new', 'cancelled'): | ||
| raise UserError("You cannot delete a new or cancelled property !") |
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.
| @api.ondelete(at_uninstall=False) | |
| def _unlike_if_stats_new_or_cancelled(self): | |
| for record in self: | |
| if record.state in ('new', 'cancelled'): | |
| raise UserError("You cannot delete a new or cancelled property !") | |
| @api.ondelete(at_uninstall=False) | |
| def _unlink_if_stats_new_or_cancelled(self): | |
| for record in self: | |
| if record.state in ('new', 'cancelled'): | |
| raise UserError("You cannot delete a new or cancelled property !") |
Spelling.
Also method ordering ! This is one of the CRUD methods, it should go higher :)
| for offer in self: | ||
| offer.status = "refused" |
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.
| for offer in self: | |
| offer.status = "refused" | |
| self.status = "refused" | |
| return True |
Assigning attributes on recordsets works !
| @api.model_create_multi | ||
| def create(self, vals_list): | ||
| for val in vals_list: | ||
| if self.env['estate.property'].browse(val['property_id']).state == 'sold': | ||
| raise UserError("You cannot create an offer for a sold property !") | ||
| offers = self.env['estate.property.offer'].search([('property_id', '=', val['property_id'])]) | ||
| if offers and val['price'] < max(offers.mapped('price')): | ||
| raise UserError("You cannot create an offer with a lower amount than an existing offer !") | ||
| offers = super().create(vals_list) | ||
| offers.property_id.state = 'offer_received' | ||
| return 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.
| @api.model_create_multi | |
| def create(self, vals_list): | |
| for val in vals_list: | |
| if self.env['estate.property'].browse(val['property_id']).state == 'sold': | |
| raise UserError("You cannot create an offer for a sold property !") | |
| offers = self.env['estate.property.offer'].search([('property_id', '=', val['property_id'])]) | |
| if offers and val['price'] < max(offers.mapped('price')): | |
| raise UserError("You cannot create an offer with a lower amount than an existing offer !") | |
| offers = super().create(vals_list) | |
| offers.property_id.state = 'offer_received' | |
| return offers | |
| @api.model_create_multi | |
| def create(self, vals_list): | |
| if self.env['estate.property'].search_count([('id', 'in', [val.get('property_id') for val in vals_list]), ('state', '=', 'sold')]): # If the number of corresponding object != 0... | |
| raise UserError("You cannot create an offer for a sold property !") | |
| for val in vals_list: | |
| offers = self.env['estate.property.offer'].search([('property_id', '=', val['property_id'])]) | |
| if offers and val['price'] < max(offers.mapped('price')): | |
| raise UserError("You cannot create an offer with a lower amount than an existing offer !") | |
| offers = super().create(vals_list) | |
| offers.property_id.state = 'offer_received' | |
| return offers |
Doing browse in a loop is a BIG nono. It means you will do 1 SQL request per element of the recordset, which is extremely bad for performance. Prefer doing checks like this ouside of the loop, with things like this
Also this is a CRUD method so it should go hisher in the ordering
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.
Also you should use float compare here.
In reality you'd have a currency attached to your price, and you'd use that for comparison.
| partner = self.env['res.partner'].create( | ||
| [{ | ||
| 'name': 'My Favorite Partner' | ||
| }] | ||
| ) |
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.
Create this guy in the setUp. means the tests will run faster if you need a partner somewhere else in the tests
| Command.create({ | ||
| 'name': self.name, | ||
| 'quantity': 1, | ||
| 'price_unit': self.selling_price | ||
| }), | ||
| Command.create({ | ||
| 'name': 'Taxes', | ||
| 'quantity': 1, | ||
| 'price_unit': self.selling_price * 0.06 | ||
| }), | ||
| Command.create({ | ||
| 'name': 'Administrative fees', | ||
| 'quantity': 1, | ||
| 'price_unit': 100.00 | ||
| }) |
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.
Just saw this but I think this is not what the exercise asks you to do.

No description provided.