Skip to content

Commit 5323dd0

Browse files
committed
[IMP] estate: add sprinkles to the module
In this commit, I've added a smart button to the form view of the property_type to display all the offers linked to this property_type and added property_offer_count field to be able to count the offers on this specific type.
1 parent f32a4ed commit 5323dd0

8 files changed

+143
-22
lines changed

estate/models/estate_property.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
class EstateProperty(models.Model):
99
_name = "estate.property"
1010
_description = "Estate Property"
11+
_order = "id desc"
1112

1213
name = fields.Char(string="Title")
1314
seller_id = fields.Many2one(
@@ -20,7 +21,7 @@ class EstateProperty(models.Model):
2021
copy=False,
2122
)
2223
expected_price = fields.Float()
23-
selling_price = fields.Float(readonly=True, copyright=False, copy=False)
24+
selling_price = fields.Float(readonly=True, copyright=False, copy=False, precision_rounding=0.01)
2425
bedrooms = fields.Integer(default=4)
2526
living_area = fields.Integer()
2627
garden_area = fields.Integer()
@@ -33,7 +34,13 @@ class EstateProperty(models.Model):
3334
selection=[("north", "North"), ("south", "South"), ("east", "East"), ("west", "West")]
3435
)
3536
status = fields.Selection(
36-
selection=[("new", "New"), ("offer_receieved", "Offer Recieved"), ("sold", "Sold"), ("cancelled", "Cancelled")],
37+
selection=[
38+
("new", "New"),
39+
("offer_receieved", "Offer Recieved"),
40+
("offer_accepted", "Offer Accepted"),
41+
("sold", "Sold"),
42+
("cancelled", "Cancelled"),
43+
],
3744
readonly=True,
3845
default="new",
3946
)
@@ -87,6 +94,10 @@ def action_mark_property_as_sold(self):
8794

8895
for record in self:
8996
record.status = "sold"
97+
accepted_offer = self.env["estate.property.offer"].search_fetch(
98+
[("status", "=", "accepted"), ("property_id", "=", record.id)], ["price"], limit=1
99+
)
100+
record.selling_price = accepted_offer.price
90101

91102
def action_mark_property_as_cancelled(self):
92103
if "sold" in self.mapped("status"):

estate/models/estate_property_offer.py

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,24 @@
11
import datetime
2+
23
from odoo import fields, models, api
34
from odoo.exceptions import UserError
45

56

67
class EstatePropertyOffer(models.Model):
78
_name = "estate.property.offer"
89
_description = "Estate Property Offer"
10+
_order = "price desc"
911

1012
price = fields.Float()
11-
status = fields.Selection([("accepted", "Accepted"), ("rejected", "Rejected")], copy=False, readonly=True)
13+
status = fields.Selection(
14+
[("accepted", "Accepted"), ("rejected", "Rejected"), ("pending", "Pending")],
15+
default="pending",
16+
copy=False,
17+
readonly=True,
18+
)
1219
partner_id = fields.Many2one("res.partner", required=True)
1320
property_id = fields.Many2one("estate.property", required=True)
21+
property_type_id = fields.Many2one(related="property_id.property_type_id", store=True)
1422
validity_days = fields.Integer(default=7)
1523
deadline_date = fields.Date(compute="_compute_deadline_date", inverse="_inverse_validity_days")
1624

@@ -22,6 +30,12 @@ class EstatePropertyOffer(models.Model):
2230
),
2331
]
2432

33+
@api.model_create_single
34+
def create(self, vals):
35+
record = super().create(vals)
36+
record.property_id.status = "offer_receieved"
37+
return record
38+
2539
@api.depends("validity_days")
2640
def _compute_deadline_date(self):
2741
for record in self:
@@ -33,20 +47,18 @@ def _inverse_validity_days(self):
3347

3448
def action_accept_offer(self):
3549
self.ensure_one()
36-
3750
if self.property_id.status == "sold":
3851
raise UserError(f"Property with id {self.property_id.id} has already been sold.")
3952

4053
has_offer_accepted = self.env["estate.property.offer"].search_count(
41-
[("status", "=", "accepted"), ("property_id", "=", self.property_id.id)]
54+
[("status", "=", "accepted"), ("property_id", "=", self.property_id.id)],
4255
)
4356

4457
if has_offer_accepted:
4558
raise UserError(f"Property with id {self.property_id.id} has an accepted offer.")
4659

4760
self.status = "accepted"
48-
49-
# self.property_id.action_mark_property_as_sold()
61+
self.property_id.status = "offer_accepted"
5062

5163
def action_reject_offer(self):
5264
for record in self:

estate/models/estate_property_tag.py

+2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
class EstatePropertyTag(models.Model):
55
_name = "estate.property.tag"
66
_description = "Estate Property Type"
7+
_order = "name"
78

89
name = fields.Char(required=True)
10+
color = fields.Integer(default=1)
911

1012
_sql_constraints = [("check_property_tag_name", "unique(name)", "Two property tags cannot have the same name.")]

estate/models/estate_property_type.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,20 @@
1-
from odoo import fields, models
1+
from odoo import api, fields, models
22

33

44
class EstatePropertyType(models.Model):
55
_name = "estate.property.type"
66
_description = "Estate Property Type"
7+
_order = "sequence, name"
78

89
name = fields.Char(required=True)
10+
property_ids = fields.One2many("estate.property", "property_type_id")
11+
property_offer_ids = fields.One2many("estate.property.offer", "property_type_id")
12+
property_offer_count = fields.Integer(compute="_compute_offer_count", readonly=True)
13+
sequence = fields.Integer("Sequence", default=1, help="Used to order property_types, depending on their name.")
914

10-
_sql_constraints = [("check_property_type_name", "unique(name)", "Two property types cannot have the same name.")]
15+
_sql_constraints = [("check_property_type_name", "UNIQUE(name)", "Two property types cannot have the same name.")]
16+
17+
@api.depends("property_offer_ids")
18+
def _compute_offer_count(self):
19+
for record in self:
20+
record.property_offer_count = len(record.property_offer_ids)

estate/views/estate_property_actions.xml

+15-8
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@
44
<field name="name">Properties</field>
55
<field name="res_model">estate.property</field>
66
<field name="search_view_id" ref="estate.estate_property_search_view"/>
7+
<field name="context">{'search_default_filter_available': True}</field>
78
<field name="view_mode">list,form</field>
89
</record>
910

1011
<record id="estate_property_list_view" model="ir.ui.view">
1112
<field name="name">estate.list_view</field>
1213
<field name="model">estate.property</field>
1314
<field name="arch" type="xml">
14-
<list string="Properties">
15+
<list string="Properties" decoration-success="status in ['offer_accepted', 'offer_receieved']" decoration-bf="status == 'offer_accepted'" decoration-muted="status in ['sold', 'cancelled']">
1516
<field name="postcode"/>
1617
<field name="bedrooms"/>
1718
<field name="living_area"/>
1819
<field name="expected_price"/>
1920
<field name="selling_price"/>
2021
<field name="date_availability"/>
2122
<field name="property_type_id"/>
22-
<field name="property_tag_ids" widget="many2many_tags"/>
23+
<field name="property_tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
2324
</list>
2425
</field>
2526
</record>
@@ -30,19 +31,22 @@
3031
<field name="arch" type="xml">
3132
<form string="New Property">
3233
<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"/>
34+
<group invisible="(status == 'cancelled') or (status == 'sold')">
35+
<button name="action_mark_property_as_sold" string="Mark as Sold" type="object" class="btn-primary"/>
36+
<button name="action_mark_property_as_cancelled" string="Cancel" type="object"/>
37+
</group>
38+
<field name="status" widget="statusbar"/>
3539
</header>
3640
<sheet>
3741
<h1 class="mb32">
3842
<field name="name"/>
3943
</h1>
4044
<group>
4145
<group>
42-
<field name="property_tag_ids" widget="many2many_tags"/>
46+
<field name="property_tag_ids" widget="many2many_tags" options="{'color_field': 'color'}"/>
4347
<field name="seller_id"/>
4448
<field name="postcode"/>
45-
<field name="property_type_id"/>
49+
<field name="property_type_id" options="{'no_create': true}"/>
4650
<field name="date_availability"/>
4751
</group>
4852
<group>
@@ -61,13 +65,16 @@
6165
<field name="facades"/>
6266
<field name="has_garage" string="Garage"/>
6367
<field name="has_garden" string="Graden"/>
68+
<field name="best_offer_price" string="Best offer price:"/>
69+
</group>
70+
<group invisible="not has_garden">
6471
<field name="garden_area"/>
6572
<field name="garden_orientation"/>
6673
</group>
6774
</page>
6875

6976
<page string="Offers">
70-
<field name="offer_ids"/>
77+
<field name="offer_ids" readonly="status == 'offer_accepted'"/>
7178
</page>
7279
</notebook>
7380
</sheet>
@@ -84,7 +91,7 @@
8491
<field name="postcode" string="Postcode"/>
8592
<field name="expected_price" string="Expected Price"/>
8693
<field name="bedrooms" string="Bedrooms"/>
87-
<field name="living_area" string="Living Area"/>
94+
<field name="living_area" string="Living Area" filter_domain="[('living_area', '>=', self)]"/>
8895
<field name="facades" string="Facades"/>
8996
<filter string="Available" name="filter_available" domain="[('status', 'in', ['new', 'offer_receieved'])]"/>
9097
<group expand="0" string="Group By">

estate/views/estate_property_offer_actions.xml

+11-5
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,21 @@
2323
<field name="name">estate.property.offer.list_view</field>
2424
<field name="model">estate.property.offer</field>
2525
<field name="arch" type="xml">
26-
<list string="Offers">
26+
<list string="Offers" default_order="price desc" editable="bottom" decoration-success="status == 'accepted'" decoration-danger="status == 'rejected'">
2727
<field name="price" string="Offer Price"/>
2828
<field name="partner_id"/>
29-
<field name="deadline_date"/>
29+
<field name="deadline_date" optional="hide"/>
3030
<field name="validity_days" string = "Validity"/>
31-
<button name="action_accept_offer" type="object" icon="fa-check" string="accept"/>
32-
<button name="action_reject_offer" type="object" icon="fa-times" string="refuse"/>
33-
<field name="status"/>
31+
<button name="action_accept_offer" type="object" icon="fa-check" string="accept" invisible="status != 'pending'"/>
32+
<button name="action_reject_offer" type="object" icon="fa-times" string="refuse" invisible="status != 'pending'"/>
3433
</list>
3534
</field>
3635
</record>
36+
37+
<record id="estate_property_offer_from_property_type" model="ir.actions.act_window">
38+
<field name="name">Offers</field>
39+
<field name="res_model">estate.property.offer</field>
40+
<field name="view_mode">list,form</field>
41+
<field name="domain">[("property_type_id", "=", active_id)]</field>
42+
</record>
3743
</odoo>

estate/views/estate_property_tag_actions.xml

+26
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,30 @@
55
<field name="res_model">estate.property.tag</field>
66
<field name="view_mode">list,form</field>
77
</record>
8+
9+
<record id="estate_property_tag_form" model="ir.ui.view">
10+
<field name="name">estate.property.tag_form</field>
11+
<field name="model">estate.property.tag</field>
12+
<field name="arch" type="xml">
13+
<form>
14+
<sheet>
15+
<group col="2" colspan="2">
16+
<field name="name" string="Name:"/>
17+
<field name="color" string="Color:" widget="color_picker"/>
18+
</group>
19+
</sheet>
20+
</form>
21+
</field>
22+
</record>
23+
24+
<record id="estate_property_tag_list" model="ir.ui.view">
25+
<field name="name">estate.property.tag_form</field>
26+
<field name="model">estate.property.tag</field>
27+
<field name="arch" type="xml">
28+
<list editable="bottom">
29+
<field name="name" string="Tag name"/>
30+
<field name="color" string="Tag color" widget="color_picker"/>
31+
</list>
32+
</field>
33+
</record>
834
</odoo>

estate/views/estate_property_type_actions.xml

+47
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,51 @@
55
<field name="res_model">estate.property.type</field>
66
<field name="view_mode">list,form</field>
77
</record>
8+
9+
10+
<record id="estate_property_type_form" model="ir.ui.view">
11+
<field name="name">estate.property.type_form</field>
12+
<field name="model">estate.property.type</field>
13+
<field name="arch" type="xml">
14+
<form string = "Property Type">
15+
<sheet>
16+
<div class="oe_button_box" name="button_box">
17+
<button name="%(estate_property_offer_from_property_type)d" type="action" class="oe_stat_button" icon="fa-money">
18+
<field name="property_offer_count" widget="statinfo" string="Offers"/>
19+
</button>
20+
</div>
21+
<div class="oe_title">
22+
<h1 class="mb32">
23+
<field name="name" />
24+
</h1>
25+
</div>
26+
<notebook>
27+
<page string="Properties">
28+
<group>
29+
<field name="property_ids">
30+
<list>
31+
<field name="name" string="Title"/>
32+
<field name="expected_price"/>
33+
<field name="status"/>
34+
</list>
35+
</field>
36+
</group>
37+
</page>
38+
</notebook>
39+
</sheet>
40+
</form>
41+
</field>
42+
</record>
43+
44+
45+
<record id="estate_property_type_list" model="ir.ui.view">
46+
<field name="name">estate.property.type_list</field>
47+
<field name="model">estate.property.type</field>
48+
<field name="arch" type="xml">
49+
<list name="Property Types">
50+
<field name="name"/>
51+
<field name="sequence" widget="handle"/>
52+
</list>
53+
</field>
54+
</record>
855
</odoo>

0 commit comments

Comments
 (0)