From 0338efb25680939df63cf56dcbf46f1d6709782d Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Fri, 3 Jul 2026 17:18:51 +0530 Subject: [PATCH 01/21] [ADD] estate: Initial module for Real Estate Business Introduce the Estate module for real estate businesses to list and manage their properties This application provides a centralized solution for maintaining property listings and supporting day-to-day real estate management here foundations of completely new odoo module are applied so Estate module can be installed as application Completed Chapter 2 --- estate/__init__.py | 0 estate/__manifest__.py | 10 ++++++++++ 2 files changed, 10 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..b13b8279b19 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': 'Estate', + 'version': '1.0', + 'category': 'Tutorials', + 'depends': ['base'], + 'installable': True, + 'application': True, + 'author': 'Prerana Yesugade', + 'license': 'LGPL-3', +} From abb1be6dd35564b2466152794c0f18f1a3e3e74a Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Mon, 6 Jul 2026 17:55:15 +0530 Subject: [PATCH 02/21] [ADD] estate: define property information Introduce the property information required to manage real estate listings Capturing essential property details enables businesses to maintain complete property records and improves the organization of their real estate portfolio Completed Chapter 3 --- estate/__init__.py | 1 + estate/__manifest__.py | 16 ++++++++-------- estate/models/__init__.py | 1 + estate/models/estate_property.py | 28 ++++++++++++++++++++++++++++ 4 files changed, 38 insertions(+), 8 deletions(-) create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py 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 b13b8279b19..4de8dbb46a2 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,10 +1,10 @@ { - 'name': 'Estate', - 'version': '1.0', - 'category': 'Tutorials', - 'depends': ['base'], - 'installable': True, - 'application': True, - 'author': 'Prerana Yesugade', - 'license': 'LGPL-3', + "name": "Estate", + "version": "1.0", + "category": "Tutorials", + "depends": ["base"], + "installable": True, + "application": True, + "author": "Prerana Yesugade", + "license": "LGPL-3", } 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..d34cc0417d0 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,28 @@ +from odoo import models, fields + + +class EstateProperty(models.Model): + _name = "estate.property" + _description = "Estate Property" + + name = fields.Char(required=True) + description = fields.Text() + postcode = fields.Char() + date_availability = fields.Date() + expected_price = 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() + garden_orientation = fields.Selection( + string="Type", + selection=[ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ], + ) From 0a5a0f18962884bd204a306cc67106917e468c92 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Tue, 7 Jul 2026 15:48:09 +0530 Subject: [PATCH 03/21] [ADD] estate: grant access to property records Grant internal users access to property records Providing the appropriate permissions allows authorized users to create, view, update and remove property listings, supporting the day-to-day management of real estate operations Completed Chapter 4 --- estate/__manifest__.py | 2 +- estate/security/ir.model.access.csv | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 4de8dbb46a2..385b1bea425 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,7 +3,7 @@ "version": "1.0", "category": "Tutorials", "depends": ["base"], - "installable": True, + "data": ["security/ir.model.access.csv"], "application": True, "author": "Prerana Yesugade", "license": "LGPL-3", diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..98f4671fb0d --- /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 +estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 From 2abb73076b1e09be050af4ce50025f4c069efc34 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Wed, 8 Jul 2026 18:44:55 +0530 Subject: [PATCH 04/21] [ADD] estate: add window action for property records Providing a dedicated window action enables users to access property listings from the Estate application and interact with them more efficiently Opening both the list and form views allows users to browse available properties, review their details and create new property records --- estate/__manifest__.py | 2 +- estate/views/estate_property_views.xml | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 385b1bea425..0a1a311d7e6 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,7 +3,7 @@ "version": "1.0", "category": "Tutorials", "depends": ["base"], - "data": ["security/ir.model.access.csv"], + "data": ["security/ir.model.access.csv", "views/estate_property_views.xml"], "application": True, "author": "Prerana Yesugade", "license": "LGPL-3", diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..038f09beff9 --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,8 @@ + + + + Properties + estate.property + list,form + + From 71e6cb610c543c24e35415c63516f33d50e9d5e6 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Thu, 9 Jul 2026 18:48:15 +0530 Subject: [PATCH 05/21] [ADD] estate: add navigation for property management Improve the property management workflow, Provide a dedicated navigation structure for the Estate application Application menus make property records easier to access, while default values reduce repetitive data entry and copy restrictions preserve data consistency when duplicating properties --- estate/__manifest__.py | 6 +++++- estate/models/estate_property.py | 11 +++++++---- estate/views/estate_menus.xml | 8 ++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 estate/views/estate_menus.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 0a1a311d7e6..da1db307166 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,7 +3,11 @@ "version": "1.0", "category": "Tutorials", "depends": ["base"], - "data": ["security/ir.model.access.csv", "views/estate_property_views.xml"], + "data": [ + "security/ir.model.access.csv", + "views/estate_property_views.xml", + "views/estate_menus.xml", + ], "application": True, "author": "Prerana Yesugade", "license": "LGPL-3", diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d34cc0417d0..9ad918b4070 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -7,16 +7,19 @@ class EstateProperty(models.Model): name = fields.Char(required=True) description = fields.Text() - postcode = fields.Char() - date_availability = fields.Date() + date_availability = fields.Date( + copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3) + ) expected_price = fields.Float(required=True) - selling_price = fields.Float() - bedrooms = fields.Integer() + active = fields.Boolean(default=True) + selling_price = fields.Float(readonly=True, copy=False) + bedrooms = fields.Integer(default=2) living_area = fields.Integer() facades = fields.Integer() garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() + postcode = fields.Char() garden_orientation = fields.Selection( string="Type", selection=[ diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..ee95cb594dc --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,8 @@ + + + + + + + + From d7d619b6f820c698ea62cc38234af28c5bc0227f Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Fri, 10 Jul 2026 15:31:33 +0530 Subject: [PATCH 06/21] [IMP] estate: manage property lifecycle Allow users to track the life cycle of estate properties to provide visibility into their current status and progress Introduce a state field so every property has a clearly defined life cycle status New properties start with a default "New" state to establish a consistent initial life cycle while duplicated records receive a fresh life cycle status to maintain data consistency Completed Chapter 5 --- estate/models/estate_property.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 9ad918b4070..f35fbef38a0 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -29,3 +29,15 @@ class EstateProperty(models.Model): ("west", "West"), ], ) + state = fields.Selection( + [ + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), + ], + required=True, + default="new", + copy=False, + ) From 008631a73b6e8f251ddfb9b45bae3862f9021b4d Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Mon, 20 Jul 2026 16:22:32 +0530 Subject: [PATCH 07/21] [IMP] estate: enhance property management interface Improve the user experience when working with property records. The list view provides an overview of available properties, while the form view organizes detailed property information for viewing and editing, Descriptive field labels further improve readability and ease of use. --- estate/models/estate_property.py | 8 ++-- estate/views/estate_property_views.xml | 54 ++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f35fbef38a0..f04a34d0c85 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -5,16 +5,18 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Estate Property" - name = fields.Char(required=True) + name = fields.Char(string="Title", required=True) description = fields.Text() date_availability = fields.Date( - copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3) + string="Available From", + copy=False, + default=lambda self: fields.Date.add(fields.Date.today(), months=3), ) expected_price = fields.Float(required=True) active = fields.Boolean(default=True) selling_price = fields.Float(readonly=True, copy=False) bedrooms = fields.Integer(default=2) - living_area = fields.Integer() + living_area = fields.Integer(string="Living Area (sqm)") facades = fields.Integer() garage = fields.Boolean() garden = fields.Boolean() diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 038f09beff9..0f57470662f 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -5,4 +5,58 @@ estate.property list,form + + estate.property.list + estate.property + + + + + + + + + + + + + + + estate.property.form + estate.property + +
+ + +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
From 2f2a4beb48bfa534b3d9ccd2ad6464bbe301d020 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Tue, 21 Jul 2026 18:00:38 +0530 Subject: [PATCH 08/21] [IMP] estate: enhance property search experience Improve the search experience for property records. Provide dedicated search options to help users quickly locate properties, filter available listings and organize property records by postcode for easier navigation. --- estate/views/estate_property_views.xml | 55 ++++++++++++++++++-------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 0f57470662f..4a6a3d26168 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -5,6 +5,7 @@ estate.property list,form + estate.property.list estate.property @@ -16,11 +17,11 @@ - - + + estate.property.form estate.property @@ -40,23 +41,43 @@ - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + estate.property.search + estate.property + + + + + + + + + + + + + + + + From 1d8ef38963bc2b3f66e934965e69542d2ad1374d Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Thu, 23 Jul 2026 16:33:14 +0530 Subject: [PATCH 09/21] [IMP] estate: improve property list view usability Improve the property list view to provide a more flexible and efficient experience when managing property records Users can customize the displayed information based on their needs and update multiple properties at once reducing repetitive actions and simplifying day-to-day property management Completed Chapter 6 --- estate/views/estate_property_views.xml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 4a6a3d26168..9d7d7db7520 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -10,14 +10,14 @@ estate.property.list estate.property - + - - - + + + - - + + From 940f65442a61e920cf60d44cc0c7ffa1776e91b1 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Mon, 27 Jul 2026 18:26:04 +0530 Subject: [PATCH 10/21] [ADD] estate: categorize properties by type Property types help businesses classify their listings into meaningful categories and make property information easier to manage -Help users distinguish properties based on their type -Keep property classification consistent across listings -Make property types easy to review and maintain during regular management -Provide a central place to configure the property types used across listings -Help users identify, filter and find properties based on their type during day to day property management --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 1 + estate/models/estate_property_type.py | 8 ++++++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menus.xml | 5 ++++- estate/views/estate_property_type.xml | 8 ++++++++ estate/views/estate_property_views.xml | 5 ++++- 8 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/views/estate_property_type.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index da1db307166..a175df287ff 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -6,6 +6,7 @@ "data": [ "security/ir.model.access.csv", "views/estate_property_views.xml", + "views/estate_property_type.xml", "views/estate_menus.xml", ], "application": True, diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..40092a2d810 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,2 @@ from . import estate_property +from . import estate_property_type diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f04a34d0c85..10d559398ed 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -43,3 +43,4 @@ class EstateProperty(models.Model): default="new", copy=False, ) + property_type_id = fields.Many2one("estate.property.type", string="Property Type") diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..eebc62e998c --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,8 @@ +from odoo import models, fields + + +class EstatePropertyType(models.Model): + _name = "estate.property.type" + _description = "Estate Property Type" + + name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 98f4671fb0d..7d4c1fcdb86 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 +estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index ee95cb594dc..86792d42b3b 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,8 +1,11 @@ - + + + + diff --git a/estate/views/estate_property_type.xml b/estate/views/estate_property_type.xml new file mode 100644 index 00000000000..34af329f2f4 --- /dev/null +++ b/estate/views/estate_property_type.xml @@ -0,0 +1,8 @@ + + + + Property Types + estate.property.type + list,form + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 9d7d7db7520..51a0a0ace0f 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -17,7 +17,8 @@ - + + @@ -33,6 +34,7 @@ + @@ -72,6 +74,7 @@ + From 1056a0f097e595a87bdb7f8319555ac19a24510a Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Tue, 28 Jul 2026 15:53:47 +0530 Subject: [PATCH 11/21] [IMP] estate: associate salesperson and buyer with properties Ensure clear responsibility and customer tracking throughout the property sales process Having a dedicated salesperson establishes clear ownership of each property, while associating a buyer keeps the relevant customer information connected to the sale Leaving the buyer empty on duplicated properties prevents unrelated customer information from carrying over to a new sale Assigning new properties to the current salesperson reduces manual work and ensures responsibility is established from the start --- estate/models/estate_property.py | 4 ++++ estate/views/estate_property_views.xml | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 10d559398ed..e4cdeb2798e 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -44,3 +44,7 @@ class EstateProperty(models.Model): copy=False, ) property_type_id = fields.Many2one("estate.property.type", string="Property Type") + buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) + salesperson_id = fields.Many2one( + "res.users", string="Salesmen", default=lambda self: self.env.user + ) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 51a0a0ace0f..ca873884b86 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -57,6 +57,12 @@ + + + + + + From 880477d2263474d20d4331166de9ebb61f35afe6 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Tue, 28 Jul 2026 18:59:42 +0530 Subject: [PATCH 12/21] [ADD] estate: add tags for property characteristics Tags help users highlight relevant property characteristics and make listings easier to distinguish and organize beyond their primary property type Allow multiple tags on each property so listings can represent several characteristics without being limited to a single classification provide dedicated access to maintain a consistent set of tags across property records make tag management available to authorized users so classifications can be maintained and reused across property listings --- estate/__manifest__.py | 1 + estate/models/__init__.py | 3 +-- estate/models/estate_property.py | 3 ++- estate/models/estate_property_tag.py | 8 ++++++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menus.xml | 1 + estate/views/estate_property_tag.xml | 8 ++++++++ estate/views/estate_property_views.xml | 6 +++++- 8 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/views/estate_property_tag.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index a175df287ff..49d62e09f48 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,6 +7,7 @@ "security/ir.model.access.csv", "views/estate_property_views.xml", "views/estate_property_type.xml", + "views/estate_property_tag.xml", "views/estate_menus.xml", ], "application": True, diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 40092a2d810..6c1ae061713 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,2 +1 @@ -from . import estate_property -from . import estate_property_type +from . import estate_property, estate_property_type, estate_property_tag diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index e4cdeb2798e..d54ecedfa9f 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -46,5 +46,6 @@ class EstateProperty(models.Model): property_type_id = fields.Many2one("estate.property.type", string="Property Type") buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) salesperson_id = fields.Many2one( - "res.users", string="Salesmen", default=lambda self: self.env.user + "res.users", string="Salesman", default=lambda self: self.env.user ) + tags_id = fields.Many2many("estate.property.tag", string="Property Tags") diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..78ce298bce9 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,8 @@ +from odoo import models, fields + + +class EstatePropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Estate Property Tag" + + name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 7d4c1fcdb86..5558d0fbc60 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 +estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 86792d42b3b..af3932a7b6c 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -6,6 +6,7 @@ + diff --git a/estate/views/estate_property_tag.xml b/estate/views/estate_property_tag.xml new file mode 100644 index 00000000000..6fe636b5168 --- /dev/null +++ b/estate/views/estate_property_tag.xml @@ -0,0 +1,8 @@ + + + + Property Tags + estate.property.tag + list,form + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index ca873884b86..ea964fb0a45 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -18,7 +18,8 @@ - + + @@ -31,6 +32,9 @@

+
+ + From 71b7511b3d03e45ee96e5d3a7b554b808d5a423e Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Wed, 29 Jul 2026 18:34:54 +0530 Subject: [PATCH 13/21] [ADD] estate: introduce offers for property listings Enable property offers to keep track of proposals made by potential buyers - Associate each offer with its property and customer so businesses can identify who made an offer and for which listing. - Record the proposed price and offer status to provide the information needed to follow each offer through the property sales process. - Ensure offer decisions are not carried over when records are duplicated so each offer starts with its own valid status. --- estate/models/__init__.py | 7 ++++++- estate/models/estate_property_offer.py | 13 +++++++++++++ estate/security/ir.model.access.csv | 1 + 3 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 estate/models/estate_property_offer.py diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 6c1ae061713..a0a8b8c501c 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,6 @@ -from . import estate_property, estate_property_type, estate_property_tag +from . import ( + estate_property, + estate_property_type, + estate_property_tag, + estate_property_offer, +) diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..3e498bd2581 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,13 @@ +from odoo import models, fields + + +class estate_property_offer(models.Model): + _name = "estate.property.offer" + _description = "Estate Property Offer" + + price = fields.Float() + status = fields.Selection( + selection=[("accepted", "Accepted"), ("refused", "Refused")], copy=False + ) + partner_id = fields.Many2one("res.partner", required=True) + property_id = fields.Many2one("estate.property", required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 5558d0fbc60..0c0b62b7fee 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -2,3 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1 +estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1 From fa5ac2a1159dc2da1a29f3f251508814886a4ff3 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Thu, 30 Jul 2026 17:48:16 +0530 Subject: [PATCH 14/21] [IMP] estate: improve property offer tracking Simplify the handling of offers received for properties Keeping offers alongside their related property gives users a clear overview of interested buyers, proposed prices and offer statuses making it easier to compare proposals Completed Chapter 7 --- estate/__manifest__.py | 1 + estate/models/estate_property.py | 1 + estate/views/estate_porperty_offer.xml | 28 ++++++++++++++++++++++++++ estate/views/estate_property_views.xml | 3 +++ 4 files changed, 33 insertions(+) create mode 100644 estate/views/estate_porperty_offer.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 49d62e09f48..8114e142acc 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -8,6 +8,7 @@ "views/estate_property_views.xml", "views/estate_property_type.xml", "views/estate_property_tag.xml", + "views/estate_porperty_offer.xml", "views/estate_menus.xml", ], "application": True, diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d54ecedfa9f..291d6ffc683 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -49,3 +49,4 @@ class EstateProperty(models.Model): "res.users", string="Salesman", default=lambda self: self.env.user ) tags_id = fields.Many2many("estate.property.tag", string="Property Tags") + offer_ids = fields.One2many("estate.property.offer", inverse_name="property_id") diff --git a/estate/views/estate_porperty_offer.xml b/estate/views/estate_porperty_offer.xml new file mode 100644 index 00000000000..7ba2a797eae --- /dev/null +++ b/estate/views/estate_porperty_offer.xml @@ -0,0 +1,28 @@ + + + + estate.property.offer.list + estate.property.offer + + + + + + + + + + + estate.property.offer.form + estate.property.offer + +
+ + + + + +
+
+
+
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index ea964fb0a45..d9e2721c440 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -61,6 +61,9 @@
+ + + From 24b748b666d33e2695f4a363352d1180cafc0cd3 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Fri, 31 Jul 2026 15:42:21 +0530 Subject: [PATCH 15/21] [ADD] estate: add application icon Make the Estate application easier to identify A dedicated icon provides a clear visual identity and helps users quickly recognize the Estate application while navigating --- estate/static/description/icon.png | Bin 0 -> 25294 bytes estate/views/estate_menus.xml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 estate/static/description/icon.png diff --git a/estate/static/description/icon.png b/estate/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..daae0367a012b9e412c0457126445b6e72b2e3fc GIT binary patch literal 25294 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 literal 0 HcmV?d00001 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index af3932a7b6c..c404e290bde 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,6 +1,6 @@ - + From 47b7ca204ee454eebc3152676640c257d0e0c97b Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Fri, 31 Jul 2026 17:39:02 +0530 Subject: [PATCH 16/21] [IMP] estate: provide total property area Give users a complete view of the usable area of each property Providing the combined living and garden area keeps the total area accurate when property dimensions change without requiring manual calculations --- estate/models/estate_property.py | 10 +++++++++- estate/views/estate_property_views.xml | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 291d6ffc683..d39840a8d4a 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import models, fields +from odoo import models, fields, api class EstateProperty(models.Model): @@ -50,3 +50,11 @@ class EstateProperty(models.Model): ) tags_id = fields.Many2many("estate.property.tag", string="Property Tags") offer_ids = fields.One2many("estate.property.offer", inverse_name="property_id") + total_area = fields.Integer( + compute="_compute_total_area", string="Total Area", store=True + ) + + @api.depends("living_area", "garden_area") + def _compute_total_area(self): + for record in self: + record.total_area = record.living_area + record.garden_area diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index d9e2721c440..7eda078b76e 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -19,7 +19,8 @@ - + + @@ -59,6 +60,7 @@ + From b985329d0c7832785e57b7e968196591fcbc359a Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Mon, 3 Aug 2026 18:21:42 +0530 Subject: [PATCH 17/21] [IMP] estate: improve offer evaluation Make the strongest buyer offer immediately visible Providing the best offer directly on the property record reduces the need to inspect every offer when evaluating a property --- estate/__manifest__.py | 2 +- estate/models/estate_property.py | 9 +++++++++ ...tate_porperty_offer.xml => estate_property_offer.xml} | 0 estate/views/estate_property_views.xml | 8 +++++--- 4 files changed, 15 insertions(+), 4 deletions(-) rename estate/views/{estate_porperty_offer.xml => estate_property_offer.xml} (100%) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 8114e142acc..6fecc99b89c 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -8,7 +8,7 @@ "views/estate_property_views.xml", "views/estate_property_type.xml", "views/estate_property_tag.xml", - "views/estate_porperty_offer.xml", + "views/estate_property_offer.xml", "views/estate_menus.xml", ], "application": True, diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d39840a8d4a..619bef4fa3a 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -53,8 +53,17 @@ class EstateProperty(models.Model): total_area = fields.Integer( compute="_compute_total_area", string="Total Area", store=True ) + best_price = fields.Float(compute="_compute_best_price", string="Best Offer") @api.depends("living_area", "garden_area") def _compute_total_area(self): for record in self: record.total_area = record.living_area + record.garden_area + + @api.depends("offer_ids.price") + def _compute_best_price(self): + for record in self: + if record.offer_ids: + record.best_price = max(record.offer_ids.mapped("price")) + else: + record.best_price = 0.0 diff --git a/estate/views/estate_porperty_offer.xml b/estate/views/estate_property_offer.xml similarity index 100% rename from estate/views/estate_porperty_offer.xml rename to estate/views/estate_property_offer.xml diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 7eda078b76e..a38dab96809 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,7 +1,7 @@ - Properties + Properties estate.property list,form @@ -18,9 +18,10 @@ - + - + + @@ -45,6 +46,7 @@
+ From 010d37b0539e0c4afd5ae83d3caeff27d6973965 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Tue, 4 Aug 2026 18:41:28 +0530 Subject: [PATCH 18/21] [IMP] estate: refine property search Improve the efficiency of finding property listings Dedicated filters help users focus on properties matching their criteria while grouping options provide better organization and navigation across property records --- estate/views/estate_property_views.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index a38dab96809..587c71fd860 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -94,8 +94,14 @@ + + + + + + From a502ea964f7bdbdae24879ecc23f824ab37791d8 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Wed, 5 Aug 2026 16:42:24 +0530 Subject: [PATCH 19/21] [IMP] estate: manage offer validity Improve the management of property offers by tracking their validity Providing an offer deadline helps users identify when an offer expires while synchronizing it with the validity period keeps offer information consistent as business requirements change --- estate/models/estate_property_offer.py | 21 ++++++++++++++++++++- estate/views/estate_property_offer.xml | 4 ++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 3e498bd2581..0dae16f2341 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,4 @@ -from odoo import models, fields +from odoo import models, fields, api class estate_property_offer(models.Model): @@ -11,3 +11,22 @@ class estate_property_offer(models.Model): ) partner_id = fields.Many2one("res.partner", required=True) property_id = fields.Many2one("estate.property", required=True) + validity = fields.Integer(default=7) + date_deadline = fields.Date( + compute="_compute_date_deadline", inverse="_inverse_date_deadline" + ) + + @api.depends("create_date", "validity") + def _compute_date_deadline(self): + for record in self: + create_date = record.create_date or fields.Date.today() + record.date_deadline = fields.Date.add( + fields.Date.to_date(create_date), days=record.validity + ) + + def _inverse_date_deadline(self): + for record in self: + create_date = record.create_date or fields.Date.today() + record.validity = ( + record.date_deadline - fields.Date.to_date(create_date) + ).days diff --git a/estate/views/estate_property_offer.xml b/estate/views/estate_property_offer.xml index 7ba2a797eae..3438742cbd6 100644 --- a/estate/views/estate_property_offer.xml +++ b/estate/views/estate_property_offer.xml @@ -7,6 +7,8 @@ + +
@@ -20,6 +22,8 @@ + + From 4e7e50897407da26696f98921193840c2dc269c3 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Thu, 6 Aug 2026 16:53:28 +0530 Subject: [PATCH 20/21] [IMP] estate: assist garden information entry Improve the user experience when entering garden information Automatically suggest relevant values while editing a property and clear them when they are no longer applicable. Completed Chapter 8 --- estate/models/estate_property.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 619bef4fa3a..eb379bc4754 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -67,3 +67,12 @@ def _compute_best_price(self): record.best_price = max(record.offer_ids.mapped("price")) else: record.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 From fb2a85eb867f07776373e96e5dfc82b838419916 Mon Sep 17 00:00:00 2001 From: pryes-odoo Date: Fri, 7 Aug 2026 17:24:25 +0530 Subject: [PATCH 21/21] [IMP] estate: preserve garden information during editing Avoid overwriting existing garden information when editing properties Restore the property's current garden details instead of suggesting default values while continuing to assist data entry for newly created properties --- estate/models/estate_property.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index eb379bc4754..977a6cbeef4 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -71,8 +71,12 @@ def _compute_best_price(self): @api.onchange("garden") def _onchange_garden(self): if self.garden: - self.garden_area = 10 - self.garden_orientation = "north" + if self._origin: + self.garden_area = self._origin.garden_area + self.garden_orientation = self._origin.garden_orientation + else: + self.garden_area = 10 + self.garden_orientation = "north" else: self.garden_area = 0 self.garden_orientation = False