Skip to content

Commit 0bb058f

Browse files
committed
[IMP] estate: add buttons to enforce property and offer workflow
Link business logic to UI buttons. Prevent cancelled properties from being sold. Prevent sold properties from being cancelled. Add ‘Accept’ and ‘Refuse’ buttons for offers. Update buyer and selling price automatically. Ensure consistent workflow and reduce errors.
1 parent b9eeebd commit 0bb058f

File tree

8 files changed

+147
-115
lines changed

8 files changed

+147
-115
lines changed

estate/models/estate_property.py

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from odoo import models, api, fields
21
from dateutil.relativedelta import relativedelta
2+
from odoo import models, api, fields, exceptions
33

44

55
class EstateProperty(models.Model):
@@ -22,10 +22,10 @@ class EstateProperty(models.Model):
2222
garden = fields.Boolean()
2323
garden_area = fields.Integer(string="Garden Area (sqft)")
2424
garden_orientation = fields.Selection([
25-
('north', 'North'),
26-
('south', 'South'),
27-
('east', 'East'),
28-
('west', 'West'),
25+
("north", "North"),
26+
("south", "South"),
27+
("east", "East"),
28+
("west", "West"),
2929
])
3030
state = fields.Selection(
3131
selection=[
@@ -46,16 +46,16 @@ class EstateProperty(models.Model):
4646
)
4747
tag_ids = fields.Many2many("estate.property.tag", string="Property Tags")
4848
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offer")
49-
total_area = fields.Integer(compute="_compute_area")
50-
best_price = fields.Integer(compute="_compute_highest")
49+
total_area = fields.Integer(compute="_total_area")
50+
best_price = fields.Integer(compute="_best_price")
5151

5252
@api.depends("living_area", "garden_area")
53-
def _compute_area(self):
53+
def _total_area(self):
5454
for record in self:
5555
record.total_area = record.living_area + record.garden_area
5656

5757
@api.depends("offer_ids.price")
58-
def _compute_highest(self):
58+
def _best_price(self):
5959
for record in self:
6060
if not record.mapped("offer_ids.price"):
6161
record.best_price = 0
@@ -70,3 +70,19 @@ def _onchange_garden(self):
7070
else:
7171
self.garden_area = 0
7272
self.garden_orientation = None
73+
74+
def action_sold_property(self):
75+
for record in self:
76+
if record.state == "cancelled":
77+
raise exceptions.UserError("Properties which are Cancelled cannot be Sold")
78+
else:
79+
record.state = "sold"
80+
return True
81+
82+
def action_cancel_offer(self):
83+
for record in self:
84+
if record.state == "sold":
85+
raise exceptions.UserError("Properties which are Sold cannot be Cancelled")
86+
else:
87+
record.state = "cancelled"
88+
return True

estate/models/estate_property_offer.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
from odoo import models, api, fields
21
from dateutil.relativedelta import relativedelta
2+
from odoo import models, api, fields
33

44

55
class EstatePropertyOffer(models.Model):
@@ -25,3 +25,17 @@ def _inverse_date(self):
2525
for record in self:
2626
base_date = record.create_date or fields.Date.today()
2727
record.validity = (record.date_deadline - fields.Date.to_date(base_date)).days
28+
29+
def action_accept(self):
30+
for record in self:
31+
record.status = "accepted"
32+
record.property_id.selling_price = record.price
33+
record.property_id.customer = record.partner_id
34+
return True
35+
36+
def action_refuse(self):
37+
for record in self:
38+
record.status = "refused"
39+
record.property_id.selling_price = 0.00
40+
record.property_id.customer = None
41+
return True

estate/security/ir.model.access.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
estate.access_estate_property,"access_estate_property",estate.model_estate_property,base.group_user,1,1,1,1
33
estate.access_estate_property_type,"access_estate_property_type",estate.model_estate_property_type,base.group_user,1,1,1,1
44
estate.access_estate_property_tag,"access_estate_property_tag",estate.model_estate_property_tag,base.group_user,1,1,1,1
5-
estate.access_estate_property_offer,"access_estate_property_offer",estate.model_estate_property_offer,base.group_user,1,1,1,1
5+
estate.access_estate_property_offer,"access_estate_property_offer",estate.model_estate_property_offer,base.group_user,1,1,1,1

estate/views/estate_property_menu.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@
3333
action="action_estate_property_tag"
3434
/>
3535
</odoo>
36+

estate/views/estate_property_offer_views.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313
<list string="Channel">
1414
<field name="price"/>
1515
<field name="partner_id"/>
16-
<field name="status"/>
1716
<field name="validity" string="Validity(days)"/>
1817
<field name="date_deadline"/>
18+
<button name="action_accept" string="Accept" type="object" icon="fa-check" />
19+
<button name="action_refuse" string="Refuse" type="object" icon="fa-times" />
20+
<field name="status"/>
1921
</list>
2022
</field>
2123
</record>
@@ -37,5 +39,4 @@
3739
</form>
3840
</field>
3941
</record>
40-
41-
</odoo>
42+
</odoo>

estate/views/estate_property_tag_views.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,5 @@
2020
</list>
2121
</field>
2222
</record>
23-
</odoo>
23+
</odoo>
24+

estate/views/estate_property_type_views.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,5 @@
2121
</list>
2222
</field>
2323
</record>
24-
</odoo>
24+
</odoo>
25+
Lines changed: 97 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,108 +1,106 @@
11
<?xml version="1.0"?>
22
<odoo>
3+
<record id="estate_property_list_view" model="ir.ui.view">
4+
<field name="name">estate.property.list</field>
5+
<field name="model">estate.property</field>
6+
<field name="arch" type="xml">
7+
<list string="Properties">
8+
<field name="name" string="Title" />
9+
<field name="postcode" />
10+
<field name="bedrooms" />
11+
<field name="living_area" string="Living Area (sqm)" />
12+
<field name="expected_price" />
13+
<field name="selling_price" />
14+
<field name="date_availability" string="Available From" />
15+
</list>
16+
</field>
17+
</record>
318

4-
<record id="estate_property_list_view" model="ir.ui.view">
5-
<field name="name">estate.property.list</field>
6-
<field name="model">estate.property</field>
7-
<field name="arch" type="xml">
8-
<list string="Properties">
9-
<field name="name" string="Title" />
10-
<field name="postcode" />
11-
<field name="bedrooms" />
12-
<field name="living_area" string="Living Area (sqm)" />
13-
<field name="expected_price" />
14-
<field name="selling_price" />
15-
<field name="date_availability" string="Available From" />
16-
</list>
17-
</field>
18-
</record>
19-
20-
21-
<record id="estate_property_form_view" model="ir.ui.view">
22-
<field name="name">estate.property.form</field>
23-
<field name="model">estate.property</field>
24-
<field name="arch" type="xml">
25-
<form string="Property">
26-
<sheet>
27-
<h1>
28-
<field name="name" string="Title" />
29-
</h1>
30-
<field name="tag_ids" widget="many2many_tags" />
31-
<group>
32-
<group>
33-
<field name="property_type_id" string="Property Type" options="{'no_create': true}"/>
34-
<field name="postcode" />
35-
<field name="date_availability" string="Available From" />
36-
</group>
37-
<group>
38-
<field name="expected_price" />
39-
<field name="selling_price" />
40-
<field name="best_price"/>
41-
</group>
42-
</group>
43-
<notebook>
44-
<page string="Description">
19+
<record id="estate_property_form_view" model="ir.ui.view">
20+
<field name="name">estate.property.form</field>
21+
<field name="model">estate.property</field>
22+
<field name="arch" type="xml">
23+
<form string="Property">
24+
<header>
25+
<button name="action_sold_property" type="object" string="Sold" />
26+
<button name="action_cancel_offer" type="object" string="Cancel" />
27+
</header>
28+
<sheet>
29+
<h1>
30+
<field name="name" string="Title" />
31+
</h1>
32+
<group>
33+
<group>
34+
<field name="state" string="Status" />
35+
<field name="tag_ids" widget="many2many_tags" />
36+
<field name="property_type_id" string="Property Type" options="{'no_create': true}" />
37+
<field name="postcode" />
38+
<field name="date_availability" string="Available From" />
39+
</group>
40+
<group>
41+
<field name="expected_price" />
42+
<field name="selling_price" />
43+
<field name="best_price" />
44+
</group>
45+
</group>
46+
<notebook>
47+
<page string="Description">
48+
<group>
4549
<group>
46-
<group>
47-
<field name="description"/>
48-
<field name="bedrooms"/>
49-
<field name="living_area" string="Living Area(sqm)"/>
50-
<field name="facades"/>
51-
<field name="garage"/>
52-
<field name="garden"/>
53-
<field name="garden_area" string="Garden Area(sqm)"/>
54-
<field name="garden_orientation"/>
55-
<field name="total_area" string="Total Area(sqm)"/>
50+
<field name="description" />
51+
<field name="bedrooms" />
52+
<field name="living_area" string="Living Area(sqm)" />
53+
<field name="facades" />
54+
<field name="garage" />
55+
<field name="garden" />
56+
<field name="garden_area" string="Garden Area(sqm)" />
57+
<field name="garden_orientation" />
58+
<field name="total_area" string="Total Area(sqm)" />
5659
</group>
5760
<group>
58-
<field name="active"/>
59-
<field name="state"/>
61+
<field name="active" />
62+
<field name="state" />
6063
</group>
61-
</group>
62-
</page>
63-
<page string="Offers">
64-
<field name="offer_ids" readonly="state in ('offer_accepted','sold','cancelled')"/>
65-
</page>
66-
<page string="Information">
67-
<group>
68-
<field name="salesperson"/>
69-
<field name="customer"/>
70-
</group>
71-
</page>
72-
</notebook>
73-
</sheet>
74-
</form>
75-
</field>
76-
</record>
77-
78-
79-
<record id="estate_property_search_options_view" model="ir.ui.view">
80-
<field name="name">Search Properties</field>
81-
<field name="model">estate.property</field>
82-
<field name="arch" type="xml">
83-
<search string="Property Search">
84-
<field name="name" string="Title" />
85-
<field name="postcode" />
86-
<field name="expected_price" />
87-
<field name="bedrooms" />
88-
<field name="living_area" string="Living Area (sqm)" />
89-
<field name="facades" />
90-
<filter name="available" string="Available"
91-
domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]" />
92-
<filter name="postcode" string="Postcode" context="{'group_by':'postcode'}" />
93-
</search>
94-
</field>
95-
</record>
64+
</group>
65+
</page>
66+
<page string="Offers">
67+
<field name="offer_ids" readonly="state in ('offer_accepted','sold','cancelled')" />
68+
</page>
69+
<page string="Information">
70+
<group>
71+
<field name="salesperson" />
72+
<field name="customer" />
73+
</group>
74+
</page>
75+
</notebook>
76+
</sheet>
77+
</form>
78+
</field>
79+
</record>
9680

97-
98-
<record id="main_action_estate" model="ir.actions.act_window">
99-
<field name="name">Estate Property</field>
100-
<field name="res_model">estate.property</field>
101-
<field name="view_mode">list,form</field>
102-
<field name="help" type="html">
103-
<p class="o_view_nocontent_smiling_face">
104-
Create your Properties here !
105-
</p>
106-
</field>
107-
</record>
81+
<record id="estate_property_search_options_view" model="ir.ui.view">
82+
<field name="name">Search Properties</field>
83+
<field name="model">estate.property</field>
84+
<field name="arch" type="xml">
85+
<search string="Property Search">
86+
<field name="name" string="Title" />
87+
<field name="postcode" />
88+
<field name="expected_price" />
89+
<field name="bedrooms" />
90+
<field name="living_area" string="Living Area (sqm)" />
91+
<field name="facades" />
92+
<filter name="available" string="Available" domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]" />
93+
<filter name="postcode" string="Postcode" context="{'group_by':'postcode'}" />
94+
</search>
95+
</field>
96+
</record>
97+
<record id="main_action_estate" model="ir.actions.act_window">
98+
<field name="name">Estate Property</field>
99+
<field name="res_model">estate.property</field>
100+
<field name="view_mode">list,form</field>
101+
<field name="help" type="html">
102+
<p class="o_view_nocontent_smiling_face">Create your Properties here !</p>
103+
</field>
104+
</record>
108105
</odoo>
106+

0 commit comments

Comments
 (0)