From 0c81ab452bb81655c28f3d7f0daaae8803068810 Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Fri, 3 Jul 2026 17:00:51 +0530 Subject: [PATCH 01/10] [ADD] estate: add initial module structure Create the initial Real Estate module for the Server Framework 101 tutorial. This introduces the base module structure with the manifest and package initialization files required for further development. --- estate/__init__.py | 0 estate/__manifest__.py | 10 ++++++++++ estate/models/__init__.py | 0 3 files changed, 10 insertions(+) create mode 100644 estate/__init__.py create mode 100644 estate/__manifest__.py create mode 100644 estate/models/__init__.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..765406975fb --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': 'Real Estate', + 'version': '1.0', + 'author': 'yacha', + 'depends': ['base'], + 'application': True, + 'category': 'Tutorials', + 'installable': True, + 'license': 'LGPL-3' +} diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..e69de29bb2d From f064b95e6bcdd4aa48ae9fabbd921f2380908940 Mon Sep 17 00:00:00 2001 From: yacha Date: Mon, 6 Jul 2026 17:55:27 +0530 Subject: [PATCH 02/10] [ADD] estate: add property model and basic fields proper --- estate/__init__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 27 +++++++++++++++++++++++++++ 3 files changed, 29 insertions(+) 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/models/__init__.py b/estate/models/__init__.py index e69de29bb2d..5e1963c9d2f 100644 --- a/estate/models/__init__.py +++ 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..78eb2568d09 --- /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( + [ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ] + ) From 66e5c64883849123837b44916097476d29a14143 Mon Sep 17 00:00:00 2001 From: yacha Date: Tue, 7 Jul 2026 18:11:29 +0530 Subject: [PATCH 03/10] [ADD] estate: Security Access Granted --- estate/__manifest__.py | 17 +++++++++-------- estate/security/ir.model.access.csv | 2 ++ 2 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 765406975fb..ba0b3ed9c20 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,10 +1,11 @@ { - 'name': 'Real Estate', - 'version': '1.0', - 'author': 'yacha', - 'depends': ['base'], - 'application': True, - 'category': 'Tutorials', - 'installable': True, - 'license': 'LGPL-3' + "name": "Real Estate", + "version": "1.0", + "author": "yacha", + "depends": ["base"], + "application": True, + "category": "Tutorials", + "installable": 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..0e11f47e58d --- /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 \ No newline at end of file From 7d130c1bc639d2b5d82593e987caa3f54206e299 Mon Sep 17 00:00:00 2001 From: yacha Date: Thu, 9 Jul 2026 17:43:09 +0530 Subject: [PATCH 04/10] [ADD] estate: add menus and model field attributes Implemented Chapter 5 of the Odoo Server Framework tutorial. - Added window action for estate.property - Split XML into estate_property_views.xml and estate_menus.xml - Added three-level menu hierarchy - Added readonly and copy attributes - Added default values for bedrooms and availability date - Added reserved fields active and state --- estate/__manifest__.py | 6 ++++- estate/models/estate_property.py | 31 +++++++++++++++++++++----- estate/views/estate_menus.xml | 21 +++++++++++++++++ estate/views/estate_property_views.xml | 11 +++++++++ 4 files changed, 63 insertions(+), 6 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 ba0b3ed9c20..ad3ebaa49d5 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,5 +7,9 @@ "category": "Tutorials", "installable": True, "license": "LGPL-3", - "data": ["security/ir.model.access.csv"], + "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 78eb2568d09..47fd06f797d 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,17 +1,25 @@ -from odoo import models, fields +from odoo import api, models, fields +from dateutil.relativedelta import relativedelta + + +@api.model +def _default_date_availability(self): + return fields.Date.today() + relativedelta(months=3) class EstateProperty(models.Model): _name = "estate.property" _description = "Real Estate Property" - name = fields.Char(required=True) + active = fields.Boolean() + + name = fields.Char(required=True, default="Unknown") description = fields.Text() postcode = fields.Char() - date_availability = fields.Date() + date_availability = fields.Date(copy=False, default=_default_date_availability) 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 +33,16 @@ class EstateProperty(models.Model): ("west", "West"), ] ) + state = fields.Selection( + [ + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), + ], + string="State", + 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..a91ca33bee7 --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ 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..00e611be6fe --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,11 @@ + + + + Properties + estate.property + list,form + + + \ No newline at end of file From 754791c61c2e9c0348ab277e615514a85f4850d3 Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Mon, 20 Jul 2026 18:51:23 +0530 Subject: [PATCH 05/10] [IMP] estate: add basic list and form views Introduce explicit list and form views for the estate.property model. The autogenerated views are sufficient for basic testing but do not provide a structured user interface. Adding custom XML views prepares the module for subsequent tutorial chapters, where the form and list views will be extended with notebooks, search views, widgets, and additional UI customizations. --- estate/views/estate_property_views.xml | 69 +++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 00e611be6fe..7290d58de62 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,5 +1,72 @@ + + + estate.property.listview + estate.property + + + + + + + + + + + + + + + estate.property + +
+ + + +

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ @@ -8,4 +75,4 @@ list,form -
\ No newline at end of file + From 563084f18c92bbb27b91fe9c5321e1125b039f3a Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Tue, 21 Jul 2026 18:43:26 +0530 Subject: [PATCH 06/10] [IMP] estate: add active field to estate.property Add the active field to support record archiving. --- estate/models/estate_property.py | 2 +- estate/views/estate_property_views.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 47fd06f797d..ef4f6e38c86 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -11,7 +11,7 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Real Estate Property" - active = fields.Boolean() + active = fields.Boolean(default=True) name = fields.Char(required=True, default="Unknown") description = fields.Text() diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 7290d58de62..2ae8fcd4cb6 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -58,6 +58,7 @@ + From 52b96f3f5e8243343d239b7f47cec38f2b66555d Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Mon, 27 Jul 2026 18:49:14 +0530 Subject: [PATCH 07/10] [IMP] estate: improve property search experience Help users find properties more efficiently by providing search shortcuts, a quick filter for available properties, and the ability to group records by postcode. This makes day-to-day property management faster as users can locate relevant records without manually browsing through the entire list. --- estate/views/estate_property_views.xml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 2ae8fcd4cb6..1ab8c7574f7 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -68,6 +68,26 @@ + + estate.property.search + estate.property + + + + + + + + + + + + + + + + + From a1d882c948f3df0462e23fb6348c7846ab5cccf3 Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Wed, 29 Jul 2026 18:45:27 +0530 Subject: [PATCH 08/10] [ADD] estate: improved property information management Add the ability to classify properties by their type and keep track of the buyer and the responsible salesperson. This makes property records more complete, easier to manage, and prepares the system for the complete property sales process. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 8 ++++++++ estate/models/estate_property_type.py | 8 ++++++++ estate/security/ir.model.access.csv | 3 ++- estate/views/estate_menus.xml | 10 ++++++++++ estate/views/estate_property_type_views.xml | 12 ++++++++++++ estate/views/estate_property_views.xml | 10 ++++++++++ 8 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ad3ebaa49d5..0109e8f4c8c 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_views.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 ef4f6e38c86..0dcd9af3bef 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -46,3 +46,11 @@ 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 + ) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..ad121b33163 --- /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 = "Real 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 0e11f47e58d..ac680bd78a6 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 -access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file +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 \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index a91ca33bee7..6c49ae29b97 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -15,6 +15,16 @@ + + + + + + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..9a98e294c57 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,12 @@ + + + + + Property Types + estate.property.type + list,form + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 1ab8c7574f7..bbd5b4459af 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -9,6 +9,7 @@ + @@ -36,6 +37,7 @@ + @@ -59,6 +61,13 @@ + + + + + + + @@ -74,6 +83,7 @@ + From b83e68dacf104f2e6cfb9c82f52c4405dc4d1e81 Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Fri, 31 Jul 2026 18:47:10 +0530 Subject: [PATCH 09/10] [ADD] estate: enhance property classification Introduce property tags to classify and organize estate records using many-to-many relationships. This improves property categorization, enables flexible tagging of listings, and lays the foundation for advanced search, filtering, and future business features. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 2 ++ estate/models/estate_property_tag.py | 8 ++++++++ estate/security/ir.model.access.csv | 3 ++- estate/views/estate_menus.xml | 4 ++++ estate/views/estate_property_tag_views.xml | 12 ++++++++++++ estate/views/estate_property_views.xml | 2 ++ 8 files changed, 32 insertions(+), 1 deletion(-) 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 0109e8f4c8c..9f7587741d9 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_views.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 0dcd9af3bef..e5150b2e931 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -54,3 +54,5 @@ class EstateProperty(models.Model): salesperson_id = fields.Many2one( "res.users", string="Salesperson", default=lambda self: self.env.user ) + + tag_ids = fields.Many2many("estate.property.tag", string="Tags") diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..3f730299abb --- /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 = "Real 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 ac680bd78a6..2f5005f9234 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 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 \ No newline at end of file +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 \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 6c49ae29b97..e43031ee108 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -22,6 +22,10 @@ + + diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml new file mode 100644 index 00000000000..f2ba7700e7b --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,12 @@ + + + + + Property Tags + estate.property.tag + list,form + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index bbd5b4459af..32ad4fa9115 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -10,6 +10,7 @@ + @@ -38,6 +39,7 @@ + From cbc80c61f6641eb2d9ea86f95a9715696ff043ed Mon Sep 17 00:00:00 2001 From: yacha-odoo Date: Fri, 7 Aug 2026 11:24:16 +0530 Subject: [PATCH 10/10] [ADD] estate: introduce property offer management Introduce a dedicated Property Offer model to record offers submitted by potential buyers for properties. Each offer stores the offered price, buyer, and current offer status, and is linked to a single property through relational fields. Display all related offers within the property form, enabling multiple offers to be managed from one place and preparing the estate module for the complete property selling workflow. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 2 ++ estate/models/estate_property_offer.py | 14 +++++++++ estate/security/ir.model.access.csv | 3 +- estate/views/estate_property_offer_views.xml | 32 ++++++++++++++++++++ estate/views/estate_property_views.xml | 7 +++-- 7 files changed, 57 insertions(+), 3 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 9f7587741d9..f18861433ab 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -12,6 +12,7 @@ "views/estate_property_views.xml", "views/estate_property_type_views.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 e5150b2e931..4874c49b24e 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -56,3 +56,5 @@ class EstateProperty(models.Model): ) tag_ids = fields.Many2many("estate.property.tag", string="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..bda51a9d147 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,14 @@ +from odoo import models, fields + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Estate Property Offer" + + price = fields.Float() + status = fields.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 2f5005f9234..05bd9eefba4 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 \ No newline at end of file +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 \ No newline at end of file diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml new file mode 100644 index 00000000000..29928dc0cea --- /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 + +
+ + + + + + + +
+
+
+ +
\ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 32ad4fa9115..2fab4845a11 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -10,7 +10,7 @@ - + @@ -66,12 +66,15 @@ - + + + +