From 684e72dbf085aed85839204f2e7a397cf3d2acb9 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 19 Mar 2026 13:34:27 +0100 Subject: [PATCH 01/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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/75] [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): From 8dec08e306720031f8fba838d3d53b3e281e5de0 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 14:45:42 +0100 Subject: [PATCH 61/75] [IMP] awewsome_owl: Chapter 1 - Add counter --- awesome_owl/static/src/playground.js | 12 +++++++++++- awesome_owl/static/src/playground.xml | 4 +++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 4ac769b0aa5..89cb2f27df5 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,5 +1,15 @@ -import { Component } from "@odoo/owl"; +import { Component, useState } from "@odoo/owl"; export class Playground extends Component { static template = "awesome_owl.playground"; + + setup() { + this.state = useState({ value: 0 }); + } + + increment() { + this.state.value ++; + } + + } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 4fb905d59f9..0fbf15cb48b 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -3,7 +3,9 @@
- hello world +

hello world

+
Counter:
+
From b06f16e02ca7e986ae1a35ecca598a212037c9e1 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 15:20:44 +0100 Subject: [PATCH 62/75] [IMP] awewsome_owl: Chapter 2 --- awesome_owl/static/src/counter/counter.js | 14 ++++++++++++++ awesome_owl/static/src/counter/counter.xml | 11 +++++++++++ awesome_owl/static/src/playground.js | 12 ++---------- awesome_owl/static/src/playground.xml | 4 ++-- 4 files changed, 29 insertions(+), 12 deletions(-) create mode 100644 awesome_owl/static/src/counter/counter.js create mode 100644 awesome_owl/static/src/counter/counter.xml diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js new file mode 100644 index 00000000000..93bc9c062cf --- /dev/null +++ b/awesome_owl/static/src/counter/counter.js @@ -0,0 +1,14 @@ +import { Component, useState } from "@odoo/owl"; + +export class Counter extends Component { + static template = "awesome_owl.counter"; + + setup() { + this.state = useState({ value: 0 }); + } + + increment() { + this.state.value ++; + } + +} diff --git a/awesome_owl/static/src/counter/counter.xml b/awesome_owl/static/src/counter/counter.xml new file mode 100644 index 00000000000..65a9f7e8833 --- /dev/null +++ b/awesome_owl/static/src/counter/counter.xml @@ -0,0 +1,11 @@ + + + + +
+
Counter:
+ +
+
+ +
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 89cb2f27df5..d7833efb827 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,15 +1,7 @@ import { Component, useState } from "@odoo/owl"; +import { Counter } from "./counter/counter" export class Playground extends Component { static template = "awesome_owl.playground"; - - setup() { - this.state = useState({ value: 0 }); - } - - increment() { - this.state.value ++; - } - - + static components = { Counter }; } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 0fbf15cb48b..18e5e721466 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -4,8 +4,8 @@

hello world

-
Counter:
- + +
From c6df3386316c20a27ff65a39079789181958bc20 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 15:30:28 +0100 Subject: [PATCH 63/75] [IMP] awewsome_owl: Chapter 3 --- awesome_owl/static/src/card/card.js | 5 +++++ awesome_owl/static/src/card/card.xml | 15 +++++++++++++++ awesome_owl/static/src/playground.js | 5 +++-- awesome_owl/static/src/playground.xml | 4 ++-- 4 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 awesome_owl/static/src/card/card.js create mode 100644 awesome_owl/static/src/card/card.xml diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js new file mode 100644 index 00000000000..4cfd7ac3550 --- /dev/null +++ b/awesome_owl/static/src/card/card.js @@ -0,0 +1,5 @@ +import { Component, useState } from "@odoo/owl"; + +export class Card extends Component { + static template = "awesome_owl.card"; +} diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml new file mode 100644 index 00000000000..bba4b999801 --- /dev/null +++ b/awesome_owl/static/src/card/card.xml @@ -0,0 +1,15 @@ + + + + +
+
+
+
+

+

+
+
+
+ +
diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index d7833efb827..e8c47bbc7d4 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,7 +1,8 @@ import { Component, useState } from "@odoo/owl"; -import { Counter } from "./counter/counter" +import { Counter } from "./counter/counter"; +import { Card } from "./card/card"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { Counter }; + static components = { Counter, Card }; } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 18e5e721466..c5f0d4832bc 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -1,12 +1,12 @@ -

hello world

+ +
-
From 89b89ed59c9e029254a7468be314ae970a7eb092 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 15:41:44 +0100 Subject: [PATCH 64/75] [IMP] awewsome_owl: Chapter 4 --- awesome_owl/static/src/card/card.js | 6 +++++- awesome_owl/static/src/card/card.xml | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 4cfd7ac3550..5d75a31c0de 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -1,5 +1,9 @@ -import { Component, useState } from "@odoo/owl"; +import { markup, Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; + + setup() { + this.state = useState({htmlLink: markup('test')}) + } } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index bba4b999801..7758449cade 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -7,6 +7,7 @@

+

From bce1ecf69e002150642bbe953c2b35a3e879eee6 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 16:00:03 +0100 Subject: [PATCH 65/75] [IMP] awewsome_owl: Chapter 5 --- awesome_owl/static/src/card/card.js | 1 + 1 file changed, 1 insertion(+) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 5d75a31c0de..cbc471d6448 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -2,6 +2,7 @@ import { markup, Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; + static props = ["title", "content"]; setup() { this.state = useState({htmlLink: markup('test')}) From 821297ff16840be43a96794b8483a9ccfe25c967 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 16:30:22 +0100 Subject: [PATCH 66/75] [IMP] awewsome_owl: Chapter 6 --- awesome_owl/static/src/counter/counter.js | 6 +++++- awesome_owl/static/src/playground.js | 8 ++++++++ awesome_owl/static/src/playground.xml | 5 +++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/awesome_owl/static/src/counter/counter.js b/awesome_owl/static/src/counter/counter.js index 93bc9c062cf..3e31ec8bdf6 100644 --- a/awesome_owl/static/src/counter/counter.js +++ b/awesome_owl/static/src/counter/counter.js @@ -2,13 +2,17 @@ import { Component, useState } from "@odoo/owl"; export class Counter extends Component { static template = "awesome_owl.counter"; + static props = { + "onChange": {type: Function, optional: true} + } setup() { this.state = useState({ value: 0 }); } increment() { - this.state.value ++; + this.state.value++; + this.props.onChange(); } } diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index e8c47bbc7d4..6830e71f923 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -5,4 +5,12 @@ import { Card } from "./card/card"; export class Playground extends Component { static template = "awesome_owl.playground"; static components = { Counter, Card }; + + setup(){ + this.sum = useState({value: 0}) + } + + incrementSum(){ + this.sum.value++; + } } diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index c5f0d4832bc..53947ec8d3e 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -3,8 +3,9 @@

hello world

- - + + +
Sum of counters:
From b9385e853220005fd0d572c28a064132dc368190 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 21:56:20 +0100 Subject: [PATCH 67/75] [IMP] awewsome_owl: Chapter 7 --- awesome_owl/static/src/playground.js | 3 ++- awesome_owl/static/src/playground.xml | 3 +++ awesome_owl/static/src/todo_list/todo_item.js | 17 +++++++++++++++++ awesome_owl/static/src/todo_list/todo_item.xml | 13 +++++++++++++ awesome_owl/static/src/todo_list/todo_list.js | 16 ++++++++++++++++ awesome_owl/static/src/todo_list/todo_list.xml | 10 ++++++++++ 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 awesome_owl/static/src/todo_list/todo_item.js create mode 100644 awesome_owl/static/src/todo_list/todo_item.xml create mode 100644 awesome_owl/static/src/todo_list/todo_list.js create mode 100644 awesome_owl/static/src/todo_list/todo_list.xml diff --git a/awesome_owl/static/src/playground.js b/awesome_owl/static/src/playground.js index 6830e71f923..f6431540330 100644 --- a/awesome_owl/static/src/playground.js +++ b/awesome_owl/static/src/playground.js @@ -1,10 +1,11 @@ import { Component, useState } from "@odoo/owl"; import { Counter } from "./counter/counter"; import { Card } from "./card/card"; +import { TodoList } from "./todo_list/todo_list"; export class Playground extends Component { static template = "awesome_owl.playground"; - static components = { Counter, Card }; + static components = { Counter, Card, TodoList }; setup(){ this.sum = useState({value: 0}) diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 53947ec8d3e..7706f95b12f 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -9,5 +9,8 @@ +
+ +
diff --git a/awesome_owl/static/src/todo_list/todo_item.js b/awesome_owl/static/src/todo_list/todo_item.js new file mode 100644 index 00000000000..0e4a3544764 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_item.js @@ -0,0 +1,17 @@ +import { Component, useState } from "@odoo/owl"; + +export class TodoItem extends Component { + static template = "awesome_owl.todo_item"; + static props = { + todo: { + type: Object, + shape: { + id: {type: Number, optional: false}, + description: {type: String, optional: false}, + isCompleted: {type: Boolean, optional: false}, + }, + }, + }; + + +} diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml new file mode 100644 index 00000000000..4d371c2bfc3 --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -0,0 +1,13 @@ + + + + +
+ [V + _] + - + +
+
+ +
diff --git a/awesome_owl/static/src/todo_list/todo_list.js b/awesome_owl/static/src/todo_list/todo_list.js new file mode 100644 index 00000000000..4f56d0441de --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_list.js @@ -0,0 +1,16 @@ +import { Component, useState } from "@odoo/owl"; +import { TodoItem } from "./todo_item"; + +export class TodoList extends Component { + static template = "awesome_owl.todo_list"; + static components = { TodoItem }; + + setup(){ + this.todos = useState([ + { id: 1, description: "buy bread", isCompleted: false }, + { id: 2, description: "buy butter", isCompleted: true }, + { id: 3, description: "buy milk", isCompleted: false }, + ]); + } + +} diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml new file mode 100644 index 00000000000..28e49081d4d --- /dev/null +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -0,0 +1,10 @@ + + + + +
+ +
+
+ +
From 2fef72dc866a20afd891874e5d7784d0f443b3ab Mon Sep 17 00:00:00 2001 From: Quentin George Date: Thu, 26 Mar 2026 21:57:11 +0100 Subject: [PATCH 68/75] [IMP] awewsome_owl: Chapter 8 --- awesome_owl/static/src/todo_list/todo_item.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml index 4d371c2bfc3..24eaae05979 100644 --- a/awesome_owl/static/src/todo_list/todo_item.xml +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -2,8 +2,8 @@ -
- [V +
+ [X _] - From ee549a50f509b293b7509bc541a04affbcf9339e Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 27 Mar 2026 08:55:03 +0100 Subject: [PATCH 69/75] [IMP] awewsome_owl: Chapter 10 --- awesome_owl/static/src/todo_list/todo_list.js | 25 ++++++++++++++----- .../static/src/todo_list/todo_list.xml | 1 + 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/awesome_owl/static/src/todo_list/todo_list.js b/awesome_owl/static/src/todo_list/todo_list.js index 4f56d0441de..15ea5d4b0d1 100644 --- a/awesome_owl/static/src/todo_list/todo_list.js +++ b/awesome_owl/static/src/todo_list/todo_list.js @@ -1,4 +1,4 @@ -import { Component, useState } from "@odoo/owl"; +import { Component, useState, useRef, onMounted } from "@odoo/owl"; import { TodoItem } from "./todo_item"; export class TodoList extends Component { @@ -6,11 +6,24 @@ export class TodoList extends Component { static components = { TodoItem }; setup(){ - this.todos = useState([ - { id: 1, description: "buy bread", isCompleted: false }, - { id: 2, description: "buy butter", isCompleted: true }, - { id: 3, description: "buy milk", isCompleted: false }, - ]); + this.todos = useState([]); + this.todoCount = 1; + this.inputRef = useRef('taskInput'); + + onMounted(()=>{ + this.inputRef.el.focus(); + }) + } + + addTask(e){ + if(e.keyCode === 13 && e.target.value !== ""){ + this.todos.push({ + id: this.todoCount++, + description: e.target.value, + isCompleted: false, + }) + e.target.value = ""; + } } } diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml index 28e49081d4d..6c62ccb3b8c 100644 --- a/awesome_owl/static/src/todo_list/todo_list.xml +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -3,6 +3,7 @@
+
From 2a175f926ee68694df359f58381e50cf4f8d6e7c Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 27 Mar 2026 09:20:06 +0100 Subject: [PATCH 70/75] [IMP] awewsome_owl: Chapter 11 --- awesome_owl/static/src/todo_list/todo_item.js | 9 ++++++++- awesome_owl/static/src/todo_list/todo_item.xml | 1 + awesome_owl/static/src/todo_list/todo_list.js | 5 +++++ awesome_owl/static/src/todo_list/todo_list.xml | 2 +- 4 files changed, 15 insertions(+), 2 deletions(-) diff --git a/awesome_owl/static/src/todo_list/todo_item.js b/awesome_owl/static/src/todo_list/todo_item.js index 0e4a3544764..e68cb73632f 100644 --- a/awesome_owl/static/src/todo_list/todo_item.js +++ b/awesome_owl/static/src/todo_list/todo_item.js @@ -11,7 +11,14 @@ export class TodoItem extends Component { isCompleted: {type: Boolean, optional: false}, }, }, + toggleState: { + type: Function, + optional: false, + }, }; - + change(){ + this.props.toggleState(this.props.todo.id); + } + } diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml index 24eaae05979..1d0069ba68d 100644 --- a/awesome_owl/static/src/todo_list/todo_item.xml +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -3,6 +3,7 @@
+ [X _] - diff --git a/awesome_owl/static/src/todo_list/todo_list.js b/awesome_owl/static/src/todo_list/todo_list.js index 15ea5d4b0d1..ca479186490 100644 --- a/awesome_owl/static/src/todo_list/todo_list.js +++ b/awesome_owl/static/src/todo_list/todo_list.js @@ -26,4 +26,9 @@ export class TodoList extends Component { } } + toggleState(id){ + let todo = this.todos.find((todo) => todo.id === id); + todo.isCompleted = !todo.isCompleted; + } + } diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml index 6c62ccb3b8c..f6bd5669830 100644 --- a/awesome_owl/static/src/todo_list/todo_list.xml +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -4,7 +4,7 @@
- +
From 06eb246c6436cc095d678d9391903832a7d72fe5 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 27 Mar 2026 09:29:25 +0100 Subject: [PATCH 71/75] [IMP] awewsome_owl: Chapter 12 --- awesome_owl/static/src/todo_list/todo_item.js | 9 ++++++++- awesome_owl/static/src/todo_list/todo_item.xml | 1 + awesome_owl/static/src/todo_list/todo_list.js | 7 +++++++ awesome_owl/static/src/todo_list/todo_list.xml | 2 +- 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/awesome_owl/static/src/todo_list/todo_item.js b/awesome_owl/static/src/todo_list/todo_item.js index e68cb73632f..56ed0c084ca 100644 --- a/awesome_owl/static/src/todo_list/todo_item.js +++ b/awesome_owl/static/src/todo_list/todo_item.js @@ -15,10 +15,17 @@ export class TodoItem extends Component { type: Function, optional: false, }, + removeTodo: { + type: Function, + optional: false, + }, }; change(){ this.props.toggleState(this.props.todo.id); } - + remove(){ + this.props.removeTodo(this.props.todo.id); + } + } diff --git a/awesome_owl/static/src/todo_list/todo_item.xml b/awesome_owl/static/src/todo_list/todo_item.xml index 1d0069ba68d..d173cac5e85 100644 --- a/awesome_owl/static/src/todo_list/todo_item.xml +++ b/awesome_owl/static/src/todo_list/todo_item.xml @@ -8,6 +8,7 @@ _] - +
diff --git a/awesome_owl/static/src/todo_list/todo_list.js b/awesome_owl/static/src/todo_list/todo_list.js index ca479186490..7f6365540d5 100644 --- a/awesome_owl/static/src/todo_list/todo_list.js +++ b/awesome_owl/static/src/todo_list/todo_list.js @@ -31,4 +31,11 @@ export class TodoList extends Component { todo.isCompleted = !todo.isCompleted; } + removeTodo(id){ + const index = this.todos.findIndex((todo) => todo.id === id); + if (index >= 0) { + this.todos.splice(index, 1); + } + } + } diff --git a/awesome_owl/static/src/todo_list/todo_list.xml b/awesome_owl/static/src/todo_list/todo_list.xml index f6bd5669830..3faea0b59b3 100644 --- a/awesome_owl/static/src/todo_list/todo_list.xml +++ b/awesome_owl/static/src/todo_list/todo_list.xml @@ -4,7 +4,7 @@
- +
From f0521449b2544604425528b0e7b5a450d424389b Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 27 Mar 2026 10:04:46 +0100 Subject: [PATCH 72/75] [IMP] awewsome_owl: Chapter 13 --- awesome_owl/static/src/card/card.js | 11 ++++++++++- awesome_owl/static/src/card/card.xml | 4 +--- awesome_owl/static/src/playground.xml | 16 ++++++++++++---- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index cbc471d6448..280559fc398 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -2,7 +2,16 @@ import { markup, Component, useState } from "@odoo/owl"; export class Card extends Component { static template = "awesome_owl.card"; - static props = ["title", "content"]; + static props = { + title: { + type: String, + optional: true, + }, + slots: { + type: Object, + optional: true, + }, + }; setup() { this.state = useState({htmlLink: markup('test')}) diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 7758449cade..49b1ee255f4 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -6,11 +6,9 @@
-

-

+

- diff --git a/awesome_owl/static/src/playground.xml b/awesome_owl/static/src/playground.xml index 7706f95b12f..025440a90df 100644 --- a/awesome_owl/static/src/playground.xml +++ b/awesome_owl/static/src/playground.xml @@ -3,11 +3,19 @@

hello world

- -
Sum of counters:
- - + +

+ Random content 1 +

+ +
+ +

+ Random content 2 +

+ +
From 6654b149d565a7f102f4af3ec129bf69bb5b1c33 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 27 Mar 2026 10:13:34 +0100 Subject: [PATCH 73/75] [IMP] awewsome_owl: Chapter 14 --- awesome_owl/static/src/card/card.js | 5 +++++ awesome_owl/static/src/card/card.xml | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/awesome_owl/static/src/card/card.js b/awesome_owl/static/src/card/card.js index 280559fc398..c0fb6e9c46c 100644 --- a/awesome_owl/static/src/card/card.js +++ b/awesome_owl/static/src/card/card.js @@ -15,5 +15,10 @@ export class Card extends Component { setup() { this.state = useState({htmlLink: markup('test')}) + this.isMinimized = useState({value: false}); + } + + toggle() { + this.isMinimized.value = !this.isMinimized.value; } } diff --git a/awesome_owl/static/src/card/card.xml b/awesome_owl/static/src/card/card.xml index 49b1ee255f4..0ad7c9ed829 100644 --- a/awesome_owl/static/src/card/card.xml +++ b/awesome_owl/static/src/card/card.xml @@ -4,9 +4,10 @@
-
+
-

+ + +

From ffe5ca4baa0b164f99f8959cbfd86071a72a0a4d Mon Sep 17 00:00:00 2001 From: Quentin George Date: Fri, 27 Mar 2026 15:44:35 +0100 Subject: [PATCH 74/75] [IMP] awewsome_dashboard: Chapter 4 --- awesome_dashboard/static/src/dashboard.js | 49 ++++++++++++++++++- awesome_dashboard/static/src/dashboard.scss | 3 ++ awesome_dashboard/static/src/dashboard.xml | 28 +++++++++++ .../src/dashboard_item/dashboard_item.js | 17 +++++++ .../src/dashboard_item/dashboard_item.scss | 5 ++ .../src/dashboard_item/dashboard_item.xml | 12 +++++ 6 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 awesome_dashboard/static/src/dashboard.scss create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.js create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.scss create mode 100644 awesome_dashboard/static/src/dashboard_item/dashboard_item.xml diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index c4fb245621b..1801e41fcfc 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -1,8 +1,55 @@ -import { Component } from "@odoo/owl"; +import { Component, useState, onWillStart } from "@odoo/owl"; import { registry } from "@web/core/registry"; +import { Layout } from "@web/search/layout"; +import { useService } from "@web/core/utils/hooks"; +import { DashboardItem } from "./dashboard_item/dashboard_item"; +import { rpc } from "@web/core/network/rpc"; class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; + static components = { Layout, DashboardItem }; + + + setup(){ + this.action = useService("action"); + this.display = useState({ + controlPanel: {} + }); + this.stats = useState({}); + onWillStart(async () => { + const result = await rpc("/awesome_dashboard/statistics"); + console.log(result); + this.stats = result; + console.log(this.stats.average_quantity); + }) + } + + + openCustomers() { + /* this.action.doAction("base_setup.action_general_configuration"); */ + + /* this.action.doAction("base.action_partner_form"); */ + + this.action.doAction({ + type: 'ir.actions.act_window', + name: 'Customers', + /* target: 'new', */ + res_model: 'res.partner', + views: [[false, 'kanban']], + }) + } + openLeads() { + /* this.action.doAction("base.action_partner_form"); */ + this.action.doAction({ + type: 'ir.actions.act_window', + name: 'Leads', + target: 'current', + /* res_id: 'crm_lead_action', */ + res_model: 'crm.lead', + views: [[false, 'list'],[false, 'form']], + }) + } + } registry.category("actions").add("awesome_dashboard.dashboard", AwesomeDashboard); diff --git a/awesome_dashboard/static/src/dashboard.scss b/awesome_dashboard/static/src/dashboard.scss new file mode 100644 index 00000000000..769fc1e72f9 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard.scss @@ -0,0 +1,3 @@ +.o_dashboard { + background-color: gray; +} \ No newline at end of file diff --git a/awesome_dashboard/static/src/dashboard.xml b/awesome_dashboard/static/src/dashboard.xml index 1a2ac9a2fed..1cb713b7765 100644 --- a/awesome_dashboard/static/src/dashboard.xml +++ b/awesome_dashboard/static/src/dashboard.xml @@ -3,6 +3,34 @@ hello dashboard + + + + + + + Average amount of ... is + + + + Average time of ... is + + + + Number of cancelled orders is + + + + Number of new orders is + + + + The total amount of new orders is + + + + + diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.js b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js new file mode 100644 index 00000000000..7dcf38870bc --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.js @@ -0,0 +1,17 @@ +import { Component, useState } from "@odoo/owl"; + +export class DashboardItem extends Component { + static template = "awesome_dashboard.dashboard_item"; + static props = { + size:{ + type: Number, + optional: true, + default: 1, + } + } + + setup(){ + this.width = useState({value: this.props.size * 18}) + } + +} diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.scss b/awesome_dashboard/static/src/dashboard_item/dashboard_item.scss new file mode 100644 index 00000000000..00874b06b30 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.scss @@ -0,0 +1,5 @@ +.card { + display: inline-block; + border: 1px solid grey; + padding: 10px; +} \ No newline at end of file diff --git a/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml new file mode 100644 index 00000000000..5d76721e3c0 --- /dev/null +++ b/awesome_dashboard/static/src/dashboard_item/dashboard_item.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + From e898cac4ed5eefb45f61e9071b3c36ed03d99540 Mon Sep 17 00:00:00 2001 From: Quentin George Date: Mon, 30 Mar 2026 11:42:01 +0200 Subject: [PATCH 75/75] [IMP] awewsome_dashboard: Chapter 5 --- awesome_dashboard/static/src/dashboard.js | 14 ++++---------- awesome_dashboard/static/src/statistics_service.js | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 10 deletions(-) create mode 100644 awesome_dashboard/static/src/statistics_service.js diff --git a/awesome_dashboard/static/src/dashboard.js b/awesome_dashboard/static/src/dashboard.js index 1801e41fcfc..d41e71bd5b5 100644 --- a/awesome_dashboard/static/src/dashboard.js +++ b/awesome_dashboard/static/src/dashboard.js @@ -3,33 +3,27 @@ import { registry } from "@web/core/registry"; import { Layout } from "@web/search/layout"; import { useService } from "@web/core/utils/hooks"; import { DashboardItem } from "./dashboard_item/dashboard_item"; -import { rpc } from "@web/core/network/rpc"; + class AwesomeDashboard extends Component { static template = "awesome_dashboard.AwesomeDashboard"; static components = { Layout, DashboardItem }; - setup(){ + this.statisticsService = useService("awesome_dashboard.statistics"); this.action = useService("action"); this.display = useState({ controlPanel: {} }); this.stats = useState({}); onWillStart(async () => { - const result = await rpc("/awesome_dashboard/statistics"); - console.log(result); + const result = await this.statisticsService.loadStatistics(); this.stats = result; - console.log(this.stats.average_quantity); }) } - openCustomers() { - /* this.action.doAction("base_setup.action_general_configuration"); */ - /* this.action.doAction("base.action_partner_form"); */ - this.action.doAction({ type: 'ir.actions.act_window', name: 'Customers', @@ -38,8 +32,8 @@ class AwesomeDashboard extends Component { views: [[false, 'kanban']], }) } + openLeads() { - /* this.action.doAction("base.action_partner_form"); */ this.action.doAction({ type: 'ir.actions.act_window', name: 'Leads', diff --git a/awesome_dashboard/static/src/statistics_service.js b/awesome_dashboard/static/src/statistics_service.js new file mode 100644 index 00000000000..f0493a2633b --- /dev/null +++ b/awesome_dashboard/static/src/statistics_service.js @@ -0,0 +1,14 @@ +import { registry } from "@web/core/registry"; +import { rpc } from "@web/core/network/rpc"; +import { memoize } from "@web/core/utils/functions"; + +const statistics_service = { + async: ["loadStatistics"], + start(env) { + return { + loadStatistics: memoize(() => rpc("/awesome_dashboard/statistics")), + } + } +} + +registry.category("services").add("awesome_dashboard.statistics", statistics_service); \ No newline at end of file