From 607f91d2617c4fb2480cd5ed984067cfd4e95c18 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Fri, 3 Jul 2026 18:08:19 +0530 Subject: [PATCH 01/12] [ADD] estate: 'add new modules' Initialize the estate module by adding the required module configuration files. This establishes the basic structure needed for future development and allows Odoo to recognize the module. --- 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..de94a36bcd2 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,10 @@ +{ + "name":"Real Estate", + + "author":"Mrunmayee Gore", + "description":"TRAINING MODULE ", + "category":"tutorials" + "application + + +} \ No newline at end of file From ce43cf1a94fcafabe7a9430c52cb9e5af768cb37 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Fri, 3 Jul 2026 18:12:15 +0530 Subject: [PATCH 02/12] [ADD] estate: 'add new modules' Initialize the estate module by adding the required module configuration files. This establishes the basic structure needed for future development and allows Odoo to recognize the module. --- estate/__manifest__.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index de94a36bcd2..2e4bf8df67b 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,10 +1,10 @@ { - "name":"Real Estate", - - "author":"Mrunmayee Gore", - "description":"TRAINING MODULE ", - "category":"tutorials" - "application - - -} \ No newline at end of file + 'name': 'Real Estate', + 'version': '1.0', + 'author': 'Mrunmayee', + 'depends': ['base'], + 'application': True, + 'category': 'tutorials', + 'installabe': True, + 'license': 'LGPL-3', +} From 7f8c9e9e548c48c3b8d7a844dd203899c854cad2 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Mon, 6 Jul 2026 18:18:56 +0530 Subject: [PATCH 03/12] [ADD] estate: create property model Create the basic property model for the Real Estate module. This model allows storing essential property information and provides the base structure for adding more features. task = chapter 3 completed --- estate/__init__.py | 1 + estate/__manifest__.py | 16 ++++++++-------- estate/models/__init__.py | 1 + estate/models/estate_property.py | 27 +++++++++++++++++++++++++++ 4 files changed, 37 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 2e4bf8df67b..5e317b0a4dc 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,10 +1,10 @@ { - 'name': 'Real Estate', - 'version': '1.0', - 'author': 'Mrunmayee', - 'depends': ['base'], - 'application': True, - 'category': 'tutorials', - 'installabe': True, - 'license': 'LGPL-3', + "name": "Real Estate", + "version": "1.0", + "author": "Mrunmayee", + "depends": ["base"], + "application": True, + "category": "tutorials", + "installabe": True, + "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..4af27ab57af --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,27 @@ +from odoo import models, fields + + +class EstateProperty(models.Model): + _name = "estate.property" + _description = "Real 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( + selection=[ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ] + ) From a9cc58d95fa24de35ecb317fda7ef5a3d3311964 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Tue, 7 Jul 2026 17:12:09 +0530 Subject: [PATCH 04/12] [ADD] estate: add access rights for estate.property Newly created models are inaccessible by default in Odoo. Define access rights so Internal Users can interact with the estate.property model and remove the missing access rules warning. Task Completed chapter 4 --- estate/__manifest__.py | 3 +++ estate/security/ir.model.access.csv | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 5e317b0a4dc..00fa2d78116 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,4 +7,7 @@ "category": "tutorials", "installabe": True, "license": "LGPL-3", + "data": [ + "security/ir.model.access.csv", + ], } diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..32389642d4f --- /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,access_estate_property,model_estate_property,base.group_user,1,1,1,1 From 707c8621603c61d5108fcde538100de467021313 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Fri, 10 Jul 2026 18:53:45 +0530 Subject: [PATCH 05/12] [IMP] estate: prepare property management interface - Allow users to access and manage property records from the UI. - Improve data consistency by protecting important field values. - Prevent unwanted data from being copied to duplicate records. - Reduce manual work by providing default field values. - Prepare the property model for future business workflows by introducing state fields. Task Completed chapter 5 --- estate/__manifest__.py | 2 ++ estate/models/estate_property.py | 21 ++++++++++++++++++--- estate/views/estate_menus.xml | 6 ++++++ estate/views/estate_property_views.xml | 10 ++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 estate/views/estate_menus.xml create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 00fa2d78116..19cb2cc323b 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -9,5 +9,7 @@ "license": "LGPL-3", "data": [ "security/ir.model.access.csv", + "views/estate_property_views.xml", + "views/estate_menus.xml", ], } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 4af27ab57af..1db22d08955 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -8,10 +8,12 @@ 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() + selling_price = fields.Float(readonly=True, copy=False) + bedrooms = fields.Integer(default=2) living_area = fields.Integer() facades = fields.Integer() garage = fields.Boolean() @@ -25,3 +27,16 @@ class EstateProperty(models.Model): ("west", "West"), ] ) + active = fields.Boolean(default=True) + state = fields.Selection( + selection=[ + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), + ], + required=True, + copy=False, + default="new", + ) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..e87c51cf7fa --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..d36caa6a08f --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,10 @@ + + + + Properties + estate.property + list,form + + + + From dfadfd1ea7ac0e465452ef901e5599edfee696d8 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Thu, 23 Jul 2026 14:05:09 +0530 Subject: [PATCH 06/12] [IMP] estate: add basic property views The default generated views are not suitable for a business application. A custom UI is required to improve data organization and allow users to efficiently manage and search property records as the application grows. Task Completed chapter 6 --- estate/__manifest__.py | 2 +- estate/models/estate_property.py | 1 - estate/views/estate_property_views.xml | 89 ++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 2 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 19cb2cc323b..4c5c1cd33f1 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -5,7 +5,7 @@ "depends": ["base"], "application": True, "category": "tutorials", - "installabe": True, + "installable": True, "license": "LGPL-3", "data": [ "security/ir.model.access.csv", diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 1db22d08955..87df44ed116 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -4,7 +4,6 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Real Estate Property" - name = fields.Char(required=True) description = fields.Text() postcode = fields.Char() diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index d36caa6a08f..f4111e72195 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -6,5 +6,94 @@ list,form + + estate.property.list + estate.property + + + + + + + + + + + + + + + estate.property.form + estate.property + +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + estate.property.search + estate.property + + + + + + + + + + + + + + + + + + + + + + + + From 793bd8ead1c866dd291fa1f9aa9f676438a72eee Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Tue, 28 Jul 2026 16:20:05 +0530 Subject: [PATCH 07/12] [ADD] estate: enable structured property categorization Introduce a dedicated property type model to improve how properties are organized and managed within the application. - Centralize the management of property types - Allow properties to be assigned reusable categories - Improve the user experience when organizing listings - Simplify property organization and maintenance --- 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 | 2 ++ estate/views/estate_menus.xml | 6 ++++-- estate/views/estate_property_type_view.xml | 9 +++++++++ estate/views/estate_property_views.xml | 3 +++ 8 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/views/estate_property_type_view.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 4c5c1cd33f1..67c6bfc9d13 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -10,6 +10,7 @@ "data": [ "security/ir.model.access.csv", "views/estate_property_views.xml", + "views/estate_property_type_view.xml", "views/estate_menus.xml", ], } 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 87df44ed116..27e4e1dc946 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -39,3 +39,4 @@ class EstateProperty(models.Model): copy=False, default="new", ) + 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..6092c30b748 --- /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 = "Property Type" + + name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 32389642d4f..eff4c41cdda 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,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 + diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index e87c51cf7fa..5921358324b 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,6 +1,8 @@ - - + + + + " diff --git a/estate/views/estate_property_type_view.xml b/estate/views/estate_property_type_view.xml new file mode 100644 index 00000000000..4d67aab4cc2 --- /dev/null +++ b/estate/views/estate_property_type_view.xml @@ -0,0 +1,9 @@ + + + + Property Types + estate.property.type + list,form + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index f4111e72195..cc764629e70 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -18,6 +18,7 @@ + @@ -35,6 +36,7 @@ + @@ -68,6 +70,7 @@ + From 89ba8b5f45ebec7e23e03404dfa27b455a573a4f Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Wed, 29 Jul 2026 12:37:41 +0530 Subject: [PATCH 08/12] [ADD] estate: support property ownership and tagging Improve property management by introducing buyer and salesperson relationships together with reusable property tags. Associate properties with buyers and salespersons, automatically assign the current user as the default salesperson, prevent buyer information from being copied during duplication, and introduce the Property Tag model with its views, menu, action, access rights, and a many2many relationship for assigning multiple tags to properties. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 5 +++++ 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_views.xml | 8 ++++++++ estate/views/estate_property_views.xml | 10 ++++++++++ 8 files changed, 35 insertions(+) create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/views/estate_property_tag_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 67c6bfc9d13..d355fa2f363 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,6 +11,7 @@ "security/ir.model.access.csv", "views/estate_property_views.xml", "views/estate_property_type_view.xml", + "views/estate_property_tag_views.xml", "views/estate_menus.xml", ], } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 40092a2d810..c620ac481a3 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,2 +1,3 @@ from . import estate_property from . import estate_property_type +from . import estate_property_tag diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 27e4e1dc946..d93c2bc4198 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -40,3 +40,8 @@ class EstateProperty(models.Model): default="new", ) 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="Salesperson", default=lambda self: self.env.user + ) + tag_ids = 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..7d6f197c1eb --- /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 = "Property Tag" + + name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index eff4c41cdda..8be0b030a67 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,4 +1,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 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 5921358324b..da9c075c985 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -5,4 +5,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..4dcd3674e34 --- /dev/null +++ b/estate/views/estate_property_tag_views.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 cc764629e70..701dc2acf31 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -19,6 +19,7 @@ + @@ -34,6 +35,9 @@ + + + @@ -58,6 +62,12 @@ + + + + + + From dfdf6eda254296173a94b5a1cdb2ac0134222635 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Fri, 31 Jul 2026 16:20:03 +0530 Subject: [PATCH 09/12] [ADD] estate: support property offers Allow properties to track offers from potential buyers without requiring a dedicated menu, keeping offer management within the property workflow. Introduce the Property Offer model with its views and access rights, link offers to properties through a many2one relationship, and expose them on the property form using a one2many field. Task Completed chapter 7 --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 1 + estate/models/estate_property_offer.py | 17 +++++++++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_property_offer_views.xml | 30 ++++++++++++++++++++ estate/views/estate_property_views.xml | 17 +++++------ 7 files changed, 60 insertions(+), 8 deletions(-) create mode 100644 estate/models/estate_property_offer.py create mode 100644 estate/views/estate_property_offer_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index d355fa2f363..f4427a49bdb 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -12,6 +12,7 @@ "views/estate_property_views.xml", "views/estate_property_type_view.xml", "views/estate_property_tag_views.xml", + "views/estate_property_offer_views.xml", "views/estate_menus.xml", ], } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index c620ac481a3..2f1821a39c1 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,3 +1,4 @@ from . import estate_property from . import estate_property_type from . import estate_property_tag +from . import estate_property_offer diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d93c2bc4198..7b118ba09c4 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -45,3 +45,4 @@ class EstateProperty(models.Model): "res.users", string="Salesperson", default=lambda self: self.env.user ) tag_ids = fields.Many2many("estate.property.tag", string=" Property Tags") + offer_ids = 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..9471ea482bd --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,17 @@ +from odoo import models, fields + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Real Esate Property Offer" + + price = fields.Float() + status = fields.Selection( + selection=[ + ("accepted", "Accepted"), + ("refused", "Refused"), + ], + 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 8be0b030a67..c097c4b42cb 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -2,4 +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_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml new file mode 100644 index 00000000000..5aa36c64087 --- /dev/null +++ b/estate/views/estate_property_offer_views.xml @@ -0,0 +1,30 @@ + + + + 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 701dc2acf31..22d6e9fb583 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -62,6 +62,15 @@
+ + + + + + + + + @@ -100,13 +109,5 @@
- - - - - - - - From a96ee70653a4e56faf7f858f6ce15b83f48b31ff Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Wed, 5 Aug 2026 16:43:59 +0530 Subject: [PATCH 10/12] [IMP] estate: address review comments - Follow Odoo coding conventions for string quoting - Reorder model fields alphabetically - Improve code consistency and readability - Apply requested review changes --- estate/__manifest__.py | 2 +- estate/models/estate_property.py | 29 +++++++++++++------------- estate/views/estate_property_views.xml | 6 ++---- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index f4427a49bdb..26550b69c5f 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,7 +1,7 @@ { "name": "Real Estate", "version": "1.0", - "author": "Mrunmayee", + "author": "Odoo S.A.", "depends": ["base"], "application": True, "category": "tutorials", diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 7b118ba09c4..8a6ace8259e 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -4,16 +4,15 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Real Estate Property" - name = fields.Char(required=True) - description = fields.Text() - postcode = fields.Char() + + active = fields.Boolean(default=True) + bedrooms = fields.Integer(default=2) + buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) date_availability = fields.Date( copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3) ) + description = fields.Text() expected_price = fields.Float(required=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() @@ -26,7 +25,15 @@ class EstateProperty(models.Model): ("west", "West"), ] ) - active = fields.Boolean(default=True) + living_area = fields.Integer() + name = fields.Char(required=True) + offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers") + postcode = fields.Char() + property_type_id = fields.Many2one("estate.property.type", string="Property Type") + salesperson_id = fields.Many2one( + "res.users", string="Salesperson", default=lambda self: self.env.user + ) + selling_price = fields.Float(readonly=True, copy=False) state = fields.Selection( selection=[ ("new", "New"), @@ -39,10 +46,4 @@ class EstateProperty(models.Model): copy=False, default="new", ) - 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="Salesperson", default=lambda self: self.env.user - ) - tag_ids = fields.Many2many("estate.property.tag", string=" Property Tags") - offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers") + tag_ids = fields.Many2many("estate.property.tag", string="Property Tags") diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 22d6e9fb583..1f579c83bf5 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -99,13 +99,11 @@ - + domain="[('state', 'in', ['new', 'offer_received'])]"/> - + context="{'group_by': 'postcode'}"/>
From 8a320188c2ec1bdaf80fa735f2f68387b7acb764 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Thu, 6 Aug 2026 15:14:07 +0530 Subject: [PATCH 11/12] [ADD] estate: compute total area The property total area should be derived automatically to ensure data consistency and avoid manual calculation. Added a computed field that calculates the total area from the living area and garden area, and displayed it in the property form view. --- estate/models/estate_property.py | 8 +++++++- estate/views/estate_property_views.xml | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 8a6ace8259e..fd3f9262179 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 api, fields, models class EstateProperty(models.Model): @@ -47,3 +47,9 @@ class EstateProperty(models.Model): default="new", ) tag_ids = fields.Many2many("estate.property.tag", string="Property Tags") + total_area = fields.Integer(compute="_compute_total_area") + + @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 1f579c83bf5..c7958700950 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -60,6 +60,7 @@ + From a0c9f8d0c6d52b3c082e0c9a6363e32c17f71e19 Mon Sep 17 00:00:00 2001 From: mrgor-odoo Date: Thu, 6 Aug 2026 18:03:58 +0530 Subject: [PATCH 12/12] [ADD] estate: compute best offer price The property best offer should be computed automatically from the related offers to ensure it always reflects the highest available offer. Added the computed `best_price` field using the related `offer_ids.price` dependency and displayed it in the property form view. --- estate/models/estate_property.py | 45 +++++++++++++++----------- estate/views/estate_property_views.xml | 1 + 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index fd3f9262179..1ca3d251327 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -2,12 +2,13 @@ class EstateProperty(models.Model): - _name = "estate.property" + _name = 'estate.property' _description = "Real Estate Property" active = fields.Boolean(default=True) bedrooms = fields.Integer(default=2) - buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) + best_price = fields.Float(compute='_compute_best_price') + buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False) date_availability = fields.Date( copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3) ) @@ -19,37 +20,45 @@ class EstateProperty(models.Model): garden_area = fields.Integer() garden_orientation = fields.Selection( selection=[ - ("north", "North"), - ("south", "South"), - ("east", "East"), - ("west", "West"), + ('north', "North"), + ('south', "South"), + ('east', "East"), + ('west', "West"), ] ) living_area = fields.Integer() name = fields.Char(required=True) - offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers") + offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") postcode = fields.Char() - property_type_id = fields.Many2one("estate.property.type", string="Property Type") + property_type_id = fields.Many2one('estate.property.type', string="Property Type") salesperson_id = fields.Many2one( - "res.users", string="Salesperson", default=lambda self: self.env.user + 'res.users', string="Salesperson", default=lambda self: self.env.user ) selling_price = fields.Float(readonly=True, copy=False) state = fields.Selection( selection=[ - ("new", "New"), - ("offer_received", "Offer Received"), - ("offer_accepted", "Offer Accepted"), - ("sold", "Sold"), - ("cancelled", "Cancelled"), + ('new', "New"), + ('offer_received', "Offer Received"), + ('offer_accepted', "Offer Accepted"), + ('sold', "Sold"), + ('cancelled', "Cancelled"), ], required=True, copy=False, - default="new", + default='new', ) - tag_ids = fields.Many2many("estate.property.tag", string="Property Tags") - total_area = fields.Integer(compute="_compute_total_area") + tag_ids = fields.Many2many('estate.property.tag', string="Property Tags") + total_area = fields.Integer(compute='_compute_total_area') - @api.depends("living_area", "garden_area") + @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_property_views.xml b/estate/views/estate_property_views.xml index c7958700950..33553c84fd7 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -46,6 +46,7 @@ +