Skip to content

Commit 9821fb8

Browse files
committed
[IMP] estate: complete ch-10 up to Attributes and options
implement statusbar widget, in List order model ordering & manual ordering and in form Attributes and options
1 parent 363b4bf commit 9821fb8

12 files changed

+354
-48
lines changed

estate/__manifest__.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,21 @@
11
{
22
'name': "estate",
3-
4-
'description': """
5-
A real-estate application"
6-
""",
7-
3+
'description': "A real-estate application",
84
'author': "meet kavathiya",
95
'website': "https://www.odoo.com/",
10-
'category': 'Real-estate',
11-
'version': '0.1',
6+
'category': "Real-estate",
7+
'version': "0.1",
128
'application': True,
139
'installable': True,
14-
'depends': ['base', 'web'],
15-
16-
'data': ['security/ir.model.access.csv',
17-
'views/estate_property_views.xml',
18-
'views/estate_menus.xml'],
19-
'assets': {
20-
21-
},
22-
'license': 'LGPL-3'
10+
'depends': ['base'],
11+
'data': [
12+
"security/ir.model.access.csv",
13+
"views/estate_property_views.xml",
14+
"views/estate_property_tag_views.xml",
15+
"views/estate_property_type_views.xml",
16+
"views/estate_property_offer_views.xml",
17+
"views/estate_menus.xml",
18+
],
19+
'assets': {},
20+
'license': "LGPL-3",
2321
}

estate/models/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
from . import estate_property
1+
from . import estate_property
2+
from . import estate_property_type
3+
from . import estate_property_tag
4+
from . import estate_property_offer

estate/models/estate_property.py

Lines changed: 93 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
1-
from odoo import fields, models
1+
from odoo import api, fields, models
2+
from odoo.exceptions import UserError, ValidationError
3+
from odoo.tools.float_utils import float_compare
4+
25

36
class EstateProperty(models.Model):
4-
_name = "estate.property"
7+
_name = 'estate.property'
58
_description = "Real-estate property"
9+
_order = 'id desc'
610

711
name = fields.Char(required=True)
812
description = fields.Text()
913
postcode = fields.Char()
10-
date_availability = fields.Date(copy=False, default=fields.Date.add(fields.Date.today(), months=3))
14+
date_availability = fields.Date(
15+
copy=False, default=fields.Date.add(fields.Date.today(), months=3)
16+
)
1117
expected_price = fields.Float(required=True)
12-
selling_price = fields.Float(readonly=True, copy=False)
18+
selling_price = fields.Float(copy=False, readonly=True)
1319
bedrooms = fields.Integer(default=2)
1420
living_area = fields.Integer()
1521
facades = fields.Integer()
@@ -18,11 +24,89 @@ class EstateProperty(models.Model):
1824
garden_area = fields.Integer()
1925
active = fields.Boolean(default=True)
2026
state = fields.Selection(
27+
[
28+
('new', "New"),
29+
('offer_received', "Offer Received"),
30+
('offer_accepted', "Offer Accepted"),
31+
('sold', "Sold"),
32+
('cancelled', "Cancelled"),
33+
],
2134
required=True,
22-
default='New',
23-
copy=False,
24-
selection=[('New', 'new'), ('Offer Received', 'offer received'), ('Offer Accepted', 'offer accepted'), ('Sold', 'sold'), ('Cancelled', 'cancelled')])
35+
default='new',
36+
copy=False,
37+
)
2538
garden_orientation = fields.Selection(
26-
string='Type',
27-
selection=[('North', 'north'), ('South', 'south'), ('East', 'east'), ('West', 'west')])
39+
string="Type",
40+
selection=[
41+
('north', "North"),
42+
('south', "South"),
43+
('east', "East"),
44+
('west', "West"),
45+
],
46+
)
47+
property_type = fields.Many2one('estate.property.type', string="property type")
48+
salesman_id = fields.Many2one(
49+
'res.users', string="Salesman", default=lambda self: self.env.user
50+
)
51+
buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False)
52+
tag_ids = fields.Many2many('estate.property.tag')
53+
offer_ids = fields.One2many('estate.property.offer', 'property_id')
54+
total_area = fields.Float(compute='_compute_total_area', store=True)
55+
best_price = fields.Float(compute='_compute_best_price', store=True)
56+
_chek_expected_price = models.Constraint(
57+
"CHECK(expected_price > 0)", "Expected price of property should be positive"
58+
)
59+
_chek_selling_price = models.Constraint(
60+
"CHECK(selling_price >= 0)", "selling price of property should be positive"
61+
)
62+
63+
@api.depends('living_area', 'garden_area')
64+
def _compute_total_area(self):
65+
for record in self:
66+
record.total_area = record.living_area + record.garden_area
67+
68+
@api.depends('offer_ids.price')
69+
def _compute_best_price(self):
70+
for record in self:
71+
record.best_price = max(record.offer_ids.mapped('price'), default=0.0)
72+
73+
@api.onchange('garden')
74+
def _onchnage_garden(self):
75+
if self.garden:
76+
self.garden_area = 10
77+
self.garden_orientation = 'north'
78+
else:
79+
self.garden_area = 0
80+
self.garden_orientation = False
81+
82+
def action_property_sold(self):
83+
for record in self:
84+
if record.state == 'cancelled':
85+
raise UserError("cancelled property cannot be sold")
86+
else:
87+
record.state = 'sold'
88+
return True
89+
90+
def action_property_cancel(self):
91+
for record in self:
92+
if record.state == 'sold':
93+
raise UserError("sold property cannot be cancelled")
94+
else:
95+
record.state = 'cancelled'
96+
return True
2897

98+
@api.constrains('selling_price')
99+
def _check_selling_price(self):
100+
for record in self:
101+
if (
102+
record.selling_price
103+
and float_compare(
104+
record.selling_price,
105+
record.expected_price * 0.9,
106+
precision_digits=2,
107+
)
108+
== -1
109+
):
110+
raise ValidationError(
111+
"Selling price should not be less than 90% of expected price"
112+
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
from odoo import fields, models, api
2+
from odoo.exceptions import UserError
3+
4+
5+
class EstatePropertyOffer(models.Model):
6+
_name = 'estate.property.offer'
7+
_description = "estate property offers"
8+
_order = 'price desc'
9+
10+
price = fields.Float()
11+
status = fields.Selection(
12+
[('accepted', "Accepted"), ('refused', "Refused")], copy=False
13+
)
14+
partner_id = fields.Many2one('res.partner', required=True)
15+
property_id = fields.Many2one('estate.property', required=True)
16+
validity = fields.Integer(default=7)
17+
date_deadline = fields.Date(
18+
compute='_compute_date_deadline', inverse='_inverse_date_deadline'
19+
)
20+
_chek_offer_price = models.Constraint(
21+
"CHECK(price > 0)", "offer price of property should be positive"
22+
)
23+
24+
@api.depends('validity')
25+
def _compute_date_deadline(self):
26+
for record in self:
27+
record.date_deadline = fields.Date.add(
28+
record.create_date or fields.Date.today(), days=record.validity
29+
)
30+
31+
def _inverse_date_deadline(self):
32+
for record in self:
33+
record.validity = (record.date_deadline - record.create_date.date()).days
34+
35+
def action_accept(self):
36+
for record in self:
37+
if record.property_id.selling_price:
38+
raise UserError("One offer is already Accepted")
39+
else:
40+
record.status = 'accepted'
41+
record.property_id.buyer_id = record.partner_id
42+
record.property_id.selling_price = record.price
43+
record.property_id.state = 'offer_accepted'
44+
return True
45+
46+
def action_refuse(self):
47+
for record in self:
48+
if record.status == 'accepted':
49+
record.property_id.selling_price = False
50+
record.status = 'refused'
51+
return True
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from odoo import fields, models
2+
3+
4+
class EstatePropertyTag(models.Model):
5+
_name = 'estate.property.tag'
6+
_description = "estate property tges"
7+
_order = 'name'
8+
9+
name = fields.Char(required=True)
10+
color = fields.Integer()
11+
_uniq_tag_name = models.Constraint(
12+
"unique(name)",
13+
"A tag already exist, tag should be unique.",
14+
)
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing import Sequence
2+
from odoo import fields, models
3+
4+
5+
class EstatePropertyType(models.Model):
6+
_name = "estate.property.type"
7+
_description = "estate property types"
8+
_order = 'name'
9+
10+
name = fields.Char(required=True)
11+
property_ids = fields.One2many("estate.property", "property_type")
12+
sequence = fields.Integer()
13+
_uniq_tag_name = models.Constraint(
14+
"unique(name)",
15+
"A Property Type already exist, Propert type should be unique.",
16+
)
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,5 @@
11
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
2-
access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1
2+
access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1
3+
access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1
4+
access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1
5+
access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1

estate/views/estate_menus.xml

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<odoo>
33

4-
<menuitem id="estate_menu_root" name="Real estate">
5-
<menuitem id="estate_first_level_menu" name="First Level">
6-
<menuitem id="estate_model_menu_action" action="estate_property_model_action"/>
4+
<menuitem id="estate_menu_root" name="Real estate">
5+
<menuitem id="estate_menu_advertisements" name="Advertisements">
6+
<menuitem id="advertisements_menu_properties" action="estate_property_model_action"/>
7+
</menuitem>
8+
<menuitem id="estate_menu_settings" name="Settings">
9+
<menuitem id="setting_menu_property_types" action="estate_property_type_model_action"/>
10+
<menuitem id="setting_menu_property_tags" action="estate_property_tag_model_action"/>
11+
</menuitem>
712
</menuitem>
8-
</menuitem>
913

10-
</odoo>
14+
</odoo>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<record id="estate_property_offer_view_list" model="ir.ui.view">
4+
<field name="name">estate.property.offer.view.list</field>
5+
<field name="model">estate.property.offer</field>
6+
<field name="arch" type="xml">
7+
<list>
8+
<field name="price"/>
9+
<field name="status"/>
10+
<field name="partner_id"/>
11+
<button name="action_accept" type="object" title="accept" icon="fa-check" invisible='status'/>
12+
<button name="action_refuse" type="object" title="refuse" icon="fa-times" invisible='status'/>
13+
<field name="validity"/>
14+
<field name="date_deadline"/>
15+
</list>
16+
</field>
17+
</record>
18+
19+
<record id="estate_property_offer_view_form" model="ir.ui.view">
20+
<field name="name">estate.property.offer.view.form</field>
21+
<field name="model">estate.property.offer</field>
22+
<field name="arch" type="xml">
23+
<form string="properties">
24+
<sheet>
25+
<group>
26+
<field name="price" />
27+
<field name="status"/>
28+
<field name="partner_id"/>
29+
<field name="validity"/>
30+
<field name="date_deadline"/>
31+
</group>
32+
</sheet>
33+
</form>
34+
</field>
35+
</record>
36+
</odoo>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<odoo>
3+
<record id="estate_property_tag_view_tree" model="ir.ui.view">
4+
<field name="name">estate.property.tag.list</field>
5+
<field name="model">estate.property.tag</field>
6+
<field name="arch" type="xml">
7+
<list string="Tag">
8+
<field name="name"/>
9+
</list>
10+
</field>
11+
</record>
12+
13+
<record id="estate_property_tag_model_action" model="ir.actions.act_window">
14+
<field name="name">Property Tags</field>
15+
<field name="res_model">estate.property.tag</field>
16+
<field name="view_mode">list</field>
17+
</record>
18+
</odoo>

0 commit comments

Comments
 (0)