-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[LOSBO] Real Estate Property Management - Tutorials #1407
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?
Changes from all commits
fcf8c80
e638942
16d935b
e640341
8070edb
0ea4e3a
f4cfa71
3782710
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 |
|---|---|---|
|
|
@@ -127,3 +127,5 @@ dmypy.json | |
|
|
||
| # Pyre type checker | ||
| .pyre/ | ||
|
|
||
| .vscode | ||
| 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,20 @@ | ||
| { | ||
| "name": "real estate", | ||
| "author": "Lokesh", | ||
| "version": "1.0.0", | ||
| "license": "LGPL-3", | ||
| # "depends": ["base"], | ||
| "application": True, | ||
| "installable": True, | ||
| "data": [ | ||
| "security/ir.model.access.csv", | ||
| "views/estate_property_views.xml", # the order should be like this, first we need to define the views and then we need to define the action and then the menu if the order is not maintained then error will be thrown. | ||
| "views/estate_property_type_view.xml", | ||
| "views/estate_property_menu.xml", | ||
| ], | ||
| "assets": { | ||
| "web.assets_backend": [ | ||
| "estate/static/src/estate.css", | ||
| ], | ||
| }, | ||
| } |
|
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. Can you please import it as per Odoo standard? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| from . import ( | ||
| estate_property, | ||
| estate_property_offers, | ||
| estate_property_tag, | ||
| estate_property_type, | ||
| ) |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,101 @@ | ||||||
| from datetime import datetime | ||||||
|
|
||||||
| from odoo import api, fields, models | ||||||
| from odoo.exceptions import ValidationError | ||||||
|
|
||||||
|
|
||||||
| class TestModel(models.Model): | ||||||
|
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. Can you improve the class name? |
||||||
| today = datetime.now() | ||||||
|
|
||||||
| month = today.month + 3 | ||||||
| year = today.year | ||||||
| day = today.day | ||||||
|
|
||||||
| if month > 12: | ||||||
| year = year + 1 | ||||||
| month = month % 12 | ||||||
|
|
||||||
| three_month_date = today.replace(year=year, month=month, day=day) | ||||||
|
Comment on lines
+8
to
+18
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. Can you explain me the purpose of this? |
||||||
|
|
||||||
| _name = "estate.property" | ||||||
| _description = "This is a dummy table" | ||||||
|
|
||||||
| name = fields.Char(translate=True, default="Unknown", required=True) | ||||||
| description = fields.Text() | ||||||
| postcode = fields.Char() | ||||||
| date_availability = fields.Date(copy=False, default=three_month_date.date()) | ||||||
| expected_price = fields.Float(required=True) | ||||||
| selling_price = fields.Float(readonly=True, copy=False) | ||||||
| bedrooms = fields.Integer() | ||||||
| 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"), | ||||||
| ], | ||||||
| string="Direction", | ||||||
| default="north", | ||||||
| ) | ||||||
| state = fields.Selection( | ||||||
| [ | ||||||
| ("new", "New"), | ||||||
| ("offer_received", "Offer Receeived"), | ||||||
| ("offer_accepted", "Offer Accepted"), | ||||||
| ("sold", "Sold"), | ||||||
| ("cancelled", "Cancelled"), | ||||||
| ] | ||||||
| ) | ||||||
| active = fields.Boolean("Active", default=True) | ||||||
| property_type_id = fields.Many2one("estate.property.type", string="Property_type") | ||||||
|
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
|
||||||
| property_tag_ids = fields.Many2many( | ||||||
| "estate.property.tag", | ||||||
| relation="losbo_property_propertyTag", | ||||||
| string="Property_Tag", | ||||||
| ondelete="cascade", | ||||||
| ) | ||||||
|
|
||||||
| buyer = fields.Many2one("res.partner", string="buyer", copy=False) | ||||||
| user_id = fields.Many2one( | ||||||
| "res.users", string="salesperson", default=lambda self: self.env.user | ||||||
| ) | ||||||
| offer_ids = fields.One2many("estate.property.offers", "property_id") | ||||||
|
|
||||||
|
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. unneccary space. |
||||||
| total_offers = fields.Integer(compute="_compute_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. unneccary space. |
||||||
| total_area = fields.Float(compute="_compute_area") | ||||||
| best_price = fields.Integer(compute="_compute_price") | ||||||
|
|
||||||
| @api.depends("offer_ids") | ||||||
| def _compute_offers(self): | ||||||
| for record in self: | ||||||
| count = 0 | ||||||
| if record.offer_ids: | ||||||
| for offers in record.offer_ids: | ||||||
| if offers.status == "accepted": | ||||||
|
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 you need this check? |
||||||
| count += 1 | ||||||
| record.total_offers = count | ||||||
|
|
||||||
| @api.constrains("name", "description") | ||||||
| def _check_description(self): | ||||||
| for record in self: | ||||||
| if record.name == record.description: | ||||||
| raise ValidationError("Fields name and description should not be equal") | ||||||
|
|
||||||
| @api.depends("living_area", "garden_area") | ||||||
| def _compute_area(self): | ||||||
| for record in self: | ||||||
| record.total_area = record.living_area + record.garden_area | ||||||
|
|
||||||
| @api.depends("offer_ids.price") | ||||||
| def _compute_price(self): | ||||||
| best_price = 0 | ||||||
| for records in self: | ||||||
| for offers in records.offer_ids: | ||||||
| best_price = max(offers.price, best_price) | ||||||
| records.best_price = best_price | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class PropertyOffer(models.Model): | ||
| _name = "estate.property.offers" | ||
| _description = "this model is used to define the offers received to the property" | ||
|
|
||
| price = fields.Float() | ||
| status = fields.Selection([("accepted", "Accepted"), ("refused", "Refused")]) | ||
| partner_id = fields.Many2one("res.partner", required=True) | ||
| property_id = fields.Many2one("estate.property", required=True, ondelete="cascade") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class PropertyTag(models.Model): | ||
| _name = "estate.property.tag" | ||
| _description = "this model is used to define tags to the properties" | ||
|
|
||
| name = fields.Char(string="Tags") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class PropertyType(models.Model): | ||
| _name = "estate.property.type" | ||
| _description = "this is used to define the types" | ||
|
|
||
| name = fields.Char(required=True, string="Type") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
| access_estate_property_user1,estate.property.user,model_estate_property,base.group_user,1,0,0,0 | ||
| access_estate_property_user,estate.property.user,model_estate_property,base.group_system,1,1,1,1 | ||
| access_estate_property_type_user,estate.property.type.user,model_estate_property_type,base.group_user,1,1,1,1 | ||
| access_estate_property_tag_user,estate.property.tag.user,model_estate_property_tag,base.group_user,1,1,1,1 | ||
| access_estate_property_offer_user,estate.property.offer.user,model_estate_property_offers,base.group_user,1,1,1,1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <menuitem id="estate_property_menu_root" name="Real Estate"/> | ||
|
|
||
| <menuitem id="estate_menu_property" | ||
| parent="estate_property_menu_root" | ||
| name="Settings" | ||
| sequence="10" | ||
| /> | ||
| <menuitem id="estate_menu_settings" | ||
| parent="estate_menu_property" | ||
| name="Property Type" | ||
| action="estate_property_type_action" | ||
| /> | ||
| <menuitem id="estate_menu_advertisement" | ||
| parent="estate_property_menu_root" | ||
| name="Advertisement" | ||
| sequence="2" | ||
| /> | ||
| <menuitem id="estate_menu_properties" | ||
| parent="estate_menu_advertisement" | ||
| name="properties" | ||
| action="estate_property_action" | ||
| /> | ||
| </odoo> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
|
|
||
| <odoo> | ||
| <record id="estate_property_type_view" model="ir.ui.view" > | ||
| <field name="model">estate.property.type</field> | ||
| <field name="arch" type="xml"> | ||
| <form string="property type"> | ||
| <sheet> | ||
| <group> | ||
| <field name="name" string="Type"/> | ||
| </group> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- action --> | ||
| <record id="estate_property_type_action" model="ir.actions.act_window"> | ||
| <field name="name">Property Type</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,104 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <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> | ||
| <div class="oe_title"> | ||
| <h1> | ||
| <field name="name" string=""/> | ||
| </h1> | ||
| <field name="property_tag_ids" widget="many2many_tags"/> | ||
| </div> | ||
| <group> | ||
| <group string="Pricing & Availability"> | ||
|
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 doesn't look good on the UI. |
||
| <field name="postcode"/> | ||
| <field name="date_availability"/> | ||
| <field name="expected_price"/> | ||
| <field name="selling_price"/> | ||
| <field name="property_type_id"/> | ||
| <field name="total_offers"/> | ||
| <field name="state"/> | ||
| </group> | ||
| <group string="Property Specs"> | ||
|
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. same here. |
||
| <field name="bedrooms"/> | ||
| <field name="living_area" string="Living Area (m²)"/> | ||
| <field name="facades"/> | ||
| <field name="garage"/> | ||
| <field name = "best_price"/> | ||
| <field name = "total_area"/> | ||
| </group> | ||
| </group> | ||
| <notebook> | ||
| <page string="Description" name="description"> | ||
| <field name="description" placeholder="Add property features, neighborhood details, etc."/> | ||
| </page> | ||
|
|
||
| <page string="Garden Details" name="garden_details"> | ||
| <group> | ||
| <field name="garden"/> | ||
| <field name="garden_area" string="Garden Area (m²)" invisible="not garden"/> | ||
| <field name="garden_orientation" invisible="not garden"/> | ||
| </group> | ||
| </page> | ||
|
|
||
| <page string="Other info" name="other_info"> | ||
| <group> | ||
| <field name="buyer" widget="many2one_avatar_user" /> | ||
| <field name="user_id" widget="many2one_avatar_user" /> | ||
| </group> | ||
| </page> | ||
| <page name="Offers"> | ||
| <field name="offer_ids"> | ||
| <list editable="bottom"> | ||
| <field name="price"/> | ||
| <field name="partner_id"/> | ||
| <field name="status"/> | ||
| </list> | ||
| </field> | ||
| </page> | ||
| </notebook> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_search_views" model="ir.ui.view"> | ||
| <field name="name" >estate property search view</field> | ||
| <field name="model">estate.property</field> | ||
| <field name="arch" type="xml"> | ||
| <search string="tests"> | ||
| <field name="expected_price"/> | ||
| <field name="name"/> | ||
| <filter name="expected_price" string="Expected Price" domain="[('expected_price','!=',0)]"/> | ||
| <filter name="date_availability" string="Available" domain="['|',('state','=','new'),('state','=','offer_received') ]"/> | ||
| </search> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_views" model = "ir.ui.view"> | ||
| <field name="name">estate property views</field> | ||
| <field name="model">estate.property</field> | ||
| <field name="arch" type="xml"> | ||
| <list> | ||
| <field name="name" width="14.2%" /> | ||
| <field name="postcode" width="14.2%" /> | ||
| <field name="bedrooms" width="14.2%" /> | ||
| <field name="living_area" width="14.2%" /> | ||
| <field name="expected_price" width="14.2%" /> | ||
| <field name="selling_price" width="14.2%" /> | ||
| <field name="date_availability" string="Available From" width="14.2%"/> | ||
| <field name="property_type_id" string="Property Type" width="14.2%"/> | ||
| <field name="total_offers" string="Total Offers" width="14.2%"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- actions --> | ||
| <record id="estate_property_action" model="ir.actions.act_window"> | ||
| <field name="name">Property</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.
unneccary changes.