Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
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
9 changes: 7 additions & 2 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
{
"name": "Estate", # The name that will appear in the App list
"version": "16.0.0", # Version
"version": "18.0.1.0.0", # Version
"application": True, # This line says the module is an App, and not a module
"depends": ["base"], # dependencies
"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_menu.xml',
'views/res_users_views.xml'
],
"installable": True,
'license': 'LGPL-3',
Expand Down
Empty file removed estate/models.py
Empty file.
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
92 changes: 92 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
from email.policy import default

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

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

name = fields.Char(required=True)
description = fields.Text()
date_availability = fields.Date(copy=False, default=lambda self: fields.Date.add(fields.date.today(), months=3))
expected_price = fields.Float()
selling_price = fields.Float(readonly=True, copy=False)
bedrooms = fields.Integer(default=2)
garden = fields.Boolean()
garden_orientation = fields.Selection([("north", "North"),("south", "South"), ("east", "East"),("west", "West")])
active= fields.Boolean(default=True)
state = fields.Selection(selection = [("new","New"),("offer_received","Offer Received"),
("offer_accepted","Offer Accepted"),("sold","Sold"),("cancelled","Cancelled")],
default="new",
copy=False,
required=True)
postcode = fields.Char()
facades = fields.Integer()
garage = fields.Boolean()
garden_area = fields.Integer()
living_area = fields.Integer()
property_type_id = fields.Many2one("estate.property.type", string="Property type")
salesperson_id = fields.Many2one("res.users", default=lambda self: self.env.user)
buyer_id = fields.Many2one("res.partner", copy=False)
tag_ids = fields.Many2many("estate.property.tag")
offer_ids = fields.One2many("estate.property.offer", "property_id")
best_price = fields.Float(compute="_compute_best_price")
total_area = fields.Integer(compute="_compute_total_area")

_sql_constraints = [
("check_expected_price", "CHECK(expected_price > 0)",
'The expected price must be strictly positive'),
("check_selling_price", "CHECK(selling_price >= 0)",
'The selling price must be positive'),
]

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

@api.depends('garden_area','living_area')
def _compute_total_area(self):
for property in self:
property.total_area = property.garden_area + property.living_area

@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 = False


def action_cancel_property(self):
for property in self:
property.state = "cancelled"

def action_sell_property(self):
for property in self:
if property.state == "cancelled":
raise UserError(_("Cancelled properties cannot be sold"))
property.state = "sold"


@api.constrains('selling_price','expected_price')
def _check_selling_price(self):
for property in self:
if (not float_is_zero(property.selling_price, precision_rounding = 0.01) and
float_compare(property.selling_price, 0.9 * property.expected_price, precision_rounding=0.01) < 0
):
raise ValidationError(_(''))

@api.ondelete(at_uninstall=False)
def _unlink_if_new_canceled(self):
for property in self:
if property.state not in ("new", "cancelled"):
raise UserError(_("Only new or canceiled property can be deleted"))
44 changes: 44 additions & 0 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from odoo import fields, models, api


class EstatePropertyOffer(models.Model):
_name = "estate.property.offer"
_description = "Estate Property Offer"
_order = "price desc"

price = fields.Float()
status = fields.Selection([("accepted", "Accepted"), ("refused","Refused")], copy=False)
property_id = fields.Many2one("estate.property", required=True)
partner_id = fields.Many2one("res.partner", required=True)
validity = fields.Integer(default = 7)
date_deadline = fields.Date(compute="_compute_deadline", inverse="_inverse_deadline")
property_type_id = fields.Many2one(related="property_id.property_type_id")

_sql_constraints = [
("check_offer_price", "CHECK(price > 0)",
'The offer price must be strictly positive')
]


@api.depends('validity','create_date')
def _compute_deadline(self):
for offer in self:
create_date = offer.create_date or fields.Date.today()
offer.date_deadline = fields.Date.add(create_date, days=offer.validity)


def _inverse_deadline(self):
for offer in self:
offer.validity = (offer.date_deadline - fields.Date.to_date(offer.create_date)).days



def action_accept_offer(self):
self.status = "accepted"
self.property_id.selling_price = self.price
self.property_id.buyer_id = self.partner_id



def action_refuse_offer(self):
self.status = "refused"
17 changes: 17 additions & 0 deletions estate/models/estate_property_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from odoo import fields, models


class EstatePropertyTag(models.Model):
_name = "estate.property.tag"
_description = "Estate Property Tag"
_order = "name desc"


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


_sql_constraints = [
("unique_name", "UNIQUE(name)",
'Tag name should be unique.')
]
23 changes: 23 additions & 0 deletions estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from odoo import fields, models, api


class EstatePropertyType(models.Model):
_name = "estate.property.type"
_description = "Estate Property Type"
_order = "sequence, name desc"


name = fields.Char(required=True)
property_ids = fields.One2many("estate.property","property_type_id")
sequence = fields.Integer('Sequence', default = 1, help="Use to order types")
offer_ids = fields.One2many("estate.property.offer", "property_type_id")
offer_count = fields.Integer(compute="_compute_offer_count")

_sql_constraints = [
('unique_name', 'UNIQUE(name)', 'The Type\'s name must be unique.')
]

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

class ResUsers(models.Model):
_inherit = "res.users"

property_ids = fields.One2many("estate.property","salesperson_id", domain=[("state", "not in", ['sold', 'canceled'])])
6 changes: 6 additions & 0 deletions estate/security/ir.model.access.csv
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
estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1
estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1
estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1
estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1

13 changes: 13 additions & 0 deletions estate/views/estate_menu.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<odoo>
<menuitem id="estate_menu_root" name="Real Estate">
<menuitem id="estate_advertisements_menu" name="Advertisements">
<menuitem id="estate_property_menu_action" name = "Properties" action="estate_property_action"/>
</menuitem>
<menuitem id="estate_settings_menu" name="Settings">
<menuitem id="estate_property_type_menu_action" name = "Property types" action="estate_property_type_action"/>
<menuitem id="estate_property_tag_menu_action" name = "Property tags" action="estate_property_tag_action"/>
</menuitem>

</menuitem>
</odoo>
24 changes: 24 additions & 0 deletions estate/views/estate_property_offer_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@

<odoo>
<record id="estate.property_offer_view_list" model="ir.ui.view">
<field name="name">Offer List</field>
<field name="model">estate.property.offer</field>
<field name="arch" type="xml">
<list string="Properties" editable="top" decoration-success="status == 'accepted'" decoration-danger="status == 'refused'">
<field name="price" string="Price"/>
<field name="partner_id" string="Partner"/>
<field name="validity" string="Validity (days)"/>
<field name="date_deadline" string="Deadline"/>
<button name="accept_offer" string="" type="object" icon="fa-check" invisible="status in ['accepted','refused']"/>
<button name="decline_offer" string="" type="object" icon="oi-close" invisible="status in ['accepted','refused']"/>
<field name="status" string="Status"/>
</list>
</field>
</record>
<record id="estate.property_offer_model_action" model="ir.actions.act_window">
<field name="name">Offer</field>
<field name="res_model">estate.property.offer</field>
<field name="view_mode">list</field>
<field name="domain">[('property_type_id', '=', active_id)]</field>
</record>
</odoo>
8 changes: 8 additions & 0 deletions estate/views/estate_property_tag_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0"?>
<odoo>
<record id="estate_property_tag_action" model="ir.actions.act_window">
<field name="name">Estate property tag action</field>
<field name="res_model">estate.property.tag</field>
<field name="view_mode">list,form</field>
</record>
</odoo>
57 changes: 57 additions & 0 deletions estate/views/estate_property_type_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?xml version="1.0"?>
<odoo>
<record id="estate_property_type_view_list" model="ir.ui.view">
<field name="name">estate.property.type.list</field>
<field name="model">estate.property.type</field>
<field name="arch" type="xml">
<list string="estate type list">
<field name="sequence" widget="handle"/>
<field name="name"/>
</list>
</field>
</record>
<record id="estate_property_type_view_form" model="ir.ui.view">
<field name="name">estate.property.type.form</field>
<field name="model">estate.property.type</field>
<field name="arch" type="xml">
<form string="properties list">
<sheet>
<!--
Copy link
Author

Choose a reason for hiding this comment

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

@jnc-odoo what is wrong with this button ? Thanks

<header>
<button type="action" name="estate.property_offer_model_action" icon="fa-money" class="oe_stat_button">
<field name="offer_count" widget="statinfo" string=""/>
<h5>Offers</h5>
</button>
</header> -->
<group>
<h1>
<field name="name" />
</h1>
</group>
<notebook>
<page>
<field name="property_ids">
<list>
<field name="name"/>
<field name="expected_price"/>
<field name="state"/>
</list>
</field>
</page>

</notebook>
</sheet>
</form>
</field>
</record>





<record id="estate_property_type_action" model="ir.actions.act_window">
<field name="name">Estate property type action</field>
<field name="res_model">estate.property.type</field>
<field name="view_mode">list,form</field>
</record>
</odoo>
Loading