From e91c815b7e655421e0e42f9cc64dd0d75213e871 Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Tue, 10 Mar 2026 16:31:24 +0530 Subject: [PATCH 1/9] [ADD] estate: add module to sell property -Created a new app called Estate. -Set up the estate addon with a proper manifest file. -Added estate property model with all required fields. -Access rights assigned to base groups. -CH2 , CH3 Completed. --- estate/__init__.py | 1 + estate/__manifest__.py | 15 +++++++++++++++ estate/models/__init__.py | 1 + estate/models/estate_property.py | 20 ++++++++++++++++++++ estate/security/ir.model.access.csv | 2 ++ 5 files changed, 39 insertions(+) create mode 100644 estate/__init__.py create mode 100644 estate/__manifest__.py create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__init__.py b/estate/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/estate/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/estate/__manifest__.py b/estate/__manifest__.py new file mode 100644 index 00000000000..90f2da81b78 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,15 @@ +{ + 'name': 'RealEstate', + 'version': '1.0', + 'category': 'RealEstate', + 'summary': 'A module to manage real estate advertisements and property offers', + 'description': """A simple module to manage real estate ads.List your properties, track details like bedrooms and garden,let buyers make offers, and accept or reject them.""", + 'author': 'Pranjali Sangavekar(prsan)', + 'license': 'LGPL-3', + 'depends': ['base'], + 'application': True, + 'installable': True, + 'data': [ + 'security/ir.model.access.csv', +], +} 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..4cf42b5905e --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,20 @@ +from odoo import models, fields + + +class Estate_Property(models.Model): + _name = "estate.property" + _description = "Real estate system" + + name = fields.Char(string="Property Name", required=True) + description = fields.Text() + postcode = fields.Char(string="Postal Code") + date_availability = fields.Date(string="Availability Date") + expected_price = fields.Float(string="Expected Selling Price", required=True) + selling_price = fields.Float(string="Selling Price") + bedrooms = fields.Integer() + living_area = fields.Integer() + facades = fields.Integer() + garage = fields.Boolean() + garden = fields.Boolean() + garden_area = fields.Integer() + garden_orientation = fields.Selection(selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..0e525a41a26 --- /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,estate.property,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file From a944174b0a18201670d62adad443dbf94af86db7 Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Wed, 11 Mar 2026 14:02:04 +0530 Subject: [PATCH 2/9] [ADD] estate: add security groups with differentiated access rights The tutorial uses base groups, giving all rights to every user. Instead, Two dedicated groups are defined: - Agent: read and write access only - Manager: full CRUD access, implies Agent group - Admin user is automatically assigned the Manager group - CH4 Done --- estate/__manifest__.py | 7 ++++--- estate/security/ir.model.access.csv | 3 ++- estate/security/security.xml | 23 +++++++++++++++++++++++ 3 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 estate/security/security.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 90f2da81b78..671ea7db71b 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,7 +1,7 @@ { 'name': 'RealEstate', 'version': '1.0', - 'category': 'RealEstate', + 'category': 'Real Estate/Brokerage', 'summary': 'A module to manage real estate advertisements and property offers', 'description': """A simple module to manage real estate ads.List your properties, track details like bedrooms and garden,let buyers make offers, and accept or reject them.""", 'author': 'Pranjali Sangavekar(prsan)', @@ -10,6 +10,7 @@ 'application': True, 'installable': True, 'data': [ - 'security/ir.model.access.csv', -], + 'security/security.xml', + 'security/ir.model.access.csv', + ], } diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 0e525a41a26..1ffcb29c930 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,estate.property,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file +access_estate_property_manager,estate.property manager,model_estate_property,estate.estate_group_manager,1,1,1,1 +access_estate_property_user,estate.property agent,model_estate_property,estate.estate_group_user,1,1,0,0 \ No newline at end of file diff --git a/estate/security/security.xml b/estate/security/security.xml new file mode 100644 index 00000000000..79e80966704 --- /dev/null +++ b/estate/security/security.xml @@ -0,0 +1,23 @@ + + + + + Real Estate + + + + + Agent + + + + + Manager + + + + + + + + \ No newline at end of file From c404b9b493ad0db329d737b5fdd93de688f398ad Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Thu, 12 Mar 2026 18:46:12 +0530 Subject: [PATCH 3/9] [IMP] estate: set field rules and reserved fields - Selling Price field is set as readonly so users cannot edit it manually; it is determined through the offer validation flow. - Selling Price and State fields are not duplicated when a property is copied, to avoid carrying over stale data. - Availability Date field is not duplicated so a fresh date is always required for new listings. - Bedrooms field defaults to 2 as a sensible starting point. - Active field defaults to True so properties are visible by default in list views. - State field is required and defaults to 'New' to track the property through its lifecycle. - CH5 done --- estate/__manifest__.py | 2 ++ estate/models/estate_property.py | 18 +++++++++++++++--- estate/views/estate_menus.xml | 8 ++++++++ estate/views/estate_property_views.xml | 8 ++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 estate/views/estate_menus.xml create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 671ea7db71b..03799c954ad 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -12,5 +12,7 @@ 'data': [ 'security/security.xml', '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 4cf42b5905e..2b6b01fad1c 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 models, fields @@ -8,13 +9,24 @@ class Estate_Property(models.Model): name = fields.Char(string="Property Name", required=True) description = fields.Text() postcode = fields.Char(string="Postal Code") - date_availability = fields.Date(string="Availability Date") + date_availability = fields.Date(copy=False, default=lambda self: fields.Date.today() + relativedelta(months=3)) expected_price = fields.Float(string="Expected Selling Price", required=True) - selling_price = fields.Float(string="Selling Price") - bedrooms = fields.Integer() + selling_price = fields.Float(readonly=True, copy=False) + bedrooms = fields.Integer(default=2) living_area = fields.Integer() facades = fields.Integer() garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() garden_orientation = fields.Selection(selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) + active = fields.Boolean(default=True) + state = fields.Selection( + selection=[ + ('new', 'New'), + ('offer_received', 'Offer Received'), + ('offer_accepted', 'Offer Accepted'), + ('sold', 'Sold'), + ('cancelled', 'Cancelled'), + ], + required=True, copy=False, default='new' + ) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..819397e809a --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..d237d5c22d5 --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,8 @@ + + + + Properties + estate.property + list,form + + \ No newline at end of file From 7020cc112db01d1960cec802bb4832dcf1922a4f Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Fri, 13 Mar 2026 19:07:41 +0530 Subject: [PATCH 4/9] [ADD] estate: add list and form views Add basic UI views for the estate.property model to allow users to interact with property records. - Add list view to display properties in a tabular format. - Add form view to create, edit, and view individual properties. - Chapter 6 partially done (list and form views). --- estate/models/estate_property.py | 2 +- estate/security/security.xml | 9 ++++- estate/views/estate_property_views.xml | 52 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 2b6b01fad1c..d9adfddf150 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -10,7 +10,7 @@ class Estate_Property(models.Model): description = fields.Text() postcode = fields.Char(string="Postal Code") date_availability = fields.Date(copy=False, default=lambda self: fields.Date.today() + relativedelta(months=3)) - expected_price = fields.Float(string="Expected Selling Price", required=True) + expected_price = fields.Float(string="Expected Price", required=True) selling_price = fields.Float(readonly=True, copy=False) bedrooms = fields.Integer(default=2) living_area = fields.Integer() diff --git a/estate/security/security.xml b/estate/security/security.xml index 79e80966704..761dca0534f 100644 --- a/estate/security/security.xml +++ b/estate/security/security.xml @@ -1,23 +1,28 @@ + Real Estate + Agent + Manager + + - - + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index d237d5c22d5..6a1cfee4b52 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,5 +1,57 @@ + + estate.property.form + estate.property + +
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + estate.property.list + estate.property + + + + + + + + + + + Properties estate.property From 29bea6757a50b6df48cea971ea8e034cb05d9b0d Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Mon, 16 Mar 2026 18:45:23 +0530 Subject: [PATCH 5/9] [IMP] estate: improve list and form views with search and filters Improve the estate.property views to make property browsing more efficient for users. - Add search view with filters for available properties and properties by current user. - Add group by postcode option in search view. - Apply domain filters on list and form views to refine displayed records. Chapter 6 completed. --- estate/views/estate_property_views.xml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 6a1cfee4b52..74efb9e01ca 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -44,6 +44,7 @@ + @@ -52,6 +53,29 @@ + + + estate.property.search + estate.property + + + + + + + + + + + + + + + Properties estate.property From 6c43077c77c1f66b4bed871ef4c19c2d91c9eaa6 Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Tue, 17 Mar 2026 18:26:07 +0530 Subject: [PATCH 6/9] [ADD] estate: add relational fields, demo data, and app logo The estate module needed relational fields to link properties to other records, demo data for easier development and testing, and an app logo for better identification in the app list. - Add Many2one fields for property type, buyer, and salesperson. - Add Many2many field for property tags. - Add One2many field for property offers. - Add demo data with 5 sample properties for testing. - Add app logo to identify the module in the app list. Chapter 7 completed. --- estate/__manifest__.py | 9 +- estate/demo/estate_property_data.xml | 78 ++++++++++++++++++ estate/models/__init__.py | 3 + estate/models/estate_property.py | 7 +- estate/models/estate_property_offer.py | 11 +++ estate/models/estate_property_tag.py | 8 ++ estate/models/estate_property_type.py | 8 ++ estate/security/ir.model.access.csv | 8 +- estate/security/security.xml | 2 +- estate/static/description/icon.png | Bin 0 -> 4777 bytes estate/views/estate_menus.xml | 10 ++- estate/views/estate_property_offers_views.xml | 30 +++++++ estate/views/estate_property_tags_views.xml | 42 ++++++++++ estate/views/estate_property_type_views.xml | 42 ++++++++++ estate/views/estate_property_views.xml | 24 +++++- 15 files changed, 271 insertions(+), 11 deletions(-) create mode 100644 estate/demo/estate_property_data.xml create mode 100644 estate/models/estate_property_offer.py create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/static/description/icon.png create mode 100644 estate/views/estate_property_offers_views.xml create mode 100644 estate/views/estate_property_tags_views.xml create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 03799c954ad..508f7064eff 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,12 +7,17 @@ 'author': 'Pranjali Sangavekar(prsan)', 'license': 'LGPL-3', 'depends': ['base'], - 'application': True, - 'installable': True, 'data': [ 'security/security.xml', 'security/ir.model.access.csv', 'views/estate_property_views.xml', + 'views/estate_property_type_views.xml', + 'views/estate_property_tags_views.xml', + 'views/estate_property_offers_views.xml', 'views/estate_menus.xml', ], + 'demo': [ + 'demo/estate_property_data.xml', + ], + 'application': True, } diff --git a/estate/demo/estate_property_data.xml b/estate/demo/estate_property_data.xml new file mode 100644 index 00000000000..23a20ff537d --- /dev/null +++ b/estate/demo/estate_property_data.xml @@ -0,0 +1,78 @@ + + + + Beautiful Villa in Downtown + A stunning 3-bedroom villa with modern amenities + 382421 + 2026-06-15 + 6767676.00 + 3 + 9234 + 2 + True + True + 5000 + south + new + + + Cozy House with Garden + Perfect starter home with large garden + 400605 + 2026-07-01 + 100000.00 + 2 + 500 + 1 + False + True + 2000 + north + new + + + Modern Apartment + Newly built apartment in city center + 382421 + 2026-05-20 + 250000.00 + 2 + 750 + 3 + True + False + 0 + east + new + + + Traditional Cottage + Charming countryside cottage + 400605 + 2026-08-10 + 180000.00 + 3 + 650 + 2 + True + True + 3000 + west + new + + + Luxury Penthouse + High-end penthouse with panoramic views + 382421 + 2026-04-01 + 500000.00 + 4 + 1200 + 2 + True + True + 1000 + south + new + + diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..2f1821a39c1 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +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 d9adfddf150..36daa6fe875 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,5 +1,5 @@ from dateutil.relativedelta import relativedelta -from odoo import models, fields +from odoo import fields, models class Estate_Property(models.Model): @@ -30,3 +30,8 @@ class Estate_Property(models.Model): ], required=True, copy=False, default='new' ) + property_type_id = fields.Many2one('estate.property.type', string="Property Type") + buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False) + seller_id = fields.Many2one('res.users', string="Seller", default=lambda self: self.env.user) + tag_ids = fields.Many2many('estate.property.tag', string="Tags") + offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..f0513912a3d --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,11 @@ +from odoo import fields, models + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Real estate system - Property Offer" + + price = fields.Float(string="Offer Price") + status = fields.Selection(selection=[('accepted', 'Accepted'), ('refused', 'Refused')], copy=False) + partner_id = fields.Many2one('res.partner', string="Partner", required=True) + property_id = fields.Many2one('estate.property', string="Property", required=True) diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..6e4099899cf --- /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 = "Real estate system - Property Tag" + + name = fields.Char(string="Tag Name", required=True) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..1dd588218ff --- /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 = "Real estate system - Property Type" + + name = fields.Char(string="Property Type Name", required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 1ffcb29c930..6905974b938 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,3 +1,9 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_estate_property_manager,estate.property manager,model_estate_property,estate.estate_group_manager,1,1,1,1 -access_estate_property_user,estate.property agent,model_estate_property,estate.estate_group_user,1,1,0,0 \ No newline at end of file +access_estate_property_user,estate.property user,model_estate_property,estate.estate_group_user,1,1,0,0 +access_estate_property_type_manager,estate.property.type manager,model_estate_property_type,estate.estate_group_manager,1,1,1,1 +access_estate_property_type_user,estate.property.type user,model_estate_property_type,estate.estate_group_user,1,0,0,0 +access_estate_property_tag_manager,estate.property.tag manager,model_estate_property_tag,estate.estate_group_manager,1,1,1,1 +access_estate_property_tag_user,estate.property.tag user,model_estate_property_tag,estate.estate_group_user,1,0,0,0 +access_estate_property_offer_manager,estate.property.offer manager,model_estate_property_offer,estate.estate_group_manager,1,1,1,1 +access_estate_property_offer_user,estate.property.offer user,model_estate_property_offer,estate.estate_group_user,1,1,1,0 diff --git a/estate/security/security.xml b/estate/security/security.xml index 761dca0534f..176df58ec89 100644 --- a/estate/security/security.xml +++ b/estate/security/security.xml @@ -25,4 +25,4 @@ -
\ No newline at end of file + diff --git a/estate/static/description/icon.png b/estate/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..6fc6561a21c5f3658dc0cf3e2932c7173fccc6b4 GIT binary patch literal 4777 zcmV;a5?1YrP)-HVtoz>7z}3r$d)c7t?+%_r_@eYli?5Nrj%Zlt%!ew8q+rHvk__l0yo#hi(7> zLtm4n`0Co*m}AehrqX&O{rU9(J#_#YOmLj7001cf049~2s{mnt@9N_K0000DGIf-! zw~l$a%+mk>Esi<>Zl5Or06y~a^XQy6001J5jE*`xP0ic70021v0384zY0B2#3l%Mi zf^^>J(siOV=eS&BXnX()JEw11I(m`f-ScvB$eLck!1E9Zs$N_ThixW-B*)I=w+fWI3)9HI8G&%Ahy2 zzLbQ9sq+dO$BLM!D7yIt1T^(=KA5i|KhRC#bCPM2qLd*ceC*ax`&?+&P-IJ!k@4kp z>vNzPx+o^J;Y2YAipU?-M+R%39Bs(Qj?1x%2$@4NP0O-0&9Y2Waz_0MA0K#5(Le3r zI+dtuoTv<(H6xL9Atzf>Utz@vpja7xy3}G;l*qA^{?N?bKy&n{dx}c_23I!KiR2E2 z*EK(d)t53i(j;z+-i+;i3h^|0L^-ZcNg%vgf18uaG(EcM&5LK#0jTuox+FZkKfjo% z9maEbYIOOV_Pimrb8#HWS?b%x`T6t-s6P zhc@J?p}o13Y>Y#n;fK+0Ei5h0dv^a}!EQ`yH#g>ZX1Gsr5X+;&+x2rj)mUV7`E!2&xB*wz?xAn&l7t3kKsCuwF{`z!QAX{Qc z8Nt(S9n#3dvf2sKR-oPRnrzzGhZB2=_$On!gc7i?-ErYA&A{>a>-n7#uqnet4R}X% z6PV=>fp%|->9mT!Q}$YPJuzTQWOYxg`@km5ZoKg6?$6f~dof~~hjijK@?GG)O451X z1^%`?J3G5^0(AHBC@1K&m1i+JqaSE@$c#H>}hN#1M#W@>k!q&)I5pc9wyi@-9rlQ(F#UeJM|c2bb(WkFFCM=;yYYwsC#hB zakkmn=NOLo+@nCT(^m*CuANB^B3`lu=#f0crq6>*!Fjr^tTFKYPFK=K)^GlmOU<_Z zUL@-~m4U--Xe`wSrx|p9>E~sQ`KB%SO9{Dutg9YSmzW+t`<2Q?!nNwIK%K5Bq zis4Q}-ByU-d9+bF;y#zDVx%sMnQCXiZEW~(r$H=`(R~zX7s1d->&ch)I?HcHGPg*F zdoMiq;ZQ-vy3rK^YZq$*NFCz(W#ODcH%*6w&hCW3A*Pj6x3E@^K-GY3#kSJqAqD0ADM~Yt3<6eKrgIi|Y&Pb);qHLaa5VdOS+nHQzcjczT)aQ%fexkkK zZ;F)?sm||}VxK*J1CyEO!0{ms4%oVK^_+2=@@k6_-W9-o`z@^qHr5TH`QS5Rk^v4zT`aadAnl3z%*>4!6u` z9l1JHwTZ+?O}QiCE;A4A4-xGurQ_9amgrB`-!8%gRk-(FU_81A9I&0qRnTq1!4zKV z$XyA~2eaXRtNrTRpF%p)*e23L(tM5SMPJAcOG5pZ_copj%n8s56dVMwde&%6RHMz| zroIJHVKYWP9P@{7zYg}Vd4pBFC`J+q9jgM?t^UVv?m_vi1Kq}n8p3^Gj7g(`b;BD1 zT}@uK8Erw$gZmW)XY@-Z6Ee%Emqmf?sUZCFo3HMno(Q!2`6N&d>DC4qPd5^DqprMd zGi%w({aX~yFJVd%oStyGck7Ew%<{c&zQSBBF4QQk5gKf}(Rz zBwf=v=kfYuG^PO@q9brHO`X={s%A{1C*Umfa>oU~ONWaqNBSVKV5yU&V0u+A0T)E8 zAgFpxu373u>|A2SV$Pd#&5f1*OgM%}QZVJUul`OB&u9*Wj>de$!bt)np+A65SKd;K&sCJnF;pd2g8sTRW>MNwf zEzS#!Q=5UH9I+LyJ=Asd&ohX4Zd^wxW}-1`DXy)|hFvv8qwpW#&1?B?}Yz1&qM;3gM1%A&{66+U=fwzWn0Fi$A$G z{CwfMcpn2pZCB+pO1o@0(yJG&Uwb(?Qdv{s9x`?ZHI@$k$^iG`<=wk?T^oMf{hiDC zbWqr82ANLh!g}?2<@^AUZ~18;i)KabrY-}ON|)J}QY<-k>LNV$y@MxDsbsbB}E*!Jv+4mO%j zQOr*5ARCK)#z0N7w@~uw;SgJ+0mpN~i%dW{VHwOc(Jwbp4y{J3#x{(siW>K8!ZC$# z8_yY4Z&urky;q^(zI*xdX5M zYodl@N>T|#0)oQ8(j!bb1R$u-0APa7G1MKJJ zo}Taxsn@$d-iN$<<%?rmkCGKc@rn12XKPrg3~oVQ+CG{I55sUbc2&WGbfbonTUuOhuNoK|jX=ufK0CE>QuN2Ad> zGWa!#P;vNQ8r)hO&LnU}E9(9vBK%wy9QNUD$X~u8x8@CeX}|4y#+Osh@#3LyZIg8K z)LKcta%$^0#QxI&IM)668f@gEpN>u7QfB-#oJxjkkOmYnCGML^xY^_5{|exK{qJ`@ z``&1Dtvsc^C^R~s{v%FukalA;``4atQ4obk80o)8W zxmtz)o4Q~BHVQ{B{3)^QO2RtS7`hT|>2H6Za4dCEdJY`w000g;0Mm@ZdDiH58a;Oy z!U@F9ODtHEWyT6e{xr}3(H?X0E8(-@T`*0I+Zr@>*s=FCi6B1)07B&9A1bAq)T zbvRbG;up&2!?E@h65nt-LT$jgodt&nxwBdwp^QahwaiHp-#t+`Jj^UnS#Z32jHY4s zYy2}84)LwFf>PN<-m#QaIe!+ zNd{aEQoTy9Cn$MJlT3xM6G(}>Mv9bsU0%7`G?b$3$zXrw9cL3g-R*q1ruyrD{;!Ak zz2?DrKKBFsGSL-yqLT$D*NpI-p;-2kA^!pdq;znNV8l2I?)%k$hH$KXj^cERn|2)) z{%p7=${l{AQT|de|Ku?$u*Nt8P9$)5{b9v$mMuw+XOfM4JrfR{)ecUgm%ntwzaVm^ zi#D&PgRt?t~O()Qlpw(nB zr%8@dow((9a^Y_UU+Ns`qxQD?lD8U@YC^qU-=VBt7cy>VQVq+VuA)FiOSi#Mwp%6H z+-8GvTyIB78bH|GKR7x(oZEepZo6}bhX)7yh&2sWTWyA3D0lQyBVq;H$c^r5yA_*E z3W(|8Xl@Q2es^~+*Wd$yzI%9hbg;j<6T2+jbSA5vhJUc;MF~2autC?~KBsT%6+kTn zYdk%$zZJ(9cF zj~a3TU8{yhvsN3qAz6L%;1GTH>w*PFcLD?QRyGwd(lw7c|>_66pVA?$9IJ$x5x|DeELX?gr7d`y|v)HQN`d8yXUc0bvu5 zCjNRTLG1`7nAE5hQ|^EOhu)Z=@!hYJcig<`D;`cPRw8XuB!;G0u4$UKZMRx5Q`Pn9 zwC&q;idOAl>S{~2X}VDMvYG^((U0JOyH9oxHj5YE@*7h@n?%`0Z*{p0wK+7w1zfiJJ5&7;5B2P)PQ3@ap@Ab4UA$F90Ip2Wuz| zd=6eahomG&yR&?Q4>!7P8=*;!J!OC%$&qLxAZdXx2Rlrv?d%^=iH9dApdet3A4h9_h>7`pa8yc<%)Ma`PZ)zZ?*%{Fe| zjA8iPft(v}b~41vGHV>p5BWYCTh$tMJ7w@-Kqp>WHwWPf+8eliG&K6AYEJCqB4f1L zwF3F%M)Pdy^$+y-yYai_9cl{3@#GmAt}}(EJBzH^ZJc{+aH`p-o}IuaZ$`bYS@eS{ z#7fV@Q?=H#(`mxI#SdQ;nvhC5T_}ZKM5@k!K7n%MxAEg+3?nl{o^v#E6isT4rtQfL z-@% z7=0uNdWcZZ)>4WSdM1c7=A-AsIPT`XjW%tRc$kX9S9(K9GSQ<{ka_d`KFh~fG5EpF zKhh$O*GqfG41LZp^*J=~g8Au2G_)%`z=z}ep9Kw>CMBMLlSjsG^|a50h7CP5Dr3Dk zN~TnL(q|>ZW|%{6tN3wS(&rV8GEM3Y#*k0q{?CbD_(5gFRLwLYbKqyZZEbBS3eR!_ zeJFkTN4)ul9*$>tX%0^q{#721cWbwHYqxf5SGWHI;_$H=VtQ4Q00000NkvXXu0mjf DQny0k literal 0 HcmV?d00001 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 819397e809a..63799e007ea 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,8 +1,12 @@ - + - + + + + + - \ No newline at end of file + diff --git a/estate/views/estate_property_offers_views.xml b/estate/views/estate_property_offers_views.xml new file mode 100644 index 00000000000..aebb1053e9d --- /dev/null +++ b/estate/views/estate_property_offers_views.xml @@ -0,0 +1,30 @@ + + + + estate.property.offer.form + estate.property.offer + +
+ + + + + + + +
+
+
+ + + estate.property.offer.list + estate.property.offer + + + + + + + + +
diff --git a/estate/views/estate_property_tags_views.xml b/estate/views/estate_property_tags_views.xml new file mode 100644 index 00000000000..6a3adee6972 --- /dev/null +++ b/estate/views/estate_property_tags_views.xml @@ -0,0 +1,42 @@ + + + + estate.property.tag.form + estate.property.tag + +
+ + + + + +
+
+
+ + + estate.property.tag.list + estate.property.tag + + + + + + + + + estate.property.tag.search + estate.property.tag + + + + + + + + + Property Tags + estate.property.tag + list,form + +
diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..a458a6db330 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,42 @@ + + + + estate.property.type.form + estate.property.type + +
+ + + + + +
+
+
+ + + estate.property.type.list + estate.property.type + + + + + + + + + estate.property.type.search + estate.property.type + + + + + + so users can + + + Property Types + estate.property.type + list,form + +
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 74efb9e01ca..f8101e6f1fd 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,6 +1,6 @@ - + estate.property.form estate.property @@ -11,6 +11,8 @@ + + @@ -20,6 +22,12 @@ + + + + + + @@ -32,6 +40,9 @@ + + + @@ -46,6 +57,10 @@ + + + + @@ -54,12 +69,15 @@ - + estate.property.search estate.property + + + @@ -81,4 +99,4 @@ estate.property list,form - \ No newline at end of file + From cfd53975c122925c4add4fd5f1f633f03aa28ef4 Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Mon, 23 Mar 2026 18:50:30 +0530 Subject: [PATCH 7/9] [ADD] estate: add computed fields for area, best price and offer deadline Computed fields are needed to automatically calculate values that depend on other fields, avoiding manual input errors. - Add total area computed field combining living area and garden area. - Add best price computed field to show the highest offer received. - Add offer deadline computed field based on creation date and validity duration, with inverse to allow direct date editing. Chapter 8 partially done (computed fields only). --- estate/__manifest__.py | 2 +- estate/demo/estate_property_data.xml | 75 +++++++++++++++++++ estate/models/estate_property.py | 32 +++++--- estate/models/estate_property_offer.py | 19 ++++- estate/views/estate_property_offers_views.xml | 8 +- estate/views/estate_property_type_views.xml | 2 +- estate/views/estate_property_views.xml | 27 +++++-- 7 files changed, 142 insertions(+), 23 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 508f7064eff..c48e05cb02a 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -20,4 +20,4 @@ 'demo/estate_property_data.xml', ], 'application': True, -} +} \ No newline at end of file diff --git a/estate/demo/estate_property_data.xml b/estate/demo/estate_property_data.xml index 23a20ff537d..8ea006ac286 100644 --- a/estate/demo/estate_property_data.xml +++ b/estate/demo/estate_property_data.xml @@ -75,4 +75,79 @@ south new + + Seaside Bungalow + Relaxing bungalow with sea view + 600001 + 2026-10-01 + 420000.00 + 2 + 800 + 2 + False + True + 1500 + east + new + + + Mountain Cabin + Cozy cabin in the mountains + 700002 + 2026-11-15 + 210000.00 + 3 + 600 + 1 + False + True + 1200 + west + new + + + City Studio + Compact studio apartment for singles + 800003 + 2026-12-01 + 95000.00 + 1 + 350 + 1 + False + False + 0 + north + new + + + Family Home + Spacious home perfect for families + 900004 + 2027-01-10 + 300000.00 + 4 + 1100 + 2 + True + True + 2000 + south + new + + + Downtown Office Space + Modern office space in business district + 100005 + 2027-02-01 + 800000.00 + 0 + 2000 + 4 + True + False + 0 + east + new + diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 36daa6fe875..2f17f8eb767 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,25 +1,27 @@ from dateutil.relativedelta import relativedelta -from odoo import fields, models +from odoo import api,fields, models - -class Estate_Property(models.Model): +class EstateProperty(models.Model): _name = "estate.property" _description = "Real estate system" + + def _get_default_date_calculation(self): + return fields.Date.today() + relativedelta(months=3) name = fields.Char(string="Property Name", required=True) description = fields.Text() postcode = fields.Char(string="Postal Code") - date_availability = fields.Date(copy=False, default=lambda self: fields.Date.today() + relativedelta(months=3)) + date_availability = fields.Date(copy=False, default=_get_default_date_calculation) expected_price = fields.Float(string="Expected Price", required=True) selling_price = fields.Float(readonly=True, copy=False) bedrooms = fields.Integer(default=2) - living_area = fields.Integer() + living_area = fields.Integer(string="Living Area", help="Living area in square meters") facades = fields.Integer() garage = fields.Boolean() - garden = fields.Boolean() + garden = fields.Boolean(string="Garden", help="Has garden") garden_area = fields.Integer() garden_orientation = fields.Selection(selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) - active = fields.Boolean(default=True) + active = fields.Boolean(default=True , help="Uncheck to archive this property") state = fields.Selection( selection=[ ('new', 'New'), @@ -30,8 +32,20 @@ class Estate_Property(models.Model): ], required=True, copy=False, default='new' ) - property_type_id = fields.Many2one('estate.property.type', string="Property Type") + property_type_id = fields.Many2one('estate.property.type', string="Property Type", ondelete='cascade') buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False) seller_id = fields.Many2one('res.users', string="Seller", default=lambda self: self.env.user) - tag_ids = fields.Many2many('estate.property.tag', string="Tags") + tag_ids = fields.Many2many('estate.property.tag','pranjali','property_id','tag_id', string="Tags") offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") + total_area = fields.Float(string="Total Area (sqm)", compute='_compute_total_area',store=True) + best_price = fields.Float(string="Best Offer", compute='_compute_best_price',readonly=True,store=True) + + @api.depends('living_area','garden_area') + def _compute_total_area(self): + for record in self: + record.total_area = record.living_area + record.garden_area + + @api.depends('offer_ids.price') + def _compute_best_price(self): + for record in self: + record.best_price = max(record.offer_ids.mapped('price'), default=0.0) \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index f0513912a3d..66623797e42 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,11 +1,24 @@ -from odoo import fields, models - +from datetime import timedelta +from odoo import api,fields, models class EstatePropertyOffer(models.Model): _name = "estate.property.offer" _description = "Real estate system - Property Offer" - + price = fields.Float(string="Offer Price") status = fields.Selection(selection=[('accepted', 'Accepted'), ('refused', 'Refused')], copy=False) partner_id = fields.Many2one('res.partner', string="Partner", required=True) property_id = fields.Many2one('estate.property', string="Property", required=True) + validity = fields.Integer(string="Validity (days)",default=7) + date_deadline = fields.Date(string="Deadline", compute='_compute_date_deadline', inverse='_inverse_date_deadline') + + @api.depends('create_date','validity') + def _compute_date_deadline(self): + for offer in self: + date=offer.create_date or fields.Date.today() + offer.date_deadline=date+timedelta(days=offer.validity) + + def _inverse_date_deadline(self): + for record in self: + start = record.create_date.date() if record.create_date else fields.Date.today() + record.validity = (record.date_deadline - start).days \ No newline at end of file diff --git a/estate/views/estate_property_offers_views.xml b/estate/views/estate_property_offers_views.xml index aebb1053e9d..b4f84395c15 100644 --- a/estate/views/estate_property_offers_views.xml +++ b/estate/views/estate_property_offers_views.xml @@ -8,8 +8,10 @@ - + + + @@ -22,8 +24,10 @@ - + + + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index a458a6db330..6fab9d23e29 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -32,7 +32,7 @@ - so users can + Property Types diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index f8101e6f1fd..d7e5d4fb79b 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -18,16 +18,11 @@ + - - - - - - @@ -38,11 +33,19 @@ + + + + + + + + @@ -87,9 +90,19 @@ string="Available" domain="[('state', 'in', ['new', 'offer_received'])]"/> - + + + + From b47c6350c7e6ff5d28807352f570537fee8d20af Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Tue, 24 Mar 2026 17:48:05 +0530 Subject: [PATCH 8/9] [IMP] estate: add onchange method for garden field When a user enables the garden option, the garden area and orientation fields should be auto-filled with sensible defaults to reduce manual input. When disabled, both fields should be cleared to avoid stale data. - Add onchange method on garden field to set default garden area and orientation when garden is enabled. - Clear garden area and orientation when garden is disabled. Chapter 8 completed. --- estate/__manifest__.py | 2 +- estate/models/estate_property.py | 56 +++++++++++++++++--------- estate/models/estate_property_offer.py | 40 +++++++++++------- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index c48e05cb02a..508f7064eff 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -20,4 +20,4 @@ 'demo/estate_property_data.xml', ], 'application': True, -} \ No newline at end of file +} diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 2f17f8eb767..c010c316906 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 api,fields, models +from odoo import api, fields, models + class EstateProperty(models.Model): _name = "estate.property" _description = "Real estate system" - + def _get_default_date_calculation(self): return fields.Date.today() + relativedelta(months=3) @@ -20,32 +21,47 @@ def _get_default_date_calculation(self): garage = fields.Boolean() garden = fields.Boolean(string="Garden", help="Has garden") garden_area = fields.Integer() - garden_orientation = fields.Selection(selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) - active = fields.Boolean(default=True , help="Uncheck to archive this property") - state = fields.Selection( - selection=[ - ('new', 'New'), - ('offer_received', 'Offer Received'), - ('offer_accepted', 'Offer Accepted'), - ('sold', 'Sold'), - ('cancelled', 'Cancelled'), - ], - required=True, copy=False, default='new' - ) + garden_orientation = fields.Selection([ + ('north', 'North'), + ('south', 'South'), + ('east', 'East'), + ('west', 'West') + ]) + active = fields.Boolean(default=True, help="Uncheck to archive this property") + + state = fields.Selection([ + ('new', 'New'), + ('offer_received', 'Offer Received'), + ('offer_accepted', 'Offer Accepted'), + ('sold', 'Sold'), + ('cancelled', 'Cancelled'), + ], required=True, copy=False, default='new') + property_type_id = fields.Many2one('estate.property.type', string="Property Type", ondelete='cascade') buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False) seller_id = fields.Many2one('res.users', string="Seller", default=lambda self: self.env.user) - tag_ids = fields.Many2many('estate.property.tag','pranjali','property_id','tag_id', string="Tags") + + tag_ids = fields.Many2many('estate.property.tag', 'pranjali', 'property_id', 'tag_id', string="Tags") offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") - total_area = fields.Float(string="Total Area (sqm)", compute='_compute_total_area',store=True) - best_price = fields.Float(string="Best Offer", compute='_compute_best_price',readonly=True,store=True) - @api.depends('living_area','garden_area') + total_area = fields.Float(compute='_compute_total_area', store=True) + best_price = fields.Float(compute='_compute_best_price', readonly=True, store=True) + + @api.depends('living_area', 'garden_area') def _compute_total_area(self): for record in self: record.total_area = record.living_area + record.garden_area - + @api.depends('offer_ids.price') def _compute_best_price(self): for record in self: - record.best_price = max(record.offer_ids.mapped('price'), default=0.0) \ No newline at end of file + record.best_price = max(record.offer_ids.mapped('price'), default=0.0) + + @api.onchange('garden') + def _onchange_garden(self): + if not self.garden: + self.garden_area = 0 + self.garden_orientation = False + else: + self.garden_area = 10 + self.garden_orientation = 'north' diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 66623797e42..9405d17dc08 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,24 +1,34 @@ from datetime import timedelta -from odoo import api,fields, models +from odoo import api, fields, models + class EstatePropertyOffer(models.Model): _name = "estate.property.offer" _description = "Real estate system - Property Offer" - + price = fields.Float(string="Offer Price") - status = fields.Selection(selection=[('accepted', 'Accepted'), ('refused', 'Refused')], copy=False) - partner_id = fields.Many2one('res.partner', string="Partner", required=True) - property_id = fields.Many2one('estate.property', string="Property", required=True) - validity = fields.Integer(string="Validity (days)",default=7) - date_deadline = fields.Date(string="Deadline", compute='_compute_date_deadline', inverse='_inverse_date_deadline') + status = fields.Selection([ + ('accepted', 'Accepted'), + ('refused', 'Refused') + ], copy=False) + + partner_id = fields.Many2one('res.partner', required=True) + property_id = fields.Many2one('estate.property', required=True) - @api.depends('create_date','validity') + validity = fields.Integer(default=7) + + date_deadline = fields.Date( + compute='_compute_date_deadline', + inverse='_inverse_date_deadline' + ) + + @api.depends('create_date', 'validity') def _compute_date_deadline(self): for offer in self: - date=offer.create_date or fields.Date.today() - offer.date_deadline=date+timedelta(days=offer.validity) - - def _inverse_date_deadline(self): - for record in self: - start = record.create_date.date() if record.create_date else fields.Date.today() - record.validity = (record.date_deadline - start).days \ No newline at end of file + date = offer.create_date or fields.Date.today() + offer.date_deadline = date + timedelta(days=offer.validity) + + def _inverse_date_deadline(self): + for record in self: + start = record.create_date.date() if record.create_date else fields.Date.today() + record.validity = (record.date_deadline - start).days From 042e840ab77b3f210b65bd200f4f196c1d70612d Mon Sep 17 00:00:00 2001 From: "Pranjali Sangavekar(prsan)" Date: Thu, 26 Mar 2026 16:46:58 +0530 Subject: [PATCH 9/9] [IMP] estate: add optional columns, search domains, and default search - Add optional hide on living area, seller, and buyer columns in list view to reduce visual clutter. - Add domain filters in search view to refine property results. - Set default search to show properties with offers received. --- estate/models/estate_property.py | 1 + estate/models/estate_property_offer.py | 1 + estate/security/security.xml | 19 +++++++------- estate/views/estate_menus.xml | 2 +- estate/views/estate_property_offers_views.xml | 2 +- estate/views/estate_property_views.xml | 26 ++++++++++++------- 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index c010c316906..73fe80f2f7c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,5 @@ from dateutil.relativedelta import relativedelta + from odoo import api, fields, models diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 9405d17dc08..3e2fd5bad5c 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,5 @@ from datetime import timedelta + from odoo import api, fields, models diff --git a/estate/security/security.xml b/estate/security/security.xml index 176df58ec89..aceaae91826 100644 --- a/estate/security/security.xml +++ b/estate/security/security.xml @@ -1,28 +1,29 @@ - + + Real Estate + Real Estate Management + + Real Estate - + - Agent - Manager - - + - - + + - + \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 63799e007ea..53f245deb28 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,6 +1,6 @@ - + diff --git a/estate/views/estate_property_offers_views.xml b/estate/views/estate_property_offers_views.xml index b4f84395c15..c8bb1198f92 100644 --- a/estate/views/estate_property_offers_views.xml +++ b/estate/views/estate_property_offers_views.xml @@ -22,7 +22,7 @@ estate.property.offer.list estate.property.offer - + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index d7e5d4fb79b..446a1b6dfce 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -10,16 +10,17 @@ - + - + - + + @@ -31,8 +32,8 @@ - - + + @@ -56,18 +57,19 @@ estate.property.list estate.property - + - - - - + + + + + @@ -103,6 +105,9 @@ + @@ -111,5 +116,6 @@ Properties estate.property list,form + {'search_default_properties_with_offers': 1}