From c797ef9107579b9063c6a212d4486beeb1c7ab5c Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Thu, 7 May 2026 21:49:33 +0530 Subject: [PATCH 01/20] [ADD] Completed chapter 1 and chapter 2 and setup for initial estate module --- estate/__init__.py | 0 estate/__manifest__.py | 0 2 files changed, 0 insertions(+), 0 deletions(-) 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..e69de29bb2d From a78e93176b2acbf719219665eb12af5f2fcc2f7e Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Fri, 8 May 2026 18:18:31 +0530 Subject: [PATCH 02/20] [ADD] Completed Python oops and completed task for chapter 2 --- app/__init__.py | 0 app/__manifest__.py | 7 +++++++ 2 files changed, 7 insertions(+) create mode 100644 app/__init__.py create mode 100644 app/__manifest__.py diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/app/__manifest__.py b/app/__manifest__.py new file mode 100644 index 00000000000..39c37450537 --- /dev/null +++ b/app/__manifest__.py @@ -0,0 +1,7 @@ +{ + "name":"app", + "version":"1.0", + "depends": ["base"], + "application": True, + "installable": True, +} \ No newline at end of file From 5594d3d1cfa02814bee96afb0b0fca309a724dc1 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Mon, 11 May 2026 18:51:54 +0530 Subject: [PATCH 03/20] [ADD] real_estate:added initial setup files for models: Completed intial set for models and started learning about ORM --- app/__manifest__.py | 7 ------- estate/__init__.py | 1 + estate/__manifest__.py | 12 ++++++++++++ estate/models/__init__.py | 1 + app/__init__.py => estate/models/estate_property.py | 0 5 files changed, 14 insertions(+), 7 deletions(-) delete mode 100644 app/__manifest__.py create mode 100644 estate/models/__init__.py rename app/__init__.py => estate/models/estate_property.py (100%) diff --git a/app/__manifest__.py b/app/__manifest__.py deleted file mode 100644 index 39c37450537..00000000000 --- a/app/__manifest__.py +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name":"app", - "version":"1.0", - "depends": ["base"], - "application": True, - "installable": True, -} \ No newline at end of file diff --git a/estate/__init__.py b/estate/__init__.py index e69de29bb2d..9a7e03eded3 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/estate/__manifest__.py b/estate/__manifest__.py index e69de29bb2d..168b476c554 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -0,0 +1,12 @@ +{ + 'name': 'estate', + 'version': '1.0', + 'depends': ['base'], + 'category': 'tutorials', + 'author': "sadeo-odoo", + 'license': 'LGPL-3', + 'description': "A real estate module", + 'installable': True, + 'application': True, + +} diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..599a1f8bdbd --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1 @@ +from . import estate_property \ No newline at end of file diff --git a/app/__init__.py b/estate/models/estate_property.py similarity index 100% rename from app/__init__.py rename to estate/models/estate_property.py From 37544c262206b8c20a0c726d6999737954238ee4 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 12 May 2026 18:41:44 +0530 Subject: [PATCH 04/20] [ADD] estate : completed task of models and added required fields in estate_property --- estate/__manifest__.py | 2 +- estate/models/estate_property.py | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 168b476c554..3842964b2b3 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -5,7 +5,7 @@ 'category': 'tutorials', 'author': "sadeo-odoo", 'license': 'LGPL-3', - 'description': "A real estate module", + 'description': 'A real estate module', 'installable': True, 'application': True, diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index e69de29bb2d..883cdb30158 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -0,0 +1,25 @@ +from odoo import fields,models + +class EstateProperty(models.Model): + _name='estate.property' + _descripion='Estate Property description module' + name=fields.Char(string='Name',required=True) + description=fields.Text(string='Description') + bedrooms=fields.Integer(string='Bedrooms') + price = fields.Float(string='Price') + garden = fields.Boolean(string='Garden') + postcode = fields.Char(string='Postal Code') + date_available = fields.Date(string='Available Date') + expected_price = fields.Float(string='Expected Price') + selling_price = fields.Float(string='Selling Price',required=True) + meeting_time = fields.Datetime(string='Meeting') + 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( + [ + ('north','North'),('south','South'),('east','East'),('west','West') + ] + ) From 8c08bd39c06937dac866c98b8fbf27cad53d088f Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 12 May 2026 18:50:30 +0530 Subject: [PATCH 05/20] [ADD] estate: add fields to estate property model Added the required fields for the estate.property model to complete the initial model structure of the Estate module tutorial. Also marked important fields such as name and selling_price as required to ensure proper data validation. --- estate/models/estate_property.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 883cdb30158..3507056d750 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import fields,models +_propertfrom odoo import fields,models class EstateProperty(models.Model): _name='estate.property' From 7697f39f08ad5f0d7937dc6bbf977709692d24f8 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Thu, 14 May 2026 18:24:27 +0530 Subject: [PATCH 06/20] [ADD] Chapter 4 (Security) Added security access rules for the Estate module. Created ir.model.access.csv in the security folder. Configured read, write, create and delete permissions for base.group_user. Updated manifest file to load security data files. --- estate/__manifest__.py | 3 +++ estate/models/estate_property.py | 4 ++-- estate/security/ir.model.access.csv | 2 ++ 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 3842964b2b3..452d41887c7 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -8,5 +8,8 @@ 'description': 'A real estate module', 'installable': True, 'application': True, + 'data':[ + 'security/ir.model.access.csv', + ] } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 3507056d750..7d1ca20a19e 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,8 +1,8 @@ -_propertfrom odoo import fields,models +from odoo import fields,models class EstateProperty(models.Model): _name='estate.property' - _descripion='Estate Property description module' + _descripion='Estate Property description modulee' name=fields.Char(string='Name',required=True) description=fields.Text(string='Description') bedrooms=fields.Integer(string='Bedrooms') 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 991777f9abb00062f29b7d6d56de51b2ba8227a4 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Fri, 15 May 2026 18:42:08 +0530 Subject: [PATCH 07/20] [ADD] estate: introduce first UI action - Learned Odoo XML data file structure - Created estate_property_views.xml in views folder - Added window action for estate.property model - Configured list and form view modes - Registered XML file in __manifest__.py --- estate/__init__.py | 2 +- estate/__manifest__.py | 2 +- estate/models/__init__.py | 2 +- estate/models/estate_property.py | 1 + estate/security/ir.model.access.csv | 2 +- estate/views/estate_property_views.xml | 7 +++++++ 6 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__init__.py b/estate/__init__.py index 9a7e03eded3..0650744f6bc 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1 +1 @@ -from . import models \ No newline at end of file +from . import models diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 452d41887c7..ca66b80832f 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -10,6 +10,6 @@ 'application': True, 'data':[ 'security/ir.model.access.csv', + 'views/estate_property_views.xml', ] - } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 599a1f8bdbd..5e1963c9d2f 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1 @@ -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 7d1ca20a19e..1c1c4e667fc 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -23,3 +23,4 @@ class EstateProperty(models.Model): ('north','North'),('south','South'),('east','East'),('west','West') ] ) + diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 0e11f47e58d..32389642d4f 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_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 diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..09424ecba91 --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,7 @@ + + + Estate Properties + estate.property + list,form + + From 2f8fef157381050c426ab8ca3ab86af6cf233922 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Mon, 18 May 2026 18:47:47 +0530 Subject: [PATCH 08/20] [ADD] estate: add menus and field improvements - Added estate_menus.xml and linked menu actions - Connected estate.property model with UI menus - Added readonly and non-copy field attributes - Set default values for bedrooms and availability date - Added active and state reserved fields with defaults - Improved Estate module UI interaction and behavior --- estate/__manifest__.py | 1 + estate/models/estate_property.py | 18 ++++++++++++++---- estate/views/estate_menus.xml | 7 +++++++ 3 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 estate/views/estate_menus.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ca66b80832f..a5678adebfc 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,5 +11,6 @@ '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 1c1c4e667fc..f5be6dc9c23 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,3 +1,4 @@ +from dateutil.relativedelta import relativedelta from odoo import fields,models class EstateProperty(models.Model): @@ -5,13 +6,13 @@ class EstateProperty(models.Model): _descripion='Estate Property description modulee' name=fields.Char(string='Name',required=True) description=fields.Text(string='Description') - bedrooms=fields.Integer(string='Bedrooms') + bedrooms=fields.Integer(string='Bedrooms',default=2) price = fields.Float(string='Price') garden = fields.Boolean(string='Garden') postcode = fields.Char(string='Postal Code') - date_available = fields.Date(string='Available Date') + date_available = fields.Date(string='Available Date',copy=False,default=lambda self:fields.Date.today() + relativedelta(months=3)) expected_price = fields.Float(string='Expected Price') - selling_price = fields.Float(string='Selling Price',required=True) + selling_price = fields.Float(string='Selling Price',readonly=True,copy=False) meeting_time = fields.Datetime(string='Meeting') living_area = fields.Integer(string='Living Area') facades = fields.Integer(string='Facades') @@ -23,4 +24,13 @@ class EstateProperty(models.Model): ('north','North'),('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'),('canceled','Canceled') + ], + default='new', + string='Status', + copy=False, + required=True + ) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..59f03384878 --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,7 @@ + + + + + + + From 058979badaf772ea406b4dfc8371880af98c8096 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Wed, 20 May 2026 18:40:04 +0530 Subject: [PATCH 09/20] [ADD] estate: create custom list and form views - Added custom list view for estate.property - Added structured form view with grouped fields - Improved UI layout for property records - Organized fields using sheet, group and notebook tags - Updated estate_property_views.xml for better usability --- estate/views/estate_property_views.xml | 94 +++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 09424ecba91..a6ecec4688e 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,7 +1,95 @@ - + Estate Properties estate.property list,form - - + + + + + Estate.properties.list + estate.property + + + + + + + + + + + + + + + + + estate.property.form + estate.property + + +
+ + + +
+

+ +

+

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + + \ No newline at end of file From 3d8835cb5be354c5ab30b3e184e460fd32537e16 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Thu, 21 May 2026 18:32:54 +0530 Subject: [PATCH 10/20] [ADD] estate: implement custom search view and filters - Added custom search view for estate.property - Added searchable fields for property records - Implemented Available properties filter using domain - Added Group By option for postcode - Improved property filtering and search experience --- estate/views/estate_property_views.xml | 34 ++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index a6ecec4688e..69980e2549a 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -91,5 +91,35 @@ - - \ No newline at end of file + + + estate.property.form + estate.property + + + + + + + + + + + + + + + + + + + + + From a9370eed7eb09caf76966086815e1e755612587e Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Fri, 22 May 2026 18:35:23 +0530 Subject: [PATCH 11/20] [IMP] estate: revise previous chapters and start relational fields - Revised Estate module concepts from previous chapters - Reviewed views, menus, actions and search functionality - Started learning relational fields in Odoo ORM - Continued module structure and model understanding --- estate/models/estate_property.py | 30 +++++++++++++++----------- estate/views/estate_menus.xml | 2 -- estate/views/estate_property_views.xml | 13 ++--------- 3 files changed, 19 insertions(+), 26 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f5be6dc9c23..53aed0ca3fb 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,33 +1,37 @@ from dateutil.relativedelta import relativedelta -from odoo import fields,models +from odoo import fields, models + class EstateProperty(models.Model): - _name='estate.property' - _descripion='Estate Property description modulee' - name=fields.Char(string='Name',required=True) - description=fields.Text(string='Description') - bedrooms=fields.Integer(string='Bedrooms',default=2) + _name = 'estate.property' + _description = 'Estate Property description modulee' + name = fields.Char(string='Name', required=True) + description = fields.Text(string='Description') + bedrooms = fields.Integer(string='Bedrooms', default=2) price = fields.Float(string='Price') garden = fields.Boolean(string='Garden') postcode = fields.Char(string='Postal Code') - date_available = fields.Date(string='Available Date',copy=False,default=lambda self:fields.Date.today() + relativedelta(months=3)) + date_available = fields.Date(string='Available Date', copy=False, + default=lambda self: fields.Date.today() + relativedelta(months=3)) expected_price = fields.Float(string='Expected Price') - selling_price = fields.Float(string='Selling Price',readonly=True,copy=False) + selling_price = fields.Float( + string='Selling Price', readonly=True, copy=False) meeting_time = fields.Datetime(string='Meeting') 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( + garden_orientation = fields.Selection( [ - ('north','North'),('south','South'),('east','East'),('west','West') + ('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West') ] ) - active=fields.Boolean(default=True) - state=fields.Selection( + active = fields.Boolean(default=True) + state = fields.Selection( [ - ('new','New'),('offer_received','Offer Received'),('offer_accepted','Offer Accepted'),('sold','Sold'),('canceled','Canceled') + ('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', + 'Offer Accepted'), ('sold', 'Sold'), ('canceled', 'Canceled') ], default='new', string='Status', diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 59f03384878..b50d5b3ea5e 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,7 +1,5 @@ - - diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 69980e2549a..29f991de316 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,11 +1,11 @@ + Estate Properties estate.property list,form - Estate.properties.list estate.property @@ -31,7 +31,6 @@ - @@ -39,15 +38,12 @@ estate.property.form estate.property -
- -

@@ -82,13 +78,9 @@ - - - - @@ -121,5 +113,4 @@ - - + \ No newline at end of file From 78e39922dd5f44f7a11c0680653f6523ca388db0 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Mon, 25 May 2026 11:49:47 +0530 Subject: [PATCH 12/20] [FIX] Fixed all the whitespaces warnings --- estate/__manifest__.py | 28 ++++++++-------- estate/models/estate_property.py | 56 +++++++++++++++++--------------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index a5678adebfc..0964fdd3cdd 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,16 +1,16 @@ { - 'name': 'estate', - 'version': '1.0', - 'depends': ['base'], - 'category': 'tutorials', - 'author': "sadeo-odoo", - 'license': 'LGPL-3', - 'description': 'A real estate module', - 'installable': True, - 'application': True, - 'data':[ - 'security/ir.model.access.csv', - 'views/estate_property_views.xml', - 'views/estate_menus.xml', - ] + "name": "estate", + "version": "1.0", + "depends": ["base"], + "category": "tutorials", + "author": "sadeo-odoo", + "license": "LGPL-3", + "description": "A real estate module", + "installable": True, + "application": True, + "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 53aed0ca3fb..ede74b23b74 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -3,38 +3,40 @@ class EstateProperty(models.Model): - _name = 'estate.property' - _description = 'Estate Property description modulee' - name = fields.Char(string='Name', required=True) - description = fields.Text(string='Description') - bedrooms = fields.Integer(string='Bedrooms', default=2) - price = fields.Float(string='Price') - garden = fields.Boolean(string='Garden') - postcode = fields.Char(string='Postal Code') - date_available = fields.Date(string='Available Date', copy=False, - default=lambda self: fields.Date.today() + relativedelta(months=3)) - expected_price = fields.Float(string='Expected Price') - selling_price = fields.Float( - string='Selling Price', readonly=True, copy=False) - meeting_time = fields.Datetime(string='Meeting') - 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') + _name = "estate.property" + _description = "Estate Property description modulee" + name = fields.Char(string="Name", required=True) + description = fields.Text(string="Description") + bedrooms = fields.Integer(string="Bedrooms", default=2) + price = fields.Float(string="Price") + postcode = fields.Char(string="Postal Code") + date_available = fields.Date( + string="Available Date", + copy=False, + default=lambda self: fields.Date.today() + relativedelta(months=3), + ) + expected_price = fields.Float(string="Expected Price") + selling_price = fields.Float(string="Selling Price", readonly=True, copy=False) + meeting_time = fields.Datetime(string="Meeting") + 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( - [ - ('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West') - ] + [("north", "North"), ("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'), ('canceled', 'Canceled') + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("canceled", "Canceled"), ], - default='new', - string='Status', + default="new", + string="Status", copy=False, - required=True + required=True, ) From 3274a175f9db49d0bf0f52246af72c040996337f Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 26 May 2026 22:51:40 +0530 Subject: [PATCH 13/20] [ADD] estate: add property type and Many2one relations - Created estate.property.type model and related menus - Added property_type_id field to estate.property - Updated form, list and search views for property type - Added buyer and salesperson Many2one fields - Added new tab for buyer and salesperson information - Set default salesperson as current user - Added required access rights and model imports --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 6 +++ estate/models/estate_property_type.py | 8 ++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menus.xml | 12 ++++-- estate/views/estate_property_type_views.xml | 43 +++++++++++++++++++++ estate/views/estate_property_views.xml | 16 +++++++- 8 files changed, 84 insertions(+), 4 deletions(-) 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 0964fdd3cdd..8d98b410df7 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,6 +11,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 ede74b23b74..ca98fe9699a 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -5,6 +5,7 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Estate Property description modulee" + name = fields.Char(string="Name", required=True) description = fields.Text(string="Description") bedrooms = fields.Integer(string="Bedrooms", default=2) @@ -40,3 +41,8 @@ class EstateProperty(models.Model): copy=False, required=True, ) + property_type_id = fields.Char(string="Property ID") + 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..8e04ff22035 --- /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 = '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 32389642d4f..11da225066f 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 +access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index b50d5b3ea5e..78ece615e70 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,5 +1,11 @@ - - - + + + + + + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..2b7eee46301 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,43 @@ + + + + + estate.property.type.list + estate.property.type + + + + + + + + + + + + estate.property.type.form + estate.property.type + + +
+ + + + + +
+
+
+ + + + + + 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 29f991de316..3b635617a63 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -31,6 +31,9 @@ + + + @@ -74,9 +77,19 @@ + + + + + + + + + + @@ -98,6 +111,7 @@ + - \ No newline at end of file + From 0d0cfb5ac45ebb73240ae62c7207794ad57cb460 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Fri, 29 May 2026 17:16:30 +0530 Subject: [PATCH 14/20] [ADD] estate: add property tags with Many2many relation - Created estate.property.tag model - Added menus and action for property tags - Added tag_ids Many2many field to estate.property - Updated form and list views with many2many_tags widget - Implemented property categorization using tags --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 7 +++- estate/models/estate_property_tag.py | 7 ++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menus.xml | 45 ++++++++++++++++++---- estate/views/estate_property_tag_views.xml | 37 ++++++++++++++++++ estate/views/estate_property_views.xml | 5 ++- 8 files changed, 93 insertions(+), 11 deletions(-) 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 8d98b410df7..769325885a8 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -12,6 +12,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 ca98fe9699a..722d76dd51e 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,10 +1,11 @@ from dateutil.relativedelta import relativedelta + from odoo import fields, models class EstateProperty(models.Model): _name = "estate.property" - _description = "Estate Property description modulee" + _description = "Estate Property description module" name = fields.Char(string="Name", required=True) description = fields.Text(string="Description") @@ -16,7 +17,7 @@ class EstateProperty(models.Model): copy=False, default=lambda self: fields.Date.today() + relativedelta(months=3), ) - expected_price = fields.Float(string="Expected Price") + expected_price = fields.Float(string="Expectddscsfed Price") selling_price = fields.Float(string="Selling Price", readonly=True, copy=False) meeting_time = fields.Datetime(string="Meeting") living_area = fields.Integer(string="Living Area") @@ -46,3 +47,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") + \ No newline at end of file diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..7fc2222a646 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,7 @@ +from odoo import fields, models + + +class EstatePropertyTag(models.Model): + _name = "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 11da225066f..1493eab4011 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 +access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 78ece615e70..f605d5495b1 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,11 +1,40 @@ + - - - - - + + + + + + + + + + + diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml new file mode 100644 index 00000000000..433126503e7 --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,37 @@ + + + + + estate.property.tag.view.list + estate.property.tag + + + + + + + + + + estate.property.tag.view.form + estate.property.tag + +
+ + + + + +
+
+
+ + + + Property Tags + estate.property.tag + list,form + + + +
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 3b635617a63..23b05655ccb 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -34,6 +34,7 @@ + @@ -55,9 +56,10 @@

- + + @@ -80,6 +82,7 @@ + From 932e5174612afa5dcdfb3f74dadfaf92f9e8ae8a Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 2 Jun 2026 18:33:23 +0530 Subject: [PATCH 15/20] [ADD] estate: implement property offers using One2many - Created estate.property.offer model - Added partner and property relations - Added offer status and price fields - Added offer_ids One2many field to properties - Created offer form and list views - Linked offers with properties through Many2one and One2many relations --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 79 +++++++++++++------- estate/models/estate_property_offer.py | 20 +++++ estate/models/estate_property_tag.py | 1 + estate/models/estate_property_type.py | 4 +- estate/security/ir.model.access.csv | 1 + estate/views/estate_property_offer_views.xml | 32 ++++++++ estate/views/estate_property_type_views.xml | 2 +- estate/views/estate_property_views.xml | 12 ++- 10 files changed, 121 insertions(+), 32 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 769325885a8..61973ace4a9 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -13,6 +13,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 722d76dd51e..b42a458fc33 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -5,30 +5,38 @@ class EstateProperty(models.Model): _name = "estate.property" - _description = "Estate Property description module" + _description = "Real Estate Property" + + name = fields.Char(required=True) + description = fields.Text() + postcode = fields.Char() - name = fields.Char(string="Name", required=True) - description = fields.Text(string="Description") - bedrooms = fields.Integer(string="Bedrooms", default=2) - price = fields.Float(string="Price") - postcode = fields.Char(string="Postal Code") date_available = fields.Date( - string="Available Date", - copy=False, - default=lambda self: fields.Date.today() + relativedelta(months=3), - ) - expected_price = fields.Float(string="Expectddscsfed Price") - selling_price = fields.Float(string="Selling Price", readonly=True, copy=False) - meeting_time = fields.Datetime(string="Meeting") - 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") + default=lambda self: fields.Date.today() + relativedelta(months=3) + ) + + expected_price = fields.Float(required=True) + selling_price = fields.Float(readonly=True, copy=False) + + bedrooms = fields.Integer(default=2) + living_area = fields.Integer() + facades = fields.Integer() + + garage = fields.Boolean() + garden = fields.Boolean() + garden_area = fields.Integer() + garden_orientation = fields.Selection( - [("north", "North"), ("south", "South"), ("east", "East"), ("west", "West")] + [ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ] ) + active = fields.Boolean(default=True) + state = fields.Selection( [ ("new", "New"), @@ -38,14 +46,33 @@ class EstateProperty(models.Model): ("canceled", "Canceled"), ], default="new", - string="Status", - copy=False, required=True, + copy=False, ) - property_type_id = fields.Char(string="Property ID") - buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) + + buyer_id = fields.Many2one( + "res.partner", + string="Buyer", + copy=False, + ) + salesperson_id = fields.Many2one( - "res.users", string="Salesperson", default=lambda self: self.env.user + "res.users", + string="Salesperson", + default=lambda self: self.env.user, + ) + + property_type_id = fields.Many2one( + "estate.property.type", + string="Property Type", + ) + + tag_ids = fields.Many2many( + "estate.property.tag", + string="Tags", + ) + offer_ids = fields.One2many( + "estate.property.offer", + "property_id", + string="Offers", ) - tag_ids = fields.Many2many("estate.property.tag") - \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..22777e86425 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,20 @@ +from odoo import models, fields + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "It is estate property offer" + + price = fields.Float() + status = fields.Selection( + [ + ("accepted", "Accepted"), + ("rejected", "Rejected"), + ], + copy=False, + ) + partner_id = fields.Many2one( + "res.partner", + required=True, + ) + property_id = fields.Many2one("estate.property", required=True) diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py index 7fc2222a646..165132d19de 100644 --- a/estate/models/estate_property_tag.py +++ b/estate/models/estate_property_tag.py @@ -3,5 +3,6 @@ class EstatePropertyTag(models.Model): _name = "estate.property.tag" + _description = "Estate Property Tag" name = fields.Char(required=True) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 8e04ff22035..7860a26125e 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -2,7 +2,7 @@ class EstatePropertyType(models.Model): - _name = 'estate.property.type' - _description = 'Estate Property Type' + _name = "estate.property.type" + _description = "Estate Property Type" name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 1493eab4011..bb71cf1297b 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,access_estate_property,model_estate_property,base.group_user,1,1,1,1 access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 +access_estate_property_offer,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..a7124f48050 --- /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 + +
+ + + + + + + + +
+
+
+ +
diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index 2b7eee46301..cd6c241e2f6 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -40,4 +40,4 @@
-
\ No newline at end of file + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 23b05655ccb..683012f32ef 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -13,10 +13,10 @@
@@ -83,6 +83,7 @@ + @@ -92,6 +93,11 @@ + + + + + From cb9f93773e0dcf7d776d40ef8269dfb11f9940ac Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Mon, 8 Jun 2026 00:42:38 +0530 Subject: [PATCH 16/20] [IMP] estate: add computed fields and inverse methods - Implemented total_area and best_price computed fields - Added dependencies using @api.depends - Added offer validity and deadline computation - Implemented inverse function for editable computed field - Updated form and list views with computed values --- estate/models/estate_property.py | 17 +++++++- estate/models/estate_property_offer.py | 29 ++++++++++--- estate/views/estate_property_offer_views.xml | 5 +++ estate/views/estate_property_views.xml | 43 ++++++-------------- 4 files changed, 58 insertions(+), 36 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b42a458fc33..1b5c70a6341 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,6 @@ from dateutil.relativedelta import relativedelta -from odoo import fields, models +from odoo import api, fields, models class EstateProperty(models.Model): @@ -25,6 +25,12 @@ class EstateProperty(models.Model): garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() + total = fields.Float(compute="_compute_total") + + @api.depends("garden_area", "living_area") + def _compute_total(self): + for record in self: + record.total = record.garden_area + record.living_area garden_orientation = fields.Selection( [ @@ -76,3 +82,12 @@ class EstateProperty(models.Model): "property_id", string="Offers", ) + best_offer = fields.Float(string="Best offer", compute="_compute_best_price") + + @api.depends("offer_ids.price") + def _compute_best_price(self): + for record in self: + if record.offer_ids: + record.best_offer = max(record.offer_ids.mapped("price")) + else: + record.best_offer = 0.0 diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 22777e86425..5b50c5bde45 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,5 +1,6 @@ -from odoo import models, fields +from datetime import timedelta +from odoo import api, models, fields class EstatePropertyOffer(models.Model): _name = "estate.property.offer" @@ -13,8 +14,26 @@ class EstatePropertyOffer(models.Model): ], copy=False, ) - partner_id = fields.Many2one( - "res.partner", - required=True, - ) + partner_id = fields.Many2one("res.partner", required=True) property_id = fields.Many2one("estate.property", required=True) + + validity = fields.Integer(string="Days", default=7) + date_deadline = fields.Date(string="Deadline Date",compute="_compute_date_deadline",inverse="_inverse_date_deadline") + + @api.depends("create_date","validity") + def _compute_date_deadline(self): + for record in self: + if record.create_date: + record.date_deadline=record.create_date.date()+timedelta(days=record.validity) + + + def _inverse_date_deadline(self): + for record in self: + if record.date_deadline: + if record.create_date: + delta=record.date_deadline-record.create_date.date() + + + record.validity=delta.days + else: + record.validity=7 diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index a7124f48050..40ed122ae61 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -8,6 +8,9 @@ + + + @@ -23,6 +26,8 @@ + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 683012f32ef..9a0ccdc8b7b 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -10,19 +10,9 @@ Estate.properties.list estate.property - + @@ -43,10 +33,7 @@ estate.property.form estate.property -
+

@@ -65,6 +52,7 @@ + @@ -75,6 +63,9 @@ + + + @@ -82,8 +73,8 @@ + - @@ -95,8 +86,6 @@ - - @@ -121,19 +110,13 @@ - - + + - + \ No newline at end of file From 7de662d8514b6885a7bf5459925c791841ac4b11 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 9 Jun 2026 18:23:46 +0530 Subject: [PATCH 17/20] [IMP] estate: add property state management actions - Added Cancel and Sold buttons to property form view - Implemented action methods for property state transitions - Prevented sold properties from being cancelled - Prevented cancelled properties from being marked as sold - Added validation using UserError - Updated property workflow and state handling --- estate/__init__.py | 1 + estate/__manifest__.py | 1 + estate/models/__init__.py | 5 ++- estate/models/estate_property.py | 41 +++++++++++++++++--- estate/models/estate_property_offer.py | 30 +++++++++----- estate/models/estate_property_tag.py | 1 + estate/views/estate_menus.xml | 1 + estate/views/estate_property_offer_views.xml | 12 +++--- estate/views/estate_property_tag_views.xml | 1 + estate/views/estate_property_type_views.xml | 1 + estate/views/estate_property_views.xml | 10 ++++- 11 files changed, 78 insertions(+), 26 deletions(-) diff --git a/estate/__init__.py b/estate/__init__.py index 0650744f6bc..899bcc97f0f 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1 +1,2 @@ from . import models + diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 61973ace4a9..af42b2b6378 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -17,3 +17,4 @@ "views/estate_menus.xml", ], } + diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 2f1821a39c1..197b793ff6c 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,4 +1,5 @@ from . import estate_property -from . import estate_property_type -from . import estate_property_tag from . import estate_property_offer +from . import estate_property_tag +from . import estate_property_type + diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 1b5c70a6341..f3ab3d80869 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,7 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models +from odoo.exceptions import UserError class EstateProperty(models.Model): @@ -27,11 +28,6 @@ class EstateProperty(models.Model): garden_area = fields.Integer() total = fields.Float(compute="_compute_total") - @api.depends("garden_area", "living_area") - def _compute_total(self): - for record in self: - record.total = record.garden_area + record.living_area - garden_orientation = fields.Selection( [ ("north", "North"), @@ -77,17 +73,50 @@ def _compute_total(self): "estate.property.tag", string="Tags", ) + offer_ids = fields.One2many( "estate.property.offer", "property_id", string="Offers", ) - best_offer = fields.Float(string="Best offer", compute="_compute_best_price") + + best_offer = fields.Float( + string="Best offer", + compute="_compute_best_price", + ) + + @api.depends("garden_area", "living_area") + def _compute_total(self): + for record in self: + record.total = record.garden_area + record.living_area @api.depends("offer_ids.price") def _compute_best_price(self): + # breakpoint() for record in self: if record.offer_ids: record.best_offer = max(record.offer_ids.mapped("price")) else: record.best_offer = 0.0 + + @api.onchange("garden") + def _onchange_garden(self): + if self.garden == True: + self.garden_area = 10 + self.garden_orientation = "north" + else: + self.garden_area = 0 + self.garden_orientation = "" + + def action_cancel(self): + for record in self: + if record.state == "sold": + raise UserError("A sold property cannot be canceled") + record.state = "canceled" + + def action_sold(self): + for record in self: + if record.state == "canceled": + raise UserError("A canceled property can't be sold") + record.state = "sold" + diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 5b50c5bde45..194638845b6 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -2,11 +2,13 @@ from odoo import api, models, fields + class EstatePropertyOffer(models.Model): _name = "estate.property.offer" _description = "It is estate property offer" price = fields.Float() + status = fields.Selection( [ ("accepted", "Accepted"), @@ -14,26 +16,34 @@ class EstatePropertyOffer(models.Model): ], copy=False, ) + partner_id = fields.Many2one("res.partner", required=True) + property_id = fields.Many2one("estate.property", required=True) - + validity = fields.Integer(string="Days", default=7) - date_deadline = fields.Date(string="Deadline Date",compute="_compute_date_deadline",inverse="_inverse_date_deadline") - @api.depends("create_date","validity") + date_deadline = fields.Date( + string="Deadline Date", + compute="_compute_date_deadline", + inverse="_inverse_date_deadline", + ) + + @api.depends("create_date", "validity") def _compute_date_deadline(self): for record in self: if record.create_date: - record.date_deadline=record.create_date.date()+timedelta(days=record.validity) + record.date_deadline = record.create_date.date() + timedelta( + days=record.validity + ) - def _inverse_date_deadline(self): for record in self: if record.date_deadline: if record.create_date: - delta=record.date_deadline-record.create_date.date() - - - record.validity=delta.days + delta = record.date_deadline - record.create_date.date() + + record.validity = delta.days else: - record.validity=7 + record.validity = 7 + diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py index 165132d19de..8b2186b3440 100644 --- a/estate/models/estate_property_tag.py +++ b/estate/models/estate_property_tag.py @@ -6,3 +6,4 @@ class EstatePropertyTag(models.Model): _description = "Estate Property Tag" name = fields.Char(required=True) + \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index f605d5495b1..f17e7982bfc 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -38,3 +38,4 @@ /> + diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index 40ed122ae61..8c1e4828ea1 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -8,9 +8,8 @@ - - - + + @@ -24,10 +23,10 @@ - - - + + + @@ -35,3 +34,4 @@ + diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml index 433126503e7..c0cab7cb1de 100644 --- a/estate/views/estate_property_tag_views.xml +++ b/estate/views/estate_property_tag_views.xml @@ -35,3 +35,4 @@ + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index cd6c241e2f6..61642b21567 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -41,3 +41,4 @@ + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 9a0ccdc8b7b..1e9e6647f05 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -11,7 +11,7 @@ estate.property @@ -30,10 +30,15 @@ + estate.property.form estate.property
+
+

@@ -119,4 +124,5 @@ - \ No newline at end of file + + From 90be9bb62c454f9395e23a08dd95594f9f872b6e Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 9 Jun 2026 18:23:46 +0530 Subject: [PATCH 18/20] [IMP] estate: add SQL and Python constraints - Added SQL constraints for positive property and offer prices - Added unique constraints on property type and tag names - Implemented Python constraint for selling price validation - Prevented selling price from being lower than 90% of expected price - Used float_compare and float_is_zero for float comparisons - Improved data consistency and validation rules --- estate/models/estate_property.py | 43 ++++++++++++++++++--- estate/models/estate_property_offer.py | 28 +++++++++++++- estate/models/estate_property_tag.py | 1 + estate/models/estate_property_type.py | 5 +++ estate/security/ir.model.access.csv | 3 +- estate/views/estate_property_type_views.xml | 7 +++- estate/views/estate_property_views.xml | 8 ++-- 7 files changed, 81 insertions(+), 14 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f3ab3d80869..44c34006a01 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,7 +1,8 @@ from dateutil.relativedelta import relativedelta from odoo import api, fields, models -from odoo.exceptions import UserError +from odoo.exceptions import UserError, ValidationError +from odoo.tools.float_utils import float_compare, float_is_zero class EstateProperty(models.Model): @@ -15,6 +16,7 @@ class EstateProperty(models.Model): date_available = fields.Date( default=lambda self: fields.Date.today() + relativedelta(months=3) ) + _log_access = False expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) @@ -41,11 +43,11 @@ class EstateProperty(models.Model): state = fields.Selection( [ - ("new", "New"), - ("offer_received", "Offer Received"), - ("offer_accepted", "Offer Accepted"), - ("sold", "Sold"), - ("canceled", "Canceled"), + ('new', "New"), + ('offer_received', "Offer Received"), + ('offer_accepted', "Offer Accepted"), + ('sold', "Sold"), + ('canceled', "Canceled"), ], default="new", required=True, @@ -108,15 +110,44 @@ def _onchange_garden(self): self.garden_area = 0 self.garden_orientation = "" + _check_expected_price = models.Constraint( + "CHECK(expected_price > 0)", "The expected price must be strictly positive." + ) + + _check_selling_price = models.Constraint( + "CHECK(selling_price >= 0)", "The selling price must be positive." + ) + + @api.constrains("selling_price", "expected_price") + def _check_seling_price(self): + for record in self: + if float_is_zero(record.selling_price, precision_digits=2): + continue + if ( + float_compare( + record.selling_price, + record.expected_price * 0.9, + precision_digits=2, + ) + < 0 + ): + raise ValidationError( + "Selling price cannot be lower than 90%of expected price!" + ) + def action_cancel(self): for record in self: if record.state == "sold": raise UserError("A sold property cannot be canceled") record.state = "canceled" + return True + def action_sold(self): for record in self: if record.state == "canceled": raise UserError("A canceled property can't be sold") record.state = "sold" + return True + diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 194638845b6..51c492e8db0 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,6 +1,8 @@ from datetime import timedelta from odoo import api, models, fields +from odoo.exceptions import UserError +from odoo.exceptions import ValidationError class EstatePropertyOffer(models.Model): @@ -11,8 +13,8 @@ class EstatePropertyOffer(models.Model): status = fields.Selection( [ - ("accepted", "Accepted"), - ("rejected", "Rejected"), + ('accepted', "Accepted"), + ('rejected', "Rejected"), ], copy=False, ) @@ -37,6 +39,12 @@ def _compute_date_deadline(self): days=record.validity ) + @api.constrains("price") + def _check_price(self): + for record in self: + if record.price <= 0: + raise ValidationError("They should be positive") + def _inverse_date_deadline(self): for record in self: if record.date_deadline: @@ -47,3 +55,19 @@ def _inverse_date_deadline(self): else: record.validity = 7 + def action_accept(self): + for offer in self.property_id.offer_ids: + if self != offer and offer.status == "accepted": + raise UserError("An offer is already accepted.") + + self.status = "accepted" + self.property_id.buyer_id = self.partner_id + self.property_id.selling_price = self.price + + return True + + def action_reject(self): + for record in self: + record.status = "rejected" + return True + diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py index 8b2186b3440..ca4073b7519 100644 --- a/estate/models/estate_property_tag.py +++ b/estate/models/estate_property_tag.py @@ -6,4 +6,5 @@ class EstatePropertyTag(models.Model): _description = "Estate Property Tag" name = fields.Char(required=True) + \ No newline at end of file diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 7860a26125e..943537afc02 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -6,3 +6,8 @@ class EstatePropertyType(models.Model): _description = "Estate Property Type" name = fields.Char(required=True) + + _name_unique = models.Constraint( + "UNIQUE(name)", "Property Type name must be unique." + ) + diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index bb71cf1297b..bc8e6d38057 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -2,4 +2,5 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 -access_estate_property_offer,estate.property.offer,model_estate_property_offer,base.group_user,1,1,1,1 \ No newline at end of file +access_estate_property_offer,estate.property.offer,model_estate_property_offer,base.group_user,1,1,1,1 + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index 61642b21567..54674e9bc65 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -22,7 +22,12 @@ - +
+

+ +

+

+
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 1e9e6647f05..01426d75de8 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -36,8 +36,8 @@
-
@@ -68,9 +68,9 @@ - + - + From c669af98d247465c3e8c369163baeea7c8c10741 Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Mon, 15 Jun 2026 17:51:13 +0530 Subject: [PATCH 19/20] [IMP] estate: improve property views and record ordering - Added property_ids One2many field to property types - Added inline property list view in property type form - Displayed property state using statusbar widget - Added default ordering for property, offer, tag, and type models - Ordered properties by descending ID - Ordered offers by descending price - Ordered tags and property types by name - Improved usability and consistency of estate views --- estate/__init__.py | 1 - estate/__manifest__.py | 1 - estate/models/__init__.py | 1 - estate/models/estate_property.py | 17 ++++++++--------- estate/models/estate_property_offer.py | 13 ++++--------- estate/models/estate_property_tag.py | 5 ++++- estate/models/estate_property_type.py | 6 +++++- estate/security/ir.model.access.csv | 1 - estate/views/estate_menus.xml | 1 - estate/views/estate_property_offer_views.xml | 3 ++- estate/views/estate_property_tag_views.xml | 1 - estate/views/estate_property_type_views.xml | 12 +++++++++++- estate/views/estate_property_views.xml | 3 ++- 13 files changed, 36 insertions(+), 29 deletions(-) diff --git a/estate/__init__.py b/estate/__init__.py index 899bcc97f0f..0650744f6bc 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1,2 +1 @@ from . import models - diff --git a/estate/__manifest__.py b/estate/__manifest__.py index af42b2b6378..61973ace4a9 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -17,4 +17,3 @@ "views/estate_menus.xml", ], } - diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 197b793ff6c..8f2187ee09e 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -2,4 +2,3 @@ from . import estate_property_offer from . import estate_property_tag from . import estate_property_type - diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 44c34006a01..01a50246dc8 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -8,6 +8,7 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Real Estate Property" + _order = "id desc" name = fields.Char(required=True) description = fields.Text() @@ -43,11 +44,11 @@ class EstateProperty(models.Model): state = fields.Selection( [ - ('new', "New"), - ('offer_received', "Offer Received"), - ('offer_accepted', "Offer Accepted"), - ('sold', "Sold"), - ('canceled', "Canceled"), + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("canceled", "Canceled"), ], default="new", required=True, @@ -94,7 +95,6 @@ def _compute_total(self): @api.depends("offer_ids.price") def _compute_best_price(self): - # breakpoint() for record in self: if record.offer_ids: record.best_offer = max(record.offer_ids.mapped("price")) @@ -103,7 +103,7 @@ def _compute_best_price(self): @api.onchange("garden") def _onchange_garden(self): - if self.garden == True: + if self.garden: self.garden_area = 10 self.garden_orientation = "north" else: @@ -132,7 +132,7 @@ def _check_seling_price(self): < 0 ): raise ValidationError( - "Selling price cannot be lower than 90%of expected price!" + "Selling price cannot be lower than 90% of expected price!" ) def action_cancel(self): @@ -150,4 +150,3 @@ def action_sold(self): record.state = "sold" return True - diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 51c492e8db0..4b9804440b5 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -2,19 +2,19 @@ from odoo import api, models, fields from odoo.exceptions import UserError -from odoo.exceptions import ValidationError class EstatePropertyOffer(models.Model): _name = "estate.property.offer" _description = "It is estate property offer" + _order = "price desc" price = fields.Float() status = fields.Selection( [ - ('accepted', "Accepted"), - ('rejected', "Rejected"), + ("accepted", "Accepted"), + ("rejected", "Rejected"), ], copy=False, ) @@ -39,11 +39,7 @@ def _compute_date_deadline(self): days=record.validity ) - @api.constrains("price") - def _check_price(self): - for record in self: - if record.price <= 0: - raise ValidationError("They should be positive") + _check_price = models.Constraint("CHECK(price>0)", "The Price should be Positive") def _inverse_date_deadline(self): for record in self: @@ -70,4 +66,3 @@ def action_reject(self): for record in self: record.status = "rejected" return True - diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py index ca4073b7519..d5cf5992aff 100644 --- a/estate/models/estate_property_tag.py +++ b/estate/models/estate_property_tag.py @@ -4,7 +4,10 @@ class EstatePropertyTag(models.Model): _name = "estate.property.tag" _description = "Estate Property Tag" + _order = "name" name = fields.Char(required=True) - \ No newline at end of file + _name_unique = models.Constraint( + "UNIQUE(name)", "Property Tag name must be unique." + ) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 943537afc02..15c678f5d11 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -6,8 +6,12 @@ class EstatePropertyType(models.Model): _description = "Estate Property Type" name = fields.Char(required=True) + property_ids = fields.One2many( + "estate.property", + "property_type_id", + string="Properties", + ) _name_unique = models.Constraint( "UNIQUE(name)", "Property Type name must be unique." ) - diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index bc8e6d38057..8c7fdb57d93 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -3,4 +3,3 @@ access_estate_property,access_estate_property,model_estate_property,base.group_u 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,estate.property.offer,model_estate_property_offer,base.group_user,1,1,1,1 - diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index f17e7982bfc..f605d5495b1 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -38,4 +38,3 @@ /> - diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index 8c1e4828ea1..e6d5099d229 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -9,6 +9,8 @@ +
+ + + + + + + + + + +
@@ -46,4 +57,3 @@ - diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 01426d75de8..c63057ea085 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -38,6 +38,8 @@
@@ -125,4 +127,3 @@ - From f6c89d4031696d90e5b9fc288413d342efcf324c Mon Sep 17 00:00:00 2001 From: sadeo-odoo Date: Tue, 16 Jun 2026 17:39:22 +0530 Subject: [PATCH 20/20] [IMP] estate: add view customization and manual ordering - Added manual ordering support for property types - Added sequence field and handle widget in property type list view - Updated property type model ordering to use sequence - Disabled create and edit options for property types in property form - Added color field to property tags - Enabled color picker for tags using many2many_tags widget options - Improved form view usability and data entry experience --- estate/models/estate_property.py | 67 ++++++++++----------- estate/models/estate_property_offer.py | 31 +++++----- estate/models/estate_property_tag.py | 8 ++- estate/models/estate_property_type.py | 12 ++-- estate/views/estate_property_type_views.xml | 2 + estate/views/estate_property_views.xml | 8 +-- 6 files changed, 68 insertions(+), 60 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 01a50246dc8..29f1ea97650 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -6,9 +6,9 @@ class EstateProperty(models.Model): - _name = "estate.property" + _name = 'estate.property' _description = "Real Estate Property" - _order = "id desc" + _order = 'id desc' name = fields.Char(required=True) description = fields.Text() @@ -17,7 +17,6 @@ class EstateProperty(models.Model): date_available = fields.Date( default=lambda self: fields.Date.today() + relativedelta(months=3) ) - _log_access = False expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) @@ -29,14 +28,14 @@ class EstateProperty(models.Model): garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() - total = fields.Float(compute="_compute_total") + total = fields.Float(compute='_compute_total') garden_orientation = fields.Selection( [ - ("north", "North"), - ("south", "South"), - ("east", "East"), - ("west", "West"), + ('north', "North"), + ('south', "South"), + ('east', "East"), + ('west', "West"), ] ) @@ -44,81 +43,81 @@ class EstateProperty(models.Model): state = fields.Selection( [ - ("new", "New"), - ("offer_received", "Offer Received"), - ("offer_accepted", "Offer Accepted"), - ("sold", "Sold"), - ("canceled", "Canceled"), + ('new', "New"), + ('offer_received', "Offer Received"), + ('offer_accepted', "Offer Accepted"), + ('sold', "Sold"), + ('canceled', "Canceled"), ], - default="new", + default='new', required=True, copy=False, ) buyer_id = fields.Many2one( - "res.partner", + 'res.partner', string="Buyer", copy=False, ) salesperson_id = fields.Many2one( - "res.users", + 'res.users', string="Salesperson", default=lambda self: self.env.user, ) property_type_id = fields.Many2one( - "estate.property.type", + 'estate.property.type', string="Property Type", ) tag_ids = fields.Many2many( - "estate.property.tag", + 'estate.property.tag', string="Tags", ) offer_ids = fields.One2many( - "estate.property.offer", - "property_id", + 'estate.property.offer', + 'property_id', string="Offers", ) best_offer = fields.Float( string="Best offer", - compute="_compute_best_price", + compute='_compute_best_price', ) - @api.depends("garden_area", "living_area") + @api.depends('garden_area', 'living_area') def _compute_total(self): for record in self: record.total = record.garden_area + record.living_area - @api.depends("offer_ids.price") + @api.depends('offer_ids.price') def _compute_best_price(self): for record in self: if record.offer_ids: - record.best_offer = max(record.offer_ids.mapped("price")) + record.best_offer = max(record.offer_ids.mapped('price')) else: record.best_offer = 0.0 - @api.onchange("garden") + @api.onchange('garden') def _onchange_garden(self): if self.garden: self.garden_area = 10 - self.garden_orientation = "north" + self.garden_orientation = 'north' else: self.garden_area = 0 - self.garden_orientation = "" + self.garden_orientation = '' _check_expected_price = models.Constraint( - "CHECK(expected_price > 0)", "The expected price must be strictly positive." + 'CHECK(expected_price > 0)', "The expected price must be strictly positive." ) _check_selling_price = models.Constraint( - "CHECK(selling_price >= 0)", "The selling price must be positive." + 'CHECK(selling_price >= 0)', "The selling price must be positive." ) - @api.constrains("selling_price", "expected_price") + @api.constrains('selling_price', 'expected_price') def _check_seling_price(self): for record in self: if float_is_zero(record.selling_price, precision_digits=2): @@ -137,16 +136,16 @@ def _check_seling_price(self): def action_cancel(self): for record in self: - if record.state == "sold": + if record.state == 'sold': raise UserError("A sold property cannot be canceled") - record.state = "canceled" + record.state = 'canceled' return True def action_sold(self): for record in self: - if record.state == "canceled": + if record.state == 'canceled': raise UserError("A canceled property can't be sold") - record.state = "sold" + record.state = 'sold' return True diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 4b9804440b5..981a08859bb 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -5,33 +5,33 @@ class EstatePropertyOffer(models.Model): - _name = "estate.property.offer" + _name = 'estate.property.offer' _description = "It is estate property offer" - _order = "price desc" + _order = 'price desc' price = fields.Float() status = fields.Selection( [ - ("accepted", "Accepted"), - ("rejected", "Rejected"), + ('accepted', "Accepted"), + ('rejected', "Rejected"), ], copy=False, ) - partner_id = fields.Many2one("res.partner", required=True) + partner_id = fields.Many2one('res.partner', required=True) - property_id = fields.Many2one("estate.property", required=True) + property_id = fields.Many2one('estate.property', required=True) validity = fields.Integer(string="Days", default=7) date_deadline = fields.Date( string="Deadline Date", - compute="_compute_date_deadline", - inverse="_inverse_date_deadline", + compute='_compute_date_deadline', + inverse='_inverse_date_deadline', ) - @api.depends("create_date", "validity") + @api.depends('create_date', 'validity') def _compute_date_deadline(self): for record in self: if record.create_date: @@ -39,7 +39,7 @@ def _compute_date_deadline(self): days=record.validity ) - _check_price = models.Constraint("CHECK(price>0)", "The Price should be Positive") + _check_price = models.Constraint('CHECK(price>0)', "The Price should be Positive") def _inverse_date_deadline(self): for record in self: @@ -53,16 +53,17 @@ def _inverse_date_deadline(self): def action_accept(self): for offer in self.property_id.offer_ids: - if self != offer and offer.status == "accepted": + if self != offer and offer.status == 'accepted': raise UserError("An offer is already accepted.") - self.status = "accepted" - self.property_id.buyer_id = self.partner_id - self.property_id.selling_price = self.price + self.status = 'accepted' + self.property_id.buyer_id = self.partner_id + self.property_id.selling_price = self.price + self.property_id.state = 'offer_accepted' return True def action_reject(self): for record in self: - record.status = "rejected" + record.status = 'rejected' return True diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py index d5cf5992aff..757fd923a46 100644 --- a/estate/models/estate_property_tag.py +++ b/estate/models/estate_property_tag.py @@ -2,12 +2,14 @@ class EstatePropertyTag(models.Model): - _name = "estate.property.tag" + _name = 'estate.property.tag' _description = "Estate Property Tag" - _order = "name" + _order = 'name' name = fields.Char(required=True) + color = fields.Integer(string="Color") + _name_unique = models.Constraint( - "UNIQUE(name)", "Property Tag name must be unique." + 'UNIQUE(name)', "Property Tag name must be unique." ) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 15c678f5d11..6d610af8191 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -2,16 +2,20 @@ class EstatePropertyType(models.Model): - _name = "estate.property.type" + _name = 'estate.property.type' _description = "Estate Property Type" + _order = "sequence, name" name = fields.Char(required=True) property_ids = fields.One2many( - "estate.property", - "property_type_id", + 'estate.property', + 'property_type_id', string="Properties", ) + sequence = fields.Integer( + "Sequence", default="1" + ) _name_unique = models.Constraint( - "UNIQUE(name)", "Property Type name must be unique." + 'UNIQUE(name)', "Property Type name must be unique." ) diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index 9070d00aa23..afa46fc1d78 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -8,6 +8,8 @@ + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index c63057ea085..3ef0fa2285c 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -39,7 +39,7 @@