Skip to content

Commit a4b2e36

Browse files
committed
[IMP]estate: Added the sprinkles and inheritance part.
1 parent 17a1bb4 commit a4b2e36

13 files changed

+227
-80
lines changed

estate/models/estate_property.py

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,21 +35,22 @@ class EstateProperty(models.Model):
3535
)
3636
state = fields.Selection(selection=[
3737
('new', 'New'),
38-
('received', 'Offer Received'),
39-
('accepted', 'Offer Accepted'),
38+
('offer_received', 'Offer Received'),
39+
('offer_accepted', 'Offer Accepted'),
4040
('sold', 'Sold'),
4141
('cancelled', 'Cancelled'),
4242
], default='new', string="Status", copy=False)
43-
property_type_id = fields.Many2one('estate.property.type', string="Property Type")
43+
property_type_id = fields.Many2one('estate.property.type', string="Property Type",required=True,
44+
options={'no_create': True, 'no_edit': True})
4445
buyer_id = fields.Many2one('res.partner', string="Buyer")
45-
seller_id = fields.Many2one('res.users', string="Salesperson", default=lambda self: self.env.user)
46+
seller_id = fields.Many2one('res.users', string="Salesperson", default=lambda self: self.env.user,required=False)
4647
status = fields.Selection([('accepted', 'Accepted'), ('refused', 'Refused')], string="Status")
47-
partner_id = fields.Many2one('res.partner', string="Partner", required=True)
48+
partner_id = fields.Many2one('res.partner', string="Partner",required=True, ondelete='restrict')
4849
salesperson = fields.Char(string = "Salesperson", required=True)
4950
buyer = fields.Char(string = "Buyers", required=True)
5051
price = fields.Float(string="Price")
5152
partners = fields.Char(string = "Partner", required=True)
52-
tag = fields.Many2one('estate.property.tag' , string="Tags")
53+
tag_ids = fields.Many2one('estate.property.tag' , string="Tags")
5354
total_area = fields.Float(string="Total Area (sqm)", compute="_compute_total_area", store=True,copy=False)
5455
best_offers = fields.Float(string="Best Offers")
5556
offer_ids = fields.One2many(
@@ -69,6 +70,10 @@ class EstateProperty(models.Model):
6970
)
7071
offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers")
7172
best_price = fields.Float(string="Best Price", compute="_compute_best_price", store=True)
73+
offer_received = fields.Boolean(string="Offer Received", compute="_compute_offer_received", store=True)
74+
offer_accepted = fields.Boolean(string="Offer Accepted", compute="_compute_offer_accepted", store=True)
75+
76+
7277

7378
@api.onchange('garden')
7479
def _onchange_garden(self):
@@ -125,5 +130,30 @@ def _check_selling_price(self):
125130
raise ValidationError(
126131
"The selling price cannot be lower than 90% of the expected price."
127132
)
128-
133+
def action_sold(self):
134+
self.state = 'sold'
135+
136+
def action_cancel(self):
137+
self.state = 'canceled'
138+
139+
140+
@api.depends('state')
141+
def _compute_offer_received(self):
142+
for record in self:
143+
record.offer_received = record.state == 'offer_received'
144+
145+
@api.depends('state')
146+
def _compute_offer_accepted(self):
147+
for record in self:
148+
record.offer_accepted = record.state == 'offer_accepted'
149+
150+
@api.ondelete(at_uninstall=False)
151+
def _check_state_on_delete(self):
152+
for record in self:
153+
if record.state not in ('new', 'cancelled'):
154+
raise UserError(
155+
"You cannot delete a property unless it is in 'New' or 'Cancelled' state."
156+
)
157+
158+
129159

estate/models/estate_property_offer.py

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@ class EstatePropertyOffer(models.Model):
99
_description = 'Real Estate Property Offer'
1010
_order = 'price desc'
1111
price = fields.Float()
12-
status = fields.Selection([('accepted', 'Accepted'), ('refused', 'Refused')], string="Status")
12+
state= fields.Selection([('new', 'New'),('accepted', 'Accepted'), ('refused', 'Refused')], string= "Status" ,default='new')
1313
partner_id = fields.Many2one('res.partner', string="Partner", required=True)
1414
property_id = fields.Many2one('estate.property', string="Property", required=True)
15+
status = fields.Selection([('accepted', 'Accepted'), ('refused', 'Refused')], string="Status")
1516
property_type_id = fields.Many2one(
1617
related='property_id.property_type_id',
1718
string="Property Type",
18-
readonly=True
19+
readonly=True,
20+
store=True
1921
)
2022
buyer_id = fields.Many2one(
2123
'res.partner',
@@ -33,6 +35,8 @@ class EstatePropertyOffer(models.Model):
3335
inverse="_inverse_date_deadline",
3436
store=True
3537
)
38+
def action_offer_accepted(self):
39+
pass
3640

3741
@api.depends('create_date', 'validity')
3842
def _compute_date_deadline(self):
@@ -49,26 +53,49 @@ def _inverse_date_deadline(self):
4953
record.validity = max(delta, 0)
5054
else:
5155
record.validity = 7
52-
def action_accept(self):
53-
if self.property_id.state == 'sold':
54-
raise UserError("Cannot accept offers for sold properties.")
55-
existing_offer = self.search([
56-
('property_id', '=', self.property_id.id),
57-
('status', '=', 'accepted')
58-
])
59-
if existing_offer:
60-
raise UserError("Only one offer can be accepted per property.")
61-
self.status = 'accepted'
62-
self.property_id.selling_price = self.price
63-
self.property_id.buyer_id = self.env.user.partner_id
6456

65-
def action_refuse(self):
66-
if self.status == 'accepted':
67-
raise UserError("Accepted offers cannot be refused.")
68-
self.status = 'refused'
57+
def action_offer_accepted(self):
58+
for record in self:
59+
record.status = 'accepted'
60+
record.property_id.selling_price = record.price
61+
record.property_id.buyer_id = record.partner_id
62+
63+
# set status 'refused' in the other offers of that particular property
64+
for offer in record.property_id.offer_ids:
65+
if offer.id != record.id:
66+
offer.status = 'refused'
67+
return True
68+
69+
def action_offer_refused(self):
70+
for record in self:
71+
record.status = 'refused'
72+
return True
73+
6974
_sql_constraints = [
7075
('offer_price_positive', 'CHECK(price > 0)',
7176
'The offer price must be strictly positive.')
72-
]
77+
]
78+
79+
80+
@api.model
81+
def create(self, vals):
82+
# Ensure property_id exists in vals
83+
property_id = self.env['estate.property'].browse(vals.get('property_id'))
84+
if not property_id:
85+
raise UserError("The property associated with this offer does not exist.")
86+
87+
# Check if the new offer amount is lower than any existing offers
88+
existing_offers = self.search([('property_id', '=', property_id.id)])
89+
for offer in existing_offers:
90+
if vals.get('price', 0.0) <= offer.price:
91+
raise UserError(
92+
"You cannot create an offer with a price lower than an existing offer."
93+
)
94+
95+
# Update the property's state to 'Offer Received'
96+
property_id.state = 'offer_received'
97+
98+
# Create the offer as usual
99+
return super(EstatePropertyOffer, self).create(vals)
73100

74101

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
from odoo import models, fields
2+
class ResUsers(models.Model):
3+
_inherit = 'res.users'
4+
5+
property_ids = fields.One2many(
6+
'estate.property',
7+
'seller_id',
8+
string="Properties",
9+
domain=[('state', 'in', ['new', 'offer_received'])]
10+
)

estate/models/estate_property_tags.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ class EstatePropertyTag(models.Model):
55
_order = "name"
66

77
name = fields.Char(string="Tag Name", required=True)
8+
color = fields.Integer(string='Color')
89
tag_ids = fields.Many2many(
910
'estate.property.tag',
1011
'estate_property_tag_rel',
Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,35 @@
1-
from odoo import models, fields
1+
from odoo import models, fields, api
22
class EstatePropertyType(models.Model):
33
_name = 'estate.property.type'
44
_description = 'Real Estate Property Type'
55
_order = "sequence,name"
6+
67
sequence = fields.Integer(default=10)
78
name = fields.Char(string="Type Name", required=True)
8-
property_type_id = fields.Many2one('estate.property.type', string="Property Type")
9-
buyer_id = fields.Many2one('res.partner', string="Buyer")
10-
seller_id = fields.Many2one('res.users', string="Salesperson", default=lambda self: self.env.user)
119
property_ids = fields.One2many('estate.property', 'property_type_id', string="Properties")
12-
expected_price = fields.Float(string="Expected Price", required=True)
13-
state = fields.Selection(selection=[
14-
('new', 'New'),
15-
('received', 'Offer Received'),
16-
('accepted', 'Offer Accepted'),
17-
('sold', 'Sold'),
18-
('cancelled', 'Cancelled'),
19-
], default='new', string="Status", copy=False)
10+
offer_ids = fields.One2many('estate.property.offer', 'property_type_id', string="Offers")
11+
offer_count = fields.Integer(string="Offer Count", compute="_compute_offer_count")
12+
2013
_sql_constraints = [
2114
('unique_type_name', 'UNIQUE(name)',
2215
'The property type name must be unique.')
2316
]
2417

2518

19+
@api.depends('offer_ids')
20+
def _compute_offer_count(self):
21+
for record in self:
22+
record.offer_count = len(record.offer_ids)
23+
24+
def action_view_offers(self):
25+
self.ensure_one()
26+
return {
27+
'type': 'ir.actions.act_window',
28+
'name': 'Offers',
29+
'view_mode': 'tree,form',
30+
'res_model': 'estate.property.offer',
31+
'domain': [('property_type_id', '=', self.id)],
32+
'context': {'default_property_type_id': self.id},
33+
}
34+
35+
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
22
access_estate_property_user,access_estate_property_user,model_estate_property,base.group_user,1,1,1,1
3-
estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,0,1,0
4-
estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,0,0,0
5-
estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,0,1,0
3+
estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1
4+
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_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1

estate/views/estate_property_offer_views.xml

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,26 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<odoo>
3+
<record id="estate_property_offer_action" model="ir.actions.act_window">
4+
<field name="name">Offers</field>
5+
<field name="res_model">estate.property.offer</field>
6+
<field name="view_mode">list,form</field>
7+
<field name="domain">[('property_type_id', '=', active_id)]</field>
8+
</record>
9+
10+
311
<record id="estate_property_offer_view_form" model="ir.ui.view">
412
<field name="name">estate.property.offers</field>
513
<field name="model">estate.property.offer</field>
614
<field name="arch" type="xml">
715
<form string='Offers'>
8-
<header>
9-
<button name="action_accept" type="object" string="Accept"
10-
icon="fa-check" data-visible= "[('state', '!=', 'new')]}"/>
11-
<button name="action_refuse" type="object" string="Refuse"
12-
icon="fa-times" data-visible= "[('state', '!=', 'new')]}"/>
13-
</header>
16+
1417
<sheet>
1518
<group>
1619
<field name="property_type_id" readonly="1"/>
1720
<field name="buyer_id"/>
1821
<field name="seller_id"/>
1922
<field name="price"/>
20-
<field name="partner_id"/>
23+
<field name="partner_id" required="1"/>
2124
<field name="status"/>
2225
<field name="validity"/>
2326
<field name="date_deadline"/>
@@ -31,9 +34,10 @@
3134
<field name="name">estate.property.offer.list</field>
3235
<field name="model">estate.property.offer</field>
3336
<field name="arch" type="xml">
34-
<list string="Offers">
37+
<list string="Offers" editable="bottom" decoration-danger="state == 'refused'" decoration-success="state == 'accepted'">
3538
<field name="price"/>
3639
<field name="partner_id"/>
40+
<field name="property_type_id"/>
3741
<field name="status"/>
3842
<field name="validity"/>
3943
<field name="date_deadline"/>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<odoo>
2+
<record id="view_users_form_inherit_property_ids" model="ir.ui.view">
3+
<field name="name">res.users.form.property.ids</field>
4+
<field name="model">res.users</field>
5+
<field name="inherit_id" ref="base.view_users_form"/>
6+
<field name="arch" type="xml">
7+
<xpath expr="//notebook" position="inside">
8+
<page string="Properties">
9+
<field name="property_ids">
10+
<list string="Properties">
11+
<field name="name"/>
12+
<field name="state"/>
13+
<field name="seller_id"/>
14+
</list>
15+
</field>
16+
</page>
17+
</xpath>
18+
</field>
19+
</record>
20+
</odoo>

estate/views/estate_property_tags_views.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<sheet>
1414
<group>
1515
<field name="name"/>
16-
<field name="tag_ids" widget="many2many_tags"/>
16+
<field name="tag_ids" widget="many2many_tags" />
1717
</group>
1818
</sheet>
1919
</form>
@@ -24,7 +24,7 @@
2424
<field name="name">estate.property.tag.list</field>
2525
<field name="model">estate.property.tag</field>
2626
<field name="arch" type="xml">
27-
<list>
27+
<list editable="bottom">
2828
<field name="name"/>
2929
<field name="tag_ids"/>
3030

estate/views/estate_property_type_views.xml

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,23 @@
44
<field name="name">Property Types</field>
55
<field name="res_model">estate.property.type</field>
66
<field name="view_mode">list,form</field>
7-
</record>
8-
<record id="estate_property_type_view_form" model="ir.ui.view">
7+
</record>
8+
<record id="estate_property_type_view_form" model="ir.ui.view">
99
<field name="name">estate.property.type.form</field>
1010
<field name="model">estate.property.type</field>
1111
<field name="arch" type="xml">
1212
<form string="Property Types">
13-
<sheet>
14-
<h1><field name="name"/></h1>
15-
<br/>
13+
<div name='button_box' >
14+
<button class="oe_stat_button" type='action'
15+
name='%(estate.estate_property_offer_action)d'
16+
icon="fa-pencil-square-o" >
17+
<field name='offer_count' /> Offers </button>
18+
</div>
19+
<sheet>
20+
<h1>
21+
<field name="name"/>
22+
</h1>
23+
1624
<notebook>
1725
<page string="Properties">
1826
<field name="property_ids">
@@ -27,15 +35,17 @@
2735
</sheet>
2836
</form>
2937
</field>
30-
</record>
31-
<record id="estate_property_type_view_list" model="ir.ui.view">
38+
</record>
39+
<record id="estate_property_type_view_list" model="ir.ui.view">
3240
<field name="name">estate.property.type.list</field>
3341
<field name="model">estate.property.type</field>
3442
<field name="arch" type="xml">
3543
<list string= "Property Type">
36-
<field name="sequence" widget='handle'/>
37-
<field name="name"/>
44+
<field name="sequence" widget='handle'/>
45+
<field name="name"/>
3846
</list>
3947
</field>
40-
</record>
48+
</record>
49+
50+
4151
</odoo>

0 commit comments

Comments
 (0)