From 684e72dbf085aed85839204f2e7a397cf3d2acb9 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 19 Mar 2026 13:34:27 +0100 Subject: [PATCH 01/60] [ADD] estate - Chapter 2 - add estate module --- estate/__ini__.py | 0 estate/__manifest__.py | 6 ++++++ 2 files changed, 6 insertions(+) create mode 100644 estate/__ini__.py create mode 100644 estate/__manifest__.py diff --git a/estate/__ini__.py b/estate/__ini__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/estate/__manifest__.py b/estate/__manifest__.py new file mode 100644 index 00000000000..d5285827d2b --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,6 @@ +{ + 'name': "estate", + 'author': 'qugeo', + 'depends': ['base'], + 'application': True, +} \ No newline at end of file From 136d6ae642572c7e901cf1c1b32ee2c269e4c9bc Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 19 Mar 2026 15:29:52 +0100 Subject: [PATCH 02/60] [MOV] estate : fix module init file name --- estate/{__ini__.py => __init__.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename estate/{__ini__.py => __init__.py} (100%) diff --git a/estate/__ini__.py b/estate/__init__.py similarity index 100% rename from estate/__ini__.py rename to estate/__init__.py From e1b1c09a7ad958f7dd0e8a9b620acfb8e70d63ba Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 19 Mar 2026 15:33:08 +0100 Subject: [PATCH 03/60] [IMP] estate: Chapter 3 - add estate property model --- estate/__init__.py | 2 ++ estate/models/__init__.py | 2 ++ estate/models/estate_property.py | 24 ++++++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py diff --git a/estate/__init__.py b/estate/__init__.py index e69de29bb2d..24c19d687df 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1,2 @@ + +from . import models \ No newline at end of file diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..eb098fa2632 --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1,2 @@ + +from . import estate_property \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py new file mode 100644 index 00000000000..b2b4f927e55 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,24 @@ +from odoo import fields, models + +class EstateProperty(models.Model): + _name = "estate_property" + _description = "Estate properties" + + name = fields.Char() + description = fields.Text() + + name = fields.Char(required=True) + description = fields.Text() + postcode = fields.Char() + date_availability = fields.Date() + expected_price = fields.Float(required=True) + selling_price = fields.Float() + bedrooms = fields.Integer() + living_area = fields.Integer() + facades = fields.Integer() + garage = fields.Boolean() + garden = fields.Boolean() + garden_area = fields.Integer() + garden_orientation = fields.Selection( + selection=[('north','North'), ('south','South'), ('east','East'), ('west','West')], + ) From 4eef21da967f1aa308a078fc034806ebef5a7ffe Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 19 Mar 2026 16:34:25 +0100 Subject: [PATCH 04/60] [IMP] estate : Chapter 4 - add access rights to esate property model --- estate/__manifest__.py | 4 ++++ estate/security/ir.model.access.csv | 2 ++ 2 files changed, 6 insertions(+) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index d5285827d2b..21d06df40be 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,4 +3,8 @@ 'author': 'qugeo', 'depends': ['base'], 'application': True, + + 'data' : [ + "security/ir.model.access.csv" + ] } \ No newline at end of file diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..fe21e56c6d2 --- /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 +estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file From 763d86b71a2b1367b22bce58b3aed3acb941c408 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 20 Mar 2026 13:15:41 +0100 Subject: [PATCH 05/60] [IMP] estate: add license --- estate/__manifest__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 21d06df40be..3f3db768d81 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,6 +3,7 @@ 'author': 'qugeo', 'depends': ['base'], 'application': True, + 'license': "LGPL-3", 'data' : [ "security/ir.model.access.csv" From cce883fe429b67fc5ae0d8a1277ffec599f32153 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 20 Mar 2026 13:17:03 +0100 Subject: [PATCH 06/60] [IMP] estate: Chapter 5 - add menus and related action --- estate/__manifest__.py | 6 +++++- estate/views/estate_menus.xml | 7 +++++++ estate/views/estate_property_views.xml | 7 +++++++ 3 files changed, 19 insertions(+), 1 deletion(-) 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 3f3db768d81..9bac694c92f 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,9 +3,13 @@ 'author': 'qugeo', 'depends': ['base'], 'application': True, + + 'license': "LGPL-3", 'data' : [ - "security/ir.model.access.csv" + "security/ir.model.access.csv", + "views/estate_property_views.xml", + "views/estate_menus.xml" ] } \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..169be2e0b4a --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,7 @@ + + + + + + + \ 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..9491296737a --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,7 @@ + + + Test action + estate.property + list,form + + \ No newline at end of file From b81747c6ee4b47ab1e8f3586f959e8af361d17bc Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 20 Mar 2026 13:22:48 +0100 Subject: [PATCH 07/60] [FIX] estate : fix dot notation of module name --- estate/models/estate_property.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b2b4f927e55..60f689c2267 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,7 +1,7 @@ from odoo import fields, models class EstateProperty(models.Model): - _name = "estate_property" + _name = "estate.property" _description = "Estate properties" name = fields.Char() @@ -22,3 +22,4 @@ class EstateProperty(models.Model): garden_orientation = fields.Selection( selection=[('north','North'), ('south','South'), ('east','East'), ('west','West')], ) + From 31f25f2807c408e72a9d683b2b29a5e203c66bb2 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 20 Mar 2026 13:24:12 +0100 Subject: [PATCH 08/60] [IMP] estate : Chapter 5 - add new fields and attributes to the model --- estate/models/estate_property.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 60f689c2267..0a0a9c2deca 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -4,16 +4,22 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Estate properties" - name = fields.Char() - description = fields.Text() + active = fields.Boolean(default=True) + state = fields.Selection([ + ("new","New"), + ("offer_received","Offer Received"), + ("offer_accepted","Offer Accepted"), + ("sold","Sold"), + ("cancelled","Cancelled"), + ]) name = fields.Char(required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date() + date_availability = fields.Date(copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3) ) expected_price = fields.Float(required=True) - selling_price = fields.Float() - bedrooms = fields.Integer() + selling_price = fields.Float(readonly=True, copy=False) + bedrooms = fields.Integer(default=2) living_area = fields.Integer() facades = fields.Integer() garage = fields.Boolean() From 78b121dbf8453c5542a76cf46125d1db92270ce2 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Sun, 22 Mar 2026 21:25:45 +0100 Subject: [PATCH 09/60] [IMP] estate: Chapter 6 - add form and list views for properties --- estate/__manifest__.py | 8 ++--- estate/views/estate_property_view_form.xml | 42 ++++++++++++++++++++++ estate/views/estate_property_view_list.xml | 17 +++++++++ 3 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 estate/views/estate_property_view_form.xml create mode 100644 estate/views/estate_property_view_list.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 9bac694c92f..ac211a14437 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,13 +3,13 @@ 'author': 'qugeo', 'depends': ['base'], 'application': True, - - 'license': "LGPL-3", 'data' : [ "security/ir.model.access.csv", "views/estate_property_views.xml", - "views/estate_menus.xml" - ] + "views/estate_menus.xml", + "views/estate_property_view_list.xml", + "views/estate_property_view_form.xml", + ], } \ No newline at end of file diff --git a/estate/views/estate_property_view_form.xml b/estate/views/estate_property_view_form.xml new file mode 100644 index 00000000000..658d58477b6 --- /dev/null +++ b/estate/views/estate_property_view_form.xml @@ -0,0 +1,42 @@ + + + estate.property.form + estate.property + +
+
+ +
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
\ No newline at end of file diff --git a/estate/views/estate_property_view_list.xml b/estate/views/estate_property_view_list.xml new file mode 100644 index 00000000000..afadd864466 --- /dev/null +++ b/estate/views/estate_property_view_list.xml @@ -0,0 +1,17 @@ + + + estate.property.list + estate.property + + + + + + + + + + + + + \ No newline at end of file From bf131bbc1014de089344e2ec1a2b29766c8d90ec Mon Sep 17 00:00:00 2001 From: Quentin George Date: Sun, 22 Mar 2026 21:30:10 +0100 Subject: [PATCH 10/60] [IMP] estate: Chapter 6 - Add search view for properties with available property filter and postcode group by --- estate/__manifest__.py | 1 + estate/views/estate_property_view_search.xml | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 estate/views/estate_property_view_search.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ac211a14437..8dce1d31338 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,5 +11,6 @@ "views/estate_menus.xml", "views/estate_property_view_list.xml", "views/estate_property_view_form.xml", + "views/estate_property_view_search.xml", ], } \ No newline at end of file diff --git a/estate/views/estate_property_view_search.xml b/estate/views/estate_property_view_search.xml new file mode 100644 index 00000000000..33352269b47 --- /dev/null +++ b/estate/views/estate_property_view_search.xml @@ -0,0 +1,19 @@ + + + estate.property.search + estate.property + + + + + + + + + + + + + + + \ No newline at end of file From 87dc5e1746a26cc1f45ed33f88efe70bc6cb408c Mon Sep 17 00:00:00 2001 From: Quentin George Date: Sun, 22 Mar 2026 21:48:59 +0100 Subject: [PATCH 11/60] [FIX] estate: rename menu items --- estate/views/estate_menus.xml | 6 +++--- estate/views/estate_property_views.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 169be2e0b4a..db1ccb0393d 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,7 +1,7 @@ - - - + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 9491296737a..a81214e39f4 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,6 +1,6 @@ - Test action + Properties estate.property list,form From ed135b900cc48182a3024317360f3fd51855cf5c Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 23 Mar 2026 11:36:26 +0100 Subject: [PATCH 12/60] [IMP] estate: Chapter 7 - Add property types, tags and offers --- estate/__manifest__.py | 13 ++++ estate/models/__init__.py | 5 +- estate/models/estate_property.py | 7 ++ estate/models/estate_property_offer.py | 15 +++++ estate/models/estate_property_tag.py | 9 +++ estate/models/estate_property_type.py | 9 +++ estate/security/ir.model.access.csv | 5 +- estate/views/estate_menus.xml | 4 ++ .../views/estate_property_offer_view_form.xml | 15 +++++ .../views/estate_property_offer_view_list.xml | 13 ++++ .../views/estate_property_tag_view_form.xml | 15 +++++ estate/views/estate_property_tag_views.xml | 7 ++ .../views/estate_property_type_view_form.xml | 15 +++++ estate/views/estate_property_type_views.xml | 7 ++ estate/views/estate_property_view_form.xml | 64 ++++++++++++------- 15 files changed, 177 insertions(+), 26 deletions(-) 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/views/estate_property_offer_view_form.xml create mode 100644 estate/views/estate_property_offer_view_list.xml create mode 100644 estate/views/estate_property_tag_view_form.xml create mode 100644 estate/views/estate_property_tag_views.xml create mode 100644 estate/views/estate_property_type_view_form.xml create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 8dce1d31338..0b9ebf3bc71 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,10 +7,23 @@ 'data' : [ "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", + "views/estate_property_view_list.xml", "views/estate_property_view_form.xml", "views/estate_property_view_search.xml", + + "views/estate_property_type_view_form.xml", + + "views/estate_property_tag_view_form.xml", + + "views/estate_property_offer_view_list.xml", + "views/estate_property_offer_view_form.xml", + ], } \ No newline at end of file diff --git a/estate/models/__init__.py b/estate/models/__init__.py index eb098fa2632..489b77213f0 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,2 +1,5 @@ -from . import estate_property \ No newline at end of file +from . import estate_property +from . import estate_property_type +from . import estate_property_tag +from . import estate_property_offer \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 0a0a9c2deca..886b1978878 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -29,3 +29,10 @@ class EstateProperty(models.Model): selection=[('north','North'), ('south','South'), ('east','East'), ('west','West')], ) + property_type_id = fields.Many2one("estate.property.type", string="Property Type") + buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) + salesman_id = fields.Many2one("res.users", string="Salesman", default=lambda self: self.env.user) + + property_tag_ids = fields.Many2many("estate.property.tag", string="Tags") + + property_offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers") \ 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..717266374f1 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,15 @@ +from odoo import fields, models + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Estate property offers" + + price = fields.Float() + 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..6884c2e0133 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,9 @@ +from odoo import fields, models + +class EstatePropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Estate property tags" + + name = fields.Char(required=True) + + diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..29b648172cb --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,9 @@ +from odoo import fields, models + +class EstatePropertyType(models.Model): + _name = "estate.property.type" + _description = "Estate property types" + + name = fields.Char(required=True) + + diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index fe21e56c6d2..c79331f2f1c 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,5 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink -estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file +estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 +estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 +estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1 +estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index db1ccb0393d..b2489962d29 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -3,5 +3,9 @@ + + + + \ No newline at end of file diff --git a/estate/views/estate_property_offer_view_form.xml b/estate/views/estate_property_offer_view_form.xml new file mode 100644 index 00000000000..a366c404bb4 --- /dev/null +++ b/estate/views/estate_property_offer_view_form.xml @@ -0,0 +1,15 @@ + + + estate.property.offer.form + estate.property.offer + +
+ + + + + +
+
+
+
\ No newline at end of file diff --git a/estate/views/estate_property_offer_view_list.xml b/estate/views/estate_property_offer_view_list.xml new file mode 100644 index 00000000000..aff3d01acb2 --- /dev/null +++ b/estate/views/estate_property_offer_view_list.xml @@ -0,0 +1,13 @@ + + + estate.property.offer.list + estate.property.offer + + + + + + + + + \ No newline at end of file diff --git a/estate/views/estate_property_tag_view_form.xml b/estate/views/estate_property_tag_view_form.xml new file mode 100644 index 00000000000..06347c9add1 --- /dev/null +++ b/estate/views/estate_property_tag_view_form.xml @@ -0,0 +1,15 @@ + + + estate.property.tag.form + estate.property.tag + +
+ + + + + +
+
+
+
\ No newline at end of file diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml new file mode 100644 index 00000000000..3920037c137 --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,7 @@ + + + Property Tags + estate.property.tag + list,form + + \ No newline at end of file diff --git a/estate/views/estate_property_type_view_form.xml b/estate/views/estate_property_type_view_form.xml new file mode 100644 index 00000000000..1e5f401ed34 --- /dev/null +++ b/estate/views/estate_property_type_view_form.xml @@ -0,0 +1,15 @@ + + + estate.property.type.form + estate.property.type + +
+ +

+ +

+
+
+
+
+
\ No newline at end of file diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..6cbd93a23cf --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,7 @@ + + + Property Types + estate.property.type + list,form + + \ No newline at end of file diff --git a/estate/views/estate_property_view_form.xml b/estate/views/estate_property_view_form.xml index 658d58477b6..e47e4636fdf 100644 --- a/estate/views/estate_property_view_form.xml +++ b/estate/views/estate_property_view_form.xml @@ -8,33 +8,49 @@ -

- -

- +

+ +

+ + - - - - - - - -
- - - - - - - - - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
From c5896c90c8b23206a66fc3552fb0c7e06d4f6fae Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 23 Mar 2026 13:46:07 +0100 Subject: [PATCH 13/60] [CLN] estate: remove extra spaces and fix quote usage --- estate/__init__.py | 1 - estate/__manifest__.py | 28 +++++------ estate/models/__init__.py | 1 - estate/models/estate_property.py | 14 +++--- estate/models/estate_property_offer.py | 8 ++-- estate/models/estate_property_tag.py | 2 +- estate/models/estate_property_type.py | 2 +- estate/views/estate_menus.xml | 12 ++--- .../views/estate_property_offer_view_form.xml | 14 +++--- .../views/estate_property_offer_view_list.xml | 14 +++--- .../views/estate_property_tag_view_form.xml | 10 ++-- estate/views/estate_property_tag_views.xml | 8 ++-- .../views/estate_property_type_view_form.xml | 10 ++-- estate/views/estate_property_type_views.xml | 8 ++-- estate/views/estate_property_view_form.xml | 46 +++++++++---------- estate/views/estate_property_view_list.xml | 22 ++++----- estate/views/estate_property_view_search.xml | 24 +++++----- estate/views/estate_property_views.xml | 8 ++-- 18 files changed, 115 insertions(+), 117 deletions(-) diff --git a/estate/__init__.py b/estate/__init__.py index 24c19d687df..9a7e03eded3 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1,2 +1 @@ - from . import models \ No newline at end of file diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 0b9ebf3bc71..cfb879b1278 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,29 +1,29 @@ { - 'name': "estate", + 'name': 'estate', 'author': 'qugeo', 'depends': ['base'], 'application': True, - 'license': "LGPL-3", + 'license': 'LGPL-3', 'data' : [ - "security/ir.model.access.csv", + 'security/ir.model.access.csv', - "views/estate_property_views.xml", - "views/estate_property_type_views.xml", - "views/estate_property_tag_views.xml", + 'views/estate_property_views.xml', + 'views/estate_property_type_views.xml', + 'views/estate_property_tag_views.xml', - "views/estate_menus.xml", + 'views/estate_menus.xml', - "views/estate_property_view_list.xml", - "views/estate_property_view_form.xml", - "views/estate_property_view_search.xml", + 'views/estate_property_view_list.xml', + 'views/estate_property_view_form.xml', + 'views/estate_property_view_search.xml', - "views/estate_property_type_view_form.xml", + 'views/estate_property_type_view_form.xml', - "views/estate_property_tag_view_form.xml", + 'views/estate_property_tag_view_form.xml', - "views/estate_property_offer_view_list.xml", - "views/estate_property_offer_view_form.xml", + 'views/estate_property_offer_view_list.xml', + 'views/estate_property_offer_view_form.xml', ], } \ No newline at end of file diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 489b77213f0..09b2099fe84 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,4 +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 886b1978878..dd4643ff005 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,7 +1,7 @@ from odoo import fields, models class EstateProperty(models.Model): - _name = "estate.property" + _name = 'estate.property' _description = "Estate properties" active = fields.Boolean(default=True) @@ -26,13 +26,13 @@ class EstateProperty(models.Model): garden = fields.Boolean() garden_area = fields.Integer() garden_orientation = fields.Selection( - selection=[('north','North'), ('south','South'), ('east','East'), ('west','West')], + selection=[("north","North"), ("south","South"), ("east","East"), ("west","West")], ) - property_type_id = fields.Many2one("estate.property.type", string="Property Type") - buyer_id = fields.Many2one("res.partner", string="Buyer", copy=False) - salesman_id = fields.Many2one("res.users", string="Salesman", default=lambda self: self.env.user) + property_type_id = fields.Many2one('estate.property.type', string="Property Type") + buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False) + salesman_id = fields.Many2one('res.users', string="Salesman", default=lambda self: self.env.user) - property_tag_ids = fields.Many2many("estate.property.tag", string="Tags") + property_tag_ids = fields.Many2many('estate.property.tag', string="Tags") - property_offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers") \ No newline at end of file + property_offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 717266374f1..32d2c5d024f 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,15 +1,15 @@ from odoo import fields, models class EstatePropertyOffer(models.Model): - _name = "estate.property.offer" + _name = 'estate.property.offer' _description = "Estate property offers" price = fields.Float() status = fields.Selection( - selection=[('accepted','Accepted'),('refused','Refused')], + 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) + 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 index 6884c2e0133..3d100b63b23 100644 --- a/estate/models/estate_property_tag.py +++ b/estate/models/estate_property_tag.py @@ -1,7 +1,7 @@ from odoo import fields, models class EstatePropertyTag(models.Model): - _name = "estate.property.tag" + _name = 'estate.property.tag' _description = "Estate property tags" name = fields.Char(required=True) diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 29b648172cb..90180e0d0e6 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -1,7 +1,7 @@ from odoo import fields, models class EstatePropertyType(models.Model): - _name = "estate.property.type" + _name = 'estate.property.type' _description = "Estate property types" name = fields.Char(required=True) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index b2489962d29..19f17eb2370 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,11 +1,11 @@ - - - + + + - - - + + + \ No newline at end of file diff --git a/estate/views/estate_property_offer_view_form.xml b/estate/views/estate_property_offer_view_form.xml index a366c404bb4..c9c9cabbfe0 100644 --- a/estate/views/estate_property_offer_view_form.xml +++ b/estate/views/estate_property_offer_view_form.xml @@ -1,13 +1,13 @@ - - estate.property.offer.form - estate.property.offer - + + estate.property.offer.form + estate.property.offer +
- - - + + +
diff --git a/estate/views/estate_property_offer_view_list.xml b/estate/views/estate_property_offer_view_list.xml index aff3d01acb2..b8e081ff30f 100644 --- a/estate/views/estate_property_offer_view_list.xml +++ b/estate/views/estate_property_offer_view_list.xml @@ -1,12 +1,12 @@ - - estate.property.offer.list - estate.property.offer - + + estate.property.offer.list + estate.property.offer + - - - + + + diff --git a/estate/views/estate_property_tag_view_form.xml b/estate/views/estate_property_tag_view_form.xml index 06347c9add1..dbc69069fa9 100644 --- a/estate/views/estate_property_tag_view_form.xml +++ b/estate/views/estate_property_tag_view_form.xml @@ -1,12 +1,12 @@ - - estate.property.tag.form - estate.property.tag - + + estate.property.tag.form + estate.property.tag +
- +
diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml index 3920037c137..a7e4634f2f4 100644 --- a/estate/views/estate_property_tag_views.xml +++ b/estate/views/estate_property_tag_views.xml @@ -1,7 +1,7 @@ - - Property Tags - estate.property.tag - list,form + + Property Tags + estate.property.tag + list,form \ No newline at end of file diff --git a/estate/views/estate_property_type_view_form.xml b/estate/views/estate_property_type_view_form.xml index 1e5f401ed34..9c37a939b41 100644 --- a/estate/views/estate_property_type_view_form.xml +++ b/estate/views/estate_property_type_view_form.xml @@ -1,12 +1,12 @@ - - estate.property.type.form - estate.property.type - + + estate.property.type.form + estate.property.type +

- +

diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index 6cbd93a23cf..b49c26d8758 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -1,7 +1,7 @@ - - Property Types - estate.property.type - list,form + + Property Types + estate.property.type + list,form \ No newline at end of file diff --git a/estate/views/estate_property_view_form.xml b/estate/views/estate_property_view_form.xml index e47e4636fdf..5af81641ce5 100644 --- a/estate/views/estate_property_view_form.xml +++ b/estate/views/estate_property_view_form.xml @@ -1,53 +1,53 @@ - - estate.property.form - estate.property - + + estate.property.form + estate.property +
- +

- +

- + - + - - + + - - + + - - - - - - - - + + + + + + + + - + - - + + diff --git a/estate/views/estate_property_view_list.xml b/estate/views/estate_property_view_list.xml index afadd864466..d0109b2c3c3 100644 --- a/estate/views/estate_property_view_list.xml +++ b/estate/views/estate_property_view_list.xml @@ -1,16 +1,16 @@ - - estate.property.list - estate.property - + + estate.property.list + estate.property + - - - - - - - + + + + + + + diff --git a/estate/views/estate_property_view_search.xml b/estate/views/estate_property_view_search.xml index 33352269b47..7a46448e047 100644 --- a/estate/views/estate_property_view_search.xml +++ b/estate/views/estate_property_view_search.xml @@ -1,18 +1,18 @@ - - estate.property.search - estate.property - + + estate.property.search + estate.property + - - - - - - + + + + + + - - + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index a81214e39f4..a84de14a873 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,7 +1,7 @@ - - Properties - estate.property - list,form + + Properties + estate.property + list,form \ No newline at end of file From fde75c1bd0a58b5a79c37f8edf653ef9ad7019ab Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 23 Mar 2026 13:47:46 +0100 Subject: [PATCH 14/60] [FIX] estate: set Odoo as author --- estate/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index cfb879b1278..8b3c9550a77 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,6 +1,6 @@ { 'name': 'estate', - 'author': 'qugeo', + 'author': 'Odoo S.A.', 'depends': ['base'], 'application': True, 'license': 'LGPL-3', From eceb38ad4cc16a2ee7950f892cbdd7e17e1244c4 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 23 Mar 2026 14:01:00 +0100 Subject: [PATCH 15/60] [FIX] estate: move string attributes from views to models --- estate/models/estate_property.py | 8 ++++---- estate/views/estate_property_type_view_form.xml | 2 +- estate/views/estate_property_view_form.xml | 10 +++++----- estate/views/estate_property_view_list.xml | 6 +++--- estate/views/estate_property_view_search.xml | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index dd4643ff005..d47d494a79c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -13,18 +13,18 @@ class EstateProperty(models.Model): ("cancelled","Cancelled"), ]) - name = fields.Char(required=True) + name = fields.Char(required=True, string="Title") description = fields.Text() postcode = fields.Char() - date_availability = fields.Date(copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3) ) + date_availability = fields.Date(copy=False, default=lambda self: fields.Date.add(fields.Date.today(), months=3), string="Available From" ) expected_price = fields.Float(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 (sqm)") facades = fields.Integer() garage = fields.Boolean() garden = fields.Boolean() - garden_area = fields.Integer() + garden_area = fields.Integer(string="Garden Area (sqm)") garden_orientation = fields.Selection( selection=[("north","North"), ("south","South"), ("east","East"), ("west","West")], ) diff --git a/estate/views/estate_property_type_view_form.xml b/estate/views/estate_property_type_view_form.xml index 9c37a939b41..c8940c8faf3 100644 --- a/estate/views/estate_property_type_view_form.xml +++ b/estate/views/estate_property_type_view_form.xml @@ -6,7 +6,7 @@

- +

diff --git a/estate/views/estate_property_view_form.xml b/estate/views/estate_property_view_form.xml index 5af81641ce5..6eee767f3a1 100644 --- a/estate/views/estate_property_view_form.xml +++ b/estate/views/estate_property_view_form.xml @@ -9,16 +9,16 @@

- +

- + - + @@ -30,11 +30,11 @@ - + - + diff --git a/estate/views/estate_property_view_list.xml b/estate/views/estate_property_view_list.xml index d0109b2c3c3..4ffa83ee22f 100644 --- a/estate/views/estate_property_view_list.xml +++ b/estate/views/estate_property_view_list.xml @@ -4,13 +4,13 @@ estate.property - + - + - +
diff --git a/estate/views/estate_property_view_search.xml b/estate/views/estate_property_view_search.xml index 7a46448e047..066be3d455d 100644 --- a/estate/views/estate_property_view_search.xml +++ b/estate/views/estate_property_view_search.xml @@ -8,7 +8,7 @@ - + From ad9f755c08ebe62f8a56ee6ce7243265a5e59f91 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 23 Mar 2026 14:12:06 +0100 Subject: [PATCH 16/60] [FIX] estate: remove redundant module ref in access rules --- estate/security/ir.model.access.csv | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index c79331f2f1c..4c593ed42e4 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,5 +1,5 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink -estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 -estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 -estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1 -estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1 \ No newline at end of file +access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 +access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 +access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 +access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 \ No newline at end of file From 4ba968b530b2ba038081aaba282e2f56197f53f2 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 23 Mar 2026 16:13:27 +0100 Subject: [PATCH 17/60] [IMP] estate: Chapter 8 - Add validty and deadline to offers, add best price and total area to properties. Set compute logic and auto fill. --- estate/models/estate_property.py | 28 +++++++++++++++++-- estate/models/estate_property_offer.py | 17 +++++++++-- .../views/estate_property_offer_view_form.xml | 2 ++ .../views/estate_property_offer_view_list.xml | 2 ++ estate/views/estate_property_view_form.xml | 3 +- 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index d47d494a79c..9f319f059ff 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import fields, models +from odoo import fields, models, api class EstateProperty(models.Model): _name = 'estate.property' @@ -35,4 +35,28 @@ class EstateProperty(models.Model): property_tag_ids = fields.Many2many('estate.property.tag', string="Tags") - property_offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") \ No newline at end of file + property_offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") + + total_area = fields.Float(compute='_compute_total_area') + @api.depends('living_area', 'garden_area') + def _compute_total_area(self): + for record in self: + record.total_area = record.living_area + record.garden_area + + best_price = fields.Float(compute='_compute_best_price', string="Best Offer") + @api.depends('property_offer_ids.price') + def _compute_best_price(self): + for record in self: + if len(record.property_offer_ids) > 0: + record.best_price = max(record.property_offer_ids.mapped('price')) + else: + record.best_price = 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 = "" \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 32d2c5d024f..217fdc78e52 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,4 @@ -from odoo import fields, models +from odoo import fields, models, api class EstatePropertyOffer(models.Model): _name = 'estate.property.offer' @@ -11,5 +11,18 @@ class EstatePropertyOffer(models.Model): ) partner_id = fields.Many2one('res.partner', string="Partner", required=True) property_id = fields.Many2one('estate.property', string="Property", required=True) - + validity = fields.Integer(default=7) + date_deadline = fields.Date(compute='_compute_deadline', inverse='_inverse_deadline', string="Deadline") + + @api.depends('create_date', 'validity') + def _compute_deadline(self): + for record in self: + if(record.create_date): + record.date_deadline = fields.Date.add(record.create_date, days=record.validity ) + else: + record.date_deadline = fields.Date.add(fields.Date.today(), days=record.validity ) + + def _inverse_deadline(self): + for record in self: + record.validity = (record.date_deadline - fields.Date.to_date(record.create_date)).days \ No newline at end of file diff --git a/estate/views/estate_property_offer_view_form.xml b/estate/views/estate_property_offer_view_form.xml index c9c9cabbfe0..ef8c83d94d5 100644 --- a/estate/views/estate_property_offer_view_form.xml +++ b/estate/views/estate_property_offer_view_form.xml @@ -7,6 +7,8 @@ + + diff --git a/estate/views/estate_property_offer_view_list.xml b/estate/views/estate_property_offer_view_list.xml index b8e081ff30f..c88034052e6 100644 --- a/estate/views/estate_property_offer_view_list.xml +++ b/estate/views/estate_property_offer_view_list.xml @@ -6,6 +6,8 @@ + + diff --git a/estate/views/estate_property_view_form.xml b/estate/views/estate_property_view_form.xml index 6eee767f3a1..e03c4fae057 100644 --- a/estate/views/estate_property_view_form.xml +++ b/estate/views/estate_property_view_form.xml @@ -16,12 +16,12 @@ - + @@ -36,6 +36,7 @@ + From c9e118fb2645b0c0aca6c6e07f85f351df30bb26 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Tue, 24 Mar 2026 08:46:45 +0100 Subject: [PATCH 18/60] [IMP] estate: Chapter 9 - Add action button on properties and offers to update states related fields --- estate/models/estate_property.py | 23 ++++++++++++++++--- estate/models/estate_property_offer.py | 16 ++++++++++++- .../views/estate_property_offer_view_list.xml | 2 ++ estate/views/estate_property_view_form.xml | 2 ++ 4 files changed, 39 insertions(+), 4 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 9f319f059ff..982c02cebb3 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import fields, models, api +from odoo import fields, models, api, exceptions class EstateProperty(models.Model): _name = 'estate.property' @@ -11,7 +11,8 @@ class EstateProperty(models.Model): ("offer_accepted","Offer Accepted"), ("sold","Sold"), ("cancelled","Cancelled"), - ]) + ], default="new" + ) name = fields.Char(required=True, string="Title") description = fields.Text() @@ -59,4 +60,20 @@ def _onchange_garden(self): self.garden_orientation = "north" else: self.garden_area = 0 - self.garden_orientation = "" \ No newline at end of file + self.garden_orientation = "" + + def action_sold(self): + for record in self: + if(record.state == "cancelled"): + raise exceptions.UserError("Cancelled properties cannot be sold.") + else: + record.state = "sold" + return True + + def action_cancelled(self): + for record in self: + if(record.state == "sold"): + raise exceptions.UserError("Sold properties cannot be cancelled.") + else: + record.state = "cancelled" + return True \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 217fdc78e52..473d61f7b76 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -25,4 +25,18 @@ def _compute_deadline(self): def _inverse_deadline(self): for record in self: - record.validity = (record.date_deadline - fields.Date.to_date(record.create_date)).days \ No newline at end of file + record.validity = (record.date_deadline - fields.Date.to_date(record.create_date)).days + + def action_accept(self): + for record in self: + for offer in record.property_id.property_offer_ids: + offer.status = "refused" + record.status = "accepted" + record.property_id.selling_price = record.price + record.property_id.buyer_id = record.partner_id + return True + + def action_refuse(self): + for record in self: + record.status = "refused" + return True \ No newline at end of file diff --git a/estate/views/estate_property_offer_view_list.xml b/estate/views/estate_property_offer_view_list.xml index c88034052e6..ca7824263d3 100644 --- a/estate/views/estate_property_offer_view_list.xml +++ b/estate/views/estate_property_offer_view_list.xml @@ -8,6 +8,8 @@ + +

From b89b0f1dd443b9bd66137f39c61f971823053835 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 09:44:17 +0100 Subject: [PATCH 34/60] [IMP] estate: Chapter 12 - prevent offer creation if price is inferior to best offer. Prevent deletion of properties not new or cancelled. --- estate/models/estate_property.py | 9 ++++++++- estate/models/estate_property_offer.py | 14 ++++++++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 9cb11267cf2..fd829117776 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -93,4 +93,11 @@ def action_cancelled(self): raise exceptions.UserError("Sold properties cannot be cancelled.") else: record.state = "cancelled" - return True \ No newline at end of file + return True + + + @api.ondelete( at_uninstall=False ) + def _check_state_before_unlink(self): + for record in self: + if not record.state in ['new', 'cancelled']: + raise exceptions.UserError("Only new or cancelled properties can be deleted...") \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 08a31bbaa8e..19ae650dcfc 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,4 @@ -from odoo import fields, models, api +from odoo import fields, models, api, exceptions class EstatePropertyOffer(models.Model): _name = 'estate.property.offer' @@ -45,4 +45,14 @@ def action_accept(self): def action_refuse(self): for record in self: record.status = "refused" - return True \ No newline at end of file + return True + + @api.model + def create(self, vals_list): + for vals in vals_list: + propertyId = self.env['estate.property'].browse(vals['property_id']) + curPrice = vals['price'] + if propertyId.best_price > curPrice: + raise exceptions.UserError(f"Cannot create an offer with a lower price than the best offer:{propertyId.best_price}") + propertyId.state = 'offer_received' + return super().create(vals_list) \ No newline at end of file From 05d2281c44f1e8b350ce6c6056a338e950f3b094 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 11:03:12 +0100 Subject: [PATCH 35/60] [IMP] estate: add property type and tags to property list view --- estate/views/estate_property_view_list.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/estate/views/estate_property_view_list.xml b/estate/views/estate_property_view_list.xml index 76e62b22ce9..eec995429fb 100644 --- a/estate/views/estate_property_view_list.xml +++ b/estate/views/estate_property_view_list.xml @@ -5,7 +5,9 @@ + + From 448d9a2b293949b8bcdcc59a3cbde5be8faea5cb Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 11:05:05 +0100 Subject: [PATCH 36/60] [IMP] estate: extend res.user model and view with available properties --- estate/__manifest__.py | 2 ++ estate/models/__init__.py | 3 ++- estate/models/res_users.py | 5 +++++ estate/views/res_users_view_form.xml | 14 ++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 estate/models/res_users.py create mode 100644 estate/views/res_users_view_form.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 33465a15aea..71ad199169e 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -28,5 +28,7 @@ 'views/estate_property_offer_view_list.xml', 'views/estate_property_offer_view_form.xml', + 'views/res_users_view_form.xml' + ], } \ No newline at end of file diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 09b2099fe84..a9459ed5906 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 \ No newline at end of file +from . import estate_property_offer +from . import res_users \ No newline at end of file diff --git a/estate/models/res_users.py b/estate/models/res_users.py new file mode 100644 index 00000000000..a916a53a7e6 --- /dev/null +++ b/estate/models/res_users.py @@ -0,0 +1,5 @@ +from odoo import fields, models +class resUsers(models.Model): + _inherit = ['res.users'] + + property_ids = fields.One2many('estate.property','salesman_id',domain=['|',('state','=','new'),('state','=','offer_received')]) \ No newline at end of file diff --git a/estate/views/res_users_view_form.xml b/estate/views/res_users_view_form.xml new file mode 100644 index 00000000000..62a149a0612 --- /dev/null +++ b/estate/views/res_users_view_form.xml @@ -0,0 +1,14 @@ + + + res.users.view.form + res.users + + + + + + + + + + \ No newline at end of file From 068ced1c583da02b640573e59376473973b7c524 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 13:38:44 +0100 Subject: [PATCH 37/60] [ADD] estate_account: Create Estate Account module to enable property invoice creation --- estate_account/__init__.py | 1 + estate_account/__manifest__.py | 10 ++++++++++ estate_account/models/__init__.py | 1 + estate_account/models/estate_property.py | 25 ++++++++++++++++++++++++ 4 files changed, 37 insertions(+) create mode 100644 estate_account/__init__.py create mode 100644 estate_account/__manifest__.py create mode 100644 estate_account/models/__init__.py create mode 100644 estate_account/models/estate_property.py diff --git a/estate_account/__init__.py b/estate_account/__init__.py new file mode 100644 index 00000000000..9a7e03eded3 --- /dev/null +++ b/estate_account/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/estate_account/__manifest__.py b/estate_account/__manifest__.py new file mode 100644 index 00000000000..ebf57755fe1 --- /dev/null +++ b/estate_account/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': 'Estate Accounting', + 'author': 'Odoo S.A.', + 'depends': ['base','estate','account'], + 'auto_install' : True, + 'license': 'LGPL-3', + + 'data' : [ + ], +} \ No newline at end of file diff --git a/estate_account/models/__init__.py b/estate_account/models/__init__.py new file mode 100644 index 00000000000..f4c8fd6db6d --- /dev/null +++ b/estate_account/models/__init__.py @@ -0,0 +1 @@ +from . import estate_property \ No newline at end of file diff --git a/estate_account/models/estate_property.py b/estate_account/models/estate_property.py new file mode 100644 index 00000000000..4c64a2f0036 --- /dev/null +++ b/estate_account/models/estate_property.py @@ -0,0 +1,25 @@ +from odoo import fields, models, Command + +class EstateProperty(models.Model): + _inherit = ['estate.property'] + + def action_sold(self): + print("test ----------------------- \n") + self.env['account.move'].create({ + 'name': self.name, + 'move_type':'out_invoice', + 'partner_id': self.buyer_id.id, + "line_ids": [ + Command.create({ + "name": "6% of selling price", + "quantity": "1", + "price_unit": self.selling_price * 0.06, + }), + Command.create({ + "name": "Administrative fee", + "quantity": "1", + "price_unit": 100.00, + }), + ], + }) + return super().action_sold() From 9783a74eeb9b7c10ba9b991844f304bb1d9057f2 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 15:35:00 +0100 Subject: [PATCH 38/60] [IMP] estate: Chapter 14 - Add kanban view for properties --- estate/__manifest__.py | 1 + estate/views/estate_property_view_kanban.xml | 31 ++++++++++++++++++++ estate/views/estate_property_views.xml | 2 +- 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 estate/views/estate_property_view_kanban.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 71ad199169e..32a85f6dc48 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -17,6 +17,7 @@ 'views/estate_property_view_list.xml', 'views/estate_property_view_form.xml', + 'views/estate_property_view_kanban.xml', 'views/estate_property_view_search.xml', 'views/estate_property_type_view_form.xml', diff --git a/estate/views/estate_property_view_kanban.xml b/estate/views/estate_property_view_kanban.xml new file mode 100644 index 00000000000..f5ffd0d0581 --- /dev/null +++ b/estate/views/estate_property_view_kanban.xml @@ -0,0 +1,31 @@ + + + estate.property.kanban + estate.property + + + + + + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 007bd1f1e71..1465a5f1bfd 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -2,7 +2,7 @@ Properties estate.property - list,form + list,form,kanban {'search_default_filter_available_properties':True}
\ No newline at end of file From 7c8adb2f3f350fd9d6ef01d22e88690325211437 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 16:23:38 +0100 Subject: [PATCH 39/60] [CLN] estate: Chapter 5 - Merge view files together --- estate/__manifest__.py | 14 -- .../views/estate_property_offer_view_form.xml | 17 --- .../views/estate_property_offer_view_list.xml | 17 --- estate/views/estate_property_offer_views.xml | 34 +++++ .../views/estate_property_tag_view_form.xml | 15 -- .../views/estate_property_tag_view_list.xml | 11 -- estate/views/estate_property_tag_views.xml | 25 ++++ .../views/estate_property_type_view_form.xml | 27 ---- .../views/estate_property_type_view_list.xml | 12 -- estate/views/estate_property_type_views.xml | 39 ++++++ estate/views/estate_property_view_form.xml | 63 --------- estate/views/estate_property_view_kanban.xml | 31 ---- estate/views/estate_property_view_list.xml | 19 --- estate/views/estate_property_view_search.xml | 19 --- estate/views/estate_property_views.xml | 132 ++++++++++++++++++ 15 files changed, 230 insertions(+), 245 deletions(-) delete mode 100644 estate/views/estate_property_offer_view_form.xml delete mode 100644 estate/views/estate_property_offer_view_list.xml delete mode 100644 estate/views/estate_property_tag_view_form.xml delete mode 100644 estate/views/estate_property_tag_view_list.xml delete mode 100644 estate/views/estate_property_type_view_form.xml delete mode 100644 estate/views/estate_property_type_view_list.xml delete mode 100644 estate/views/estate_property_view_form.xml delete mode 100644 estate/views/estate_property_view_kanban.xml delete mode 100644 estate/views/estate_property_view_list.xml delete mode 100644 estate/views/estate_property_view_search.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 32a85f6dc48..28dad4984d2 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -15,20 +15,6 @@ 'views/estate_menus.xml', - 'views/estate_property_view_list.xml', - 'views/estate_property_view_form.xml', - 'views/estate_property_view_kanban.xml', - 'views/estate_property_view_search.xml', - - 'views/estate_property_type_view_form.xml', - 'views/estate_property_type_view_list.xml', - - 'views/estate_property_tag_view_form.xml', - 'views/estate_property_tag_view_list.xml', - - 'views/estate_property_offer_view_list.xml', - 'views/estate_property_offer_view_form.xml', - 'views/res_users_view_form.xml' ], diff --git a/estate/views/estate_property_offer_view_form.xml b/estate/views/estate_property_offer_view_form.xml deleted file mode 100644 index ef8c83d94d5..00000000000 --- a/estate/views/estate_property_offer_view_form.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - estate.property.offer.form - estate.property.offer - - - - - - - - - - - - - \ No newline at end of file diff --git a/estate/views/estate_property_offer_view_list.xml b/estate/views/estate_property_offer_view_list.xml deleted file mode 100644 index f4fde437020..00000000000 --- a/estate/views/estate_property_offer_view_list.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - estate.property.offer.list - estate.property.offer - - - - - - - - -

- -

- - - - - - - -
- -
-
-
\ No newline at end of file diff --git a/estate/views/estate_property_type_view_list.xml b/estate/views/estate_property_type_view_list.xml deleted file mode 100644 index 7047afd2782..00000000000 --- a/estate/views/estate_property_type_view_list.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - estate.property.type.list - estate.property.type - - - - - - - - \ No newline at end of file diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index b49c26d8758..e61d6502b30 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -4,4 +4,43 @@ estate.property.type list,form
+ + + + estate.property.type.list + estate.property.type + + + + + + + + + + + estate.property.type.form + estate.property.type + +
+ +
+ +
+

+ +

+ + + + + + + +
+
+
+
\ No newline at end of file diff --git a/estate/views/estate_property_view_form.xml b/estate/views/estate_property_view_form.xml deleted file mode 100644 index d994833b877..00000000000 --- a/estate/views/estate_property_view_form.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - estate.property.form - estate.property - -
-
- -
- -

- -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
\ No newline at end of file diff --git a/estate/views/estate_property_view_kanban.xml b/estate/views/estate_property_view_kanban.xml deleted file mode 100644 index f5ffd0d0581..00000000000 --- a/estate/views/estate_property_view_kanban.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - estate.property.kanban - estate.property - - - - - - - - \ No newline at end of file diff --git a/estate/views/estate_property_view_list.xml b/estate/views/estate_property_view_list.xml deleted file mode 100644 index eec995429fb..00000000000 --- a/estate/views/estate_property_view_list.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - estate.property.list - estate.property - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/estate/views/estate_property_view_search.xml b/estate/views/estate_property_view_search.xml deleted file mode 100644 index 3a27b9ba121..00000000000 --- a/estate/views/estate_property_view_search.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - estate.property.search - estate.property - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 1465a5f1bfd..0d5a19ee1f1 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -5,4 +5,136 @@ list,form,kanban {'search_default_filter_available_properties':True}
+ + + + estate.property.list + estate.property + + + + + + + + + + + + + + + + + + estate.property.form + estate.property + +
+
+ +
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + + estate.property.kanban + estate.property + + + + + + + + + + + estate.property.search + estate.property + + + + + + + + + + + + + +
\ No newline at end of file From de60394ca7de46ca6dff92a3e8408582086872a9 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 16:24:48 +0100 Subject: [PATCH 40/60] [CLN] estate_account: remove print and unused import --- estate_account/models/estate_property.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/estate_account/models/estate_property.py b/estate_account/models/estate_property.py index 4c64a2f0036..6e3255576cb 100644 --- a/estate_account/models/estate_property.py +++ b/estate_account/models/estate_property.py @@ -1,10 +1,9 @@ -from odoo import fields, models, Command +from odoo import models, Command class EstateProperty(models.Model): _inherit = ['estate.property'] def action_sold(self): - print("test ----------------------- \n") self.env['account.move'].create({ 'name': self.name, 'move_type':'out_invoice', From 48677c50ec5814209cb7f010d0135db57fccf31a Mon Sep 17 00:00:00 2001 From: Quentin George Date: Wed, 25 Mar 2026 16:51:20 +0100 Subject: [PATCH 41/60] [CLN] estate & estate_account: rename actions --- estate/models/estate_property.py | 4 ++-- estate/models/estate_property_offer.py | 4 ++-- estate/views/estate_property_offer_views.xml | 4 ++-- estate/views/estate_property_views.xml | 4 ++-- estate_account/models/estate_property.py | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index fd829117776..b160212f94b 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -79,7 +79,7 @@ def _onchange_garden(self): self.garden_area = 0 self.garden_orientation = "" - def action_sold(self): + def estate_property_action_sold(self): for record in self: if(record.state == "cancelled"): raise exceptions.UserError("Cancelled properties cannot be sold.") @@ -87,7 +87,7 @@ def action_sold(self): record.state = "sold" return True - def action_cancelled(self): + def estate_property_action_cancelled(self): for record in self: if(record.state == "sold"): raise exceptions.UserError("Sold properties cannot be cancelled.") diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 19ae650dcfc..3d957c5cd73 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -33,7 +33,7 @@ def _inverse_deadline(self): for record in self: record.validity = (record.date_deadline - fields.Date.to_date(record.create_date)).days - def action_accept(self): + def estate_property_offer_action_accept(self): for record in self: for offer in record.property_id.property_offer_ids: offer.status = "refused" @@ -42,7 +42,7 @@ def action_accept(self): record.property_id.buyer_id = record.partner_id return True - def action_refuse(self): + def estate_property_offer_action_refuse(self): for record in self: record.status = "refused" return True diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index 0ff08bba08c..963a55ff1d8 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -16,8 +16,8 @@ -

- +

- + - - - + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 0d5a19ee1f1..89e7773a1f7 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,85 +1,85 @@ - - Properties - estate.property - list,form,kanban - {'search_default_filter_available_properties':True} + + Properties + estate.property + list,form,kanban + {"search_default_filter_available_properties":True} - - estate.property.list - estate.property - + + estate.property.list + estate.property + - - - - - - - - - + + + + + + + + + - - estate.property.form - estate.property - + + estate.property.form + estate.property +

- +

- + - - - + + + - - - + + + - - - - - - - - - + + + + + + + + + - + - - + + @@ -89,30 +89,30 @@
- - estate.property.kanban - estate.property - + + estate.property.kanban + estate.property + @@ -120,20 +120,20 @@ - - estate.property.search - estate.property - + + estate.property.search + estate.property + - - - - - - + + + + + + - - + + diff --git a/estate/views/res_users_view_form.xml b/estate/views/res_users_view_form.xml index 62a149a0612..b26d51da95a 100644 --- a/estate/views/res_users_view_form.xml +++ b/estate/views/res_users_view_form.xml @@ -1,10 +1,10 @@ - - res.users.view.form - res.users - - - + + res.users.view.form + res.users + + + From 7567d2ebb34f32cd06f35851392709c9d4381314 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 14:03:59 +0100 Subject: [PATCH 59/60] [CLN] estate: add missing trailing comma --- estate/__manifest__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 83192397089..504a35cd038 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -15,7 +15,7 @@ 'views/estate_menus.xml', - 'views/res_users_view_form.xml' + 'views/res_users_view_form.xml', ], } From 6f4d8631aede9824d9bec8022224b6030cb4e209 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 14:09:48 +0100 Subject: [PATCH 60/60] [CLN] estate: simplify action logic --- estate/models/estate_property.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index cb1f18c7080..0fec1263d56 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -62,10 +62,7 @@ def _compute_total_area(self): @api.depends('property_offer_ids.price') def _compute_best_price(self): for record in self: - if len(record.property_offer_ids) > 0: - record.best_price = max(record.property_offer_ids.mapped('price')) - else: - record.best_price = 0.0 + record.best_price = max(record.property_offer_ids.mapped('price'), default=0) @api.onchange('garden') def _onchange_garden(self):