Skip to content
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

[ADD] estate: Manage Your Properties, Maximize Your Returns #135

Draft
wants to merge 2 commits into
base: 17.0
Choose a base branch
from
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
3 changes: 3 additions & 0 deletions estate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import models
from . import demo
from . import data
30 changes: 30 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "Real_Estate",
"depends": ["base"],
"Description": "Estate Module by aneg",
"category": "Real Estate/Brokerage",
"license": "LGPL-3",
"summary": "Real_Estate module for different purpose",
"author": "aneg_odoo",
"version": "0.1",
"application": True,
"installable": True,
"data": [
"views/estate_property_views.xml",
"views/estate_property_offer.xml",
"views/estate_property_type.xml",
"views/estate_property_tag.xml",
"views/estate_menus.xml",
"views/res_users_view.xml",
"data/estate.property.type.csv",
"report/subtemplate_offers_table.xml",
"report/estate_property_templates.xml",
"report/estate_property_reports.xml",
"security/security.xml",
"security/ir.model.access.csv",
],
"demo": [
"demo/estate_demo.xml",
"demo/estate_offer_demo.xml",
],
}
5 changes: 5 additions & 0 deletions estate/data/estate.property.type.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id,name
id4,Residential
id1,Commercial
id2,Industrial
id3,Land
55 changes: 55 additions & 0 deletions estate/demo/estate_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<odoo>
<record id="estate_demo_data3" model="estate.property">
<field name="property_type" ref="id4" />
<field name="name">Big Villa</field>
<field name="status">new</field>
<field name="myestate_model">A nice and big villa</field>
<field name="postcode">12345</field>
<field name="date_availability">2020-02-02</field>
<field name="expected_price">1600</field>
<field name="selling_price">144000</field>
<field name="bedrooms">6</field>
<field name="living_area">100</field>
<field name="facades">4</field>
<field name="garage">True</field>
<field name="garden">True</field>
<field name="garden_area">100000</field>
<field name="garden_orientation">south</field>
</record>
<record id="estate_demo_data5" model="estate.property">
<field name="property_type" ref="id4" />
<field name="name">Trailor Home</field>
<field name="status">cancelled</field>
<field name="myestate_model">Home in a trailer park</field>
<field name="postcode">54321</field>
<field name="date_availability">1970-01-01</field>
<field name="expected_price">100000</field>
<field name="selling_price">120000</field>
<field name="bedrooms">1</field>
<field name="living_area">10</field>
<field name="facades">4</field>
<field name="garage">False</field>
</record>
<record id="estate_demo_data4" model="estate.property">
<field name="property_type" ref="id4" />
<field name="name">Trailor Home3</field>
<field name="status">cancelled</field>
<field name="myestate_model">Home in a trailer park</field>
<field name="postcode">54321</field>
<field name="date_availability">1970-01-01</field>
<field name="expected_price">100000</field>
<field name="selling_price">120000</field>
<field name="bedrooms">1</field>
<field name="living_area">10</field>
<field name="facades">4</field>
<field name="garage">False</field>
<field name="offer_id"
eval="[
Command.create({
'partner_id': ref('base.res_partner_12'),
'price': '15000002',
'validity':14,
}),
]" />
</record>
</odoo>

Choose a reason for hiding this comment

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

Leave a blank line at the EOF
Make sure to check in other files also.

27 changes: 27 additions & 0 deletions estate/demo/estate_offer_demo.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="estate_property_offer_demo_1" model="estate.property.offer">
<field name="partner_id" ref="base.res_partner_12" />
<field name="property_id" ref="estate.estate_demo_data3" />
<field name="price">10000</field>
<field name="validity">14</field>
<field name="date_deadline" eval="(datetime.now()+timedelta(days=14))" />
</record>
<record id="estate_property_offer_demo_2" model="estate.property.offer">
<field name="partner_id" ref="base.res_partner_12" />
<field name="property_id" ref="estate.estate_demo_data3" />
<field name="price">15000000</field>
<field name="validity">14</field>
<field name="date_deadline" eval="(datetime.now()+timedelta(days=14))" />
</record>
<record id="estate_property_offer_demo_3" model="estate.property.offer">
<field name="partner_id" ref="base.res_partner_2" />
<field name="property_id" ref="estate.estate_demo_data3" />
<field name="price">15000001</field>
<field name="validity">14</field>
<field name="date_deadline" eval="(datetime.now()+timedelta(days=14))" />
</record>
<function model="estate.property.offer" name="action_confirm">
<value eval="[ref('estate_property_offer_demo_3')]" />
</function>
</odoo>
5 changes: 5 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import estate_property
from . import estate_property_type
from . import estate_property_tag
from . import estate_property_offer
from . import res_users
104 changes: 104 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
from datetime import datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
from odoo.exceptions import UserError, ValidationError


class estateproperty(models.Model):
_name = "estate.property"
_description = "estate_model"
_order = "id desc"
name = fields.Char("Title", default="Unknown")
myestate_model = fields.Text("Description")
postcode = fields.Char("Postcode")
date_availability = fields.Date(
"Available From", copy=False, default=datetime.now() + relativedelta(months=3)
)
expected_price = fields.Float("Expected Price", default=0)
selling_price = fields.Float("Selling Price", copy=False)
bedrooms = fields.Integer("Bedrooms", default=3)
living_area = fields.Integer("Living Area (sqm)", default=2)
facades = fields.Integer("Facades", default=2)
garage = fields.Boolean("Garage")
garden = fields.Boolean("Garden")
garden_area = fields.Integer("Garden Area (sqm)", default=0)
garden_orientation = fields.Selection(
[("north", "north"), ("south", "south"), ("east", "east"), ("west", "west")]
)
active = fields.Boolean("Active", default=True)
status = fields.Selection(
[
("new", "New"),
("offer received", "Offer Received"),
("offer accepted", "Offer Accepted"),
("sold", "sold"),
("cancelled", "Cancelled"),
],
default="new",
copy=False,
)
last_seen = fields.Datetime("Last Seen", default=fields.Datetime.now)
property_type = fields.Many2one("estate.property.type", string="Property Type")
sale_id = fields.Many2one(
"res.users", string="Salesman", default=lambda self: self.env.user
)
Buyer_id = fields.Many2one("res.users", string="Buyer", copy=False)
property_tag = fields.Many2many("estate.property.tag", string="Property Tag")
offer_id = fields.One2many("estate.property.offer", "property_id", string="Offers")
total = fields.Float(compute="_compute_total", string="Total Area (sqm)")
best_price = fields.Float(compute="_compute_price", string="Best offer")
_sql_constraints = [
(
"check_sellingprice_expectedprice_not_negative",
"CHECK(selling_price >= 0.0 and expected_price >= 0.0)",
"The selling price and expected_price should be greater than 0.",
),
]

@api.depends("living_area", "garden_area")
def _compute_total(self):
for ele in self:
ele.total = ele.living_area + ele.garden_area

@api.depends("offer_id.price")
def _compute_price(self):
for ele in self:
ele.best_price = max(ele.mapped("offer_id.price"), default=0)

@api.onchange("garden")
def _onchange_garden(self):
if self.garden:
self.garden_area = 100
self.garden_orientation = "north"
else:
self.garden_area = 0
self.garden_orientation = None

def sold_button(self):
if self.status == "cancelled":
raise UserError("Cancelled Properties cannot be sold")
else:
self.status = "sold"

def cancel_button(self):
if self.status == "sold":
raise UserError("sold Properties cannot be cancelled")
else:
self.status = "cancelled"

@api.constrains("selling_price", "expected_price")
def validate_selling_price(self):
for record in self:
if (
record.selling_price < (0.9 * record.expected_price)
and record.selling_price != 0.0
):
raise ValidationError(
"the selling price cannot be lower than 90% of the expected price."
)

@api.ondelete(at_uninstall=False)
def _prevent_property_deletion(self):
for record in self:
if record.status not in ("new", "Cancelled"):
raise UserError("Only new and cancelled properties can be deleted")
56 changes: 56 additions & 0 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from datetime import date, timedelta
from odoo import api, fields, models
from odoo.exceptions import ValidationError


class EstatePropertyOffer(models.Model):
_name = "estate.property.offer"
_description = "Estate Property Offer"
_order = "price desc"
price = fields.Float("Price")
status = fields.Selection(
[("Accepted", "Accepted"), ("Refused", "Refused")], readonly=True
)
partner_id = fields.Many2one("res.partner")
property_id = fields.Many2one("estate.property")
property_type_id = fields.Many2one(related="property_id.property_type", store=True)
validity = fields.Integer(string="Validity(days)", default=7)
date_deadline = fields.Date(
string="Deadline", compute="_compute_deadline", inverse="_inverse_deadline"
)
_sql_constraints = [
(
"check_offerprice_not_negative",
"CHECK(price >= 0.0)",
"The offer price should be greater than 0",
),
]

@api.depends("validity")
def _compute_deadline(self):
for ele in self:
if not ele.create_date:
ele.create_date = date.today()
ele.date_deadline = ele.create_date + timedelta(days=ele.validity)

def _inverse_deadline(self):
for ele in self:
ele.validity = abs((ele.date_deadline - ele.create_date.date()).days)

def action_confirm(self):
for record in self:
record.status = "Accepted"
record.property_id.selling_price = record.price

def action_cancel(self):
for record in self:
record.status = "Refused"

@api.model
def create(self, vals):
record = super().create(vals)
if record.property_id:
record.property_id.status = "offer received"
if record.price < record.property_id.best_price:
raise ValidationError("the offer must be higher than the best price")
return record
12 changes: 12 additions & 0 deletions estate/models/estate_property_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from odoo import fields, models


class EstatePropertyTag(models.Model):
_name = "estate.property.tag"
_description = "EstatePropertyTag"
_order = "name"
name = fields.Char(string="tag", required=True)
_sql_constraints = [
("uniq_propertytag", "unique(name)", "A property tag name must be unique"),
]
color = fields.Integer("color index")
24 changes: 24 additions & 0 deletions estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from odoo import api, fields, models


class EstateProperty(models.Model):
_name = "estate.property.type"
_description = "EstatePropertyType"
_order = "name"
name = fields.Char("Property Types", required=True)
_sql_constraints = [
("uniq_propertytype", "unique(name)", "A property type name must be unique"),
]
property_ids = fields.One2many("estate.property", "property_type")
offer_ids = fields.One2many(
comodel_name="estate.property.offer", inverse_name="property_type_id"
)
offer_count = fields.Integer(compute="_num_of_offers", string="Offer Count")
sequence = fields.Integer(
"Sequence", default=1, help="To manually reorder property types"
)
api.depends("offer_id")

def _num_of_offers(self):
for record in self:
record.offer_count = len(record.offer_ids)
11 changes: 11 additions & 0 deletions estate/models/res_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from datetime import datetime
from odoo import fields, models


class Resusers(models.Model):
_inherit = "res.users"
property_ids = fields.One2many(
"estate.property",
"sale_id",
domain=lambda self: [("date_availability", "<=", datetime.now())],
)
26 changes: 26 additions & 0 deletions estate/report/estate_property_reports.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<odoo>
<data>
<record id="report_estate_property_offers" model="ir.actions.report">
<field name="name">Property Offers</field>
<field name="model">estate.property</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">estate.report_property_offers</field>
<field name="report_file">estate.report_property_offers</field>
<field name="print_report_name">'Estate Property - %s' % (object.name or
'Attendee').replace('/','')</field>
<field name="binding_model_id" ref="model_estate_property" />
<field name="binding_type">report</field>
</record>
<record id="report_user_properties" model="ir.actions.report">
<field name="name">User Properties</field>
<field name="model">res.users</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">estate.report_user_properties3</field>
<field name="report_file">estate.report_user_properties3</field>
<field name="print_report_name">'Estate Users - %s' % (object.name or
'Attendee').replace('/','')</field>
<field name="binding_model_id" ref="base.model_res_users" />
<field name="binding_type">report</field>
</record>
</data>
</odoo>
Loading