From c262b3569db7796fd3363fce100c46f92cbbb5a1 Mon Sep 17 00:00:00 2001 From: hemeh Date: Thu, 5 Feb 2026 18:45:47 +0530 Subject: [PATCH 01/14] [ADD] estate: add basic real estate management module This introduces the initial estate module to manage real estate properties. --- estate/__init__.py | 0 estate/__manifest__.py | 15 +++++++++++++++ 2 files changed, 15 insertions(+) create mode 100644 estate/__init__.py create mode 100644 estate/__manifest__.py diff --git a/estate/__init__.py b/estate/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/estate/__manifest__.py b/estate/__manifest__.py new file mode 100644 index 00000000000..1d05ce0e910 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,15 @@ +{ + 'name': 'Real Estate', + 'version': '19.0.0', + 'category': 'Tutorials', + 'depends': ['base'], + 'author': 'hemeh', + 'application': True, + 'summary': 'Manage real estate properties', + 'description': """ + Manage real estate properties. + """, + 'website': 'https://odoo.com', + 'license': 'LGPL-3', + 'installable' : True, +} From 6ad274c6da7c1d774d848efda0c53e8a1334724c Mon Sep 17 00:00:00 2001 From: hemeh Date: Thu, 5 Feb 2026 20:08:58 +0530 Subject: [PATCH 02/14] [CLN] estate: fix manifest style for installable [ADD] estate: add base estate.property model This commit is to initialise real estate property model which is used to store basic property records. The model definition and module structure is according to the standard Odoo ORM module documentation. [IMP] added security folder and [CLN] estate_property.py with an extra line [CLN] Added extra space [CLN] Added End of line in estate/models/__init__.py file [ADD] Added estate_menus.xml and estate_property.xml Chapter 5 [IMP] Improved estate_menus.xml added estate_menu_advertisements_properties --- estate/__init__.py | 1 + estate/__manifest__.py | 27 +++++++----- estate/models/__init__.py | 1 + estate/models/estate_property.py | 61 ++++++++++++++++++++++++++ estate/security/ir.model.access.csv | 2 + estate/security/security.xml | 9 ++++ estate/views/estate_menus.xml | 19 ++++++++ estate/views/estate_property_views.xml | 8 ++++ 8 files changed, 117 insertions(+), 11 deletions(-) create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py create mode 100644 estate/security/ir.model.access.csv create mode 100644 estate/security/security.xml create mode 100644 estate/views/estate_menus.xml create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__init__.py b/estate/__init__.py index e69de29bb2d..0650744f6bc 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 1d05ce0e910..bd88b9a5ed5 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,15 +1,20 @@ { - 'name': 'Real Estate', - 'version': '19.0.0', - 'category': 'Tutorials', - 'depends': ['base'], - 'author': 'hemeh', - 'application': True, - 'summary': 'Manage real estate properties', - 'description': """ + "name": "Real Estate", + "version": "19.0.0", + "category": "Tutorials", + "depends": ["base"], + "author": "hemeh", + "application": True, + "summary": "Manage real estate properties", + "description": """ Manage real estate properties. """, - 'website': 'https://odoo.com', - 'license': 'LGPL-3', - 'installable' : True, + "website": "https://odoo.com", + "license": "LGPL-3", + "installable": True, + "data": [ + "security/ir.model.access.csv", + "views/estate_property_views.xml", + "views/estate_menus.xml", + ], } diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..5e1963c9d2f --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1 @@ +from . import estate_property diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py new file mode 100644 index 00000000000..cfeff7cba58 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,61 @@ +from odoo import fields, models + + +class EstateProperty(models.Model): + _name = "estate.property" + _description = "Real Estate Property" + + name = fields.Char(string="Property Name", required=True) + description = fields.Text(string="Description", required=True) + postcode = fields.Char( + string="Postcode", + ) + date_availability = fields.Date( + string="Date of Availability", + default=lambda self: fields.Date.add(fields.Date.today(), months=3), + copy=False, + ) + expected_price = fields.Float( + string="Expected Price", + required=True, + ) + selling_price = fields.Float(string="Selling Price", readonly=True, copy=False) + bedrooms = fields.Integer(string="Bedrooms", default=2) + living_area = fields.Integer( + string="Living Area (sqm)", + ) + facades = fields.Integer( + string="Number of Facades", + ) + garage = fields.Boolean( + string="Has Garage", + ) + garden = fields.Boolean( + string="Has Garden", + ) + garden_area = fields.Integer( + string="Garden Area (sqm)", + ) + garden_orientation = fields.Selection( + string="Garden Orientation", + selection=[ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ], + ) + state = fields.Selection( + selection=[ + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), + ], + string="Status", + default="new", + copy=False, + ) + active = fields.Boolean(string="Active", default=False) + \ No newline at end of file diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..b3462e66993 --- /dev/null +++ b/estate/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_estate_property_user,estate.property user,model_estate_property,base.group_user,1,1,1,1 diff --git a/estate/security/security.xml b/estate/security/security.xml new file mode 100644 index 00000000000..f6a51c35c4c --- /dev/null +++ b/estate/security/security.xml @@ -0,0 +1,9 @@ + + + + + + Agent + + + diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..956d5064e63 --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..b7ddf5dcdcc --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,8 @@ + + + + Estate Property + estate.property + list,form + + \ No newline at end of file From 784f6c5dbb0d69c709cb01cb49e9deb3da8150b6 Mon Sep 17 00:00:00 2001 From: hemeh Date: Tue, 10 Feb 2026 00:40:11 +0530 Subject: [PATCH 03/14] [CLN] improved whitespace error --- estate/models/estate_property.py | 60 +++++++------------------------- 1 file changed, 13 insertions(+), 47 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index cfeff7cba58..d59021ec662 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -3,41 +3,21 @@ class EstateProperty(models.Model): _name = "estate.property" - _description = "Real Estate Property" + _description = "estate property definition" - name = fields.Char(string="Property Name", required=True) - description = fields.Text(string="Description", required=True) - postcode = fields.Char( - string="Postcode", - ) - date_availability = fields.Date( - string="Date of Availability", - default=lambda self: fields.Date.add(fields.Date.today(), months=3), - copy=False, - ) - expected_price = fields.Float( - string="Expected Price", - required=True, - ) - selling_price = fields.Float(string="Selling Price", readonly=True, copy=False) - bedrooms = fields.Integer(string="Bedrooms", default=2) - living_area = fields.Integer( - string="Living Area (sqm)", - ) - facades = fields.Integer( - string="Number of Facades", - ) - garage = fields.Boolean( - string="Has Garage", - ) - garden = fields.Boolean( - string="Has Garden", - ) - garden_area = fields.Integer( - string="Garden Area (sqm)", - ) + name = fields.Char(required=True) + description = fields.Text() + postcode = fields.Char() + data_availability = fields.Date() + expected_salary = fields.Float(required=True) + selling_price = fields.Float() + bedrooms = fields.Integer() + living_area = fields.Integer() + facades = fields.Integer() + garage = fields.Boolean() + garden = fields.Boolean() + garden_area = fields.Integer(required=True) garden_orientation = fields.Selection( - string="Garden Orientation", selection=[ ("north", "North"), ("south", "South"), @@ -45,17 +25,3 @@ class EstateProperty(models.Model): ("west", "West"), ], ) - state = fields.Selection( - selection=[ - ("new", "New"), - ("offer_received", "Offer Received"), - ("offer_accepted", "Offer Accepted"), - ("sold", "Sold"), - ("cancelled", "Cancelled"), - ], - string="Status", - default="new", - copy=False, - ) - active = fields.Boolean(string="Active", default=False) - \ No newline at end of file From 81da3c4f37d3c209857c58040be4b23bff16e531 Mon Sep 17 00:00:00 2001 From: hemeh Date: Tue, 10 Feb 2026 10:34:30 +0530 Subject: [PATCH 04/14] [ADD] Added a new selection field state in estate property.py for selecting state of the property --- estate/models/estate_property.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d59021ec662..d7f3ad93c8e 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,5 @@ from odoo import fields, models +from dateutil.relativedelta import relativedelta class EstateProperty(models.Model): @@ -8,10 +9,15 @@ class EstateProperty(models.Model): name = fields.Char(required=True) description = fields.Text() postcode = fields.Char() - data_availability = fields.Date() + date_availability = fields.Date( + default=lambda self: fields.Date.context_today(self) + relativedelta(months=3), + copy=False, + ) expected_salary = fields.Float(required=True) - selling_price = fields.Float() - bedrooms = fields.Integer() + selling_price = fields.Float(readonly=True, copy=False) + bedrooms = fields.Integer( + default=2, + ) living_area = fields.Integer() facades = fields.Integer() garage = fields.Boolean() @@ -23,5 +29,18 @@ class EstateProperty(models.Model): ("south", "South"), ("east", "East"), ("west", "West"), + ] + ) + + state = fields.Selection( + selection=[ + ("New", "New"), + ("Offer Accepted", "Offer Accepted"), + ("Offer Received", "Offer Received"), + ("Sold", "Sold"), + ("Cancelled", "Cancelled"), ], + string="State", ) + + active = fields.Boolean(default=False) From 4341f51f9d1f7b7b491decb0402eceee9f2450c5 Mon Sep 17 00:00:00 2001 From: hemeh Date: Tue, 10 Feb 2026 15:46:26 +0530 Subject: [PATCH 05/14] [ADD] Added list view in estate_property_views.xml because till now estate module was using default fallback view mechanism --- estate/models/estate_property.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d7f3ad93c8e..2ba895c7618 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,7 @@ -from odoo import fields, models from dateutil.relativedelta import relativedelta +from odoo import fields, models + class EstateProperty(models.Model): _name = "estate.property" @@ -29,7 +30,7 @@ class EstateProperty(models.Model): ("south", "South"), ("east", "East"), ("west", "West"), - ] + ], ) state = fields.Selection( From 4e7976ff1db6b36cacbe166d58c111935f1a7f53 Mon Sep 17 00:00:00 2001 From: hemeh Date: Tue, 10 Feb 2026 15:55:18 +0530 Subject: [PATCH 06/14] [ADD] Added list view in estate_property_views.xml because till now estate module was using default fallback view mechanism --- estate/views/estate_menus.xml | 36 ++++++++++++++------------ estate/views/estate_property_views.xml | 32 ++++++++++++++++++----- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 956d5064e63..adb72c6ea63 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,19 +1,21 @@ - - - - - - - - - - \ No newline at end of file + + + + + + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index b7ddf5dcdcc..826d174b2a5 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,8 +1,28 @@ - - Estate Property - estate.property - list,form - - \ No newline at end of file + + + + estate.property.tree + estate.property + + + + + + + + + + + + + + + Properties + estate.property + list,form + + + + From a33f84b549cd72bc747861db55fde023fc59cb05 Mon Sep 17 00:00:00 2001 From: hemeh Date: Tue, 10 Feb 2026 19:13:54 +0530 Subject: [PATCH 07/14] [ADD] Added form view in estate_property_views.xml --- estate/views/estate_property_views.xml | 44 +++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 826d174b2a5..76406e37fb5 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -18,6 +18,48 @@ + + estate.property.form + estate.property + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ Properties estate.property @@ -25,4 +67,4 @@ - + \ No newline at end of file From b38142910f90a6a8afa83cefcfdc396a1ef14b89 Mon Sep 17 00:00:00 2001 From: hemeh Date: Tue, 10 Feb 2026 20:08:43 +0530 Subject: [PATCH 08/14] [ADD] Added search view in estate_property_views.xml Chapter 6 --- estate/views/estate_property_views.xml | 28 ++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 76406e37fb5..d65a5730531 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -43,14 +43,14 @@ - - + + - - - - + + + + @@ -60,6 +60,22 @@ + + estate.property.view.search + estate.property + + + + + + + + + + + + + Properties estate.property From b70ee104bc7441cef597e9ca7704db1c742909fe Mon Sep 17 00:00:00 2001 From: Het Mehta Date: Wed, 11 Feb 2026 16:36:24 +0530 Subject: [PATCH 09/14] [CLN] estate: removed extra spaces between fields Removed unnecessary blank lines between fields in estate_property.py Co-authored-by: mash-odoo <124269532+mash-odoo@users.noreply.github.com> --- estate/models/estate_property.py | 1 - 1 file changed, 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 2ba895c7618..b2e0782dbfe 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -32,7 +32,6 @@ class EstateProperty(models.Model): ("west", "West"), ], ) - state = fields.Selection( selection=[ ("New", "New"), From 87c6dd2bc9cd3ddb471ef440a12c65dcc8305a29 Mon Sep 17 00:00:00 2001 From: Het Mehta Date: Wed, 11 Feb 2026 17:44:25 +0530 Subject: [PATCH 10/14] [IMP] Improved on suggestions added underscores while defining keys for selection field in estate_property.py file and in estate_property_views.xml file renamed id from estate.property.tree to estate.property.view.list and removed unecessary whitespaces. --- estate/models/estate_property.py | 14 +++++++------- estate/views/estate_property_views.xml | 24 +++++++++++------------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b2e0782dbfe..a1b9470800c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -5,7 +5,7 @@ class EstateProperty(models.Model): _name = "estate.property" - _description = "estate property definition" + _description = "estate property used to buy and sell houses" name = fields.Char(required=True) description = fields.Text() @@ -14,7 +14,7 @@ class EstateProperty(models.Model): default=lambda self: fields.Date.context_today(self) + relativedelta(months=3), copy=False, ) - expected_salary = fields.Float(required=True) + expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) bedrooms = fields.Integer( default=2, @@ -34,11 +34,11 @@ class EstateProperty(models.Model): ) state = fields.Selection( selection=[ - ("New", "New"), - ("Offer Accepted", "Offer Accepted"), - ("Offer Received", "Offer Received"), - ("Sold", "Sold"), - ("Cancelled", "Cancelled"), + ("new", "New"), + ("offer_accepted", "Offer Accepted"), + ("offer_received", "Offer Received"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), ], string="State", ) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index d65a5730531..8a52c4d7d16 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -2,23 +2,23 @@ - - estate.property.tree + + estate.property.view.list estate.property - + - + - + estate.property.form estate.property @@ -34,7 +34,7 @@ - + @@ -60,19 +60,17 @@ - + estate.property.view.search estate.property - - - + + + - - @@ -83,4 +81,4 @@ - \ No newline at end of file + From 0e2657257c9494dc9c9981866b6ffd79588ff0f6 Mon Sep 17 00:00:00 2001 From: Het Mehta Date: Fri, 13 Feb 2026 18:50:15 +0530 Subject: [PATCH 11/14] [ADD] estate: add relational fields on property model ch-7 Added relational fields on estate.property Many2one and Many2many relationships. Many2one: Adds a foreign key to link many records to one. Many2many: Uses a junction table with foreign keys to allow flexible multi-record associations. --- estate/__manifest__.py | 11 ++++--- estate/models/__init__.py | 2 +- estate/models/estate_property.py | 23 ++++++++++++++ estate/models/estate_property_tag.py | 8 +++++ estate/models/estate_property_type.py | 8 +++++ estate/security/ir.model.access.csv | 4 ++- estate/security/security.xml | 4 +-- estate/views/estate_menus.xml | 23 +++++++++++++- estate/views/estate_property_tag_views.xml | 33 +++++++++++++++++++++ estate/views/estate_property_type_views.xml | 33 +++++++++++++++++++++ estate/views/estate_property_views.xml | 26 ++++++++-------- 11 files changed, 151 insertions(+), 24 deletions(-) create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/views/estate_property_tag_views.xml create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index bd88b9a5ed5..e40793b6fb5 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -9,12 +9,15 @@ "description": """ Manage real estate properties. """, - "website": "https://odoo.com", - "license": "LGPL-3", - "installable": True, "data": [ - "security/ir.model.access.csv", + "security/ir.model.access.csv", + "views/estate_property_type_views.xml", + "views/estate_property_tag_views.xml", "views/estate_property_views.xml", "views/estate_menus.xml", ], + "website": "https://odoo.com", + "license": "LGPL-3", + "installable": True, + } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..95039dab5e2 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1 @@ -from . import estate_property +from . import estate_property, estate_property_tag, estate_property_type diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index a1b9470800c..d7a60e6587b 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -44,3 +44,26 @@ class EstateProperty(models.Model): ) active = fields.Boolean(default=False) + + property_type_id = fields.Many2one( + "estate.property.type", + string="Property Type", + ) + + salesman_id = fields.Many2one( + 'res.users', + string="Salesman", + default=lambda self: self.env.user, + + ) + + buyer_id = fields.Many2one( + 'res.partner', + string="Buyer", + copy=False, + ) + + tag_id = fields.Many2many( + string='Tags', + comodel_name='estate.property.tag', + ) diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..5d1aa16bd66 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Estate Property Tags" + + name = fields.Char(string="Name", required=True) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..4cd08f83daa --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyType(models.Model): + _name = "estate.property.type" + _description = "Estate Property Types" + + name = fields.Char(string="Property Type", required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index b3462e66993..1493eab4011 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_estate_property_user,estate.property user,model_estate_property,base.group_user,1,1,1,1 +access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 +access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 +access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 diff --git a/estate/security/security.xml b/estate/security/security.xml index f6a51c35c4c..7bbacf4f6a7 100644 --- a/estate/security/security.xml +++ b/estate/security/security.xml @@ -1,9 +1,7 @@ - - + Agent - diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index adb72c6ea63..dddd6641c30 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -9,7 +9,8 @@ + parent="estate_menu_root" + sequence="5" /> + + + + + + + diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml new file mode 100644 index 00000000000..79b50be3072 --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,33 @@ + + + + estate.property.tag.view.list + estate.property.tag + + + + + + + + + estate.property.tag.view.form + estate.property.tag + +
+ + + + + +
+
+
+ + + Property Tags + estate.property.tag + list,form + + +
diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..2cc1ad6cf4d --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,33 @@ + + + + estate.property.type.view.list + estate.property.type + + + + + + + + + estate.property.type.view.form + estate.property.type + +
+ + + + + +
+
+
+ + + + Property Types + estate.property.type + list,form + +
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 8a52c4d7d16..4a0f55dc812 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -7,6 +7,7 @@ estate.property + @@ -24,21 +25,16 @@
- - - - - - - + + + + + + - - - - - - + + @@ -50,7 +46,9 @@ - + + + From a2067647ddf386df8d86e4a9083b09c9a90a920d Mon Sep 17 00:00:00 2001 From: Het Mehta Date: Mon, 16 Feb 2026 12:46:04 +0530 Subject: [PATCH 12/14] [ADD] estate: add one2many field to manage property offers CH-7 The estate.property model lacked a direct way to access and manage related offers from the property form view. This change introduces a one2many field linking estate.property to estate.property.offer, allowing users to easily view and manage all offers associated with a property in a single place. --- estate/__manifest__.py | 11 +++--- estate/models/__init__.py | 7 +++- estate/models/estate_property.py | 11 ++++++ estate/models/estate_property_offer.py | 26 +++++++++++++ estate/security/ir.model.access.csv | 2 + estate/security/security.xml | 7 ---- estate/views/estate_property_offer_views.xml | 32 ++++++++++++++++ estate/views/estate_property_type_views.xml | 3 +- estate/views/estate_property_views.xml | 40 ++++++++++++-------- 9 files changed, 108 insertions(+), 31 deletions(-) create mode 100644 estate/models/estate_property_offer.py delete mode 100644 estate/security/security.xml create mode 100644 estate/views/estate_property_offer_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index e40793b6fb5..3cf9d0db241 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -10,11 +10,12 @@ Manage real estate properties. """, "data": [ - "security/ir.model.access.csv", - "views/estate_property_type_views.xml", - "views/estate_property_tag_views.xml", - "views/estate_property_views.xml", - "views/estate_menus.xml", + "security/ir.model.access.csv", + "views/estaso te_property_type_views.xml", + "views/estate_property_offer_views.xml", + "views/estate_property_tag_views.xml", + "views/estate_property_views.xml", + "views/estate_menus.xml", ], "website": "https://odoo.com", "license": "LGPL-3", diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 95039dab5e2..3683ff97b61 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,6 @@ -from . import estate_property, estate_property_tag, estate_property_type +from . import ( + estate_property, + estate_property_offer, + estate_property_tag, + estate_property_type, +) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d7a60e6587b..a8127e0a7b4 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -67,3 +67,14 @@ class EstateProperty(models.Model): string='Tags', comodel_name='estate.property.tag', ) + property_id = fields.One2many( + string='property', + comodel_name='estate.property.offer', + inverse_name='property_id', + ) + + offer_id = fields.One2many( + 'estate.property.offer', + 'property_id', + string='Offers', + ) diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..35796ee6934 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,26 @@ +from odoo import fields, models + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Real Estate Property Offer" + + price = fields.Float(string="Price") + status = fields.Selection( + selection=[ + ("accepted", "Accepted"), + ("refused", "Refused"), + ], + string="Status", + copy=False, + ) + partner_id = fields.Many2one( + "res.partner", + string="Partner", + required=True, + ) + property_id = fields.Many2one( + "estate.property", + string="Property", + required=True, + ) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 1493eab4011..60ec865d16f 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -2,3 +2,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 +access_estate_property_,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 +access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 diff --git a/estate/security/security.xml b/estate/security/security.xml deleted file mode 100644 index 7bbacf4f6a7..00000000000 --- a/estate/security/security.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - Agent - - diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml new file mode 100644 index 00000000000..c243950f7be --- /dev/null +++ b/estate/views/estate_property_offer_views.xml @@ -0,0 +1,32 @@ + + + + estate.property.offer.list + estate.property.offer + + + + + + + + + + + + estate.property.offer.form + estate.property.offer + + + + + + + + + + + + + + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index 2cc1ad6cf4d..2fdda570a79 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -23,8 +23,7 @@
- - + Property Types estate.property.type diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 4a0f55dc812..c67de94a560 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,14 +1,12 @@ - - estate.property.view.list estate.property - - + + @@ -25,16 +23,16 @@
- - - - + + + + - + @@ -46,14 +44,26 @@ - - - + + + + + + + + + + + + + + + + -
@@ -63,7 +73,7 @@ estate.property - + @@ -77,6 +87,4 @@ estate.property list,form
- - From ac4331de0228e2bb993e4b3775f0a6a12ac8cb26 Mon Sep 17 00:00:00 2001 From: Het Mehta Date: Mon, 16 Feb 2026 07:33:50 +0000 Subject: [PATCH 13/14] [FIX] estate: correct manifest view path (estate_property_type_views.xml) --- estate/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 3cf9d0db241..69484e84425 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,7 +11,7 @@ """, "data": [ "security/ir.model.access.csv", - "views/estaso te_property_type_views.xml", + "views/estate_property_type_views.xml", "views/estate_property_offer_views.xml", "views/estate_property_tag_views.xml", "views/estate_property_views.xml", From cf2b4faf156ab62bdc1b9ffdfdbb301b2e4dfb67 Mon Sep 17 00:00:00 2001 From: Het Mehta Date: Tue, 17 Feb 2026 18:55:07 +0530 Subject: [PATCH 14/14] [IMP] estate: add computed fields and onchange logic The property form required automatic updates of dependent values to reduce manual input errors and improve data consistency. This change introduces computed fields to dynamically calculate values based on other field dependencies, ensuring the data remains accurate when related fields are modified. It also adds onchange methods to provide immediate feedback in the form view without requiring a record save, improving the user experience during data entry. These additions enhance data integrity while keeping the form interaction intuitive and responsive. --- estate/models/estate_property.py | 34 +++++++++- estate/models/estate_property_offer.py | 26 ++++++- estate/views/estate_property_offer_views.xml | 16 +++-- estate/views/estate_property_views.xml | 71 ++++++++++---------- 4 files changed, 106 insertions(+), 41 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index a8127e0a7b4..ccf225b606d 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,6 @@ from dateutil.relativedelta import relativedelta -from odoo import fields, models +from odoo import api, fields, models class EstateProperty(models.Model): @@ -43,7 +43,7 @@ class EstateProperty(models.Model): string="State", ) - active = fields.Boolean(default=False) + active = fields.Boolean(default=True) property_type_id = fields.Many2one( "estate.property.type", @@ -78,3 +78,33 @@ class EstateProperty(models.Model): 'property_id', string='Offers', ) + + total_area = fields.Float( + compute="_auto_total_area", + string='Total Area', + store=True, + hint="Auto Computed field", + ) + best_price = fields.Integer(string="Best Price", compute="_compute_best_price") + + @api.depends('living_area', 'garden_area') + def _auto_total_area(self): + for rec in self: + rec.total_area = rec.living_area + rec.garden_area + + @api.depends('offer_id.price') + def _compute_best_price(self): + for rec in self: + if rec.offer_id: + rec.best_price = max(rec.offer_id.mapped("price")) + else: + rec.best_price = 0.0 + + @api.onchange('garden') + def _onchange_garden(self): + if self.garden: + self.garden_area = 10 + self.garden_orientation = "north" + else: + self.garden_area = 0 + self.garden_orientation = False diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 35796ee6934..8e1e4544625 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,6 @@ -from odoo import fields, models +from datetime import timedelta + +from odoo import api, fields, models class EstatePropertyOffer(models.Model): @@ -24,3 +26,25 @@ class EstatePropertyOffer(models.Model): string="Property", required=True, ) + validity = fields.Integer(string="Validity") + date_deadline = fields.Date( + string='date_deadline', + default=fields.Date.context_today, + compute='_compute_date_deadline', + inverse='_inverse_date_deadline', + ) + + @api.depends('create_date', 'validity') + def _compute_date_deadline(self): + for rec in self: + if rec.create_date: + rec.date_deadline = rec.create_date.date() + timedelta(days=rec.validity) + else: + rec.date_deadline = fields.Date.today() + timedelta(days=rec.validity) + + def _inverse_date_deadline(self): + for rec in self: + if rec.create_date: + rec.validity = (rec.date_deadline - rec.create_date.date()).days + else: + rec.validity = (rec.date_deadline - fields.Date.today()).days diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index c243950f7be..1719d3c86b0 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -5,10 +5,11 @@ estate.property.offer - - - - + + + + + @@ -25,6 +26,13 @@ + + + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index c67de94a560..3e99a3ad69c 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -5,14 +5,14 @@ estate.property - - - - - - - - + + + + + + + + @@ -24,42 +24,45 @@
- - - - - + + + + + + - - + + + - - - - - - - - - + + + + + + + + + + - - - + + + - - + + @@ -73,11 +76,11 @@ estate.property - - - - - + + + + +