From d87cc906f1d7640ac2077ed3121dff171355e35f Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Thu, 2 Jul 2026 18:11:48 +0530 Subject: [PATCH 01/19] [ADD] estate: initial module setup Add the basic structure for the estate module as part of the Odoo Server Framework 101 training. --- estate/__init__.py | 3 +++ estate/__manifest__.py | 5 +++++ 2 files changed, 8 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..eb7fb394659 --- /dev/null +++ b/estate/__init__.py @@ -0,0 +1,3 @@ +# estate/__init__.py + +from . import models \ No newline at end of file diff --git a/estate/__manifest__.py b/estate/__manifest__.py new file mode 100644 index 00000000000..a57eb8bae01 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,5 @@ +{ + 'name': 'Estate', + 'depends': ['base'], + 'application': True, +} \ No newline at end of file From 350ef88ea97ea6cace99be6cf4f630a41088c095 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Thu, 2 Jul 2026 18:14:46 +0530 Subject: [PATCH 02/19] [IMP] estate: added estate_property model --- estate/__init__.py | 1 - estate/__manifest__.py | 11 +++-- estate/models/__init__.py | 3 ++ estate/models/estate_property.py | 69 ++++++++++++++++++++++++++++++++ 4 files changed, 79 insertions(+), 5 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 eb7fb394659..33211e577b6 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1,3 +1,2 @@ # estate/__init__.py - from . import models \ No newline at end of file diff --git a/estate/__manifest__.py b/estate/__manifest__.py index a57eb8bae01..7528a3ced53 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,5 +1,8 @@ { - 'name': 'Estate', - 'depends': ['base'], - 'application': True, -} \ No newline at end of file + "name": "Estate", + "version": "1.0", + "depends": ["base"], + "application": True, + "category": "Tutorials", + "author": "Thakor Anish", +} diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..39cd975ecd7 --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1,3 @@ +# estate/models/__init__.py + +from . import estate_property \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py new file mode 100644 index 00000000000..3fb5213cad1 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,69 @@ +from odoo import fields, models + + +class EstateProperty(models.Model): + _name = "estate.property" + _description = "Real Estate Property" + + name = fields.Char( + string="Property Name", + required=True, + help="Name of the property", + index=True, + ) + + description = fields.Text( + string="Description" + ) + + postcode = fields.Char( + string="Postcode" + ) + + date_availability = fields.Date( + string="Available From" + ) + + expected_price = fields.Float( + string="Expected Price", + required=True, + help="Expected selling price of the property", + ) + + selling_price = fields.Float( + string="Selling Price" + ) + + bedrooms = fields.Integer( + string="Bedrooms" + ) + + living_area = fields.Integer( + string="Living Area (sqm)" + ) + + facades = fields.Integer( + string="Facades" + ) + + garage = fields.Boolean( + string="Garage" + ) + + garden = fields.Boolean( + string="Garden" + ) + + garden_area = fields.Integer( + string="Garden Area (sqm)" + ) + + garden_orientation = fields.Selection( + [ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ], + string="Garden Orientation", + ) \ No newline at end of file From bdaafbc7b45e152838609afbf1fa9947e91f72c9 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Fri, 3 Jul 2026 10:44:45 +0530 Subject: [PATCH 03/19] [LINT] Fix Code Formatting --- estate/__init__.py | 2 +- estate/models/__init__.py | 2 +- estate/models/estate_property.py | 42 +++++++++----------------------- 3 files changed, 13 insertions(+), 33 deletions(-) diff --git a/estate/__init__.py b/estate/__init__.py index 33211e577b6..2b06bb8ef07 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1,2 +1,2 @@ # estate/__init__.py -from . import models \ No newline at end of file +from . import models diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 39cd975ecd7..df9a3b1fcf5 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,3 +1,3 @@ # estate/models/__init__.py -from . import estate_property \ No newline at end of file +from . import estate_property diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 3fb5213cad1..ed672269991 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -12,17 +12,11 @@ class EstateProperty(models.Model): index=True, ) - description = fields.Text( - string="Description" - ) + description = fields.Text(string="Description") - postcode = fields.Char( - string="Postcode" - ) + postcode = fields.Char(string="Postcode") - date_availability = fields.Date( - string="Available From" - ) + date_availability = fields.Date(string="Available From") expected_price = fields.Float( string="Expected Price", @@ -30,33 +24,19 @@ class EstateProperty(models.Model): help="Expected selling price of the property", ) - selling_price = fields.Float( - string="Selling Price" - ) + selling_price = fields.Float(string="Selling Price") - bedrooms = fields.Integer( - string="Bedrooms" - ) + bedrooms = fields.Integer(string="Bedrooms") - living_area = fields.Integer( - string="Living Area (sqm)" - ) + living_area = fields.Integer(string="Living Area (sqm)") - facades = fields.Integer( - string="Facades" - ) + facades = fields.Integer(string="Facades") - garage = fields.Boolean( - string="Garage" - ) + garage = fields.Boolean(string="Garage") - garden = fields.Boolean( - string="Garden" - ) + garden = fields.Boolean(string="Garden") - garden_area = fields.Integer( - string="Garden Area (sqm)" - ) + garden_area = fields.Integer(string="Garden Area (sqm)") garden_orientation = fields.Selection( [ @@ -66,4 +46,4 @@ class EstateProperty(models.Model): ("west", "West"), ], string="Garden Orientation", - ) \ No newline at end of file + ) From 95e276028008b85aa2fac298bc2f07fa4fd94015 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Fri, 3 Jul 2026 10:59:38 +0530 Subject: [PATCH 04/19] [LINT] Fix Code Formatting and add module license --- estate/__manifest__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 7528a3ced53..49e31f8390e 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -5,4 +5,5 @@ "application": True, "category": "Tutorials", "author": "Thakor Anish", + "license": "LGPL-3", } From 5371919f445b93cb515ca07ab8f38a8ec0d9ff12 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Fri, 3 Jul 2026 11:14:01 +0530 Subject: [PATCH 05/19] [LINT] Fix Code Formatting and add lincense data and add security file(csv) --- estate/__manifest__.py | 3 +++ estate/models/security/ir.model.access.csv | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 estate/models/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 49e31f8390e..3fe4938a865 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -6,4 +6,7 @@ "category": "Tutorials", "author": "Thakor Anish", "license": "LGPL-3", + "data": [ + "security/ir.model.access.csv", + ], } diff --git a/estate/models/security/ir.model.access.csv b/estate/models/security/ir.model.access.csv new file mode 100644 index 00000000000..0e11f47e58d --- /dev/null +++ b/estate/models/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 f888899453aeaf67dc03881ce51c004b56b5b18d Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Fri, 3 Jul 2026 11:22:12 +0530 Subject: [PATCH 06/19] [LINT] Fix Code Formatting and add lincense data and add security file(csv) --- estate/{models => }/security/ir.model.access.csv | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename estate/{models => }/security/ir.model.access.csv (100%) diff --git a/estate/models/security/ir.model.access.csv b/estate/security/ir.model.access.csv similarity index 100% rename from estate/models/security/ir.model.access.csv rename to estate/security/ir.model.access.csv From a6e7ce2d05b37f3c691843190ad783759392bad2 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Fri, 3 Jul 2026 16:18:26 +0530 Subject: [PATCH 07/19] [IMP] estate: add basic UI and property defaults Introduce the initial user interface for the estate module by defining the window action and menu hierarchy required to access property records from the Odoo web client. This change makes the estate.property model accessible through the application, providing the foundation for interacting with records using the default list and form views before introducing custom views in later chapters. The property model is also improved by configuring field attributes and defaults. Read-only and copy behaviors are defined for system-managed fields, default values are added to reduce manual data entry, and the reserved active and state fields are introduced to support record archiving and future workflow-related features. --- estate/__manifest__.py | 2 + estate/models/estate_property.py | 59 ++++++++++++++++----------- estate/security/ir.model.access.csv | 2 - estate/view/estate_property_views.xml | 10 +++++ 4 files changed, 48 insertions(+), 25 deletions(-) delete mode 100644 estate/security/ir.model.access.csv create mode 100644 estate/view/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 3fe4938a865..8a23061b527 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -8,5 +8,7 @@ "license": "LGPL-3", "data": [ "security/ir.model.access.csv", + "view/estate_property_views.xml", + "view/estate_menus.xml", ], } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index ed672269991..be7013a3457 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,42 +1,41 @@ +from datetime import timedelta + from odoo import fields, models class EstateProperty(models.Model): _name = "estate.property" - _description = "Real Estate Property" - - name = fields.Char( - string="Property Name", - required=True, - help="Name of the property", - index=True, - ) + _description = "Estate Property" - description = fields.Text(string="Description") + name = fields.Char(required=True) - postcode = fields.Char(string="Postcode") + description = fields.Text() - date_availability = fields.Date(string="Available From") + postcode = fields.Char() - expected_price = fields.Float( - string="Expected Price", - required=True, - help="Expected selling price of the property", + date_availability = fields.Date( + copy=False, + default=lambda self: fields.Date.today() + timedelta(days=90), ) - selling_price = fields.Float(string="Selling Price") + expected_price = fields.Float(required=True) + + selling_price = fields.Float( + readonly=True, + copy=False, + ) - bedrooms = fields.Integer(string="Bedrooms") + bedrooms = fields.Integer(default=2) - living_area = fields.Integer(string="Living Area (sqm)") + living_area = fields.Integer() - facades = fields.Integer(string="Facades") + facades = fields.Integer() - garage = fields.Boolean(string="Garage") + garage = fields.Boolean() - garden = fields.Boolean(string="Garden") + garden = fields.Boolean() - garden_area = fields.Integer(string="Garden Area (sqm)") + garden_area = fields.Integer() garden_orientation = fields.Selection( [ @@ -44,6 +43,20 @@ class EstateProperty(models.Model): ("south", "South"), ("east", "East"), ("west", "West"), + ] + ) + + active = fields.Boolean(default=True) + + state = fields.Selection( + [ + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), ], - string="Garden Orientation", + required=True, + copy=False, + default="new", ) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv deleted file mode 100644 index 0e11f47e58d..00000000000 --- a/estate/security/ir.model.access.csv +++ /dev/null @@ -1,2 +0,0 @@ -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 diff --git a/estate/view/estate_property_views.xml b/estate/view/estate_property_views.xml new file mode 100644 index 00000000000..b97fd94ee63 --- /dev/null +++ b/estate/view/estate_property_views.xml @@ -0,0 +1,10 @@ + + + + + Properties + estate.property + list,form + + + \ No newline at end of file From 2f23484f829bf8845f3a6c9756267e0a93895861 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Fri, 3 Jul 2026 17:03:34 +0530 Subject: [PATCH 08/19] [IMP] estate: add basic UI and property defaults Introduce the initial user interface for the estate module by defining the window action and menu hierarchy required to access property records from the Odoo web client. This change makes the estate.property model accessible through the application, providing the foundation for interacting with records using the default list and form views before introducing custom views in later chapters. The property model is also improved by configuring field attributes and defaults. Read-only and copy behaviors are defined for system-managed fields, default values are added to reduce manual data entry, and the reserved active and state fields are introduced to support record archiving and future workflow-related features. --- estate/security/ir.model.access.csv | 2 ++ estate/view/estate_menus.xml | 14 ++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 estate/security/ir.model.access.csv create mode 100644 estate/view/estate_menus.xml 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 diff --git a/estate/view/estate_menus.xml b/estate/view/estate_menus.xml new file mode 100644 index 00000000000..e95db13978c --- /dev/null +++ b/estate/view/estate_menus.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file From 6583a65de503cd584e5c20e7a19745583b9eed83 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Mon, 6 Jul 2026 17:40:40 +0530 Subject: [PATCH 09/19] [IMP] estate: add custom list and form views Replace the automatically generated views with custom list and form views to provide a clearer and more user-friendly interface for managing estate properties. The custom views organize the property information into logical groups, making property creation and editing easier while exposing the most important fields directly from the list view. This change prepares the module for future UI enhancements such as custom search views, buttons and advanced form layouts introduced in later chapters. --- estate/models/estate_property.py | 2 +- estate/view/estate_property_views.xml | 60 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index be7013a3457..520de2a7983 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -18,7 +18,7 @@ class EstateProperty(models.Model): default=lambda self: fields.Date.today() + timedelta(days=90), ) - expected_price = fields.Float(required=True) + expected_price = fields.Float() selling_price = fields.Float( readonly=True, diff --git a/estate/view/estate_property_views.xml b/estate/view/estate_property_views.xml index b97fd94ee63..08128440287 100644 --- a/estate/view/estate_property_views.xml +++ b/estate/view/estate_property_views.xml @@ -1,10 +1,70 @@ + Properties estate.property list,form + + + estate.property.list + estate.property + + + + + + + + + + + + + + + + + estate.property.form + estate.property + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
\ No newline at end of file From 748158483e2d16a86669caef1b14b81481efaf4a Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Tue, 7 Jul 2026 18:58:00 +0530 Subject: [PATCH 10/19] [IMP] estate: Add search view for estate properties --- estate/view/estate_property_views.xml | 32 ++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/estate/view/estate_property_views.xml b/estate/view/estate_property_views.xml index 08128440287..3a7a121a2ef 100644 --- a/estate/view/estate_property_views.xml +++ b/estate/view/estate_property_views.xml @@ -12,9 +12,11 @@ estate.property.list estate.property + + @@ -25,7 +27,16 @@ - + + + estate.property.search + estate.property + + + + + + estate.property.form @@ -36,6 +47,7 @@ + @@ -58,6 +70,24 @@ + + + + + + + + + + + + + + + + + + From 5da110cf57a7260903d15f762f6431a03558be3a Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Wed, 8 Jul 2026 10:09:07 +0530 Subject: [PATCH 11/19] [ADD] estate: add property type model and relation --- estate/models/estate_property.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 520de2a7983..35a0532f5a0 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -8,6 +8,30 @@ class EstateProperty(models.Model): _description = "Estate Property" name = fields.Char(required=True) + 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="Tags", + ) + offer_ids = fields.One2many( + "estate.property.offer", + "property_id", + string="Offers", + ) description = fields.Text() From 953315055f9d45d6a3a76c297ef922bc8293c3cc Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Thu, 9 Jul 2026 14:21:50 +0530 Subject: [PATCH 12/19] [IMP] estate: add menus for property type and tag and custom search view --- estate/view/estate_menus.xml | 15 +++++++++++++++ estate/view/estate_property_views.xml | 17 ++++++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/estate/view/estate_menus.xml b/estate/view/estate_menus.xml index e95db13978c..74255db5a92 100644 --- a/estate/view/estate_menus.xml +++ b/estate/view/estate_menus.xml @@ -10,5 +10,20 @@ + + + + \ No newline at end of file diff --git a/estate/view/estate_property_views.xml b/estate/view/estate_property_views.xml index 3a7a121a2ef..975f5f83e8f 100644 --- a/estate/view/estate_property_views.xml +++ b/estate/view/estate_property_views.xml @@ -34,6 +34,14 @@ + + + + + @@ -44,16 +52,22 @@
+ +

+ +

- + + + @@ -65,6 +79,7 @@ + From bab61c079412a79936c62f9f2cae93025124c962 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Thu, 9 Jul 2026 14:41:03 +0530 Subject: [PATCH 13/19] [IMP] estate: add security access rules and update __init__.py and manifest file --- estate/__manifest__.py | 3 +++ estate/models/__init__.py | 3 +++ estate/security/ir.model.access.csv | 5 ++++- 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 8a23061b527..7061bccc374 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -9,6 +9,9 @@ "data": [ "security/ir.model.access.csv", "view/estate_property_views.xml", + "view/estate_property_type_views.xml", + "view/estate_property_tag_views.xml", + "view/estate_property_offer_views.xml", "view/estate_menus.xml", ], } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index df9a3b1fcf5..c156212c9c0 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,3 +1,6 @@ # estate/models/__init__.py from . import estate_property +from . import estate_property_type +from . import estate_property_tag +from . import estate_property_offer diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 0e11f47e58d..47cf706f8ea 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +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 \ 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_tag,estate.property.tag,model_estate_property_tag,base.group_user,1,1,1,1 +access_estate_property_offer,estate.property.offer,model_estate_property_offer,base.group_user,1,1,1,1 +access_estate_property_type,estate.property.type,model_estate_property_type,base.group_user,1,1,1,1 From f9dce554a879fb5398a19db93c9eac335ac34c1c Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Thu, 9 Jul 2026 14:55:07 +0530 Subject: [PATCH 14/19] [IMP] estate: Add property types, tags, offers, and model relations --- estate/models/estate_property_offer.py | 31 ++++++++++++++ estate/models/estate_property_tag.py | 8 ++++ estate/models/estate_property_type.py | 8 ++++ estate/view/estate_property_offer_views.xml | 45 +++++++++++++++++++++ estate/view/estate_property_tag_views.xml | 37 +++++++++++++++++ estate/view/estate_property_type_views.xml | 37 +++++++++++++++++ 6 files changed, 166 insertions(+) create mode 100644 estate/models/estate_property_offer.py create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/view/estate_property_offer_views.xml create mode 100644 estate/view/estate_property_tag_views.xml create mode 100644 estate/view/estate_property_type_views.xml diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..a39599edd47 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,31 @@ +from odoo import fields, models + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "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, + ) + offer_ids = fields.One2many( + "estate.property.offer", + "property_id", + string="Offers", + ) diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..9e477ca23b7 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Property Tag" + + name = fields.Char(required=True) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..ea6d79c3a10 --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyType(models.Model): + _name = "estate.property.type" + _description = "Property Type" + + name = fields.Char(required=True) diff --git a/estate/view/estate_property_offer_views.xml b/estate/view/estate_property_offer_views.xml new file mode 100644 index 00000000000..7f6ef5a1171 --- /dev/null +++ b/estate/view/estate_property_offer_views.xml @@ -0,0 +1,45 @@ + + + + + + Property Offers + estate.property.offer + list,form + + + + + estate.property.offer.list + estate.property.offer + + + + + + + + + + + + + + estate.property.offer.form + estate.property.offer + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/estate/view/estate_property_tag_views.xml b/estate/view/estate_property_tag_views.xml new file mode 100644 index 00000000000..f9da1ca3be2 --- /dev/null +++ b/estate/view/estate_property_tag_views.xml @@ -0,0 +1,37 @@ + + + + + + Property Tags + estate.property.tag + list,form + + + + + estate.property.tag.list + estate.property.tag + + + + + + + + + + estate.property.tag.form + estate.property.tag + +
+ + + + + +
+
+
+ +
\ No newline at end of file diff --git a/estate/view/estate_property_type_views.xml b/estate/view/estate_property_type_views.xml new file mode 100644 index 00000000000..c9d5ad89b87 --- /dev/null +++ b/estate/view/estate_property_type_views.xml @@ -0,0 +1,37 @@ + + + + + Property Types + estate.property.type + list,form + + + + estate.property.type.list + estate.property.type + + + + + + + + + + estate.property.type.form + estate.property.type + + +
+ + + + + +
+ +
+
+ +
\ No newline at end of file From 9f22c07ddfed7c0c0cd2c01d9c1d68701ef4e325 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Mon, 13 Jul 2026 17:50:37 +0530 Subject: [PATCH 15/19] [IMP] estate: Add computed total_area field using @api.depends --- estate/models/estate_property.py | 9 ++++++++- estate/view/estate_property_views.xml | 5 +++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 35a0532f5a0..09c5c819278 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,6 @@ from datetime import timedelta -from odoo import fields, models +from odoo import fields, models, api class EstateProperty(models.Model): @@ -8,6 +8,13 @@ class EstateProperty(models.Model): _description = "Estate Property" name = fields.Char(required=True) + 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 + property_type_id = fields.Many2one( "estate.property.type", string="Property Type", diff --git a/estate/view/estate_property_views.xml b/estate/view/estate_property_views.xml index 975f5f83e8f..c5052df402e 100644 --- a/estate/view/estate_property_views.xml +++ b/estate/view/estate_property_views.xml @@ -74,9 +74,10 @@ - - + + + From 0b416badfb6c04475d7ab00aa801ec30251a4d7f Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Thu, 23 Jul 2026 10:52:30 +0530 Subject: [PATCH 16/19] [IMP] estate: add total-area, best-price, offer validity and deadline -compute the total-area of the property -compute the best-price of the property using private methods -compute the deadline from create_date and validity -implement an inverse method to update validity from the deadline -handle record creation by providing a fallback when create_date is not yet available -display the new fields in the offer tree and form views --- estate/models/estate_property.py | 23 ++++++++++++++++++ estate/models/estate_property_offer.py | 27 ++++++++++++++++++++- estate/view/estate_property_offer_views.xml | 4 +++ estate/view/estate_property_views.xml | 10 +++++--- 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 09c5c819278..0267c0e3c25 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -15,6 +15,29 @@ def _compute_total_area(self): for record in self: record.total_area = record.living_area + record.garden_area + best_price = fields.Float( + string="Best Offer", + compute="_compute_best_price", + store=True, + ) + + @api.depends("offer_ids.price") + def _compute_best_price(self): + for property in self: + if property.offer_ids: + property.best_price = max(property.offer_ids.mapped("price")) + else: + property.best_price = 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 + property_type_id = fields.Many2one( "estate.property.type", string="Property Type", diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index a39599edd47..912c44480a8 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,5 @@ -from odoo import fields, models +from odoo import fields, models, api +from datetime import timedelta class EstatePropertyOffer(models.Model): @@ -29,3 +30,27 @@ class EstatePropertyOffer(models.Model): "property_id", string="Offers", ) + validity = fields.Integer( + string="Validity (days)", + default=7, + ) + deadline = fields.Date( + string="Deadline", + compute="_compute_date_deadline", + inverse="_inverse_date_deadline", + store=True, + ) + create_date = fields.Datetime() + + @api.depends("create_date", "validity") + def _compute_date_deadline(self): + for record in self: + create_date = ( + record.create_date.date() if record.create_date else fields.Date.today() + ) + record.deadline = create_date + timedelta(days=record.validity) + + def _inverse_date_deadline(self): + for record in self: + if record.create_date and record.deadline: + record.validity = (record.deadline - record.create_date.date()).days diff --git a/estate/view/estate_property_offer_views.xml b/estate/view/estate_property_offer_views.xml index 7f6ef5a1171..8270c0f78c7 100644 --- a/estate/view/estate_property_offer_views.xml +++ b/estate/view/estate_property_offer_views.xml @@ -17,6 +17,8 @@ + + @@ -34,6 +36,8 @@ + + diff --git a/estate/view/estate_property_views.xml b/estate/view/estate_property_views.xml index c5052df402e..7f330be306f 100644 --- a/estate/view/estate_property_views.xml +++ b/estate/view/estate_property_views.xml @@ -62,6 +62,7 @@ + @@ -86,6 +87,11 @@ + + + + + @@ -99,11 +105,7 @@ - - - -
From 9d5c18a5b2460c19b29edf756ae00e8b9d14f068 Mon Sep 17 00:00:00 2001 From: amtha-odoo Date: Tue, 28 Jul 2026 18:08:23 +0530 Subject: [PATCH 17/19] [IMP] estate: Add actions for property and offer management --- estate/models/estate_property.py | 19 +++++++++++++++++++ estate/models/estate_property_offer.py | 10 ++++++++++ estate/view/estate_menus.xml | 12 +++++++----- estate/view/estate_property_offer_views.xml | 5 +++-- estate/view/estate_property_views.xml | 7 +++++-- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 0267c0e3c25..c6d480f5452 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,7 @@ from datetime import timedelta from odoo import fields, models, api +from odoo.exceptions import UserError class EstateProperty(models.Model): @@ -15,6 +16,24 @@ def _compute_total_area(self): for record in self: record.total_area = record.living_area + record.garden_area + def action_sold(self): + for record in self: + if record.state == "cancelled": + raise UserError("Cancelled property cannot be sold.") + + record.state = "sold" + + return True + + def action_cancel(self): + for record in self: + if record.state == "sold": + raise UserError("Sold property cannot be cancelled.") + + record.state = "cancelled" + + return True + best_price = fields.Float( string="Best Offer", compute="_compute_best_price", diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 912c44480a8..f712479d4f7 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -8,6 +8,16 @@ class EstatePropertyOffer(models.Model): price = fields.Float() + def action_confirm(self): + for record in self: + record.status = "accepted" + record.property_id.selling_price = record.price + record.property_id.buyer_id = record.partner_id + + def action_cancel(self): + for record in self: + record.status = "refused" + status = fields.Selection( [ ("accepted", "Accepted"), diff --git a/estate/view/estate_menus.xml b/estate/view/estate_menus.xml index 74255db5a92..33fa2a5c39f 100644 --- a/estate/view/estate_menus.xml +++ b/estate/view/estate_menus.xml @@ -1,18 +1,20 @@ - + - + + - + - +