Skip to content

Commit 7d28247

Browse files
author
raibr
committed
[ADD] estate(Chapter 9): Add property state workflow with sold/cancel actions and offer acceptance
1 parent 23dc969 commit 7d28247

File tree

6 files changed

+106
-42
lines changed

6 files changed

+106
-42
lines changed

.DS_Store

0 Bytes
Binary file not shown.

estate/.DS_Store

0 Bytes
Binary file not shown.

estate/models/estate_property.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Part of Odoo. See LICENSE file for full copyright and licensing details.
33

44
from odoo import api, fields, models
5+
from odoo.exceptions import UserError
56

67

78
class EstateProperty(models.Model):
@@ -28,6 +29,18 @@ class EstateProperty(models.Model):
2829
('west', 'West')
2930
]
3031
)
32+
state = fields.Selection(
33+
selection=[
34+
('new', 'New'),
35+
('offer_received', 'Offer Received'),
36+
('offer_accepted', 'Offer Accepted'),
37+
('sold', 'Sold'),
38+
('cancelled', 'Cancelled')
39+
],
40+
default='new',
41+
required=True
42+
)
43+
buyer_id = fields.Many2one('res.partner', string='Buyer')
3144
property_type_id = fields.Many2one("estate.property.type", string="Property Type")
3245
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
3346
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
@@ -55,3 +68,17 @@ def _onchange_garden(self):
5568
else:
5669
self.garden_area = 0
5770
self.garden_orientation = False
71+
72+
def action_sold(self):
73+
for record in self:
74+
if record.state == 'cancelled':
75+
raise UserError("Cancelled property cannot be sold.")
76+
record.state = 'sold'
77+
return True
78+
79+
def action_cancel(self):
80+
for record in self:
81+
if record.state == 'sold':
82+
raise UserError("Sold property cannot be cancelled.")
83+
record.state = 'cancelled'
84+
return True

estate/models/estate_property_offer.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
from datetime import timedelta
55
from odoo import api, fields, models
6+
from odoo.exceptions import UserError
67

78

89
class EstatePropertyOffer(models.Model):
@@ -11,6 +12,14 @@ class EstatePropertyOffer(models.Model):
1112
_order = "price desc"
1213

1314
price = fields.Float(required=True)
15+
status = fields.Selection(
16+
selection=[
17+
('accepted', 'Accepted'),
18+
('refused', 'Refused')
19+
],
20+
copy=False
21+
)
22+
partner_id = fields.Many2one('res.partner', string='Partner', required=True)
1423
property_id = fields.Many2one("estate.property", string="Property", required=True)
1524
validity = fields.Integer(default=7, string="Validity (days)")
1625
date_deadline = fields.Date(
@@ -30,4 +39,18 @@ def _inverse_date_deadline(self):
3039
for record in self:
3140
if record.date_deadline:
3241
record.validity = (record.date_deadline - fields.Date.today()).days
33-
print("Inversed deadlines")
42+
print("Inversed deadlines")
43+
44+
def action_accept(self):
45+
for record in self:
46+
if record.property_id.offer_ids.filtered(lambda o: o.status == 'accepted' and o.id != record.id):
47+
raise UserError("Only one offer can be accepted per property.")
48+
record.status = 'accepted'
49+
record.property_id.buyer_id = record.partner_id
50+
record.property_id.selling_price = record.price
51+
return True
52+
53+
def action_refuse(self):
54+
for record in self:
55+
record.status = 'refused'
56+
return True

estate/views/estate_property_offer_views.xml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
<field name="arch" type="xml">
88
<list>
99
<field name="price"/>
10-
<field name="property_id"/>
10+
<field name="partner_id"/>
1111
<field name="validity"/>
1212
<field name="date_deadline"/>
13+
<field name="status"/>
14+
<button name="action_accept" type="object" icon="fa-check" title="Accept"/>
15+
<button name="action_refuse" type="object" icon="fa-times" title="Refuse"/>
1316
</list>
1417
</field>
1518
</record>
@@ -23,9 +26,11 @@
2326
<sheet>
2427
<group>
2528
<field name="price"/>
29+
<field name="partner_id"/>
2630
<field name="property_id"/>
2731
<field name="validity"/>
2832
<field name="date_deadline"/>
33+
<field name="status"/>
2934
</group>
3035
</sheet>
3136
</form>

estate/views/estate_property_views.xml

Lines changed: 49 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@
66
<field name="model">estate.property</field>
77
<field name="arch" type="xml">
88
<list string="Properties">
9-
<field name="name"/>
10-
<field name="property_type_id"/>
11-
<field name="postcode"/>
12-
<field name="tag_ids" widget="many2many_tags"/>
13-
<field name="bedrooms"/>
14-
<field name="living_area"/>
15-
<field name="expected_price"/>
16-
<field name="selling_price"/>
17-
<field name="date_availability"/>
9+
<field name="name" />
10+
<field name="property_type_id" />
11+
<field name="postcode" />
12+
<field name="tag_ids" widget="many2many_tags" />
13+
<field name="bedrooms" />
14+
<field name="living_area" />
15+
<field name="expected_price" />
16+
<field name="selling_price" />
17+
<field name="date_availability" />
1818
</list>
1919
</field>
2020
</record>
@@ -25,39 +25,45 @@
2525
<field name="model">estate.property</field>
2626
<field name="arch" type="xml">
2727
<form string="Property">
28+
<header>
29+
<button name="action_sold" type="object" string="Sold"/>
30+
<button name="action_cancel" type="object" string="Cancel"/>
31+
<field name="state" widget="statusbar" statusbar_visible="new,offer_received,offer_accepted,sold"/>
32+
</header>
2833
<sheet>
2934
<h1>
30-
<field name="name"/>
35+
<field name="name" />
3136
</h1>
32-
<field name="tag_ids" widget="many2many_tags"/>
37+
<field name="tag_ids" widget="many2many_tags" />
3338
<group>
3439
<group>
35-
<field name="property_type_id"/>
36-
<field name="postcode"/>
37-
<field name="date_availability"/>
40+
<field name="property_type_id" />
41+
<field name="postcode" />
42+
<field name="date_availability" />
3843
</group>
3944
<group>
40-
<field name="expected_price"/>
41-
<field name="best_price"/>
42-
<field name="selling_price"/>
45+
<field name="expected_price" />
46+
<field name="best_price" />
47+
<field name="selling_price" />
48+
<field name="buyer_id" />
4349
</group>
4450
</group>
4551
<notebook>
4652
<page string="Description">
4753
<group>
48-
<field name="description"/>
49-
<field name="bedrooms"/>
50-
<field name="living_area"/>
51-
<field name="facades"/>
52-
<field name="garage"/>
53-
<field name="garden"/>
54-
<field name="garden_area"/>
55-
<field name="garden_orientation"/>
56-
<field name="total_area"/>
54+
<field name="description" />
55+
<field name="bedrooms" />
56+
<field name="living_area" />
57+
<field name="facades" />
58+
<field name="garage" />
59+
<field name="garden" />
60+
<field name="garden_area" />
61+
<field name="garden_orientation" />
62+
<field name="total_area" />
5763
</group>
5864
</page>
5965
<page string="Offers">
60-
<field name="offer_ids"/>
66+
<field name="offer_ids" />
6167
</page>
6268
</notebook>
6369
</sheet>
@@ -71,22 +77,25 @@
7177
<field name="model">estate.property</field>
7278
<field name="arch" type="xml">
7379
<search string="Properties">
74-
<field name="name" string="Title"/>
75-
<field name="property_type_id"/>
76-
<field name="postcode"/>
77-
<field name="expected_price"/>
78-
<field name="bedrooms"/>
79-
<field name="living_area"/>
80+
<field name="name" string="Title" />
81+
<field name="property_type_id" />
82+
<field name="postcode" />
83+
<field name="expected_price" />
84+
<field name="bedrooms" />
85+
<field name="living_area" />
8086

81-
<separator/>
87+
<separator />
8288

83-
<filter name="filter_garden" string="Garden" domain="[('garden', '=', True)]"/>
84-
<filter name="filter_garage" string="Garage" domain="[('garage', '=', True)]"/>
85-
<filter name="filter_high_price" string="High Expected Price" domain="[('expected_price', '&gt;=', 100000)]"/>
89+
<filter name="filter_garden" string="Garden" domain="[('garden', '=', True)]" />
90+
<filter name="filter_garage" string="Garage" domain="[('garage', '=', True)]" />
91+
<filter name="filter_high_price" string="High Expected Price"
92+
domain="[('expected_price', '&gt;=', 100000)]" />
8693

8794
<group name="group_by">
88-
<filter name="group_postcode" string="Postcode" context="{'group_by': 'postcode'}"/>
89-
<filter name="group_bedrooms" string="Bedrooms" context="{'group_by': 'bedrooms'}"/>
95+
<filter name="group_postcode" string="Postcode"
96+
context="{'group_by': 'postcode'}" />
97+
<filter name="group_bedrooms" string="Bedrooms"
98+
context="{'group_by': 'bedrooms'}" />
9099
</group>
91100
</search>
92101
</field>
@@ -98,4 +107,4 @@
98107
<field name="res_model">estate.property</field>
99108
<field name="view_mode">list,form</field>
100109
</record>
101-
</odoo>
110+
</odoo>

0 commit comments

Comments
 (0)