Skip to content

Commit e908e63

Browse files
[IMP] estate: Server101 Finished Chapter 10
[IMP] estate: Server101 Finished Chapter 10 [IMP] estate: Server101 WIP Chapter 11 [CLN] estate: code cleanup to match Ruff [CLN] estate: Server101 Cleanup [CLN] estate: Server101 Cleanup final [CLN] estate: Server101 Appling PR requested changes and cleanup of the code for readability [FIX] estate: Server101 Fixing bugs based on cleanup
1 parent 5490607 commit e908e63

File tree

9 files changed

+124
-70
lines changed

9 files changed

+124
-70
lines changed

estate/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
from . import models
1+
from . import models

estate/__manifest__.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
1-
# -*- coding: utf-8 -*-
21
{
3-
'name':"estate",
4-
'description':"test",
2+
'name': "estate",
3+
'description': "test",
54
'depends': [
65
'base_setup'
76
],
87
'category': "Tutorials",
98
'installable': True,
109
'application': True,
11-
'data':[
10+
'data': [
1211
'views/estate_property_views.xml',
1312
'views/estate_property_type_views.xml',
1413
'views/estate_property_tag_views.xml',
1514
'views/estate_property_offer_views.xml',
1615
'views/estate_menu_views.xml',
17-
'security/ir.model.access.csv']
16+
'security/ir.model.access.csv'],
17+
'author': 'Odoo S.A.',
18+
'license': 'LGPL-3'
1819

19-
}
20+
}

estate/models/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
from . import estate_property
22
from . import estate_property_type
33
from . import estate_property_tag
4-
from . import estate_property_offer
4+
from . import estate_property_offer

estate/models/estate_property.py

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,90 @@
11
from dateutil.relativedelta import relativedelta
2-
from odoo import fields, models,api,exceptions
2+
from odoo import fields, models, api, exceptions
3+
from odoo.tools.float_utils import float_compare, float_is_zero
4+
from odoo.exceptions import ValidationError, UserError
35

46

57
class EstateProperty(models.Model):
68
_name = "estate.property"
79
_description = "Property"
8-
state = fields.Selection(selection = [("New","New"), ("Offer_Received","Offer Received") ,("Offer_Accepted","Offer Accepted"), ("Sold","Sold"), ("Cancelled","Cancelled")])
9-
active = fields.Boolean('Active',default=True)
10-
name = fields.Char(required=True,default="Unkown")
10+
_order = "id desc"
11+
12+
_positif_expected_price = models.Constraint("CHECK (expected_price > 0)", "A price can't be negatif")
13+
_positif_selling_price = models.Constraint("CHECK (selling_price > 0)", "A price can't be negatif")
14+
15+
state = fields.Selection(selection=[
16+
("new", "New"),
17+
("offer_received", "Offer Received"),
18+
("offer_accepted", "Offer Accepted"),
19+
("sold", "Sold"),
20+
("cancelled", "Cancelled")
21+
], default='new')
22+
23+
active = fields.Boolean('Active', default=True)
24+
name = fields.Char(required=True, default="Unkown")
1125
description = fields.Text()
1226
postcode = fields.Char()
13-
date_availability = fields.Date("Available From",copy=False,default= fields.Datetime.today() + relativedelta(months=3))
14-
last_seen= fields.Date("Last Seen", default=fields.Datetime.now)
27+
date_availability = fields.Date("Available From", copy=False, default=lambda self: fields.Datetime.today() + relativedelta(months=3))
28+
last_seen = fields.Date("Last Seen", default=lambda self: fields.Datetime.now())
1529
expected_price = fields.Float(required=True)
16-
selling_price = fields.Float(readonly=True,copy=False)
17-
best_price = fields.Float(string="Best Price",compute="_get_best_price")
30+
selling_price = fields.Float(readonly=True, copy=False)
31+
best_price = fields.Float(string="Best Price", compute="_compute_best_price")
1832
bedrooms = fields.Integer(default=2)
1933
living_area = fields.Integer()
2034
facades = fields.Integer()
2135
garage = fields.Boolean()
2236
garden = fields.Boolean()
2337
garden_area = fields.Integer()
24-
garden_orientation = fields.Selection(selection=[('North','North'),('South','South'),('East','East'),('West','West')])
25-
total_area = fields.Float(compute="_get_total_area",string="Total Area");
26-
property_type_id = fields.Many2one("estate.property.type",string="Type")
27-
buyer_id = fields.Many2one("res.partner",string="Buyer")
28-
seller_id = fields.Many2one("res.users",default=lambda self : self.env.user,string="Seller")
29-
tag_ids = fields.Many2many("estate.property.tag",string="Tags")
30-
offer_ids = fields.One2many("estate.property.offer","property_id",string="Offers")
38+
garden_orientation = fields.Selection(selection=[
39+
('north', 'North'),
40+
('south', 'South'),
41+
('east', 'East'),
42+
('west', 'West')])
43+
44+
total_area = fields.Float(compute="_compute_total_area", string="Total Area")
45+
property_type_id = fields.Many2one("estate.property.type", string="Type")
46+
buyer_id = fields.Many2one("res.partner", string="Buyer")
47+
seller_id = fields.Many2one("res.users", default=lambda self: self.env.user, string="Seller")
48+
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
49+
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
3150

3251
def sell_property(self):
3352
for record in self:
34-
if(record.state == "Cancelled"):
35-
raise exceptions.UserError("Can't sell cancelled property.")
36-
record.state = "Sold"
53+
if (record.state == "cancelled"):
54+
raise UserError("Can't sell cancelled property.")
55+
record.state = "sold"
3756
return True
38-
57+
3958
def cancel_property(self):
4059
for record in self:
41-
if(record.state == "Sold"):
42-
raise exceptions.UserError("Can't cancel sold property.")
43-
record.state = "Cancelled"
60+
if (record.state == "sold"):
61+
raise UserError("Can't cancel sold property.")
62+
record.state = "cancelled"
4463
return True
4564

46-
@api.depends('living_area','garden_area')
47-
def _get_total_area(self):
65+
@api.depends('living_area', 'garden_area')
66+
def _compute_total_area(self):
4867
for record in self:
49-
record.total_area = record.garden_area + record.living_area;
50-
68+
record.total_area = record.garden_area + record.living_area
5169

5270
@api.depends('offer_ids')
53-
def _get_best_price(self):
71+
def _compute_best_price(self):
5472
for record in self:
55-
max:int = 0
56-
57-
if(len(record.offer_ids)==0):
73+
if (not record.offer_ids):
5874
record.best_price = 0
5975
continue
60-
61-
for offer in record.offer_ids:
62-
if(offer.price >= max):
63-
max = offer.price
64-
record.best_price = max
76+
77+
record.best_price = max(record.offer_ids.mapped('price'))
6578

6679
@api.onchange("garden")
67-
def _garden_pre_fill(self):
80+
def _on_change_garden(self):
6881
self.garden_area = 10 if self.garden else 0
69-
self.garden_orientation = 'North' if self.garden else ''
82+
self.garden_orientation = 'North' if self.garden else ''
83+
84+
@api.constrains('selling_price', 'expected_price')
85+
def _constrain_prices(self):
86+
for record in self:
87+
if float_is_zero(record.selling_price, 2):
88+
continue
89+
if (float_compare(record.selling_price, record.expected_price * 0.8, 2) == -1):
90+
raise ValidationError(f"Selling price is too low {record.selling_price}")

estate/models/estate_property_offer.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,41 @@
66
class EstatePropertyOffer(models.Model):
77
_name = "estate.property.offer"
88
_description = "Property Offer"
9+
_order = "price desc"
10+
11+
_postif_price = models.Constraint("CHECK (price > 0)", "A price can't be negatif")
12+
913
price = fields.Float(string="Price")
10-
status = fields.Selection(copy=False,selection = [("Accepted","Accepted"),("Refused","Refused")])
11-
partner_id = fields.Many2one('res.partner',required=True)
14+
status = fields.Selection(copy=False, selection=[
15+
("accepted", "Accepted"),
16+
("refused", "Refused")])
17+
18+
partner_id = fields.Many2one('res.partner', required=True)
1219
property_id = fields.Many2one('estate.property', required=True)
13-
validity = fields.Integer(string="Validity Duration",default=7)
14-
date_deadline = fields.Date(string="Deadline",compute="_get_date_deadline",inverse="_set_date_deadline")
20+
validity = fields.Integer(string="Validity Duration", default=7)
21+
date_deadline = fields.Date(string="Deadline", compute="_compute_date_deadline", inverse="_inverse_date_deadline")
1522

1623
def accept_offer(self):
1724
for record in self:
18-
if(record.property_id.selling_price == 0):
19-
record.status = "Accepted";
20-
print(type(record.property_id.seller_id))
21-
print(type(record.partner_id))
22-
record.property_id.buyer_id = record.partner_id;
23-
record.property_id.selling_price = record.price;
24-
25-
return True;
26-
25+
if (record.property_id.selling_price == 0):
26+
record.status = "accepted"
27+
record.property_id.buyer_id = record.partner_id
28+
record.property_id.selling_price = record.price
29+
return True
30+
2731
def refused_offer(self):
2832
for record in self:
29-
record.status = "Refused";
30-
return True;
31-
33+
record.status = "refused"
34+
return True
3235

3336
@api.depends("validity")
34-
def _get_date_deadline(self):
37+
def _compute_date_deadline(self):
3538
for record in self:
36-
if(isinstance(record.create_date,bool)):
39+
if (isinstance(record.create_date, bool)):
3740
record.date_deadline = fields.Datetime.now() + relativedelta(days=record.validity)
3841
return
3942
record.date_deadline = record.create_date + relativedelta(days=record.validity)
4043

41-
def _set_date_deadline(self):
44+
def _inverse_date_deadline(self):
4245
for record in self:
43-
record.validity = (datetime.combine(record.date_deadline,time()) - record.create_date).days
46+
record.validity = (datetime.combine(record.date_deadline, time()) - record.create_date).days

estate/models/estate_property_tag.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,8 @@
44
class EstatePropertyTag(models.Model):
55
_name = "estate.property.tag"
66
_description = "Property Tag"
7-
name = fields.Char(required=True)
7+
_order = "name asc"
8+
9+
_unique_tag = models.UniqueIndex("(name)", "Tag name must be unique in database")
10+
11+
name = fields.Char(required=True)

estate/models/estate_property_type.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,10 @@
44
class EstatePropertyType(models.Model):
55
_name = "estate.property.type"
66
_description = "Property Type"
7-
name = fields.Char(required=True)
7+
_order = "sequence, name asc"
8+
9+
_unique_type = models.UniqueIndex("(name)", "Property type name must be unique in database")
10+
11+
name = fields.Char(required=True)
12+
property_ids = fields.One2many("estate.property", "property_type_id")
13+
sequence = fields.Integer('Sequence', default=1, help="use to order the list inside the type view")

estate/views/estate_property_type_views.xml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,34 @@
1111
<field name ="name">estate.property.type.form</field>
1212
<field name="model">estate.property.type</field>
1313
<field name="arch" type="xml">
14-
<form string="Property list">
14+
<form string="Property type Form">
1515
<sheet>
1616
<group>
1717
<h1 class="mb32">
1818
<field name="name"/>
1919
</h1>
2020
</group>
21+
<field name="property_ids">
22+
<list>
23+
<field name="name"/>
24+
<field name="expected_price"/>
25+
<field name="state"/>
26+
</list>
27+
</field>
2128
</sheet>
2229
</form>
2330
</field>
2431
</record>
2532

33+
<record id="estate_property_type_model_list" model="ir.ui.view">
34+
<field name ="name">estate.property.type.list</field>
35+
<field name="model">estate.property.type</field>
36+
<field name="arch" type="xml">
37+
<list string="Property type list">
38+
<field name="sequence" widget="handle"/>
39+
<field name="name"/>
40+
</list>
41+
</field>
42+
</record>
43+
2644
</odoo>

estate/views/estate_property_views.xml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
<header>
3030
<button name="sell_property" type="object" string="Sell"/>
3131
<button name="cancel_property" type="object" string="Cancel"/>
32+
<field name="state" widget="statusbar" statusbar_visible="new,offer_received,offer_accepted,sold,cancelled"/>
3233
</header>
3334
<sheet>
3435
<group>
@@ -38,11 +39,11 @@
3839
</group>
3940
<group>
4041
<field name="tag_ids" widget="many2many_tags"/>
41-
<field name="state"/>
42+
4243
</group>
4344
<group>
4445
<group>
45-
<field name="property_type_id"/>
46+
<field name="property_type_id" options="{'no_create_edit': true, 'no_quick_creat':true, 'no_create':true}"/>
4647
<field name="postcode"/>
4748
<field name="date_availability"/>
4849
</group>

0 commit comments

Comments
 (0)