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
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
16 changes: 16 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
'name': 'Estate',
'version': '0.1',
'summary': 'This is the Real Estate Advertisement module',
'description': 'This is the Real Estate Advertisement module.',
'data': [
'security/ir.model.access.csv',
'views/estate_property_offer_views.xml',
'views/estate_property_views.xml',
'views/estate_property_type_views.xml',
'views/estate_property_tag_views.xml',
'views/estate_menus.xml'
],
'author': 'Milan Bavishi',
'license': 'LGPL-3'
}
4 changes: 4 additions & 0 deletions estate/models/__init__.py
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
121 changes: 121 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
from dateutil.relativedelta import relativedelta

from odoo import _, api, fields, models
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_compare, float_is_zero


class EstateProperty(models.Model):
_name = "estate.property"
_description = "This is the table of real estate property data"
_order = "id desc"

name = fields.Char(required=True)
description = fields.Text()
postcode = fields.Char()
date_availability = fields.Date(
copy=False, default=lambda self: fields.Date.today() + relativedelta(month=3)
)
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(
string="Garden Orientation",
selection=[
("north", "North"),
("south", "South"),
("east", "East"),
("west", "West"),
],
)
state = fields.Selection(
string="State",
default="new",
required=True,
copy=False,
selection=[
("new", "New"),
("offer received", "Offer Received"),
("offer accepted", "Offer accepted"),
("sold", "Sold"),
("cancelled", "Cancelled"),
],
)
active = fields.Boolean()
property_type_id = fields.Many2one("estate.property.type", string="Property Type")
customer = fields.Many2one(
"res.partner", string="Customer", copy=False, readonly=True
)
salesperson = fields.Many2one(
"res.users",
string="Salesperson",
readonly=True,
default=lambda self: self.env.user,
)
tag_ids = fields.Many2many("estate.property.tag", string="Tag type")
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
total_area = fields.Integer(compute="_compute_total_area")
best_price = fields.Float(compute="_compute_best_price")

_check_expected_price = models.Constraint(
"check(expected_price > 0)",
"The Expected Price must be positive",
)

@api.depends("living_area", "garden_area")
def _compute_total_area(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:
prices = record.offer_ids.mapped("price")
record.best_price = max(prices) if prices else 0.0

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

def action_cancel(self):
for record in self:
if record.state == 'sold':
raise UserError(_("You cannot cannoy cancel the property that already cancelled"))
self.write({"state": "cancelled"})

def action_sold(self):
if self.filtered(lambda record: record.state == "cancelled"):
raise UserError(
_("You cannot Sold the property offer that already Cancelled")
)
if not self.customer:
raise UserError(
_("You can not sold the property that has no customer")
)
self.write({"state": "sold"})

@api.constrains("selling_price", "expected_price")
def _check_selling_price(self):
for record in self:
if float_is_zero(record.selling_price, precision_digits=2):
continue

min_price = record.expected_price * 0.9
if float_compare(record.selling_price, min_price, precision_digits=2) < 0:
raise ValidationError(_("The Selling price cannot be lower than 90% of the expected price."))

@api.constrains("offer_ids")
def _check_offer_vaild(self):
for record in self:
if record.state == "sold":
UserError(_("already offer is accept"))
60 changes: 60 additions & 0 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from dateutil.relativedelta import relativedelta

from odoo import _, api, fields, models
from odoo.exceptions import UserError


class EstatePropertyOffer(models.Model):
_name = "estate.property.offer"
_description = "This is the table of offer that is received for property"
_order = "price desc"

price = fields.Float('price')
status = fields.Selection(
string="Status",
selection=[
('accepted', 'Accepted'),
('refused', 'Refused')
],
copy=False
)
partner_id = fields.Many2one('res.partner', required=True)
property_id = fields.Many2one('estate.property', required=True)
validity = fields.Integer(default=7)
date_deadline = fields.Date(compute="_compute_date_deadline", inverse="_inverse_date_deadline", store=True)
property_type_id = fields.Many2one("estate.property.type", related="property_id.property_type_id", store=True)

_check_offer_price = models.Constraint(
"check(price > 0)",
"Offer price must be positive",
)

@api.depends("validity")
def _compute_date_deadline(self):
for record in self:
create = record.create_date or fields.Date.today()
record.date_deadline = (create + relativedelta(days=record.validity))

def _inverse_date_deadline(self):
for record in self:
create = record.create_date or fields.Date.today()
record.validity = (record.date_deadline - fields.Date.today(create)).days

def action_accept_offer(self):
for offer in self:
if offer.property_id.customer:
raise UserError(_("Only one offer can be accepted."))
offer.property_id.customer = offer.partner_id
offer.property_id.selling_price = offer.price
offer.property_id.state = "sold"
offer.status = "accepted"
other_offer = offer.property_id.offer_ids.filtered(
lambda s: s.status != offer.status
)
other_offer.status = "refused"

def action_refuse_offer(self):
for offer in self:
offer.status = "refused"

return True
15 changes: 15 additions & 0 deletions estate/models/estate_property_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from odoo import fields, models


class EstatePropertyTags(models.Model):
_name = "estate.property.tag"
_description = "This table contain the types of tags"
_order = "name asc"

name = fields.Char(required=True)
color = fields.Integer(string="color")

_name_uniq = models.Constraint(
"unique(name)",
"Tag name is must be Unique",
)
22 changes: 22 additions & 0 deletions estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from odoo import api, fields, models


class EstatePropertyTypes(models.Model):
_name = "estate.property.type"
_description = "This is table contain the types of property"
_order = "name asc"

name = fields.Char(required=True)
property_ids = fields.One2many("estate.property", "property_type_id")
offer_ids = fields.One2many("estate.property.offer", "property_type_id")
offer_count = fields.Integer(compute="_compute_offer_count")

_name_uniq = models.Constraint(
"unique(name)",
"Property Types must be Unique",
)

@api.depends("offer_ids")
def _compute_offer_count(self):
for record in self:
record.offer_count = len(record.offer_ids)
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,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
35 changes: 35 additions & 0 deletions estate/views/estate_menus.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<odoo>
<data>
<menuitem
id="estate_property_menu"
name="Estate Property"/>
<menuitem
id="estate_property_menu_advertisements"
name="Advertisements"
parent="estate_property_menu"
sequence="5"/>
<menuitem
id="estate_property_menu_properties"
name="Properties"
parent="estate_property_menu_advertisements"
action="estate_property_action"
sequence="5"/>
<menuitem
id="estate_property_menu_settings"
name="Settings"
parent="estate_property_menu"
sequence="10"/>
<menuitem
id="estate_property_menu_types"
name="Property Types"
parent="estate_property_menu_settings"
action="estate_property_type_action"
sequence="5"/>
<menuitem
id="estate_property_menu_tags"
name="Property Tags"
parent="estate_property_menu_settings"
action="estate_property_tag_action"
sequence="10"/>
</data>
</odoo>
54 changes: 54 additions & 0 deletions estate/views/estate_property_offer_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="estate_property_offer_action" model="ir.actions.act_window">
<field name="name">Property Offer</field>
<field name="res_model">estate.property.offer</field>
<field name="view_mode">list,form</field>
<field name="domain">[("property_type_id", "=", active_id)]</field>
</record>

<record id="estate_property_offer_view_form" model="ir.ui.view">
<field name="name">estate.property.offer.view.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="validity"/>
<field name="date_deadline"/>
</group>
</sheet>
</form>
</field>
</record>

<record id="estate_property_offer_view_list" model="ir.ui.view">
<field name="name">estate_property_offer.view.list</field>
<field name="model">estate.property.offer</field>
<field name="arch" type="xml">
<list editable="bottom" decoration-danger="status == 'refused'"
decoration-success="status == 'accepted'">
<field name="price"/>
<field name="partner_id"/>
<field name="validity"/>
<button
name="action_accept_offer"
type="object"
string="Accpet"
icon="fa-check"
invisible="status in ('accepted', 'refused')"/>
<button
name="action_refuse_offer"
type="object"
string="refuse"
icon="fa-close"
invisible="status in ('accepted', 'refused')"/>
<field name="date_deadline"/>
<field name="status"/>
</list>
</field>
</record>

</odoo>
34 changes: 34 additions & 0 deletions estate/views/estate_property_tag_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="estate_property_tag_action" model="ir.actions.act_window">
<field name="name">Property Tag</field>
<field name="res_model">estate.property.tag</field>
<field name="view_mode">list,form</field>
</record>

<record id="estate_property_tag_view_form" model="ir.ui.view">
<field name="name">estate.property.tag.view.form</field>
<field name="model">estate.property.tag</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<h1>
<field name="name" placeholder="Add Tag"/>
</h1>
</group>
</sheet>
</form>
</field>
</record>

<record id="estate_property_type_view_list" model="ir.ui.view">
<field name="name">estate.property.tag.view.list</field>
<field name="model">estate.property.tag</field>
<field name="arch" type="xml">
<list editable="bottom">
<field name="name" string="Tags"/>
</list>
</field>
</record>
</odoo>
Loading