-
Notifications
You must be signed in to change notification settings - Fork 3.3k
19.0 Tutorials YACHA #1381
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?
19.0 Tutorials YACHA #1381
Changes from all commits
0c81ab4
f064b95
66e5c64
7d130c1
754791c
563084f
52b96f3
a1d882c
b83e68d
cbc80c6
65dfaa2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import models |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| { | ||
| "name": "Real Estate", | ||
| "version": "1.0", | ||
| "author": "yacha", | ||
| "depends": ["base"], | ||
| "application": True, | ||
| "category": "Tutorials", | ||
| "installable": True, | ||
| "license": "LGPL-3", | ||
| "data": [ | ||
| "security/ir.model.access.csv", | ||
| "views/estate_property_views.xml", | ||
| "views/estate_property_type_views.xml", | ||
| "views/estate_property_tag_views.xml", | ||
| "views/estate_property_offer_views.xml", | ||
| "views/estate_menus.xml", | ||
| ], | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| from . import estate_property | ||
| from . import estate_property_type | ||
| from . import estate_property_tag | ||
| from . import estate_property_offer |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,77 @@ | ||||||||||||||||||||||||||||||||||
| from odoo import api, models, fields | ||||||||||||||||||||||||||||||||||
| from dateutil.relativedelta import relativedelta | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+1
to
+2
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can refer to this for ordering your imports. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @api.model | ||||||||||||||||||||||||||||||||||
| def _default_date_availability(self): | ||||||||||||||||||||||||||||||||||
| return fields.Date.today() + relativedelta(months=3) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+5
to
+7
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be placed inside the class. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| class EstateProperty(models.Model): | ||||||||||||||||||||||||||||||||||
| _name = "estate.property" | ||||||||||||||||||||||||||||||||||
| _description = "Real Estate Property" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| active = fields.Boolean(default=True) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| name = fields.Char(required=True, default="Unknown") | ||||||||||||||||||||||||||||||||||
| description = fields.Text() | ||||||||||||||||||||||||||||||||||
| postcode = fields.Char() | ||||||||||||||||||||||||||||||||||
| date_availability = fields.Date(copy=False, default=_default_date_availability) | ||||||||||||||||||||||||||||||||||
| expected_price = fields.Float(required=True) | ||||||||||||||||||||||||||||||||||
| selling_price = fields.Float(readonly=True, copy=False) | ||||||||||||||||||||||||||||||||||
| bedrooms = fields.Integer(default=2) | ||||||||||||||||||||||||||||||||||
| living_area = fields.Integer() | ||||||||||||||||||||||||||||||||||
| facades = fields.Integer() | ||||||||||||||||||||||||||||||||||
| garage = fields.Boolean() | ||||||||||||||||||||||||||||||||||
| garden = fields.Boolean() | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| garden_area = fields.Integer() | ||||||||||||||||||||||||||||||||||
| garden_orientation = fields.Selection( | ||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||
| ("north", "North"), | ||||||||||||||||||||||||||||||||||
| ("south", "South"), | ||||||||||||||||||||||||||||||||||
| ("east", "East"), | ||||||||||||||||||||||||||||||||||
| ("west", "West"), | ||||||||||||||||||||||||||||||||||
| ] | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+28
to
+35
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Try to keep the key i.e the technical strings in single quotes and the values which are to be displayed to the user in double quotes |
||||||||||||||||||||||||||||||||||
| state = fields.Selection( | ||||||||||||||||||||||||||||||||||
| [ | ||||||||||||||||||||||||||||||||||
| ("new", "New"), | ||||||||||||||||||||||||||||||||||
| ("offer_received", "Offer Received"), | ||||||||||||||||||||||||||||||||||
| ("offer_accepted", "Offer Accepted"), | ||||||||||||||||||||||||||||||||||
| ("sold", "Sold"), | ||||||||||||||||||||||||||||||||||
| ("cancelled", "Cancelled"), | ||||||||||||||||||||||||||||||||||
| ], | ||||||||||||||||||||||||||||||||||
| string="State", | ||||||||||||||||||||||||||||||||||
| required=True, | ||||||||||||||||||||||||||||||||||
| copy=False, | ||||||||||||||||||||||||||||||||||
| default="new", | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| property_type_id = fields.Many2one("estate.property.type", string="Property Type") | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) | ||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if you do not write the string here?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Odoo automatically derives the string name explicitly from the variable name. So if we don't give this string then also it is deriving string to Property Type. I tested it. So i think i should remove it. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| salesperson_id = fields.Many2one( | ||||||||||||||||||||||||||||||||||
| "res.users", string="Salesperson", default=lambda self: self.env.user | ||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+50
to
+56
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Do not leave unnecessary lines between the field declarations. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| 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. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How will I be able to view that which offers are linked to which property?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The property_id field in estate.property.offer stores which property the offer belongs to. The One2many field uses this inverse field to retrieve all offers linked to that particular property. |
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| total_area = fields.Integer(compute="_compute_total") | ||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| best_price = fields.Float(compute="_compute_best_price") | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @api.depends("living_area", "garden_area") | ||||||||||||||||||||||||||||||||||
| def _compute_total(self): | ||||||||||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||||||||||
| record.total_area = record.living_area + record.garden_area | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| @api.depends("offer_ids.price") | ||||||||||||||||||||||||||||||||||
| def _compute_best_price(self): | ||||||||||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||||||||||
| if record.offer_ids: | ||||||||||||||||||||||||||||||||||
| record.best_price = max(record.offer_ids.mapped("price")) | ||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||
| record.best_price = 0 | ||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| from odoo import models, fields | ||
|
|
||
|
|
||
| class EstatePropertyOffer(models.Model): | ||
| _name = "estate.property.offer" | ||
| _description = "Estate Property Offer" | ||
|
|
||
| price = fields.Float() | ||
| status = fields.Selection( | ||
| [("accepted", "Accepted"), ("refused", "Refused")], copy=False | ||
| ) | ||
|
|
||
| partner_id = fields.Many2one("res.partner", required=True) | ||
| property_id = fields.Many2one("estate.property", required=True) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference between setting a field as
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. required=True makes the field mandatory at the model level, so it applies whenever the field is used. required="1" in the XML only makes the field mandatory in that specific view. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| from odoo import models, fields | ||
|
|
||
|
|
||
| class EstatePropertyTag(models.Model): | ||
| _name = "estate.property.tag" | ||
| _description = "Real Estate Property Tag" | ||
|
|
||
| name = fields.Char(required=True) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| from odoo import models, fields | ||
|
|
||
|
|
||
| class EstatePropertyType(models.Model): | ||
| _name = "estate.property.type" | ||
| _description = "Real Estate Property Type" | ||
|
|
||
| name = fields.Char(required=True) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| 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 | ||
| access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 | ||
| access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 | ||
| access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Always leave an extra line at the end of every file. |
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,35 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <?xml version="1.0" encoding="utf-8"?> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <odoo> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id="estate_menu_root" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name="Real Estate"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id="estate_advertisements_menu" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name="Advertisements"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id="estate_property_menu_action" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| action="estate_property_action"/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </menuitem> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+4
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Re-format this file a bit. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id="estate_property_type_menu" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name="Settings"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id="estate_property_type_menu_action" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| action="estate_property_type_action"/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <menuitem | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id="estate_property_tag_menu_action" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| action="estate_property_tag_action"/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </menuitem> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </menuitem> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </odoo> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
|
|
||
| <record id="estate_property_offer_view_list" model="ir.ui.view"> | ||
| <field name="name">estate.property.offer.list</field> | ||
| <field name="model">estate.property.offer</field> | ||
| <field name="arch" type="xml"> | ||
| <list> | ||
| <field name="price"/> | ||
| <field name="partner_id"/> | ||
| <field name="status"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_offer_view_form" model="ir.ui.view"> | ||
| <field name="name">estate.property.offer.form</field> | ||
| <field name="model">estate.property.offer</field> | ||
| <field name="arch" type="xml"> | ||
| <form> | ||
| <sheet> | ||
| <group> | ||
| <field name="price"/> | ||
| <field name="partner_id"/> | ||
| <field name="status"/> | ||
| </group> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| </odoo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
|
|
||
| <record | ||
| id="estate_property_tag_action" | ||
| model="ir.actions.act_window"> | ||
| <field name="name">Property Tags</field> | ||
| <field name="res_model">estate.property.tag</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
|
|
||
| </odoo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it compulsory to write this?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's the XML declaration that identifies the file as an XML 1.0 document. It's the standard way to start an XML file. |
||
| <odoo> | ||
|
|
||
| <record | ||
| id="estate_property_type_action" | ||
| model="ir.actions.act_window"> | ||
| <field name="name">Property Types</field> | ||
| <field name="res_model">estate.property.type</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
|
|
||
| </odoo> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
|
|
||
| <record | ||
| id="estate_property_view_list" | ||
| model="ir.ui.view"> | ||
| <field name="name">estate.property.listview</field> | ||
| <field name="model">estate.property</field> | ||
| <field name="arch" type="xml"> | ||
| <list string="Properties"> | ||
| <field name="name"/> | ||
| <field name="property_type_id"/> | ||
| <field name="tag_ids" widget="many2many_tags"/> | ||
| <field name="postcode"/> | ||
| <field name="bedrooms"/> | ||
| <field name="living_area"/> | ||
| <field name="expected_price"/> | ||
| <field name="selling_price"/> | ||
| <field name="date_availability"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record | ||
| id="estate_property_view_form" | ||
| model="ir.ui.view"> | ||
| <field name="model">estate.property</field> | ||
| <field name="arch" type="xml"> | ||
| <form string="Property"> | ||
| <sheet> | ||
|
|
||
| <group> | ||
| <h1> | ||
| <field name="name"/> | ||
| </h1> | ||
| </group> | ||
|
|
||
| <group> | ||
|
|
||
| <group> | ||
| <field name="property_type_id"/> | ||
| <field name="tag_ids" widget="many2many_tags"/> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why do we use a widget?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use a widget when we want to change the default way a field is displayed or interacted with in the view. It allows us to provide a more suitable UI for that particular field. |
||
| <field name="postcode"/> | ||
| <field name="date_availability"/> | ||
| </group> | ||
|
|
||
| <group> | ||
| <field name="expected_price"/> | ||
| <field name="selling_price"/> | ||
| </group> | ||
|
|
||
| </group> | ||
|
|
||
| <notebook> | ||
| <page string="Description"> | ||
| <group> | ||
| <field name="description"/> | ||
| <field name="bedrooms"/> | ||
| <field name="living_area"/> | ||
| <field name="facades"/> | ||
| <field name="garage"/> | ||
| <field name="garden"/> | ||
| <field name="garden_area" invisible="not garden"/> | ||
| <field name="garden_orientation" invisible="not garden"/> | ||
| <field name="total_area"/> | ||
| <field name="best_price"/> | ||
| <field name="active"/> | ||
| <field name="state"/> | ||
| </group> | ||
| </page> | ||
| <page string="Other Info"> | ||
| <group> | ||
| <field name="buyer_id"/> | ||
| <field name="salesperson_id"/> | ||
| </group> | ||
| </page> | ||
| <page string="Offers"> | ||
| <field name="offer_ids"/> | ||
| </page> | ||
| </notebook> | ||
|
|
||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_view_search" model="ir.ui.view"> | ||
| <field name="name">estate.property.search</field> | ||
| <field name="model">estate.property</field> | ||
| <field name="arch" type="xml"> | ||
| <search string="Properties"> | ||
| <field name="name"/> | ||
| <field name="property_type_id"/> | ||
| <field name="postcode"/> | ||
| <field name="bedrooms"/> | ||
| <field name="expected_price"/> | ||
| <field name="living_area"/> | ||
| <field name="garden_area"/> | ||
| <field name="total_area"/> | ||
| <field name="facades"/> | ||
|
|
||
| <filter string="Available" name="date_availability" domain="[('state','in',('new','offer_received'))]"/> | ||
|
|
||
| <filter string="Postcode" name="postcode" context="{'group_by':'postcode'}"/> | ||
|
|
||
| </search> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record | ||
| id="estate_property_action" | ||
| model="ir.actions.act_window"> | ||
| <field name="name">Properties</field> | ||
| <field name="res_model">estate.property</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
|
|
||
| </odoo> | ||
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.
When you are working for a company, you should keep the author name as
Odoo S.A.or just skip writing it.