Skip to content

Commit bed7d1f

Browse files
committed
[IMP] estate: UI Enhancements, Ordering, Filters, and Constraints
. Enhanced UI with inline list views, status bar widget, color picker for tags, and visual decorations. . Improved form behavior by hiding garden fields conditionally and making availability date optional and hidden by default. . Controlled editing by preventing direct modification of property types from property forms. . Enabled manual ordering using sequence fields and set default/custom ordering across models. . Restricted actions such as offer submission based on property state and adjusted button visibility accordingly. . Refined views and filters with editable list views, default filter for available properties, improved living area search, and stat buttons with filtered results.
1 parent 1d2d753 commit bed7d1f

10 files changed

+141
-66
lines changed

estate/__manifest__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
"data": [
77
"security/ir.model.access.csv",
88
"views/estate_property_views.xml",
9+
"views/estate_property_offer_views.xml",
910
"views/estate_property_type_views.xml",
1011
"views/estate_property_tag_views.xml",
11-
"views/estate_property_offer_views.xml",
1212
"views/estate_menus.xml",
1313
],
14-
"license": "LGPL-3"
14+
"license": "LGPL-3",
1515
}

estate/models/estate_property.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ class EstateModel(models.Model):
1313
description = fields.Text()
1414
postcode = fields.Char()
1515
date_availability = fields.Date(
16-
copy=False, default=fields.Date.today() + timedelta(days=90)
16+
copy=False,
17+
default=fields.Date.today() + timedelta(days=90),
1718
)
1819
active = fields.Boolean(default=True)
1920
expected_price = fields.Float(required=True)
@@ -25,7 +26,7 @@ class EstateModel(models.Model):
2526
garden = fields.Boolean()
2627
garden_area = fields.Integer()
2728
state = fields.Selection(
28-
string="state",
29+
string="State",
2930
default="new",
3031
required=True,
3132
copy=False,
@@ -53,7 +54,7 @@ class EstateModel(models.Model):
5354
tag_ids = fields.Many2many("estate.property.tag")
5455
offer_ids = fields.One2many("estate.property.offer", inverse_name="property_id")
5556
total_area = fields.Float(compute="_compute_total_area", store=True)
56-
best_price = fields.Float(compute="_compute_best_price", store=True)
57+
best_price = fields.Float(compute="_compute_best_price", store=True, default=0.0)
5758

5859
_sql_constraints = [
5960
(
@@ -93,7 +94,13 @@ def _compute_total_area(self):
9394
@api.depends("offer_ids.price")
9495
def _compute_best_price(self):
9596
for record in self:
96-
record.best_price = max(record.offer_ids.mapped("price"), default=0.0)
97+
self.write(
98+
{
99+
"best_price": max(record.offer_ids.mapped("price"), default=0.0),
100+
}
101+
)
102+
if record.best_price > 0.0:
103+
record.state = "offer_received"
97104

98105
@api.onchange("garden")
99106
def _set_garden_default_values(self):
@@ -103,15 +110,14 @@ def _set_garden_default_values(self):
103110
self.write({"garden_area": 0, "garden_orientation": ""})
104111

105112
def action_property_sold(self):
106-
if self.state in ["sold", "cancelled"]:
107-
raise UserError(f"Property is already {self.state}")
108113
if float_is_zero(self.selling_price, precision_rounding=0.01):
109114
raise UserError(
110115
"Atleast one offer must be accepted before selling the property"
111116
)
112117
self.state = "sold"
113118

114119
def action_property_cancelled(self):
115-
if self.state in ["sold", "cancelled"]:
116-
raise UserError(f"Property is already {self.state}")
117120
self.state = "cancelled"
121+
for offer in self.offer_ids:
122+
if not offer.status:
123+
offer.status = "refused"

estate/models/estate_property_offer.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,18 @@ class EstateOfferModel(models.Model):
1414
)
1515
partner_id = fields.Many2one("res.partner", required=True)
1616
property_id = fields.Many2one("estate.property", required=True)
17+
property_type_id = fields.Many2one(
18+
"estate.property.type", related="property_id.property_type_id", required=True
19+
)
1720
validity = fields.Integer(
1821
default=7,
1922
help="offer validity period in days; the offer will be automatically refused when this expires.",
2023
)
21-
date_deadline = fields.Date(default=fields.Date.today() + timedelta(days=7))
24+
date_deadline = fields.Date(
25+
compute="_compute_date_deadline",
26+
inverse="_inverse_date_deadline",
27+
default=fields.Date.today() + timedelta(days=7),
28+
)
2229

2330
_sql_constraints = [
2431
(
@@ -44,22 +51,20 @@ def _inverse_date_deadline(self):
4451
)
4552

4653
def action_offer_confirm(self):
47-
for record in self:
48-
if record.status in ["accepted", "refused"]:
49-
raise UserError(f"Offer is already {record.status}")
50-
# breakpoint()
51-
for offer in record.property_id.offer_ids:
52-
if offer.id == record.id:
53-
record.status = "accepted"
54-
record.property_id.write(
55-
{
56-
"state": "offer_accepted",
57-
"buyer": record.partner_id,
58-
"selling_price": record.price,
59-
}
60-
)
61-
else:
62-
offer.status = "refused"
54+
if self.status in ["accepted", "refused"]:
55+
raise UserError(f"Offer is already {self.status}")
56+
for offer in self.property_id.offer_ids:
57+
if offer.id == self.id:
58+
self.status = "accepted"
59+
self.property_id.write(
60+
{
61+
"state": "offer_accepted",
62+
"buyer": self.partner_id,
63+
"selling_price": self.price,
64+
}
65+
)
66+
else:
67+
offer.status = "refused"
6368

6469
def action_offer_cancel(self):
6570
for record in self:

estate/models/estate_property_tag.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ class EstateTagModel(models.Model):
77
_order = "name"
88

99
name = fields.Char(required=True)
10+
color = fields.Integer(string="Color", default=0)
1011

1112
_sql_constraints = [
1213
("check_property_tag_name", "UNIQUE(name)", "Property Tag Name must be unique")

estate/models/estate_property_type.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from odoo import fields, models
1+
from odoo import api, fields, models
22

33

44
class EstateTypeModel(models.Model):
@@ -8,7 +8,15 @@ class EstateTypeModel(models.Model):
88

99
name = fields.Char(required=True)
1010
property_ids = fields.One2many("estate.property", "property_type_id")
11-
sequence = fields.Integer("Sequence", default=1, help="Used to change the sequence of Property Types")
11+
sequence = fields.Integer(
12+
"Sequence", default=1, help="Used to change the sequence of Property Types"
13+
)
14+
offer_ids = fields.One2many(
15+
"estate.property.offer", inverse_name="property_type_id"
16+
)
17+
offer_count = fields.Integer(
18+
default=0, readonly=True, compute="_compute_offers_by_type"
19+
)
1220

1321
_sql_constraints = [
1422
(
@@ -17,3 +25,7 @@ class EstateTypeModel(models.Model):
1725
"Property Type Name must be unique",
1826
)
1927
]
28+
29+
@api.depends("offer_ids")
30+
def _compute_offers_by_type(self):
31+
self.offer_count = len(self.offer_ids)

estate/views/estate_menus.xml

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

33
<odoo>
4+
45
<menuitem id="estate_menu_root" name="Real Estate">
6+
57
<menuitem id="estate_advertisements_menu" name="Advertisements">
68
<menuitem id="estate_property_adv_menu_action" action="action_estate_property" name="Property" />
79
</menuitem>
10+
811
<menuitem id="estate_settings_menu" name="Settings">
912
<menuitem id="estate_property_menu_action" action="action_estate_property" name="Property" />
1013
<menuitem id="estate_property_type_menu_action" action="action_estate_property_type" name="Property Types" />
1114
<menuitem id="estate_property_tag_menu_action" action="action_estate_property_tag" name="Property Tags" />
1215
</menuitem>
16+
1317
</menuitem>
18+
1419
</odoo>
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,34 @@
11
<?xml version="1.0"?>
22

33
<odoo>
4-
<record id="action_estate_property_offer" model="ir.actions.act_window">
4+
5+
<record id="estate_property_offer_action" model="ir.actions.act_window">
56
<field name="name">Property Offers</field>
67
<field name="res_model">estate.property.offer</field>
7-
<field name="view_mode">list,form</field>
8+
<field name="view_mode">list</field>
9+
<field name="domain">[('property_type_id', '=', active_id)]</field>
810
<field name="help" type="html">
911
<p class="o_view_nocontent_smiling_face">
1012
Create the first property Type
1113
</p>
1214
</field>
1315
</record>
16+
1417
<record id="list_view_estate_property_offer" model="ir.ui.view">
1518
<field name="name">Estate Properties Offer list</field>
1619
<field name="model">estate.property.offer</field>
1720
<field name="arch" type="xml">
18-
<list>
21+
<list editable="bottom" decoration-danger="status == 'refused'" decoration-success="status == 'accepted'">
1922
<field name="price" string="Price" />
2023
<field name="partner_id" string="Partner" />
24+
<field name="property_type_id" string="Type" />
2125
<field name="validity" string="Validity" />
2226
<field name="date_deadline" string="Deadline" />
23-
<button name="action_offer_confirm" type="object" icon="fa-check" invisible="status == 'refused'" />
24-
<button name="action_offer_cancel" type="object" icon="fa-times" invisible="status == 'refused'" />
25-
<field name="status" string="Status" />
27+
<button name="action_offer_confirm" type="object" icon="fa-check" invisible="status == 'refused' or status == 'accepted'" />
28+
<button name="action_offer_cancel" type="object" icon="fa-times" invisible="status in ['refused', 'accepted']" />
29+
<field name="status" string="Status" readonly="True"/>
2630
</list>
2731
</field>
2832
</record>
33+
2934
</odoo>
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
11
<?xml version="1.0"?>
22

33
<odoo>
4+
45
<record id="action_estate_property_tag" model="ir.actions.act_window">
56
<field name="name">Property Tag</field>
67
<field name="res_model">estate.property.tag</field>
7-
<field name="view_mode">list,form</field>
8+
<field name="view_mode">list</field>
89
<field name="help" type="html">
910
<p class="o_view_nocontent_smiling_face">
1011
Create the first property Tag
1112
</p>
1213
</field>
1314
</record>
15+
16+
<record id="list_estate_property_tag" model="ir.ui.view">
17+
<field name="name">Property Tag List</field>
18+
<field name="model">estate.property.tag</field>
19+
<field name="arch" type="xml">
20+
<list editable="bottom">
21+
<field name="name" string="Tag Name"/>
22+
<field name="color" string="Color" options="{'color_field' : 'color'}"/>
23+
</list>
24+
</field>
25+
</record>
26+
1427
</odoo>

estate/views/estate_property_type_views.xml

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,6 @@
22

33
<odoo>
44

5-
<record id="estate_property_type_view_list" model="ir.ui.view">
6-
<field name="name">estate.property.type.view.list</field>
7-
<field name="model">estate.property.type</field>
8-
<field name="arch" type="xml">
9-
<list name="estate_property_type_list" string="Estate Property Type">
10-
<field name="sequence" widget="handle" />
11-
<field name="name"></field>
12-
</list>
13-
</field>
14-
</record>
155
<record id="action_estate_property_type" model="ir.actions.act_window">
166
<field name="name">Property Types</field>
177
<field name="res_model">estate.property.type</field>
@@ -22,12 +12,35 @@
2212
</p>
2313
</field>
2414
</record>
15+
16+
<record id="estate_property_type_view_list" model="ir.ui.view">
17+
<field name="name">Estate Property Type List</field>
18+
<field name="model">estate.property.type</field>
19+
<field name="arch" type="xml">
20+
<list string="Estate Property Type">
21+
<field name="sequence" widget="handle" />
22+
<field name="name" string="Property Type"/>
23+
</list>
24+
</field>
25+
</record>
26+
2527
<record id="action_estate_property_type_form" model="ir.ui.view">
2628
<field name="name">Properties by Types</field>
2729
<field name="model">estate.property.type</field>
2830
<field name="arch" type="xml">
2931
<form>
3032
<sheet>
33+
<div class="oe_button_box" name='button_box'>
34+
<button class="oe_stat_button" type='action'
35+
name='estate.estate_property_offer_action'
36+
icon="fa-th-list"
37+
invisible="offer_count == 0">
38+
<field name='offer_count' string='Offers' widget='statinfo'/>
39+
</button>
40+
</div>
41+
<h1>
42+
<field name="name" string="Type Name" placeholder="Property Type Name" />
43+
</h1>
3144
<notebook>
3245
<page name="properties" string="Properties">
3346
<field name="property_ids">
@@ -43,4 +56,5 @@
4356
</form>
4457
</field>
4558
</record>
59+
4660
</odoo>

0 commit comments

Comments
 (0)