Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions .idea/dataSources.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions .idea/db-forest-config.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/pyLspTools.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions .idea/tutorials.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions estate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
17 changes: 17 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "estate",
"category": "",
"depends": [
"base",
],
"application": True,
"author": "Ansh Chamriya",

Copy link
Copy Markdown

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.

"license": "LGPL-3",
"data": [
"security/ir.model.access.csv",
"views/estate_property.xml",
"views/estate_property_offers.xml",
"views/estate_property_types.xml",
"views/estate_property_menus.xml",
],
}
6 changes: 6 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from . import (
estate_property,
estate_property_type,
estate_property_tags,
estate_property_offers,
)
90 changes: 90 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from odoo import models, fields, api
from odoo.exceptions import UserError


class EstateProperty(models.Model):
_name = "estate.property"
_description = "Real Estate Property"

name = fields.Char(required=True, default="Unknown")
property_type_id = fields.Many2one("estate.property.type", string="Type")
description = fields.Text()
tag_ids = fields.Many2many("estate.property.tags", string="Tags")
salesman_id = fields.Many2one(
"res.partner", string="Salesman", default=lambda self: self.env.user.id
)
buyer_id = fields.Many2one(
"res.users", string="Buyer", default=lambda self: self.env.user.id, copy=False
)
postcode = fields.Char()
date_availability = fields.Date(copy=False)
expected_price = fields.Float(required=True, default=15.6)
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()
total_area = fields.Float(compute="_compute_total_area")
best_price = fields.Float(compute="_compute_best_price")
garden_orientation = fields.Selection(
[
("north", "North"),
("south", "South"),
("east", "East"),
("west", "West"),
],
string="Garden Orientation",
)
active = fields.Boolean(default=True)
state = fields.Selection(
[
("new", "New"),
("offer_received", "Offer Received"),
("offer_accepted", "Offer Accepted"),
("sold", "Sold"),
("cancelled", "Cancelled"),
],
Comment on lines +41 to +48

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
state = fields.Selection(
[
("new", "New"),
("offer_received", "Offer Received"),
("offer_accepted", "Offer Accepted"),
("sold", "Sold"),
("cancelled", "Cancelled"),
],
state = fields.Selection(
[
('new', "New"),
('offer_received', "Offer Received"),
('offer_accepted', "Offer Accepted"),
('sold', "Sold"),
('cancelled', "Cancelled"),
],

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

required=True,
copy=False,
default="new",
readonly=True,
)
offer_ids = fields.One2many(
"estate.property.offers", "property_id", string="Offers"
)

@api.depends("living_area", "garden_area")
def _compute_total_area(self):
for realEstateProperty in self:

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a for loop here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need it because self is a recordset and it's length is not fixed.

realEstateProperty.total_area = (
realEstateProperty.living_area + realEstateProperty.garden_area
)

@api.depends("offer_ids")
def _compute_best_price(self):
self.best_price = max(self.offer_ids.mapped("price")) if self.offer_ids else 0

@api.onchange("garden")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we pass multiple arguments here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in onchange() decorator we can pass multiple arguments but they must belong to the same object
e.g.
Image

def _onchange_garden(self):
if self.garden:
self.garden_area = 10
self.garden_orientation = "north"
else:
self.garden_area = 0
self.garden_orientation = ""

def set_sold(self):
if self.state == "cancelled":
raise UserError("Cancelled Properties Cannot be Sold")
else:
self.state = "sold"
return True

def set_cancel(self):
if self.state == "sold":
raise UserError("Sold Properties cannot be Cancelled")
else:
self.state = "cancelled"
return True
54 changes: 54 additions & 0 deletions estate/models/estate_property_offers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from datetime import timedelta

from odoo import models, fields, api


class EstatePropertyOffers(models.Model):
_name = "estate.property.offers"
_description = "Property Offers"

price = fields.Float(string="Price")
status = fields.Selection(
Comment on lines +10 to +11

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need to explicitly pass string here if you want to have the string name same as the field name.
You can have a look at the codebase regarding how the string value is calculated if you do not pass explicitly.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

[("accepted", "Accepted"), ("refused", "Refused")],
string="Status",
copy="False",
)
partner_id = fields.Many2one("res.partner", string="Customer", required=True)
property_id = fields.Many2one("estate.property", string="Property", required=True)
validity = fields.Integer(string="Validity", default=7)
date_deadline = fields.Date(
string="Date Deadline",
compute="_compute_date_deadline",
inverse="_inverse_date_deadline",
)

@api.depends("create_date", "validity")
def _compute_date_deadline(self):
for record in self:
if record.create_date:
record.date_deadline = record.create_date.date() + timedelta(
days=record.validity
)
else:
record.date_deadline = fields.Date.today() + timedelta(
days=record.validity
)

def _inverse_date_deadline(self):
for record in self:
if record.create_date and record.date_deadline:
record.validity = (
record.date_deadline - record.create_date.date()
).days

def set_accepted(self):
for record in self:
record.status = "accepted"
record.property_id.selling_price = record.price
record.property_id.buyer_id.name = record.partner_id.name
return True

def set_refused(self):
for record in self:
record.status = "refused"
return True
8 changes: 8 additions & 0 deletions estate/models/estate_property_tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from odoo import models, fields


class EstatePropertyTags(models.Model):
_name = "estate.property.tags"
_description = "Estate Property Tags"

name = fields.Char(string="Name", required=True)
8 changes: 8 additions & 0 deletions estate/models/estate_property_type.py
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 = "Types of estate property"

name = fields.Char(string="Name", required=True)
5 changes: 5 additions & 0 deletions estate/security/ir.model.access.csv
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,estate.property.type,model_estate_property_type,base.group_user,1,1,1,1
access_estate_property_tag,estate.property.tag,model_estate_property_tags,base.group_user,1,1,1,1
access_estate_property_offer,estate.property.offer,model_estate_property_offers,base.group_user,1,1,1,1
Loading