Skip to content

Commit 046086f

Browse files
committed
[ADD] estate: added invoicing and user Category
Added Kanban View to the property page Added automated invoicing for the sold property added user types in module defined in user defination
1 parent 3b4f20c commit 046086f

16 files changed

+153
-32
lines changed

estate/__manifest__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@
1313
'data': [
1414
'security/ir.model.access.csv',
1515
'views/estate_property_views.xml',
16+
'views/estate_property_offer_views.xml',
1617
'views/estate_property_type_views.xml',
1718
'views/estate_property_tag_views.xml',
18-
'views/estate_property_offer_views.xml',
19-
'views/estate_menus.xml'
20-
]
19+
'views/estate_res_user_views.xml',
20+
'views/estate_menus.xml',
21+
]
2122

2223
}

estate/models/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
from . import estate_property_type
33
from . import estate_property_tag
44
from . import estate_property_offer
5+
from . import estate_res_user

estate/models/estate_property.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,11 @@
33
from odoo.exceptions import UserError, ValidationError
44
from odoo.tools import float_utils, _
55

6+
67
class EstateProperty(models.Model):
78
_name = "estate.property"
89
_description = "Real Estate Property"
910
_order = "id desc"
10-
11-
1211
name = fields.Char('Name', required=True, default='Unknown Property')
1312
description = fields.Text('Description')
1413
postcode = fields.Char('Postcode')
@@ -42,6 +41,10 @@ class EstateProperty(models.Model):
4241
total_area = fields.Float(compute="_compute_total_area", string="Total Area", readonly=True)
4342
best_price = fields.Float(compute="_compute_best_price", string="Best Price", readonly=True)
4443

44+
_sql_constraints = [
45+
('check_expected_price', 'CHECK(expected_price > 0)', 'The expected price must strictly be Positive.'),
46+
('check_selling_price', 'CHECK(selling_price > 0)', 'The selling price must strictly be positive.'),
47+
]
4548

4649
@api.depends("garden_area", "living_area")
4750
def _compute_total_area(self):
@@ -88,3 +91,8 @@ def _check_price(self):
8891

8992
if float_utils.float_compare(record.selling_price, record.expected_price * 0.9, precision_rounding=3) == -1:
9093
raise ValidationError(_('The selling cannot be lower than 90% of the expected price.'))
94+
95+
@api.ondelete(at_uninstall=False)
96+
def _unlink_if_state_check(self):
97+
if any(record.state not in ('new', 'canceled') for record in self):
98+
raise UserError(_("You cannot delete a property that is not in the 'New' or 'Canceled' state."))

estate/models/estate_property_offer.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
from odoo import api, fields, models, api
1+
from odoo import api, fields, models
2+
from datetime import timedelta
23
from odoo.exceptions import UserError
34

45

@@ -23,36 +24,26 @@ class EstatePropertyOffer(models.Model):
2324
_sql_constraints = [
2425
("check_price", "CHECK(price > 0)", "The price must be strictly positive.")
2526
]
26-
27+
2728
@api.depends("validity")
2829
def _compute_date_deadline(self):
2930
for record in self:
3031
if not record.create_date:
3132
today = fields.Datetime.today()
32-
record.date_deadline = base_date + timedelta(days=record.validity)
33+
record.date_deadline = today + timedelta(days=record.validity)
3334
else:
3435
record.date_deadline = record.create_date + timedelta(days=record.validity)
3536

3637
def _inverse_date_deadline(self):
3738
for record in self:
3839
record.validity = (record.date_deadline - record.create_date.date()).days
3940

40-
def action_accept_offer(self):
41-
for record in self:
42-
record.status = "accepted"
43-
if record.property_id:
44-
record.property_id.selling_price = record.price
45-
record.property_id.buyer_id = record.partner_id
46-
record.property_id.state = "offer_accepted"
47-
return True
48-
4941
def action_accept_offer(self):
5042
for offer in self:
5143
if offer.property_id.state in {'accepted', 'sold'}:
52-
raise UserError(_('An offer has already been accepted for this property.'))
44+
raise UserError('An offer has already been accepted for this property.')
5345

5446
offer.write({'status': 'accepted'})
55-
5647
offer.property_id.write({
5748
'selling_price': offer.price,
5849
'buyer_id': offer.partner_id.id,
@@ -65,3 +56,12 @@ def action_refuse_offer(self):
6556
for record in self:
6657
record.status = "refused"
6758
return True
59+
60+
@api.model_create_multi
61+
def create(self, vals_list):
62+
for vals in vals_list:
63+
property = self.env["estate.property"].browse(vals["property_id"])
64+
property.state = "offer_received"
65+
if property.best_price > vals["price"]:
66+
raise UserError("The offer must be higher than the existing offer")
67+
return super().create(vals_list)

estate/models/estate_property_type.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class EstatePropertyType(models.Model):
1616
('check_proterty_type_name', 'UNIQUE(name)', 'A Type must be unique.'),
1717
]
1818

19-
2019
@api.depends('offer_ids')
2120
def compute_offer_count(self):
2221
for record in self:

estate/models/estate_res_user.py

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

estate/views/estate_property_offer_views.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@
4141
</form>
4242
</field>
4343
</record>
44-
</odoo>
44+
</odoo>

estate/views/estate_property_tag_views.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,4 @@
2929
</form>
3030
</field>
3131
</record>
32-
</odoo>
32+
</odoo>

estate/views/estate_property_type_views.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@
4949
</form>
5050
</field>
5151
</record>
52-
</odoo>
52+
</odoo>

estate/views/estate_property_views.xml

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<odoo>
3-
<record id="action_estate_property" model="ir.actions.act_window">
4-
<field name="name">Properties</field>
5-
<field name="res_model">estate.property</field>
6-
<field name="view_mode">list,form</field>
7-
<field name="domain">[('active', '=', True)]</field>
8-
<field name="context">{'search_default_state': True}</field>
9-
</record>
10-
<record id="estate_property_view_list" model="ir.ui.view">
3+
<record id="estate_property_view_list" model="ir.ui.view">
114
<field name="name">estate.property.list.view</field>
125
<field name="model">estate.property</field>
136
<field name="arch" type="xml">
@@ -51,7 +44,6 @@
5144
</field>
5245
</record>
5346

54-
5547
<record id="estate_property_properties_form_view" model="ir.ui.view">
5648
<field name="name">estate.property.properties.form.view</field>
5749
<field name="model">estate.property</field>
@@ -111,4 +103,45 @@
111103
</form>
112104
</field>
113105
</record>
106+
<record id="estate_property_kanban" model="ir.ui.view">
107+
<field name="name">estate.property.kanban</field>
108+
<field name="model">estate.property</field>
109+
<field name="arch" type="xml">
110+
<kanban class="o_kanban_mobile" default_group_by="property_type_id" records_draggable="False">
111+
<templates>
112+
<t t-name="card">
113+
<div class="row mb4">
114+
<field class="fw-bolder" name="name"/>
115+
<div>
116+
Expected Price:
117+
<field name="expected_price"/>
118+
</div>
119+
<div t-if = "state == 'offer_received'">
120+
Best Price:
121+
<field name="best_price"/>
122+
</div>
123+
<div t-if = "state == 'offer_accepted'">
124+
Selling Price:
125+
<field name="selling_price"/>
126+
</div>
127+
<field name="tags_ids"/>
128+
</div>
129+
</t>
130+
</templates>
131+
</kanban>
132+
</field>
133+
</record>
134+
135+
<record id="action_estate_property" model="ir.actions.act_window">
136+
<field name="name">Properties</field>
137+
<field name="res_model">estate.property</field>
138+
<field name="view_mode">list,form,kanban</field>
139+
<field name="domain">[('active', '=', True)]</field>
140+
<field name="context">{'search_default_state': True}</field>
141+
<field name="views" eval="[
142+
(ref('estate_property_view_list'), 'list'),
143+
(ref('estate_property_properties_form_view'), 'form'),
144+
(ref('estate_property_kanban'), 'kanban')
145+
]"/>
146+
</record>
114147
</odoo>

0 commit comments

Comments
 (0)