Skip to content

Commit 0f407c6

Browse files
committed
ch.11 - all exercises
ch.11 - added list of properties to property types ch.11 - added status bar to estate_property ch.11 - added oredering to estate_property, offer, tags and types ch.11 - added sequence and manual sorting to types ch.11 - prevented adding types in estate property form, added color to tags. ch.11 - hide sell and cancel buttons when they may not be used. ch.11 - garden options are invisible when garden is disabeled, accept and refuse buttons on offers are hidden when the offer is accepted or refused, offers cannot be added or edited once an offer has been accepted. ch.11 - made offers and tags editable, made date_available optional on the list view ch.11 - added colors to various fields ch.11 - made availability the default filter for estate_property_list_view, added search on living area greater or equal to given value ch.11 - add action button to offers
1 parent 4f49572 commit 0f407c6

9 files changed

+91
-26
lines changed

realestatinator/.__manifest__.py.swp

-12 KB
Binary file not shown.
-12 KB
Binary file not shown.

realestatinator/models/estate_property.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
class EstatePropery(models.Model):
44
_name = 'estate_property'
55
_description = 'real estate property'
6-
_order = 'sequence'
6+
_order = 'id desc'
77
_sql_constraints = [
88
('check_expected_price_positive', 'CHECK (0 < expected_price)', 'Check that the expected price is strictly positive'),
99

@@ -80,6 +80,7 @@ def mark_cancelled(self):
8080
raise exceptions.UserError('This property cannot be cancelled because it has already been sold.')
8181

8282
record.state = 'cancelled'
83+
record.active = False
8384

8485
def mark_sold(self):
8586
for record in self:
@@ -91,10 +92,10 @@ def mark_sold(self):
9192
raise exceptions.UserError('This property cannot be sold because it has already been cancelled.')
9293

9394
record.state = 'sold'
95+
record.active = False
9496

9597
@api.constrains('selling_price')
9698
def _check_selling_price(self):
97-
print('\n\nconstraint\n\n')
9899
for record in self:
99100
if record.state not in ['offer_accepted', 'sold']:
100101
return

realestatinator/models/estate_property_offer.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
class EstatePropertyOffer(models.Model):
44
_name = 'estate.property.offer'
55
_description = 'estate property offer'
6+
_order = 'price desc'
67
_sql_constraints = [
78
('check_offer_price_positive', 'CHECK (0 < price)', 'Check that the offer price is strictly positive.'),
89
]
@@ -15,7 +16,9 @@ class EstatePropertyOffer(models.Model):
1516
partner_id = fields.Many2one('res.partner', string='Partner')
1617
property_id = fields.Many2one('estate_property', string='Property')
1718
validity = fields.Integer('Validity', default=7)
18-
date_deadline = fields.Date('Deadline', compute='_compute_deadline', inverse='_inverse_deadline', store=True)
19+
date_deadline = fields.Date('Deadline', compute='_compute_deadline', inverse='_inverse_deadline')
20+
property_type_id = fields.Many2one(related='property_id.property_type_id', store=True)
21+
1922

2023
@api.depends('validity')
2124
def _compute_deadline(self):

realestatinator/models/estate_property_tags.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
class EstatePropertyTags(models.Model):
44
_name = 'estate.property.tags'
55
_description = 'estate property tag'
6+
_order = 'name'
67
_sql_constraints = [
78
('name_unique', 'UNIQUE (name)', 'make sure tag name is unique.')
89
]
910
name = fields.Char('Name', required=True)
11+
color = fields.Integer('Colour')
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,22 @@
1-
from odoo import fields, models
1+
from odoo import api, fields, models
22

33
class EstatePropertyType(models.Model):
44
_name = 'estate.property.type'
55
_description = 'real estate property type'
6+
_order = 'name, sequence'
67
_sql_constraints = [
78
('name_unique', 'UNIQUE (name)', 'make sure type name is unique.')
89
]
9-
# _order = 'sequence'
10-
10+
1111
name = fields.Char('Name', required=True)
12+
property_ids = fields.One2many('estate_property', 'property_type_id', string='Property Type')
13+
sequence = fields.Integer('sequence', default=1)
14+
offer_ids = fields.One2many('estate.property.offer', 'property_type_id', string='Offers')
15+
offer_count = fields.Integer(string='Offer Count', compute='_count_offers')
16+
17+
18+
@api.depends('offer_ids')
19+
def _count_offers(self):
20+
for record in self:
21+
record.offer_count = len(record.offer_ids)
22+

realestatinator/views/estate_property_offer_views.xml

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,24 @@
11
<?xml version="1.0"?>
22
<odoo>
33
<record id="estate_property_offer_action" model="ir.actions.act_window">
4-
<field name='name'>Estate Property Offer</field>
4+
<field name='name'>estate.property.offer.action</field>
55
<field name='res_model'>estate.property.offer</field>
66
<field name='view_mode'>list,form</field>
7+
<field name='domain'>[('property_type_id', '=', active_id)]</field>
78
</record>
89
<record id="estate_property_offer_list" model="ir.ui.view">
910
<field name="name">estate_property_offer_list</field>
1011
<field name="model">estate.property.offer</field>
1112
<field name="arch" type="xml">
12-
<list string="Offers">
13+
<list string="Offers"
14+
editable="bottom"
15+
decoration-success="status == 'accepted'"
16+
decoration-danger="status == 'refused'"
17+
>
1318
<field name="price"/>
1419
<field name="partner_id"/>
15-
<button name="accept_offer" type="object" icon="fa-check"/>
16-
<button name="refuse_offer" type="object" icon="fa-times"/>
17-
<field name="status"/>
20+
<button name="accept_offer" type="object" icon="fa-check" invisible="status == 'accepted' or status == 'refused'"/>
21+
<button name="refuse_offer" type="object" icon="fa-times" invisible="status == 'accepted' or status == 'refused'"/>
1822
<field name="date_deadline"/>
1923
<field name="validity"/>
2024
</list>

realestatinator/views/estate_property_type_views.xml

+35
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,39 @@
55
<field name='res_model'>estate.property.type</field>
66
<field name='view_mode'>list,form</field>
77
</record>
8+
<record id="estate_property_type_view_list" model="ir.ui.view">
9+
<field name="name">estate.property.type.view.list</field>
10+
<field name="model">estate.property.type</field>
11+
<field name="arch" type="xml">
12+
<list string='Properties'>
13+
<field name='sequence' widget='handle'/>
14+
<field name='name'/>
15+
</list>
16+
</field>
17+
</record>
18+
<record id='estate_property_type_view_form' model='ir.ui.view'>
19+
<field name="name">estate.property.type.view.form</field>
20+
<field name="model">estate.property.type</field>
21+
<field name="arch" type="xml">
22+
<form>
23+
<h1><field name="name"/></h1>
24+
<button type="action" name="%(estate_property_offer_action)d" string='Offers' />
25+
<field name="offer_count"/>
26+
<notebook>
27+
<page string="Properties">
28+
<field name="property_ids">
29+
<list>
30+
<field name="name"/>
31+
<field name="expected_price"/>
32+
<field name="state"/>
33+
</list>
34+
</field>
35+
</page>
36+
<page string="Offers">
37+
<field name="offer_ids"/>
38+
</page>
39+
</notebook>
40+
</form>
41+
</field>
42+
</record>
843
</odoo>

realestatinator/views/estate_property_views.xml

+24-15
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@
44
<field name="name">Estate Property Model Action</field>
55
<field name="res_model">estate_property</field>
66
<field name="view_mode">list,form</field>
7+
<field name="context">{'search_default_available': True}</field>
78
</record>
89
<record id="estate_property_model_list" model="ir.ui.view">
910
<field name="name">estate_property_list</field>
1011
<field name="model">estate_property</field>
1112
<field name="arch" type="xml">
12-
<list string='Properties'>
13+
<list string='Properties'
14+
decoration-success="state == 'offer_received' or state == 'offer_accepted'"
15+
decoration-bf="state == 'offer_accepted'"
16+
decoration-muted="state == 'sold' or state == 'cancelled'"
17+
>
1318
<field name='name'/>
14-
<field name='property_type_id'/>
15-
<field name='tag_ids' widget="many2many_tags"/>
19+
<field name='property_type_id' options="{'no_create': true}"/>
20+
<field name='state' optional="1"/>
21+
<field name='tag_ids' widget="many2many_tags" options="{'color_field': 'color'}"/>
1622
<field name='postcode'/>
17-
<field name='bedrooms'/>
18-
<field name='living_area'/>
19-
<field name='expected_price'/>
20-
<field name='selling_price'/>
21-
<field name='date_availability'/>
23+
<field name='bedrooms' optional="1"/>
24+
<field name='living_area' optional="1"/>
25+
<field name='expected_price' optional="1"/>
26+
<field name='selling_price' optional="1"/>
27+
<field name='date_availability' optional="1"/>
2228
</list>
2329
</field>
2430
</record>
@@ -28,11 +34,12 @@
2834
<field name="arch" type="xml">
2935
<form>
3036
<header>
31-
<button name='mark_sold' type='object' string='Sell'/>
32-
<button name='mark_cancelled' type='object' string='Cancel'/>
37+
<button name='mark_sold' type='object' string='Sell' invisible="state != 'offer_accepted'"/>
38+
<button name='mark_cancelled' type='object' string='Cancel' invisible="state == 'sold' or state == 'cancelled'"/>
39+
<field name='state' widget='statusbar' statusbar_visible='new, offer_received, offer_accepted, sold'/>
3340
</header>
3441
<h1><field name='name'/></h1>
35-
<field name='tag_ids' widget="many2many_tags"/>
42+
<field name='tag_ids' widget="many2many_tags" options="{'color_field': 'color'}"/>
3643
<group>
3744
<group>
3845
<field name='postcode'/>
@@ -49,19 +56,19 @@
4956
<page string='Description'>
5057
<group>
5158
<field name='description'/>
52-
<field name='property_type_id'/>
59+
<field name='property_type_id' options="{'no_create': true}"/>
5360
<field name='bedrooms'/>
5461
<field name='living_area'/>
5562
<field name='facades'/>
5663
<field name='garden'/>
5764
<field name='garage'/>
58-
<field name='garden_area'/>
59-
<field name='garden_orientation'/>
65+
<field name='garden_area' invisible="not garden"/>
66+
<field name='garden_orientation' invisible="not garden"/>
6067
<field name='total_area'/>
6168
</group>
6269
</page>
6370
<page string='Offers'>
64-
<field name='offer_ids'/>
71+
<field name='offer_ids' readonly="state == 'offer_accepted' or state == 'sold' or state == 'cancelled'"/>
6572
</page>
6673
<page string='Other'>
6774
<group>
@@ -87,10 +94,12 @@
8794
<field name='expected_price'/>
8895
<field name='facades'/>
8996
<field name='tag_ids'/>
97+
<field name="living_area" filter_domain="[('living_area', '>=', self)]"/>
9098
<separator/>
9199
<filter string="Include archived" name="archived" domain="['|', ('active', '=', True), ('active', '=', False)]"/>
92100
<filter string="Available Properties" name="available" domain="['|', ('state', '=', 'new'), ('state', '=', 'offer_received')]"/>
93101
<separator/>
102+
<filter string='State' name='state' context="{'group_by':'state', 'residual_visible':True}"/>
94103
<filter string='Postcode' name='postcode' context="{'group_by':'postcode', 'residual_visible':True}"/>
95104
<filter string='Property Type' name='property_type_id' context="{'group_by':'property_type_id', 'residual_visible':True}"/>
96105
</search>

0 commit comments

Comments
 (0)