Skip to content

Commit bfe3033

Browse files
committed
[IMP] estate: add button actions to offers and property model
In this commit, I've added button actions to easily accept and reject offer, and added the necessary business logic to handle the different scenarios that might happen while modifying the status of both the offer and the property model. I've modified some of the code to follow the guidelines.
1 parent e8881a1 commit bfe3033

7 files changed

+81
-27
lines changed

estate/__manifest__.py

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
"depends": ["base"],
55
"data": [
66
"security/ir.model.access.csv",
7+
"views/estate_property_offer_actions.xml",
78
"views/estate_property_actions.xml",
89
"views/estate_property_type_actions.xml",
910
"views/estate_property_tag_actions.xml",

estate/models/estate_property.py

+23-17
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,23 @@
11
import datetime
22

33
from odoo import api, fields, models
4+
from odoo.excepetions import UserError
45

56

67
class EstateProperty(models.Model):
78
_name = "estate.property"
89
_description = "Estate Property"
10+
911
name = fields.Char(string="Title")
1012
seller_id = fields.Many2one(
1113
"res.users", string="Salesperson", index=True, copy=True, default=lambda self: self.env.user
1214
)
1315
description = fields.Text()
1416
postcode = fields.Char()
1517
date_availability = fields.Date(
16-
default=datetime.datetime.now()
17-
+ datetime.timedelta(days=90), # Setting the date availability 3 months from now.
18+
default=datetime.datetime.now() + datetime.timedelta(days=90),
1819
copy=False,
1920
)
20-
validity_days = fields.Integer(default=7)
21-
deadline_date = fields.Date(compute="_compute_deadline_date", inverse="_inverse_validity_days")
2221
expected_price = fields.Float()
2322
selling_price = fields.Float(readonly=True, copyright=False, copy=False)
2423
bedrooms = fields.Integer(default=4)
@@ -38,7 +37,7 @@ class EstateProperty(models.Model):
3837
default="new",
3938
)
4039
property_type_id = fields.Many2one("estate.property.type", string="Property type")
41-
property_tag_id = fields.Many2many("estate.property.tag", string="Property tag")
40+
property_tag_ids = fields.Many2many("estate.property.tag", string="Property tag")
4241
offer_ids = fields.One2many("estate.property.offer", "property_id")
4342
best_offer_price = fields.Float(compute="_compute_best_offer_price")
4443

@@ -50,21 +49,28 @@ def _compute_total_area(self):
5049
@api.depends("offer_ids.price")
5150
def _compute_best_offer_price(self):
5251
for record in self:
53-
record.best_offer_price = max(record.offer_ids.mapped("price")) if record.offer_ids else 0.0
54-
55-
def _compute_deadline_date(self):
56-
for record in self:
57-
record.deadline_date = datetime.date.today() + datetime.timedelta(days=record.validity_days)
58-
59-
@api.depends("deadline_date")
60-
def _inverse_validity_days(self):
61-
for record in self:
62-
record.validity_days = (record.deadline_date - datetime.date.today()).days
52+
record.best_offer_price = max(record.offer_ids.mapped("price"), default=0.0)
6353

6454
@api.onchange("has_garden")
6555
def _onchange_has_garden(self):
6656
for record in self:
6757
if record.has_garden:
68-
record.garden_orientation, record.garden_area = "north", 10
58+
record.garden_orientation = "north"
59+
record.garden_area = 10
6960
else:
70-
record.garden_orientation, record.garden_area = None, None
61+
record.garden_orientation = False
62+
record.garden_area = False
63+
64+
def action_mark_property_as_sold(self):
65+
if "cancelled" in self.mapped("status"):
66+
raise UserError("Cannot sell a property that was canceled.")
67+
68+
for record in self:
69+
record.status = "sold"
70+
71+
def action_mark_property_as_cancelled(self):
72+
if "sold" in self.mapped("status"):
73+
raise UserError("Cannot cancel a property that was sold.")
74+
75+
for record in self:
76+
record.status = "cancelled"
+32-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,41 @@
1-
from odoo import fields, models
1+
import datetime
2+
from odoo import fields, models, api
3+
from odoo.exceptions import UserError
24

35

46
class EstatePropertyOffer(models.Model):
57
_name = "estate.property.offer"
68
_description = "Estate Property Offer"
79

810
price = fields.Float()
9-
status = fields.Selection([("accepted", "Accepted"), ("rejected", "Rejected")], copy=False)
11+
status = fields.Selection([("accepted", "Accepted"), ("rejected", "Rejected")], copy=False, readonly=True)
1012
partner_id = fields.Many2one("res.partner", required=True)
1113
property_id = fields.Many2one("estate.property", required=True)
14+
validity_days = fields.Integer(default=7)
15+
deadline_date = fields.Date(compute="_compute_deadline_date", inverse="_inverse_validity_days")
16+
17+
@api.depends("validity_days")
18+
def _compute_deadline_date(self):
19+
for record in self:
20+
record.deadline_date = datetime.date.today() + datetime.timedelta(days=record.validity_days)
21+
22+
def _inverse_validity_days(self):
23+
for record in self:
24+
record.validity_days = (record.deadline_date - datetime.date.today()).days
25+
26+
def action_accept_offer(self):
27+
self.ensure_one()
28+
29+
if self.property_id.status == "sold":
30+
raise UserError(f"Property with this id {self.property_id} has already been sold.")
31+
32+
self.status = "accepted"
33+
34+
self.property_id.action_mark_property_as_sold()
35+
36+
def action_reject_offer(self):
37+
for record in self:
38+
if record.status == "accepted" and record.property_id.status == "sold":
39+
raise UserError(f"Property with id {record.property_id.id} has already been sold.")
40+
41+
record.status = "rejected"

estate/models/estate_property_tag.py

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
class EstatePropertyTag(models.Model):
55
_name = "estate.property.tag"
6-
76
_description = "Estate Property Type"
87

98
name = fields.Char(required=True)

estate/models/estate_property_type.py

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
class EstatePropertyType(models.Model):
55
_name = "estate.property.type"
6-
76
_description = "Estate Property Type"
87

98
name = fields.Char(required=True)

estate/views/estate_property_actions.xml

+7-5
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<field name="selling_price"/>
2020
<field name="date_availability"/>
2121
<field name="property_type_id"/>
22-
<field name="property_tag_id" widget="many2many_tags"/>
22+
<field name="property_tag_ids" widget="many2many_tags"/>
2323
</list>
2424
</field>
2525
</record>
@@ -29,19 +29,21 @@
2929
<field name="model">estate.property</field>
3030
<field name="arch" type="xml">
3131
<form string="New Property">
32+
<header>
33+
<button name="action_mark_property_as_sold" string="Mark as Sold" type="object" class="btn-primary"/>
34+
<button name="action_mark_property_as_cancelled" string="Cancel" type="object"/>
35+
</header>
3236
<sheet>
3337
<h1 class="mb32">
3438
<field name="name"/>
3539
</h1>
3640
<group>
3741
<group>
38-
<field name="property_tag_id" widget="many2many_tags"/>
42+
<field name="property_tag_ids" widget="many2many_tags"/>
3943
<field name="seller_id"/>
4044
<field name="postcode"/>
4145
<field name="property_type_id"/>
4246
<field name="date_availability"/>
43-
<field name="deadline_date"/>
44-
<field name="validity_days" string="Validity"/>
4547
</group>
4648
<group>
4749
<field name="expected_price"/>
@@ -86,7 +88,7 @@
8688
<field name="bedrooms" string="Bedrooms"/>
8789
<field name="living_area" string="Living Area"/>
8890
<field name="facades" string="Facades"/>
89-
<filter string="New or Offer Received" name="filter_available" domain="['|', ('status', '=', 'new'), ('status', '=', 'offer_receieved')]"/>
91+
<filter string="Available" name="filter_available" domain="[('status', 'in', ['new', 'offer_receieved'])]"/>
9092
<group expand="0" string="Group By">
9193
<filter string="Postcode" name="post_code_grouping" context="{'group_by': 'postcode'}"/>
9294
</group>

estate/views/estate_property_offer_actions.xml

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<list string="Offers">
88
<field name="price"/>
99
<field name="partner_id"/>
10-
<field name="status"/>
1110
</list>
1211
</field>
1312
</record>
@@ -18,6 +17,8 @@
1817
<field name="arch" type="xml">
1918
<form string="Property Offer">
2019
<sheet>
20+
<button name="action_accept_offer" class="btn-success" string="Accept" type="object"/>
21+
<button name="action_reject_offer" class="btn-danger" string="Reject" type="object"/>
2122
<h1 class="mb32">
2223
<field name="property_id"/>
2324
</h1>
@@ -30,4 +31,20 @@
3031
</form>
3132
</field>
3233
</record>
34+
35+
<record id="estate_property_offer_list_view" model="ir.ui.view">
36+
<field name="name">estate.property.offer.list_view</field>
37+
<field name="model">estate.property.offer</field>
38+
<field name="arch" type="xml">
39+
<list string="Offers">
40+
<field name="price" string="Offer Price"/>
41+
<field name="partner_id"/>
42+
<field name="deadline_date"/>
43+
<field name="validity_days" string = "Validity"/>
44+
<button name="action_accept_offer" type="object" icon="fa-check"/>
45+
<button name="action_reject_offer" type="object" icon="fa-times"/>
46+
<field name="status"/>
47+
</list>
48+
</field>
49+
</record>
3350
</odoo>

0 commit comments

Comments
 (0)