From d2a042c2eeae1524ae6517f6afecf3514369719a Mon Sep 17 00:00:00 2001 From: odoo Date: Fri, 3 Apr 2026 17:26:55 +0530 Subject: [PATCH 01/31] [ADD] estate: added estate module Enables users to access and use estate management features directly within the system. Simplifies setup so users can quickly start managing property-related tasks without additional configuration. Chapter 1: Architecture Overview --- estate/__init__.py | 0 estate/__manifest__.py | 7 +++++++ 2 files changed, 7 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..200243f9f4c --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,7 @@ +{ + 'name': 'estate', + 'depends': ['base'], + 'category': 'tutorials', + 'installable': True, + 'application': True +} From 3ffb95365a3f0fef01acace3a791b4d4c57ffa17 Mon Sep 17 00:00:00 2001 From: odoo Date: Fri, 3 Apr 2026 18:16:03 +0530 Subject: [PATCH 02/31] [IMP] estate: added model to estate module Allows users to store and manage detailed property information in a structured way. Improves tracking of property-related activities by linking them with recurring plans, making workflows more organized and efficient. Chapter 2: A NEW MODEL --- estate/__init__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+) 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/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..2517b6f103a --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,20 @@ +from odoo import fields, models + + +class EstateProperty(models.Model): + _name = 'estate.property' + _description = 'Estate Property' + + name = fields.Char(string="Name", required="True") + description = fields.Text(string="Description") + date_availability = fields.Date(String="Date availability") + postcode = fields.Char(string = "Postcode", required = "True") + expected_price = fields.Float(string = "Expected Price") + selling_price = fields.Float(string = "Selling Price") + bedrooms = fields.Integer(string = "Bedrooms") + living_area = fields.Integer(string = "Living Area") + facades = fields.Integer(string = "Facades") + garage = fields.Boolean(string = "Garage") + garden = fields.Boolean(string = "Garden") + garden_area = fields.Integer(string = "Garden_area") + garden_orientation = fields.Selection(string = "Garden Orientation", selection = [("north", "North"), ("east", "East"), ("west", "West"), ("south", "South")]) From fe7d4dc6b78f171a279c369416b35eba85ca22c0 Mon Sep 17 00:00:00 2001 From: odoo Date: Fri, 3 Apr 2026 18:25:26 +0530 Subject: [PATCH 03/31] [IMP] estate: added estate_property model to module Enables users to maintain structured property records with all necessary details in one place. Improves workflow efficiency by connecting properties with suggestion from recurring plans for better tracking and management. Chapter 3: Model and some basic fields --- estate/models/estate_property.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 2517b6f103a..d7e49440ca1 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -8,13 +8,13 @@ class EstateProperty(models.Model): name = fields.Char(string="Name", required="True") description = fields.Text(string="Description") date_availability = fields.Date(String="Date availability") - postcode = fields.Char(string = "Postcode", required = "True") - expected_price = fields.Float(string = "Expected Price") - selling_price = fields.Float(string = "Selling Price") - bedrooms = fields.Integer(string = "Bedrooms") - living_area = fields.Integer(string = "Living Area") - facades = fields.Integer(string = "Facades") - garage = fields.Boolean(string = "Garage") - garden = fields.Boolean(string = "Garden") - garden_area = fields.Integer(string = "Garden_area") - garden_orientation = fields.Selection(string = "Garden Orientation", selection = [("north", "North"), ("east", "East"), ("west", "West"), ("south", "South")]) + postcode = fields.Char(string="Postcode", required="True") + expected_price = fields.Float(string="Expected Price") + selling_price = fields.Float(string="Selling Price") + bedrooms = fields.Integer(string="Bedrooms") + living_area = fields.Integer(string="Living Area") + facades = fields.Integer(string="Facades") + garage = fields.Boolean(string="Garage") + garden = fields.Boolean(string="Garden") + garden_area = fields.Integer(string="Garden_area") + garden_orientation = fields.Selection(string="Garden Orientation", selection=[("north", "North"), ("east", "East"), ("west", "West"), ("south", "South")]) From 385014849bbc3de0e76d6c63a4d5b10e8f3a5dcf Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 6 Apr 2026 10:47:03 +0530 Subject: [PATCH 04/31] [IMP] estate: improved module by adding security Ensures users have appropriate access to estate data based on their roles. Improves data security and prevents unauthorized actions while allowing smooth and controlled interactions with the system. Chapter 4: Security : A brief introduction --- estate/__manifest__.py | 3 ++- estate/security/ir.model.access.csv | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 200243f9f4c..4d194b44b76 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,5 +3,6 @@ 'depends': ['base'], 'category': 'tutorials', 'installable': True, - 'application': True + 'application': True, + '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..e933f00e58e --- /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_test_model,access_test_model,model_test_model,base.group_user,1,1,1,1 From b3e3a0f36b2874435ac381cfe34c180fa5c49894 Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 6 Apr 2026 11:07:28 +0530 Subject: [PATCH 05/31] [IMP] estate: improved security feature Provides users with controlled access to perform necessary actions like viewing, editing, and deleting data. Ensures a secure and reliable experience by preventing unauthorized operations while maintaining usability. Chapter 4: Security : A brief --- estate/__manifest__.py | 4 +++- estate/models/estate_property.py | 6 +++--- estate/security/ir.model.access.csv | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 4d194b44b76..6cd096d753f 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -4,5 +4,7 @@ 'category': 'tutorials', 'installable': True, 'application': True, - 'data':['security/ir.model/access.csv'] + 'data':[ + 'security/ir.model.access.csv' + ] } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d7e49440ca1..a972607d367 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -5,10 +5,10 @@ class EstateProperty(models.Model): _name = 'estate.property' _description = 'Estate Property' - name = fields.Char(string="Name", required="True") + name = fields.Char(string="Name", required=True) description = fields.Text(string="Description") - date_availability = fields.Date(String="Date availability") - postcode = fields.Char(string="Postcode", required="True") + date_availability = fields.Date(string="Available From") + postcode = fields.Char(string="Postcode", required=True) expected_price = fields.Float(string="Expected Price") selling_price = fields.Float(string="Selling Price") bedrooms = fields.Integer(string="Bedrooms") diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index e933f00e58e..bc86bfa4ea8 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,2 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink -access_test_model,access_test_model,model_test_model,base.group_user,1,1,1,1 +access_estate_property,acess_estate_property,model_estate_property,base.group_user,1,1,1,1 From bc403177459923e37f78e5aa46124077c53a3d01 Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 6 Apr 2026 15:01:45 +0530 Subject: [PATCH 06/31] [IMP] estate: added action in estate Allows users to easily access and navigate estate data through a dedicated interface. Improves usability by providing a clear and structured view for managing records. Chapter 5: Finally some UI to play with. --- estate/__manifest__.py | 8 +++++--- estate/views/estate_property_view.xml | 11 +++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 estate/views/estate_property_view.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 6cd096d753f..eba0b463071 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -4,7 +4,9 @@ 'category': 'tutorials', 'installable': True, 'application': True, - 'data':[ - 'security/ir.model.access.csv' - ] + 'data': [ + 'security/ir.model.access.csv', + + 'views/estate_property_view.xml' + ] } diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml new file mode 100644 index 00000000000..17a3815e026 --- /dev/null +++ b/estate/views/estate_property_view.xml @@ -0,0 +1,11 @@ + + + + + Properties + estate.property + list,form + + + + From 04229c37090b27423a0cef6c93894cb58328f6a6 Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 6 Apr 2026 15:48:45 +0530 Subject: [PATCH 07/31] [IMP] estate: added menu XML Added menu hierarchy to improve navigation and feature accessibility for users to navigate using provided views Chapter 5: Finally some UI to play with --- estate/__manifest__.py | 3 ++- estate/views/estate_menu.xml | 9 +++++++++ estate/views/estate_property_view.xml | 14 +++++--------- 3 files changed, 16 insertions(+), 10 deletions(-) create mode 100644 estate/views/estate_menu.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index eba0b463071..4dbd59d2604 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,6 +7,7 @@ 'data': [ 'security/ir.model.access.csv', - 'views/estate_property_view.xml' + 'views/estate_property_view.xml', + 'views/estate_menu.xml' ] } diff --git a/estate/views/estate_menu.xml b/estate/views/estate_menu.xml new file mode 100644 index 00000000000..cbadae390f5 --- /dev/null +++ b/estate/views/estate_menu.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 17a3815e026..108e168e06a 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -1,11 +1,7 @@ - - - - Properties - estate.property - list,form - - - + + Properties + estate.property + list,form + From 25407f8cce4af7588a9c745e8a8c7e5a8a74ccbe Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 6 Apr 2026 18:10:14 +0530 Subject: [PATCH 08/31] [IMP] estate: added active and state for better visibility Added active and state fields to ensure better record visibility and track property status clearly for users Chapter 5: Finally some UI to play with --- estate/models/estate_property.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index a972607d367..f709e2824d4 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -5,16 +5,22 @@ class EstateProperty(models.Model): _name = 'estate.property' _description = 'Estate Property' - name = fields.Char(string="Name", required=True) + name = fields.Char(string="Name", required=True, default="Unknown") + last_seen = fields.Datetime("Last Seen", default=fields.Datetime.now) description = fields.Text(string="Description") - date_availability = fields.Date(string="Available From") + date_availability = fields.Date(string="Available From", copy=False, default=fields.Date.add(fields.Date.today(), months=3)) postcode = fields.Char(string="Postcode", required=True) expected_price = fields.Float(string="Expected Price") - selling_price = fields.Float(string="Selling Price") - bedrooms = fields.Integer(string="Bedrooms") + selling_price = fields.Float(string="Selling Price", readonly=True) + bedrooms = fields.Integer(string="Bedrooms", default=2) living_area = fields.Integer(string="Living Area") facades = fields.Integer(string="Facades") garage = fields.Boolean(string="Garage") garden = fields.Boolean(string="Garden") garden_area = fields.Integer(string="Garden_area") garden_orientation = fields.Selection(string="Garden Orientation", selection=[("north", "North"), ("east", "East"), ("west", "West"), ("south", "South")]) + + # If it is false then newly created record won't be appear. but record is created when active is set true record will appear. + active = fields.Boolean("Active", default=True) + # State can get selected and as copy is set False in duplicate it cannot get copied + state = fields.Selection(string="state", selection=[("new", "New"), ("offer recieved", "Offer Recieved"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) \ No newline at end of file From 22b6c5637e4631476a4fbb7e7498dd106c4bfdf7 Mon Sep 17 00:00:00 2001 From: odoo Date: Tue, 7 Apr 2026 14:43:22 +0530 Subject: [PATCH 09/31] [IMP] estate: added list view to property module Added list view to help users quickly browse, compare, and manage multiple properties efficiently Chapter 6: Basic Views --- estate/models/estate_property.py | 2 +- estate/views/estate_property_view.xml | 24 +++++++++++++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f709e2824d4..74223f11cb4 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -23,4 +23,4 @@ class EstateProperty(models.Model): # If it is false then newly created record won't be appear. but record is created when active is set true record will appear. active = fields.Boolean("Active", default=True) # State can get selected and as copy is set False in duplicate it cannot get copied - state = fields.Selection(string="state", selection=[("new", "New"), ("offer recieved", "Offer Recieved"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) \ No newline at end of file + state = fields.Selection(string="state", selection=[("new", "New"), ("offer received", "Offer Received"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 108e168e06a..83a8e2f1b29 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -1,7 +1,29 @@ Properties + estate.property + list,form - + + + + + + estate.property.list.view + + estate.property + + + + + + + + + + + + + From ea3c8ce965b4462fd9c1eefad6d81dc4d5da2ee6 Mon Sep 17 00:00:00 2001 From: odoo Date: Tue, 7 Apr 2026 19:00:11 +0530 Subject: [PATCH 10/31] [IMP] estate: added form view to property module Added form view for detailed property management enables users to easily view, create, and update property records improves data entry accuracy and overall usability Chapter 6: Basic Views --- estate/models/estate_property.py | 2 +- estate/views/estate_property_view.xml | 40 +++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 74223f11cb4..b5ed6f68fda 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -19,7 +19,7 @@ class EstateProperty(models.Model): garden = fields.Boolean(string="Garden") garden_area = fields.Integer(string="Garden_area") garden_orientation = fields.Selection(string="Garden Orientation", selection=[("north", "North"), ("east", "East"), ("west", "West"), ("south", "South")]) - + # If it is false then newly created record won't be appear. but record is created when active is set true record will appear. active = fields.Boolean("Active", default=True) # State can get selected and as copy is set False in duplicate it cannot get copied diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 83a8e2f1b29..0f0d870fe2a 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -26,4 +26,44 @@ + + + estate.property.form.view + estate.property + +
+ +
+

+ My new house +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
From 8db7e88efefdbb383cace8c576ed5cf18d14a697 Mon Sep 17 00:00:00 2001 From: odoo Date: Wed, 8 Apr 2026 14:33:51 +0530 Subject: [PATCH 11/31] [IMP] estate: added search view to property module Added search view with state filters and postcode grouping helps users quickly find and organize properties based on status and location improves efficiency in browsing and managing large datasets Chapter 6: Basic Views --- estate/models/estate_property.py | 2 +- estate/views/estate_property_view.xml | 37 ++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b5ed6f68fda..aaa56107b30 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -23,4 +23,4 @@ class EstateProperty(models.Model): # If it is false then newly created record won't be appear. but record is created when active is set true record will appear. active = fields.Boolean("Active", default=True) # State can get selected and as copy is set False in duplicate it cannot get copied - state = fields.Selection(string="state", selection=[("new", "New"), ("offer received", "Offer Received"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) + state = fields.Selection(string="state", selection=[("new", "New"), ("offer_received", "Offer Received"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 0f0d870fe2a..6b9c0c57bba 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -4,7 +4,7 @@ estate.property - list,form + tree, form @@ -25,18 +25,22 @@ - + estate.property.form.view + estate.property
+
+

- My new house +

+ @@ -47,8 +51,11 @@ + + + @@ -58,6 +65,7 @@ + @@ -66,4 +74,27 @@ + + + estate.property.search.view + estate.property + + + + + + + + + + + + + + + + + + + From fc48f2303b1b8e6bf7f21303fc042ab6e49e3379 Mon Sep 17 00:00:00 2001 From: odoo Date: Thu, 9 Apr 2026 15:38:01 +0530 Subject: [PATCH 12/31] [IMP] estate: module link link property with property type using Many2one relationship allows users to categorize properties for better organization and filtering improves data structure and usability across the estate module Chapter 7: Relations between models --- estate/__manifest__.py | 6 +++++- estate/models/__init__.py | 1 + estate/models/estate_property.py | 3 +++ estate/models/estate_property_type.py | 9 +++++++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menu.xml | 5 ++++- estate/views/estate_property_type_view.xml | 17 +++++++++++++++++ estate/views/estate_property_view.xml | 13 ++++++++++--- 8 files changed, 50 insertions(+), 5 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 4dbd59d2604..9b3974f4bd1 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -8,6 +8,10 @@ 'security/ir.model.access.csv', 'views/estate_property_view.xml', + 'views/estate_property_type_view.xml', 'views/estate_menu.xml' - ] + ], + + 'author': 'RADHR', + 'license': 'LGPL-3', } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..97aee757823 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,2 @@ from . import estate_property +from . import estate_property_type \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index aaa56107b30..350b8107f01 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -24,3 +24,6 @@ class EstateProperty(models.Model): active = fields.Boolean("Active", default=True) # State can get selected and as copy is set False in duplicate it cannot get copied state = fields.Selection(string="state", selection=[("new", "New"), ("offer_received", "Offer Received"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) + property_type_id = fields.Many2one("estate.property.type", string="Property type") + buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False, default=lambda self: self.env.user.partner_id) + sales_person = fields.Many2one("res.users", string="Sales person", index=True, tracking=True, 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..8b8542eb3f9 --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,9 @@ +from odoo import fields, models + + +class EstatePropertyType(models.Model): + _name = "estate.property.type" + _description = "Estate Property Type" + + name = fields.Char(string="name", required=True) + \ No newline at end of file diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index bc86bfa4ea8..5c0bb52d2d4 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,acess_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_menu.xml b/estate/views/estate_menu.xml index cbadae390f5..2f02c1e4a16 100644 --- a/estate/views/estate_menu.xml +++ b/estate/views/estate_menu.xml @@ -1,9 +1,12 @@ - + + + + diff --git a/estate/views/estate_property_type_view.xml b/estate/views/estate_property_type_view.xml new file mode 100644 index 00000000000..9e325a8969a --- /dev/null +++ b/estate/views/estate_property_type_view.xml @@ -0,0 +1,17 @@ + + + Property Types + estate.property.type + list,form + + + + estate.property.type.form.view + estate.property.type + + + + + + + diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 6b9c0c57bba..72a4398eec8 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -4,7 +4,7 @@ estate.property - tree, form + list,form @@ -43,6 +43,7 @@ + @@ -56,7 +57,7 @@ - + @@ -68,7 +69,13 @@ - + + + + + + +
From d64021be1ec1cb35f800282d8833c73c8bee3b1d Mon Sep 17 00:00:00 2001 From: odoo Date: Fri, 10 Apr 2026 11:28:57 +0530 Subject: [PATCH 13/31] [IMP] estate: added property tags many2many Added property tags (Many2Many) to enhance property classification and flexibility. Enables users to quickly filter and identify properties based on features like cozy, renovated, etc.Improves searchability and overall user experience. Chapter 7: Relations between model : Many2many --- estate/__manifest__.py | 1 + estate/models/__init__.py | 3 ++- estate/models/estate_property.py | 1 + estate/models/estate_property_tag.py | 8 ++++++++ estate/models/estate_property_type.py | 1 - estate/security/ir.model.access.csv | 3 ++- estate/views/estate_menu.xml | 3 ++- estate/views/estate_property_tag_view.xml | 7 +++++++ estate/views/estate_property_view.xml | 1 + 9 files changed, 24 insertions(+), 4 deletions(-) create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/views/estate_property_tag_view.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 9b3974f4bd1..e1cd9f5e782 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -9,6 +9,7 @@ 'views/estate_property_view.xml', 'views/estate_property_type_view.xml', + 'views/estate_property_tag_view.xml', 'views/estate_menu.xml' ], diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 97aee757823..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 \ No newline at end of file +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 350b8107f01..01a68fb8a55 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -27,3 +27,4 @@ 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, default=lambda self: self.env.user.partner_id) sales_person = fields.Many2one("res.users", string="Sales person", index=True, tracking=True, default=lambda self: self.env.user) + property_tag = 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..331b056fc51 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Estate Property Tag" + + name = fields.Char(string="name", required=True) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 8b8542eb3f9..3d7662ab348 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -6,4 +6,3 @@ class EstatePropertyType(models.Model): _description = "Estate Property Type" name = fields.Char(string="name", required=True) - \ No newline at end of file diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 5c0bb52d2d4..f0889abaab0 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,acess_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 diff --git a/estate/views/estate_menu.xml b/estate/views/estate_menu.xml index 2f02c1e4a16..79a59c54f2c 100644 --- a/estate/views/estate_menu.xml +++ b/estate/views/estate_menu.xml @@ -6,7 +6,8 @@ - + + diff --git a/estate/views/estate_property_tag_view.xml b/estate/views/estate_property_tag_view.xml new file mode 100644 index 00000000000..101a920e526 --- /dev/null +++ b/estate/views/estate_property_tag_view.xml @@ -0,0 +1,7 @@ + + + Property Tags + estate.property.tag + list,form + + diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 72a4398eec8..60f8756c277 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -46,6 +46,7 @@ + From 3e626b729a806b4fd0ca9774bcad1e0fb1267095 Mon Sep 17 00:00:00 2001 From: odoo Date: Fri, 10 Apr 2026 16:02:42 +0530 Subject: [PATCH 14/31] [IMP] estate: add page for property offer Allows users to view and manage all buyer offers in one place, making it easier to compare prices and track offer status. Improves decision-making and overall property management experience. Chapter 7: Relations between model : One2many --- estate/__manifest__.py | 1 + estate/models/__init__.py | 2 ++ estate/models/estate_property.py | 7 ++++--- estate/models/estate_property_offer.py | 12 ++++++++++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_property_offer_view.xml | 14 ++++++++++++++ estate/views/estate_property_view.xml | 5 ++++- 7 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 estate/models/estate_property_offer.py create mode 100644 estate/views/estate_property_offer_view.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index e1cd9f5e782..2003ea53451 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -10,6 +10,7 @@ 'views/estate_property_view.xml', 'views/estate_property_type_view.xml', 'views/estate_property_tag_view.xml', + 'views/estate_property_offer_view.xml', 'views/estate_menu.xml' ], diff --git a/estate/models/__init__.py b/estate/models/__init__.py index c620ac481a3..9752b464357 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,3 +1,5 @@ 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 01a68fb8a55..74a7acf9c31 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -25,6 +25,7 @@ class EstateProperty(models.Model): # State can get selected and as copy is set False in duplicate it cannot get copied state = fields.Selection(string="state", selection=[("new", "New"), ("offer_received", "Offer Received"), ("accepted", "Accepted"), ("sold", "Sold"), ("cancelled", "Cancelled")], default="new", copy=False) property_type_id = fields.Many2one("estate.property.type", string="Property type") - buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False, default=lambda self: self.env.user.partner_id) - sales_person = fields.Many2one("res.users", string="Sales person", index=True, tracking=True, default=lambda self: self.env.user) - property_tag = fields.Many2many("estate.property.tag", string="Property Tags") + buyer_id = fields.Many2one(comodel_name="res.partner", string="Buyer", copy=False, default=lambda self: self.env.user.partner_id) + sales_person = fields.Many2one(comodel_name="res.users", string="Sales person", index=True, tracking=True, default=lambda self: self.env.user) + property_tag = fields.Many2many(comodel_name="estate.property.tag", string="Property Tags") + offer_id = fields.One2many(comodel_name="estate.property.offer", inverse_name="property_id", string="Property offer") diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..99a2c864fd9 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,12 @@ +from odoo import fields, models + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Estate Property Offer" + + name = fields.Char(string="Property Offer", required=True) + price = fields.Integer(string="Price", required=True) + status = fields.Selection(string="Status", 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 f0889abaab0..ca940030189 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 access_estate_property,acess_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_view.xml b/estate/views/estate_property_offer_view.xml new file mode 100644 index 00000000000..b2779893ba0 --- /dev/null +++ b/estate/views/estate_property_offer_view.xml @@ -0,0 +1,14 @@ + + + estate.property.offer.list.view + estate.property.offer + + + + + + + + + + diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 60f8756c277..7a551d0d8cd 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -40,13 +40,13 @@

+ - @@ -70,6 +70,9 @@ + + + From a79d97d4fd548f62fa33c8bb95fcfbd27dffc115 Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 13 Apr 2026 12:02:58 +0530 Subject: [PATCH 15/31] [IMP] estate: computed field total area added Added computed field for total area by summing garden and living space, giving users a quick and accurate view of overall property size. Chapter 8: Computed fields and onChanges --- estate/models/estate_property.py | 9 ++++++++- estate/views/estate_property_view.xml | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 74a7acf9c31..ee0612aa284 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import fields, models +from odoo import fields, models, api class EstateProperty(models.Model): @@ -29,3 +29,10 @@ class EstateProperty(models.Model): sales_person = fields.Many2one(comodel_name="res.users", string="Sales person", index=True, tracking=True, default=lambda self: self.env.user) property_tag = fields.Many2many(comodel_name="estate.property.tag", string="Property Tags") offer_id = fields.One2many(comodel_name="estate.property.offer", inverse_name="property_id", string="Property offer") + + total_area = fields.Integer(string="total_area", name="Total area", compute="_compute_total") + + @api.depends("garden_area", "living_area") + def _compute_total(self): + for record in self: + record.total_area = record.garden_area + record.living_area diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 7a551d0d8cd..f01803d313d 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -68,6 +68,7 @@ + From 2d76721b50fd5ed4dabd29505c2de0ce92b92bb7 Mon Sep 17 00:00:00 2001 From: odoo Date: Tue, 14 Apr 2026 12:46:17 +0530 Subject: [PATCH 16/31] [IMP] estate: added garden onchange feature Auto-updates garden area and orientation based on garden selection, reducing manual input and preventing user errors.Clears dependent fields when disabled, ensuring data consistency and a cleaner user experience. Chapter : 8 Computed fields and onChanges --- estate/models/estate_property.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index ee0612aa284..07b56c57ef4 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -36,3 +36,18 @@ class EstateProperty(models.Model): def _compute_total(self): for record in self: record.total_area = record.garden_area + record.living_area + + @api.depends("offer_id.price") + def _compute_best_price(self): + for record in self: + record.best_price = max(record.mapped("offer_id.price")) + +# to add when garden is clicked then its area and orientation is set to default values. works on decorators concepts + @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 217b4f767097caaddf9d4d245f5f13a28b972fc5 Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 13 Apr 2026 14:18:35 +0530 Subject: [PATCH 17/31] [IMP] estate: computed field best price added Add function to surface the best (highest) price prominently in the header. Improves user experience by making optimal pricing instantly visible without extra effort. Chapter 8: Computed fields and onChanges --- estate/models/__init__.py | 1 - estate/models/estate_property.py | 1 + estate/models/estate_property_offer.py | 2 +- estate/views/estate_property_view.xml | 1 + 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 9752b464357..2f1821a39c1 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -2,4 +2,3 @@ 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 07b56c57ef4..53139e20b0c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -31,6 +31,7 @@ class EstateProperty(models.Model): offer_id = fields.One2many(comodel_name="estate.property.offer", inverse_name="property_id", string="Property offer") total_area = fields.Integer(string="total_area", name="Total area", compute="_compute_total") + best_price = fields.Integer(string="best_price", name="Best Price", compute="_compute_best_price") @api.depends("garden_area", "living_area") def _compute_total(self): diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 99a2c864fd9..9d3c3a9d235 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,4 @@ -from odoo import fields, models +from odoo import fields, models, api class EstatePropertyOffer(models.Model): diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index f01803d313d..240ece5b051 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -51,6 +51,7 @@ + From 89f31b48e0d2969dbf500552e3116f7a81191210 Mon Sep 17 00:00:00 2001 From: odoo Date: Tue, 14 Apr 2026 15:51:40 +0530 Subject: [PATCH 18/31] [IMP] estate: added inverse for validity and deadline Add computed validity & deadline fields with inverse sync for seamless updates that ensures accurate offer timelines and reduces manual date calculations for users. Chapter : 8 Computed fields and onChanges --- estate/models/estate_property.py | 5 +++-- estate/models/estate_property_offer.py | 17 +++++++++++++++++ estate/views/estate_property_offer_view.xml | 2 ++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 53139e20b0c..5e2217e86ce 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -32,7 +32,7 @@ class EstateProperty(models.Model): total_area = fields.Integer(string="total_area", name="Total area", compute="_compute_total") best_price = fields.Integer(string="best_price", name="Best Price", compute="_compute_best_price") - + @api.depends("garden_area", "living_area") def _compute_total(self): for record in self: @@ -41,7 +41,8 @@ def _compute_total(self): @api.depends("offer_id.price") def _compute_best_price(self): for record in self: - record.best_price = max(record.mapped("offer_id.price")) + prices = record.mapped("offer_id.price") + record.best_price = max(prices) if prices else 0 # to add when garden is clicked then its area and orientation is set to default values. works on decorators concepts @api.onchange("garden") diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 9d3c3a9d235..cfa6b984fb0 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -10,3 +10,20 @@ class EstatePropertyOffer(models.Model): status = fields.Selection(string="Status", 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) + # create_date = fields.Date(string="Date for creation") + validity = fields.Integer(string="Validity", default=7) + date_deadline = fields.Date(string="Deadline", compute="_compute_deadline", inverse="_inverse_deadline", readonly=False) + + # It gets changed on each changes because it works based on cache + @api.depends("create_date", "validity") + def _compute_deadline(self): + for records in self: + default_date = records.create_date.date() if records.create_date else fields.Date.today() + records.date_deadline = fields.Date.add(default_date, days=records.validity) + + #Inverse is triggered when the computed field is written (usually during save), not during live editing. + def _inverse_deadline(self): + for records in self: + default_date = records.create_date.date() if records.create_date else fields.Date.today() + if records.date_deadline: + records.validity = (records.date_deadline - default_date).days diff --git a/estate/views/estate_property_offer_view.xml b/estate/views/estate_property_offer_view.xml index b2779893ba0..ce70a4e008f 100644 --- a/estate/views/estate_property_offer_view.xml +++ b/estate/views/estate_property_offer_view.xml @@ -8,6 +8,8 @@ + +
From 37dc1c14e5dafcdc5b592f1fab1696f1bd72397b Mon Sep 17 00:00:00 2001 From: odoo Date: Tue, 14 Apr 2026 18:06:28 +0530 Subject: [PATCH 19/31] [IMP] estate: confirm and reject added in offer list view Helps users efficiently manage offers while automatically assigning buyer and final price to the property. Chapter 9 : Ready For Some Action? --- estate/models/estate_property.py | 2 +- estate/models/estate_property_offer.py | 20 ++++++++++++++++++-- estate/views/estate_property_offer_view.xml | 3 +++ 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 5e2217e86ce..864fa85bb9f 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -32,7 +32,7 @@ class EstateProperty(models.Model): total_area = fields.Integer(string="total_area", name="Total area", compute="_compute_total") best_price = fields.Integer(string="best_price", name="Best Price", compute="_compute_best_price") - + @api.depends("garden_area", "living_area") def _compute_total(self): for record in self: diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index cfa6b984fb0..ca7c337e627 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -19,11 +19,27 @@ class EstatePropertyOffer(models.Model): def _compute_deadline(self): for records in self: default_date = records.create_date.date() if records.create_date else fields.Date.today() - records.date_deadline = fields.Date.add(default_date, days=records.validity) + records.date_deadline = fields.Date.add(default_date, days=records.validity) - #Inverse is triggered when the computed field is written (usually during save), not during live editing. + #Inverse is triggered when the computed field is written (usually during save),not during live editing. def _inverse_deadline(self): for records in self: default_date = records.create_date.date() if records.create_date else fields.Date.today() if records.date_deadline: records.validity = (records.date_deadline - default_date).days + + def save_offer(self): + for record in self: + if record.status != 'accepted' or record.status != 'refused': + record.status = 'accepted' + record.property_id.selling_price = record.price + record.property_id.buyer_id = record.partner_id + record.property_id.state = 'accepted' + + def cancel_offer(self): + for record in self: + if record.status != 'accepted' or record.status != 'refused': + record.status = 'refused' + if record.property_id.buyer_id == record.partner_id: + record.property_id.selling_price = False + record.property_id.state = False diff --git a/estate/views/estate_property_offer_view.xml b/estate/views/estate_property_offer_view.xml index ce70a4e008f..aa89b9da957 100644 --- a/estate/views/estate_property_offer_view.xml +++ b/estate/views/estate_property_offer_view.xml @@ -8,9 +8,12 @@ + + - + diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 9e21ab10e1b..2765b9cc53e 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -21,7 +21,7 @@
-
- + -
- +

- - + - + - + - - - - - - + + + - + @@ -81,43 +73,27 @@ - estate.property.search.view estate.property - - - - - - + + - - - - - - - - - - + + + + + - Properties - - - estate.property - - - list,form - - - {'search_default_available': True} + Properties + estate.property + list,form + {'search_default_available': True} diff --git a/estate/views/user_res_view.xml b/estate/views/user_res_view.xml new file mode 100644 index 00000000000..34796b71eba --- /dev/null +++ b/estate/views/user_res_view.xml @@ -0,0 +1,14 @@ + + + res.users.view.form.inherit.estate.property + res.users + + + + + + + + + + From d43058b0dcb25cc503e9b4c80bed6d01393d3925 Mon Sep 17 00:00:00 2001 From: odoo Date: Mon, 27 Apr 2026 19:00:48 +0530 Subject: [PATCH 29/31] [ADD] estate account: get automatic invoices created estate account module to generate invoices for sold properties. it will automates the invoicing process, reducing manual effort and errors. ch. 13 : Interact with other modules --- estate/models/__init__.py | 1 - estate_account/__init__.py | 1 + estate_account/__manifest__.py | 7 +++++++ estate_account/models/__init__.py | 1 + estate_account/models/estate_property.py | 8 ++++++++ 5 files changed, 17 insertions(+), 1 deletion(-) create mode 100644 estate_account/__init__.py create mode 100644 estate_account/__manifest__.py create mode 100644 estate_account/models/__init__.py create mode 100644 estate_account/models/estate_property.py diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 748269a7b4e..c0917a3d550 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -3,4 +3,3 @@ from . import estate_property_tag from . import estate_property_offer from . import inherited_model - diff --git a/estate_account/__init__.py b/estate_account/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/estate_account/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/estate_account/__manifest__.py b/estate_account/__manifest__.py new file mode 100644 index 00000000000..56e4469422f --- /dev/null +++ b/estate_account/__manifest__.py @@ -0,0 +1,7 @@ +{ + "name": "estate account", + "depends": ["account", "estate"], + "installable": True, + "author": "RADHR", + "license": "LGPL-3", +} diff --git a/estate_account/models/__init__.py b/estate_account/models/__init__.py new file mode 100644 index 00000000000..5e1963c9d2f --- /dev/null +++ b/estate_account/models/__init__.py @@ -0,0 +1 @@ +from . import estate_property diff --git a/estate_account/models/estate_property.py b/estate_account/models/estate_property.py new file mode 100644 index 00000000000..67b2bd59c53 --- /dev/null +++ b/estate_account/models/estate_property.py @@ -0,0 +1,8 @@ +from odoo import models + + +class EstateProperty(models.Model): + _inherit = "estate.property" + + def action_sold_offer(self): + return super().action_sold_offer() From eac3b2b0335578b36bc397de2e69330745afa861 Mon Sep 17 00:00:00 2001 From: odoo Date: Tue, 28 Apr 2026 18:24:07 +0530 Subject: [PATCH 30/31] [IMP] estate_account: invoice feature introduced Automatically generates an invoice using invoice functionality, when a property is marked as sold. Reduces manual effort for users and administrators in creating invoices. ch. 13: Interact with other modules --- estate_account/models/estate_property.py | 25 +++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/estate_account/models/estate_property.py b/estate_account/models/estate_property.py index 67b2bd59c53..c4e6520aee8 100644 --- a/estate_account/models/estate_property.py +++ b/estate_account/models/estate_property.py @@ -1,8 +1,31 @@ -from odoo import models +from odoo import models, Command class EstateProperty(models.Model): _inherit = "estate.property" def action_sold_offer(self): + + invoice = self.env["account.move"].create( + { + "partner_id": self.buyer_id.id, + "move_type": "out_invoice", + "line_ids": [ + Command.create( + { + "name": "Amount", + "quantity": 1, + "price_unit": self.selling_price * 0.06, + } + ), + Command.create( + { + "name": "Administration Fess", + "quantity": 1, + "price_unit": 100, + } + ), + ], + } + ) return super().action_sold_offer() From 4b4de221b4237b999ee167913002ae2bb47c25c6 Mon Sep 17 00:00:00 2001 From: odoo Date: Thu, 30 Apr 2026 11:52:35 +0530 Subject: [PATCH 31/31] [IMP] estate: property Management with Kanban View & Smart Fields Implemented Kanban view for a good visual user experience. Displays conditional fields like selling price upon offer acceptance and best price when offers are received. Adds grouping by property type for better organization and quick filtering. Helps users easily track property status, compare offers, and make faster decisions. ch. 14 : A Brief History Of Qweb --- estate/views/estate_property_view.xml | 41 +++++++++++++++++++++++- estate_account/models/estate_property.py | 2 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/estate/views/estate_property_view.xml b/estate/views/estate_property_view.xml index 2963cf83ebd..02be1453ab1 100644 --- a/estate/views/estate_property_view.xml +++ b/estate/views/estate_property_view.xml @@ -90,10 +90,49 @@ + + estate.property.kanban.view + estate.property + + + + + +
+

+ +

+
+

+ Expected Price: + +

+
+
+

+ Best Price: + +

+
+
+

+ Selling Price: + +

+
+
+ +
+
+
+
+
+
+
Properties estate.property - list,form + list,form,kanban {'search_default_available': True} diff --git a/estate_account/models/estate_property.py b/estate_account/models/estate_property.py index c4e6520aee8..da0ee9e5ee8 100644 --- a/estate_account/models/estate_property.py +++ b/estate_account/models/estate_property.py @@ -6,7 +6,7 @@ class EstateProperty(models.Model): def action_sold_offer(self): - invoice = self.env["account.move"].create( + self.env["account.move"].create( { "partner_id": self.buyer_id.id, "move_type": "out_invoice",