[ADD] estate: Added a new module named estate#733
[ADD] estate: Added a new module named estate#733
Conversation
a35abec to
329a381
Compare
| 'installable': True, | ||
| 'application': True, | ||
| 'auto_install': False | ||
| } |
There was a problem hiding this comment.
Don't forget the license key to avoid warnings in the log.
|
@msho-odoo For the title of the commit, be aware that the commit message header should make a valid sentence once concatenated with if applied, this commit will
|
| 'data': [ | ||
| 'security/ir.model.access.csv', | ||
| 'views/estate_property_views.xml', | ||
| 'views/estate_menu.xml', | ||
| ], |
There was a problem hiding this comment.
| 'data': [ | |
| 'security/ir.model.access.csv', | |
| 'views/estate_property_views.xml', | |
| 'views/estate_menu.xml', | |
| ], | |
| 'data': [ | |
| 'security/ir.model.access.csv', | |
| 'views/estate_property_views.xml', | |
| 'views/estate_menu.xml', | |
| ], |
| @@ -0,0 +1,2 @@ | |||
| id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink | |||
| access_estate_property, access_estate_property,model_estate_property,base.group_user,1,1,1,1 No newline at end of file | |||
| <menuitem id="estate_property_action_menu" action="estate_property_action"></menuitem> | ||
| </menuitem> | ||
| </menuitem> | ||
| </odoo> No newline at end of file |
| <field name="res_model">estate.property</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
| </odoo> No newline at end of file |
6f5effe to
450100a
Compare
| postcode = fields.Char('postcode') | ||
| date_availability = fields.Date( | ||
| 'availabilty date', copy=False, default=fields.Date.today()+relativedelta(months=3)) | ||
| 'availabilty date', copy=False, default=fields.Date.today() + relativedelta(months=3)) |
There was a problem hiding this comment.
For this diff you could use git commit --amend to correct the previous commit :)
There was a problem hiding this comment.
@SergeBayet
yes, I wasn't used to using it in that sense but sure it makes sense.
Thank you for pointing these things out, it helps :)
| buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) | ||
| tag_ids = fields.Many2many("estate.property.tag", string="Tags") | ||
| offer_ids = fields.One2many( | ||
| "estate.property.offer", "property_id", string="Offers") |
There was a problem hiding this comment.
Silly little remark, but choose if you want to use double quotes or single quotes and stick to it :) In Python, this kind of convention depends of the team you'll be in.
|
|
||
| @api.depends("offer_ids") | ||
| def _compute_best_offer(self): | ||
| try: |
There was a problem hiding this comment.
Why this try/except block? What could happen?
There was a problem hiding this comment.
It was giving me some error but I fixed it later, removing it
| if len(record.offer_ids) > 0: | ||
| record.best_offer = max(record.offer_ids.mapped("price")) | ||
| else: | ||
| record.best_offer = 0.0 |
There was a problem hiding this comment.
A more pyhtonic way:
for prop in self:
prop.best_price = max(prop.offer_ids.mapped("price")) if prop.offer_ids else 0.0| date_deadline = fields.Date( | ||
| compute="_compute_date_deadline", inverse="_inverse_date_deadline") | ||
|
|
||
| @api.depends("validity") |
There was a problem hiding this comment.
It depends of create_date too, isn't it?
| for record in self: | ||
| start_date = fields.Date.today() | ||
| if record.create_date: | ||
| start_date = record.create_date |
There was a problem hiding this comment.
Be aware that record.create_date is a DateTime field. You can extract the date with the method date()
So maybe this could be better:
for offer in self:
date = offer.create_date.date() if offer.create_date else fields.Date.today()
offer.date_deadline = date + relativedelta(days=offer.validity)| for record in self: | ||
| start_date = fields.Date.today() | ||
| if record.create_date: | ||
| start_date = record.create_date |
|
|
||
| def _inverse_date_deadline(self): | ||
| for record in self: | ||
| start_date = fields.Date.today() |
eec66c2 to
658e49e
Compare
|
@vava-odoo You can take over this one. :) Thanks |
|
@SergeBayet I don't review red runbot PRs 😇 |
658e49e to
fc150fb
Compare
|
@vava-odoo |
vava-odoo
left a comment
There was a problem hiding this comment.
A few comments passing by. Good luck with next chapters 💪
| ], | ||
| 'installable': True, | ||
| 'application': True, | ||
| 'auto_install': False, |
There was a problem hiding this comment.
Default value are not needed (in community, this would raise a warning in runbot)
| 'auto_install': False, |
| @@ -0,0 +1,81 @@ | |||
| from odoo import api, fields, models | |||
| from odoo.exceptions import UserError | |||
| from dateutil.relativedelta import relativedelta | |||
|
|
||
| class EstateProperty(models.Model): | ||
| _name = "estate.property" | ||
| _description = "Estate Property discription" |
| selection=[('north', 'North'), ('south', 'South'), | ||
| ('east', 'East'), ('west', 'West')] |
There was a problem hiding this comment.
usually we indent a bit differently
| selection=[('north', 'North'), ('south', 'South'), | |
| ('east', 'East'), ('west', 'West')] | |
| selection=[ | |
| ('north', 'North'), | |
| ('south', 'South'), | |
| ('east', 'East'), | |
| ('west', 'West'), | |
| ], |
| property_type_id = fields.Many2one( | ||
| "estate.property.type", string="property type") |
There was a problem hiding this comment.
We avoid long lines, but don't be extreme. Here a one-liner is fine
| property_type_id = fields.Many2one( | |
| "estate.property.type", string="property type") | |
| property_type_id = fields.Many2one("estate.property.type", string="property type") |
| record.best_offer = max(record.offer_ids.mapped( | ||
| "price")) if record.offer_ids else 0.0 |
There was a problem hiding this comment.
Could use default kwarg
| record.best_offer = max(record.offer_ids.mapped( | |
| "price")) if record.offer_ids else 0.0 | |
| record.best_offer = max(record.offer_ids.mapped("price"), default=0.0) |
|
|
||
| @api.onchange("garden") | ||
| def _onchange_garden(self): | ||
| if self.garden: |
There was a problem hiding this comment.
I'd say has_garden is a clearer name, but that is debatable
There was a problem hiding this comment.
agree, just for the sake of the tutorial
| for record in self: | ||
| if record.state == "cancelled": | ||
| raise UserError("You can't sell a cancelled property") | ||
| record.state = "sold" |
There was a problem hiding this comment.
Better to raise first and assign in batch. For example:
| for record in self: | |
| if record.state == "cancelled": | |
| raise UserError("You can't sell a cancelled property") | |
| record.state = "sold" | |
| if "cancelled" in record.mapped('state'): | |
| raise UserError("You can't sell a cancelled property") | |
| self.state = "sold" |
| <field name="name">properties.view.type.form</field> | ||
| <field name="model">estate.property.type</field> | ||
| <field name="arch" type="xml"> | ||
| <form string="properties type from"> |
There was a problem hiding this comment.
typo
| <form string="properties type from"> | |
| <form string="properties type form"> |
Do you need to define this view? I think a default one is automatically created, and not quite different
There was a problem hiding this comment.
yes you're right.
I was following the tutorial in case I would add something later to the view, so I did it
| <field name="expected_price"/> | ||
| <field name="selling_price"/> | ||
| <field name="availability_date"/> | ||
| <filter string="Available" name="state" domain="['|',('state','=','new'),('state','=','offer_received')]"/> |
There was a problem hiding this comment.
Simpler:
| <filter string="Available" name="state" domain="['|',('state','=','new'),('state','=','offer_received')]"/> | |
| <filter string="Available" name="state" domain="[('state', 'in', ['new', 'offer_received'])]"/> |
c011c65 to
8ebd0af
Compare
8ebd0af to
a3d2623
Compare
a3d2623 to
57d42f0
Compare
| @api.model | ||
| def create(self, vals): | ||
| property_record = self.env["estate.property"].browse(vals["property_id"]) | ||
| if vals["price"] < property_record.best_offer: |
There was a problem hiding this comment.
Pay attention that price is not required, you need to handle cases where it is not defined
There was a problem hiding this comment.
@vava-odoo
I made a sql constraint on the price so it can't be left empty or 0
| @api.model | ||
| def create(self, vals): |
There was a problem hiding this comment.
We tend to prefer recordset over single records in odoo, could you try to adapt this to support multiple-records creation?
| _name = "estate.property.tag" | ||
| _description = "Estate property tag" | ||
| _sql_constraints = [ | ||
| ("check_unique_name", "UNIQUE(name)", "Property tag must be unqie") |
| <header> | ||
| <button name="action_sell" type="object" string="Mark as Sold" invisible="state in ['sold', 'cancelled']"/> | ||
| <button name="action_cancel" type="object" string="Cancel" invisible="state in ['sold', 'cancelled']"/> | ||
| <field name="state" widget="statusbar" statusbar_visible="new,offer_received,offer_accepted,sold"/> |
There was a problem hiding this comment.
is statusbar_visible necessary when you use all values of the selection field?
There was a problem hiding this comment.
@vava-odoo
There is also "cancelled", but the request was to show only those states
| 'name': 'Estate Account', | ||
| 'depends': | ||
| ['estate', 'account'], | ||
| 'data': [], |
There was a problem hiding this comment.
no need 🤷
| 'data': [], |
| 'installable': True, | ||
| 'application': True, |
There was a problem hiding this comment.
Ok, but would be nice to have it installed as soon as dependency modules are


No description provided.