Skip to content

Commit bc6fa2c

Browse files
committed
[IMP] Estate: Improve security, added actions in the properties form, Improve the aesthetics. .
Security: prohibit: duplicate tags and negative prices Actions: added visuals for properties state, linked status of offer to state of properties, added action to accept/refuse offer, added action to sold/cancel properties. Aesthetics : Added color to tags, hidden sold/cancelled/accepted/refused button (properties view), added status as a status bar on top (properties view), added properties (in properties type view)
1 parent c5e1685 commit bc6fa2c

8 files changed

+114
-12
lines changed

estate/models/estate_property.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
from dateutil.relativedelta import relativedelta
2-
from odoo import api, fields, models
2+
from odoo import api, exceptions, fields, models
33

44

55
class Estate(models.Model):
66
_name = 'estate.property'
77
_description = 'It allows to manage your properties'
8+
_order = 'id desc'
89

910
name = fields.Char(required=True, default='Unknown')
1011
property_type_id = fields.Many2one('estate.property.type')
@@ -44,11 +45,26 @@ class Estate(models.Model):
4445
readonly=True,
4546
)
4647

48+
_sql_constraints = [
49+
('expected_price', 'CHECK(expected_price >= 0 )', 'A price should always be possitive'),
50+
('selling_price', 'CHECK(selling_price >= 0 )', 'A price should always be possitive'),
51+
]
52+
4753
@api.depends('living_area', 'garden_area')
4854
def _compute_total_area(self):
4955
for record in self:
5056
record.total_area = record.living_area + record.garden_area
5157

58+
@api.onchange('offer_ids')
59+
def _onchange_status(self):
60+
for record in self:
61+
if record.state not in ['offer accepted', 'sold', 'cancelled']:
62+
all_status = record.offer_ids.mapped('status')
63+
new_state = 'new'
64+
if all_status:
65+
new_state = 'offer received'
66+
record.state = new_state
67+
5268
@api.depends('offer_ids')
5369
def _compute_best_offer(self):
5470
for record in self:
@@ -58,3 +74,23 @@ def _compute_best_offer(self):
5874
else:
5975
record.best_offer = 0
6076

77+
@api.onchange('garden')
78+
def _onchange_garden(self):
79+
if self.garden:
80+
self.garden_area = 10
81+
self.garden_orientation = 'north'
82+
else:
83+
self.garden_area = 0
84+
self.garden_orientation = ''
85+
86+
def action_property_sold(self):
87+
for record in self:
88+
if record.state == 'cancelled':
89+
raise exceptions.UserError('property already cancelled')
90+
record.state = 'sold'
91+
92+
def action_property_cancelled(self):
93+
for record in self:
94+
if record.state == 'sold':
95+
raise exceptions.UserError('property already sold')
96+
record.state = 'cancelled'
Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
11
from dateutil.relativedelta import relativedelta
2-
from odoo import api, fields, models
2+
from odoo import api, exceptions, fields, models
33

44

55
class EstateOffer(models.Model):
66
_name = 'estate.property.offer'
77
_description = 'It allows to create a new property offer'
8+
_order = 'price desc'
89

910
price = fields.Float(required=True)
1011
validity = fields.Integer()
1112
date_deadline = fields.Date(compute='_compute_date_deadline', inverse='_inverse_date')
1213
create_date = fields.Date(default=fields.Date.today(), required=True)
1314
partner_id = fields.Many2one('res.partner', string='Customer')
1415
property_id = fields.Many2one('estate.property', string='Property')
15-
status= fields.Selection(
16+
status = fields.Selection(
1617
string='State',
1718
selection=[
1819
('pending', 'Pending'),
@@ -22,15 +23,39 @@ class EstateOffer(models.Model):
2223
default='pending',
2324
)
2425

26+
_sql_constraints = [('price', 'CHECK(price >= 0 )', 'A price should always be possitive')]
27+
2528
@api.depends('create_date', 'validity')
2629
def _compute_date_deadline(self):
2730
for record in self:
2831
if record.create_date:
2932
record.date_deadline = record.create_date + relativedelta(days=record.validity)
3033
else:
31-
record.date_deadline = fields.Date.today() + relativedelta(days=record.validity)
32-
34+
record.date_deadline = fields.Date.today() + relativedelta(days=record.validity)
3335

3436
def _inverse_date(self):
3537
for record in self:
3638
record.validity = (record.date_deadline - fields.Date.today()).days
39+
40+
def action_accept_offer(self):
41+
for record in self:
42+
if record.property_id.state not in ['sold', 'cancelled']:
43+
for offer in record.property_id.offer_ids:
44+
offer.status = 'refused'
45+
record.status = 'accepted'
46+
record.property_id.selling_price = record.price
47+
record.property_id.state = 'offer accepted'
48+
else:
49+
raise exceptions.UserError('property already cancelled')
50+
return True
51+
52+
def action_refuse_offer(self):
53+
for record in self:
54+
if record.property_id.state not in ['sold', 'cancelled']:
55+
if record.status == 'accepted':
56+
record.property_id.selling_price = 0
57+
record.property_id.state = 'offer received'
58+
else:
59+
raise exceptions.UserError('property already sold or cancelled')
60+
record.status = 'refused'
61+
return True

estate/models/estate_property_tag.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,9 @@
44
class EstateTags(models.Model):
55
_name = 'estate.property.tag'
66
_description = 'It allows to create a new property tag'
7+
_order = 'name desc'
78

89
name = fields.Char(required=True)
10+
color = fields.Integer(default=0)
11+
12+
_sql_constraints = [('unique_tag_by_estate_property', 'UNIQUE(name)', 'Only one name by tag')]

estate/models/estate_property_type.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,8 @@
44
class EstateType(models.Model):
55
_name = 'estate.property.type'
66
_description = 'It allows to create a new property type'
7+
_order = 'sequence desc'
78

89
name = fields.Char(required=True)
10+
sequence = fields.Integer('Sequence', default=1, help='Used to order properties types. Lower is better.')
11+
properties_ids = fields.One2many('estate.property', 'property_type_id')

estate/view/estate_property_offer_views.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
<field name="partner_id"/>
99
<field name="price"/>
1010
<field name="status"/>
11+
<button name="action_accept_offer" title="allows to accept an offer" type="object" class="fa fa-check" invisible="status in ['accepted', 'refused']"/>
12+
<button name="action_refuse_offer" title="allows to refuse an offer" type="object" class="fa fa-times" invisible="status in ['accepted', 'refused']"/>
1113
</list>
1214
</field>
1315
</record>

estate/view/estate_property_tag_views.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
<field name="arch" type="xml">
66
<list string="Channel" editable="top">
77
<field name="name"/>
8+
<field name="color" widget="color_picker"/>
89
</list>
910
</field>
1011
</record>

estate/view/estate_property_type_views.xml

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
<field name="name">estate.type.main.list</field>
44
<field name="model">estate.property.type</field>
55
<field name="arch" type="xml">
6-
<list string="Channel" editable="top">
6+
<list string="Channel">
7+
<field name="sequence" widget="handle"/>
78
<field name="name"/>
89
</list>
910
</field>
@@ -12,6 +13,31 @@
1213
<record id='estate_property_type_action' model='ir.actions.act_window'>
1314
<field name='name'>property_type_action</field>
1415
<field name='res_model'>estate.property.type</field>
15-
<field name='view_mode'>list</field>
16+
<field name='view_mode'>list,form</field>
17+
</record>
18+
19+
<record id="estate_property_type_view_form" model="ir.ui.view">
20+
<field name="name">estate.property.type.form</field>
21+
<field name="model">estate.property.type</field>
22+
<field name="arch" type="xml">
23+
<form string="Estate Offer">
24+
<sheet>
25+
<h1 class="oe_title">
26+
<field name="name"/>
27+
</h1>
28+
<notebook>
29+
<page string="Properties">
30+
<field name="properties_ids">
31+
<list>
32+
<field name="name"/>
33+
<field name="expected_price"/>
34+
<field name="state"/>
35+
</list>
36+
</field>
37+
</page>
38+
</notebook>
39+
</sheet>
40+
</form>
41+
</field>
1642
</record>
1743
</odoo>

estate/view/estate_property_views.xml

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,16 @@
2020
<field name="model">estate.property</field>
2121
<field name="arch" type="xml">
2222
<form string="Estate">
23+
<header>
24+
<button name="action_property_sold" type="object" string="SOLD" invisible="state in ['sold', 'cancelled']"/>
25+
<button name="action_property_cancelled" type="object" string="CANCELLED" invisible="state in ['sold', 'cancelled']"/>
26+
<field name="state" widget="statusbar" statusbar_visible="new,offer received,offer accepted,sold" options="{'clickable': 1}"/>
27+
</header>
2328
<sheet>
2429
<h1 class="oe_title">
2530
<field name="name"/>
2631
</h1>
27-
<field name="tag_ids" widget="many2many_tags" class="mb16"/>
32+
<field name="tag_ids" widget="many2many_tags" class="mb16" options="{'color_field': 'color'}"/>
2833
<div class="row">
2934
<div class="col-6">
3035
<group>
@@ -48,8 +53,8 @@
4853
<field name="facades"/>
4954
<field name="garage"/>
5055
<field name="garden"/>
51-
<field name="garden_orientation"/>
52-
<field name="garden_area"/>
56+
<field name="garden_orientation" invisible="not garden"/>
57+
<field name="garden_area" invisible="not garden"/>
5358
<field name="living_area"/>
5459
<field name="total_area"/>
5560
<field name="property_type_id"/>
@@ -62,7 +67,7 @@
6267
</group>
6368
</page>
6469
<page string="Offers">
65-
<field name="offer_ids"/>
70+
<field name="offer_ids" readonly="state not in ['new', 'offer received']"/>
6671
</page>
6772
</notebook>
6873
</sheet>
@@ -76,7 +81,7 @@
7681
<field name="arch" type="xml">
7782
<search string="Search Estates">
7883
<field name="name"/>
79-
<filter string="Available" name="available" domain="[('state', '!=', 'sold' ), ('state', '!=', 'cancelled'), ('state', '!=', 'offer_accepted')]"/>
84+
<filter string="Available" name="available" domain="[('state', 'not in', ['sold','cancelled','offer_accepted'] )]"/>
8085
<filter string="Garage" name="garage" domain="[('garage', '!=', True )]"/>
8186
<group expand="True" string="Group By">
8287
<filter string="Poscode" name="postcode" context="{'group_by':'postcode'}"/>

0 commit comments

Comments
 (0)