From 9db531dc3cb0d32bb31579576276906aacdec031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:00:07 +0300 Subject: [PATCH 01/53] Update folder structure and add Technical Training link for Odoo 16.0 --- estate/__manifest__.py | 2 +- estate/models/__init__.py | 1 + estate/models/estate_property.py | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py diff --git a/estate/__manifest__.py b/estate/__manifest__.py index d7cfa57d4c5..000a4136d22 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,6 +1,6 @@ { "name": "Estate", # The name that will appear in the App list - "version": "16.0.0", # Version + "version": "18.0.0", # Version "application": True, # This line says the module is an App, and not a module "depends": ["base"], # dependencies "data": [ diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..5e1963c9d2f --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1 @@ +from . import estate_property diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py new file mode 100644 index 00000000000..5d84ee05302 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,4 @@ +from odoo import models + +class TestModel(models.Model): + _name = "estate.property" \ No newline at end of file From 1eecc7cdc7498617935f914322d79c006737ad3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:05:24 +0300 Subject: [PATCH 02/53] Update estate module version to 18.0.1.0.0 and standardize manifest formatting --- estate/__manifest__.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 000a4136d22..12b9a8caaa2 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,11 +1,10 @@ { - "name": "Estate", # The name that will appear in the App list - "version": "18.0.0", # Version - "application": True, # This line says the module is an App, and not a module - "depends": ["base"], # dependencies + "name": "Estate", + "version": "18.0.1.0.0", + "application": True, + "depends": ["base"], "data": [ - ], "installable": True, - 'license': 'LGPL-3', + "license": "LGPL-3", } From e85f7f6a77505c85b83ba09d350fab911e4c8f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:11:53 +0300 Subject: [PATCH 03/53] Rename TestModel to EstateProperty and add description for clarity --- estate/models/estate_property.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 5d84ee05302..f2ab1aa80c5 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,5 @@ from odoo import models -class TestModel(models.Model): - _name = "estate.property" \ No newline at end of file +class EstateProperty(models.Model): + _name = "estate.property" + _description = "Estate Property" \ No newline at end of file From 8baa1ba10942954d409253efadafe20f32fb04ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:16:47 +0300 Subject: [PATCH 04/53] Add basic fields to EstateProperty model including title, description, and amenities --- estate/models/estate_property.py | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f2ab1aa80c5..34d3a32a63b 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,5 +1,28 @@ -from odoo import models +from odoo import models, fields class EstateProperty(models.Model): _name = "estate.property" - _description = "Estate Property" \ No newline at end of file + _description = "Estate Property" + + # Basic fields + name = fields.Char(string="Title", required=True) + description = fields.Text(string="Description") + postcode = fields.Char(string="Postcode") + date_availability = fields.Date(string="Available From") + expected_price = fields.Float(string="Expected Price", required=True) + selling_price = fields.Float(string="Selling Price", readonly=True) + bedrooms = fields.Integer(string="Bedrooms", default=2) + living_area = fields.Integer(string="Living Area (sqm)") + facades = fields.Integer(string="Facades") + garage = fields.Boolean(string="Garage") + garden = fields.Boolean(string="Garden") + garden_area = fields.Integer(string="Garden Area (sqm)") + garden_orientation = fields.Selection( + selection=[ + ('north', 'North'), + ('south', 'South'), + ('east', 'East'), + ('west', 'West') + ], + string="Garden Orientation" + ) \ No newline at end of file From da04814dfc32987d7d16f8bf364085960bebe56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:42:26 +0300 Subject: [PATCH 05/53] Add security access control for EstateProperty model and update manifest data order --- estate/__manifest__.py | 14 ++++++++++++++ estate/security/ir.model.access.csv | 2 ++ 2 files changed, 16 insertions(+) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 12b9a8caaa2..ea27344a746 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -4,6 +4,20 @@ "application": True, "depends": ["base"], "data": [ + # Security files first + "security/ir.model.access.csv", + + # Data files in dependency order + # "data/estate_property_type_data.xml", # Base data first + # "data/estate_property_tag_data.xml", # Independent data + # "data/estate_property_offer_data.xml", # Depends on property types + + # Views and menus last + # "views/estate_property_views.xml", + # "views/estate_property_type_views.xml", + # "views/estate_property_tag_views.xml", + # "views/estate_property_offer_views.xml", + # "views/estate_menus.xml", ], "installable": True, "license": "LGPL-3", diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..32389642d4f --- /dev/null +++ b/estate/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 From ed95dd255e2f09496967bde682dbdb515a2187e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 11:53:21 +0200 Subject: [PATCH 06/53] Implement estate property views and update manifest to include new view file --- estate/__manifest__.py | 6 +++--- estate/views/estate_property_views.xml | 13 +++++++++++++ 2 files changed, 16 insertions(+), 3 deletions(-) create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ea27344a746..8c329a9c70e 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -6,14 +6,14 @@ "data": [ # Security files first "security/ir.model.access.csv", - + # Data files in dependency order # "data/estate_property_type_data.xml", # Base data first # "data/estate_property_tag_data.xml", # Independent data # "data/estate_property_offer_data.xml", # Depends on property types - + # Views and menus last - # "views/estate_property_views.xml", + "views/estate_property_views.xml", # "views/estate_property_type_views.xml", # "views/estate_property_tag_views.xml", # "views/estate_property_offer_views.xml", diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..755b3d829b5 --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,13 @@ + + + + Properties + estate.property + tree,form + +

+ Create the first property +

+
+
+
From eda473979b8d76a3c8124fcb108a9a4437e1514a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:05:35 +0200 Subject: [PATCH 07/53] Add estate menus XML file and update manifest to include it --- estate/__manifest__.py | 2 +- estate/views/estate_menus.xml | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 estate/views/estate_menus.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 8c329a9c70e..7f54314ba16 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -14,10 +14,10 @@ # Views and menus last "views/estate_property_views.xml", + "views/estate_menus.xml", # "views/estate_property_type_views.xml", # "views/estate_property_tag_views.xml", # "views/estate_property_offer_views.xml", - # "views/estate_menus.xml", ], "installable": True, "license": "LGPL-3", diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..04438c4b95a --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + From bfc946e8f59d6e00633133cdd7aa2227e5c4f964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:37:41 +0200 Subject: [PATCH 08/53] Update view mode in estate property action from 'tree' to 'list' --- estate/views/estate_property_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 755b3d829b5..c4a0ae39d38 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -3,7 +3,7 @@ Properties estate.property - tree,form + list,form

Create the first property From 535dcdb1770e26f1ec2a510f01a80fd33dec9dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 12:51:55 +0200 Subject: [PATCH 09/53] Enhance EstateProperty model by adding default values for date_availability and state fields, and updating selling_price to be non-copyable. Introduce active field for property status management. --- estate/models/estate_property.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 34d3a32a63b..7b742b85675 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -8,9 +8,13 @@ class EstateProperty(models.Model): name = fields.Char(string="Title", required=True) description = fields.Text(string="Description") postcode = fields.Char(string="Postcode") - date_availability = fields.Date(string="Available From") + date_availability = fields.Date( + string="Available From", + copy=False, + default=lambda self: fields.Date.add(fields.Date.today(), months=3), + ) expected_price = fields.Float(string="Expected Price", required=True) - selling_price = fields.Float(string="Selling Price", readonly=True) + selling_price = fields.Float(string="Selling Price", readonly=True, copy=False) bedrooms = fields.Integer(string="Bedrooms", default=2) living_area = fields.Integer(string="Living Area (sqm)") facades = fields.Integer(string="Facades") @@ -25,4 +29,14 @@ class EstateProperty(models.Model): ('west', 'West') ], string="Garden Orientation" + ) + + # Reserved/common fields + active = fields.Boolean(string="Active", default=True) + state = fields.Selection( + selection=[('new', 'New')], + string="Status", + required=True, + copy=False, + default='new', ) \ No newline at end of file From e405ad19e3a55fde8396fd2f1560c451140b6404 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 13:01:15 +0200 Subject: [PATCH 10/53] Expand status options in EstateProperty model by adding 'Offer Received', 'Offer Accepted', 'Sold', and 'Cancelled' to the state field selection. --- estate/models/estate_property.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 7b742b85675..02c73789987 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -34,7 +34,13 @@ class EstateProperty(models.Model): # Reserved/common fields active = fields.Boolean(string="Active", default=True) state = fields.Selection( - selection=[('new', 'New')], + selection=[ + ('new', 'New'), + ('offer_received', 'Offer Received'), + ('offer_accepted', 'Offer Accepted'), + ('sold', 'Sold'), + ('cancelled', 'Cancelled'), + ], string="Status", required=True, copy=False, From dabf46c619777ee1cd0165119785cdfb3548b956 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 13:07:42 +0200 Subject: [PATCH 11/53] Add list view for estate.property model to display key property details including name, postcode, bedrooms, living area, expected price, selling price, and date availability. --- estate/views/estate_property_views.xml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index c4a0ae39d38..33158cd2511 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,5 +1,22 @@ + + + estate.property.list + estate.property + + + + + + + + + + + + + Properties estate.property From abd796b2462bdd95e5856fcab65a2b31522af923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 13:19:22 +0200 Subject: [PATCH 12/53] Add form view for estate.property model to facilitate detailed property entry, including fields for name, availability date, pricing, description, and various property features. --- estate/views/estate_property_views.xml | 44 ++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 33158cd2511..4c4eb109d01 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -17,6 +17,50 @@ + + + estate.property.form + estate.property + +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ Properties estate.property From 3741db7c7f6037a2c675e3ba304d508a615d6017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 13:30:14 +0200 Subject: [PATCH 13/53] Add search view for estate.property model to enable efficient property searching with quick search fields, filters, and grouping options. --- estate/views/estate_property_views.xml | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 4c4eb109d01..aece07c347a 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -61,10 +61,36 @@ + + + estate.property.search + estate.property + + + + + + + + + + + + + + + + + + + + + Properties estate.property list,form +

Create the first property From 6951850313087ff0f3deb5f0eddafd9db50e93a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 13:44:39 +0200 Subject: [PATCH 14/53] Add estate property type model and views, including list and form views, and update estate property model to include property type relation. Enhance manifest and access control for new model. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 18 +++++++++++ estate/models/estate_property_type.py | 8 +++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menus.xml | 4 +++ estate/views/estate_property_type_views.xml | 35 +++++++++++++++++++++ estate/views/estate_property_views.xml | 11 +++++++ 8 files changed, 79 insertions(+) create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 7f54314ba16..db004c096c4 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -14,6 +14,7 @@ # Views and menus last "views/estate_property_views.xml", + "views/estate_property_type_views.xml", "views/estate_menus.xml", # "views/estate_property_type_views.xml", # "views/estate_property_tag_views.xml", diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..40092a2d810 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,2 @@ from . import estate_property +from . import estate_property_type diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 02c73789987..11b9c68d4bd 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -45,4 +45,22 @@ class EstateProperty(models.Model): required=True, copy=False, default='new', + ) + + # Relations + property_type_id = fields.Many2one( + comodel_name="estate.property.type", + string="Property Type", + ) + + # Parties + salesman_id = fields.Many2one( + comodel_name="res.users", + string="Salesman", + default=lambda self: self.env.user, + ) + buyer_id = fields.Many2one( + comodel_name="res.partner", + string="Buyer", + copy=False, ) \ No newline at end of file diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..6c0abb3b4ae --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,8 @@ +from odoo import models, fields + + +class EstatePropertyType(models.Model): + _name = "estate.property.type" + _description = "Estate Property Type" + + name = fields.Char(string="Name", required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 32389642d4f..11da225066f 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,3 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 +access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 04438c4b95a..3d7ceb0fd39 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -8,4 +8,8 @@ + + + + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..99f11123822 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,35 @@ + + + + estate.property.type.list + estate.property.type + + + + + + + + + estate.property.type.form + estate.property.type + +

+ +
+
+
+
+
+
+ + + Property Types + estate.property.type + list,form + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index aece07c347a..bf8ae7441f6 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -7,6 +7,7 @@ + @@ -40,10 +41,19 @@ + + + + + + + + + @@ -69,6 +79,7 @@ + From 5e9f9c1cab3646033436a1046ad0f65b1c5fc923 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 13:55:33 +0200 Subject: [PATCH 15/53] Add estate property tag model, views, and access control. Update estate property model to include many2many relationship for tags and enhance manifest and menu structure to support new functionality. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 5 ++++ estate/models/estate_property_tag.py | 8 +++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_menus.xml | 1 + estate/views/estate_property_tag_views.xml | 35 ++++++++++++++++++++++ estate/views/estate_property_views.xml | 2 ++ 8 files changed, 54 insertions(+) create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/views/estate_property_tag_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index db004c096c4..2399fb85242 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -15,6 +15,7 @@ # Views and menus last "views/estate_property_views.xml", "views/estate_property_type_views.xml", + "views/estate_property_tag_views.xml", "views/estate_menus.xml", # "views/estate_property_type_views.xml", # "views/estate_property_tag_views.xml", diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 40092a2d810..c620ac481a3 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,2 +1,3 @@ from . import estate_property from . import estate_property_type +from . import estate_property_tag diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 11b9c68d4bd..8022c4f0496 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -63,4 +63,9 @@ class EstateProperty(models.Model): comodel_name="res.partner", string="Buyer", copy=False, + ) + + tag_ids = fields.Many2many( + comodel_name="estate.property.tag", + string="Tags", ) \ No newline at end of file diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..91a3c2216dc --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,8 @@ +from odoo import models, fields + + +class EstatePropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Estate Property Tag" + + name = fields.Char(string="Name", required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 11da225066f..1493eab4011 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,3 +1,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 +access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 3d7ceb0fd39..ce072ba5daf 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -12,4 +12,5 @@ + diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml new file mode 100644 index 00000000000..0a8e4663307 --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,35 @@ + + + + estate.property.tag.list + estate.property.tag + + + + + + + + + estate.property.tag.form + estate.property.tag + +
+ +
+
+
+
+
+
+ + + Property Tags + estate.property.tag + list,form + +
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index bf8ae7441f6..996c2b59de9 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -8,6 +8,7 @@ + @@ -43,6 +44,7 @@
+ From 34fbb4fcf5ae285fd7cb291a4450ebf19fe2f37d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 14:00:02 +0200 Subject: [PATCH 16/53] Add estate property offer model, views, and access control. Update estate property model to include one2many relationship for offers and enhance manifest to support new functionality. --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 6 ++++ estate/models/estate_property_offer.py | 15 ++++++++++ estate/security/ir.model.access.csv | 1 + estate/views/estate_property_offer_views.xml | 31 ++++++++++++++++++++ estate/views/estate_property_views.xml | 16 ++++++++++ 7 files changed, 71 insertions(+) create mode 100644 estate/models/estate_property_offer.py create mode 100644 estate/views/estate_property_offer_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 2399fb85242..194fa91287a 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -16,6 +16,7 @@ "views/estate_property_views.xml", "views/estate_property_type_views.xml", "views/estate_property_tag_views.xml", + "views/estate_property_offer_views.xml", "views/estate_menus.xml", # "views/estate_property_type_views.xml", # "views/estate_property_tag_views.xml", diff --git a/estate/models/__init__.py b/estate/models/__init__.py index c620ac481a3..2f1821a39c1 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,3 +1,4 @@ from . import estate_property from . import estate_property_type from . import estate_property_tag +from . import estate_property_offer diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 8022c4f0496..f5004ad8e1b 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -68,4 +68,10 @@ class EstateProperty(models.Model): tag_ids = fields.Many2many( comodel_name="estate.property.tag", string="Tags", + ) + + offer_ids = fields.One2many( + comodel_name="estate.property.offer", + inverse_name="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..b543a319517 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,15 @@ +from odoo import models, fields + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Estate Property Offer" + + price = fields.Float(string="Price") + status = fields.Selection( + selection=[("accepted", "Accepted"), ("refused", "Refused")], + string="Status", + copy=False, + ) + partner_id = fields.Many2one("res.partner", string="Partner", required=True) + property_id = fields.Many2one("estate.property", string="Property", required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 1493eab4011..89f97c50842 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -2,3 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 +access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml new file mode 100644 index 00000000000..7fa07b279c3 --- /dev/null +++ b/estate/views/estate_property_offer_views.xml @@ -0,0 +1,31 @@ + + + + estate.property.offer.list + estate.property.offer + + + + + + + + + + + estate.property.offer.form + estate.property.offer + +
+ + + + + + + + +
+
+
+
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 996c2b59de9..cc42662d593 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -50,6 +50,22 @@ + + + + + + + +
+ + + + + +
+
+
From 354f4899f929bad5b927db38b757f782790ccad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 14:04:46 +0200 Subject: [PATCH 17/53] Change view mode from 'tree' to 'list' for offers in estate property views to improve consistency and clarity in the user interface. --- estate/views/estate_property_views.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index cc42662d593..7e251a4a072 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -52,11 +52,11 @@ - + - +
From a2cfc4062f618d9ceb3ee823ee09254f000d6056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 14:08:09 +0200 Subject: [PATCH 18/53] Update context for offer_ids field in estate property views to use 'id' instead of 'active_id' for improved data accuracy. --- estate/views/estate_property_views.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 7e251a4a072..dd3d6a5a3d7 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -51,7 +51,7 @@ - + From 772bca6e55a65bd2b900539af13bd4a9f78c891e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 14:17:41 +0200 Subject: [PATCH 19/53] Add computed fields for total area and best price in EstateProperty model, and implement validity and deadline fields in EstatePropertyOffer model. Update views to display new fields. --- estate/models/estate_property.py | 29 ++++++++++++++++++++++++-- estate/models/estate_property_offer.py | 21 ++++++++++++++++++- estate/views/estate_property_views.xml | 12 +++++++++++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f5004ad8e1b..75290a5bd7c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import models, fields +from odoo import models, fields, api class EstateProperty(models.Model): _name = "estate.property" @@ -74,4 +74,29 @@ class EstateProperty(models.Model): comodel_name="estate.property.offer", inverse_name="property_id", string="Offers", - ) \ No newline at end of file + ) + + # Computed fields + total_area = fields.Integer( + string="Total Area (sqm)", + compute="_compute_total_area", + store=False, + ) + best_price = fields.Float( + string="Best Offer", + compute="_compute_best_price", + store=False, + ) + + @api.depends("living_area", "garden_area") + def _compute_total_area(self) -> None: + for record in self: + living = record.living_area or 0 + garden = record.garden_area or 0 + record.total_area = living + garden + + @api.depends("offer_ids.price") + def _compute_best_price(self) -> None: + for record in self: + prices = record.offer_ids.mapped("price") + record.best_price = max(prices) if prices else 0.0 \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index b543a319517..23c79456117 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,5 @@ -from odoo import models, fields +from odoo import models, fields, api +from datetime import date, timedelta class EstatePropertyOffer(models.Model): @@ -13,3 +14,21 @@ 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(string="Validity (days)", default=7) + date_deadline = fields.Date(string="Deadline", compute="_compute_date_deadline", inverse="_inverse_date_deadline", store=False) + + @api.depends("validity", "create_date") + def _compute_date_deadline(self) -> None: + for offer in self: + created = (offer.create_date or fields.Datetime.now()) + base_date = created.date() if hasattr(created, "date") else date.today() + offer.date_deadline = base_date + timedelta(days=offer.validity or 0) + + def _inverse_date_deadline(self) -> None: + for offer in self: + created = (offer.create_date or fields.Datetime.now()) + base_date = created.date() if hasattr(created, "date") else date.today() + if offer.date_deadline: + delta = offer.date_deadline - base_date + offer.validity = max(delta.days, 0) diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index dd3d6a5a3d7..29d36266e8d 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -46,6 +46,14 @@ + + + + + + + + @@ -56,12 +64,16 @@ + + + + From 7fe65e550d07affa8f0bb08cda46d60bf3e78c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 14:26:56 +0200 Subject: [PATCH 20/53] Add onchange methods for validity and date_deadline in EstatePropertyOffer model, and implement onchange method for garden in EstateProperty model to automatically set garden area and orientation based on garden presence. --- estate/models/estate_property.py | 11 ++++++++++- estate/models/estate_property_offer.py | 17 +++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 75290a5bd7c..80190750f58 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -99,4 +99,13 @@ def _compute_total_area(self) -> None: def _compute_best_price(self) -> None: for record in self: prices = record.offer_ids.mapped("price") - record.best_price = max(prices) if prices else 0.0 \ No newline at end of file + record.best_price = max(prices) if prices else 0.0 + + @api.onchange("garden") + def _onchange_garden(self) -> None: + if self.garden: + self.garden_area = 10 + self.garden_orientation = "north" + else: + self.garden_area = 0 + self.garden_orientation = False \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 23c79456117..b0ce1d08ab0 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -32,3 +32,20 @@ def _inverse_date_deadline(self) -> None: if offer.date_deadline: delta = offer.date_deadline - base_date offer.validity = max(delta.days, 0) + + # Make the form reactive while editing (no need to wait for save) + @api.onchange("validity") + def _onchange_validity(self): + for offer in self: + created = (offer.create_date or fields.Datetime.now()) + base_date = created.date() if hasattr(created, "date") else date.today() + offer.date_deadline = base_date + timedelta(days=offer.validity or 0) + + @api.onchange("date_deadline") + def _onchange_date_deadline(self): + for offer in self: + if offer.date_deadline: + created = (offer.create_date or fields.Datetime.now()) + base_date = created.date() if hasattr(created, "date") else date.today() + delta = offer.date_deadline - base_date + offer.validity = max(delta.days, 0) From 6c5a82c20d4e571e00b25066eb0a6b485f883f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?AleccFilterPlusO=C3=9C?= Date: Tue, 16 Sep 2025 14:36:20 +0200 Subject: [PATCH 21/53] Add action methods for accepting and refusing offers in EstatePropertyOffer model, and implement cancellation and sold state actions in EstateProperty model. Update views to include new action buttons for improved user interaction. --- estate/models/estate_property.py | 18 ++++++++++++++++- estate/models/estate_property_offer.py | 21 ++++++++++++++++++++ estate/views/estate_property_offer_views.xml | 4 ++++ estate/views/estate_property_views.xml | 5 +++++ 4 files changed, 47 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 80190750f58..9b780f9df85 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,5 @@ from odoo import models, fields, api +from odoo.exceptions import UserError class EstateProperty(models.Model): _name = "estate.property" @@ -108,4 +109,19 @@ def _onchange_garden(self) -> None: self.garden_orientation = "north" else: self.garden_area = 0 - self.garden_orientation = False \ No newline at end of file + self.garden_orientation = False + + # Actions + def action_cancel(self): + for record in self: + if record.state == "sold": + raise UserError("A sold property cannot be cancelled.") + record.state = "cancelled" + return True + + def action_set_sold(self): + for record in self: + if record.state == "cancelled": + raise UserError("A cancelled property cannot be sold.") + record.state = "sold" + 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 b0ce1d08ab0..b85cc1a1b81 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,5 @@ from odoo import models, fields, api +from odoo.exceptions import UserError from datetime import date, timedelta @@ -49,3 +50,23 @@ def _onchange_date_deadline(self): base_date = created.date() if hasattr(created, "date") else date.today() delta = offer.date_deadline - base_date offer.validity = max(delta.days, 0) + + # Actions on offers + def action_accept(self): + for offer in self: + if offer.property_id.state == "sold": + raise UserError("Cannot accept an offer on a sold property.") + # set other offers to refused + siblings = offer.property_id.offer_ids - offer + siblings.write({"status": "refused"}) + offer.status = "accepted" + offer.property_id.write({ + "buyer_id": offer.partner_id.id, + "selling_price": offer.price, + "state": "offer_accepted", + }) + return True + + def action_refuse(self): + self.write({"status": "refused"}) + return True diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index 7fa07b279c3..c31a0e1516b 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -18,6 +18,10 @@
+
+
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 29d36266e8d..a3564cce95f 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -26,6 +26,11 @@ +
+
+ + +
diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index 99f11123822..7d6552e6037 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -4,7 +4,8 @@ estate.property.type.list estate.property.type - + + @@ -16,12 +17,30 @@
+
+
+ + + + + + + + + + + + + +
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 607e960291b..ae8771e59dd 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -5,7 +5,7 @@ estate.property.list estate.property - + @@ -14,7 +14,9 @@ - + + + @@ -48,8 +50,8 @@
- - + + @@ -65,10 +67,10 @@
- + - +