From 3458fe5df828cc6060fc0bc99184f634c626cef3 Mon Sep 17 00:00:00 2001 From: djhan Date: Tue, 18 Nov 2025 14:12:02 +0100 Subject: [PATCH 01/16] [ADD] estate: init --- estate/__init__.py | 0 estate/__manifest__.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 estate/__init__.py create mode 100644 estate/__manifest__.py diff --git a/estate/__init__.py b/estate/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/estate/__manifest__.py b/estate/__manifest__.py new file mode 100644 index 00000000000..2fe56ab9c71 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + + +{ + 'name': 'Estate', + 'version': '1.0', + 'category': 'Sales/Estate', + 'sequence': 15, + 'summary': 'Track all the properties you own', + 'website': 'https://www.odoo.com/app/estate', + 'depends': [ + 'base_setup', + 'sales_team', + 'mail', + 'calendar', + 'resource', + 'utm', + 'web_tour', + 'contacts', + 'digest', + 'phone_validation', + ], + 'data': [ + ], + 'demo': [ + ], + 'installable': True, + 'application': True, + 'assets': { + }, + 'author': 'Odoo S.A.', + 'license': 'LGPL-3', +} \ No newline at end of file From d929277073a5657e6d8018ea3e2fc67e358e6838 Mon Sep 17 00:00:00 2001 From: djhan Date: Tue, 18 Nov 2025 15:29:51 +0100 Subject: [PATCH 02/16] [ADD] estate: add estate.property model --- estate/__init__.py | 1 + estate/__manifest__.py | 11 +---------- estate/models/__init__.py | 1 + estate/models/estate_property.py | 23 +++++++++++++++++++++++ 4 files changed, 26 insertions(+), 10 deletions(-) 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..0650744f6bc 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 2fe56ab9c71..60be7e0ff95 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -10,16 +10,7 @@ 'summary': 'Track all the properties you own', 'website': 'https://www.odoo.com/app/estate', 'depends': [ - 'base_setup', - 'sales_team', - 'mail', - 'calendar', - 'resource', - 'utm', - 'web_tour', - 'contacts', - 'digest', - 'phone_validation', + 'base' ], '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..f5016f1bf2c --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,23 @@ +from odoo import models, fields + +class EstateProperty(models.Model): + _name = "estate.property" + _description = "Estate properties" + + + name = fields.Char('Property Name', required=True, translate=True) + description = fields.Text('Property Description', required=True) + postcode = fields.Char('Property postcode') + date_availability = fields.Date('Property availability date') + expected_price = fields.Float('Property expected price') + selling_price = fields.Float('Property selling price') + bedrooms = fields.Integer() + living_area = fields.Integer() + facades = fields.Integer() + garage = fields.Boolean() + garden = fields.Boolean() + garden_area = fields.Integer() + garden_orientation = fields.Selection( + string='Type', + selection=[('north', 'North'), ('south', 'South'), ('east','East'), ('west', 'West')]) + From 6b5c153c9bee8dae73a10a978b259a8919ff743f Mon Sep 17 00:00:00 2001 From: djhan Date: Tue, 18 Nov 2025 15:44:17 +0100 Subject: [PATCH 03/16] [FIX] estate: fix lint --- estate/__manifest__.py | 4 +--- estate/models/estate_property.py | 6 ++---- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 60be7e0ff95..31516c67368 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,7 +1,5 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. - { 'name': 'Estate', 'version': '1.0', @@ -22,4 +20,4 @@ }, 'author': 'Odoo S.A.', 'license': 'LGPL-3', -} \ No newline at end of file +} diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f5016f1bf2c..5982db6ab2d 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,10 +1,9 @@ from odoo import models, fields + class EstateProperty(models.Model): _name = "estate.property" _description = "Estate properties" - - name = fields.Char('Property Name', required=True, translate=True) description = fields.Text('Property Description', required=True) postcode = fields.Char('Property postcode') @@ -19,5 +18,4 @@ class EstateProperty(models.Model): garden_area = fields.Integer() garden_orientation = fields.Selection( string='Type', - selection=[('north', 'North'), ('south', 'South'), ('east','East'), ('west', 'West')]) - + selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) From d8510306e6e78b23752ae20b6d48120779f7f782 Mon Sep 17 00:00:00 2001 From: djhan Date: Wed, 19 Nov 2025 10:00:25 +0100 Subject: [PATCH 04/16] [IMP] estate: add ir rules --- estate/__manifest__.py | 1 + estate/security/ir.model.access.csv | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 31516c67368..3532c9ab553 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,6 +11,7 @@ 'base' ], 'data': [ + 'security/ir.model.access.csv' ], 'demo': [ ], 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 2b746610ca1945d01066da19e370c133f10ec490 Mon Sep 17 00:00:00 2001 From: djhan Date: Wed, 19 Nov 2025 11:37:39 +0100 Subject: [PATCH 05/16] [IMP] estate: add UI using default views --- estate/__manifest__.py | 4 +++- estate/models/estate_property.py | 15 +++++++++++---- estate/views/estate_menus.xml | 8 ++++++++ estate/views/estate_property_views.xml | 19 +++++++++++++++++++ 4 files changed, 41 insertions(+), 5 deletions(-) create mode 100644 estate/views/estate_menus.xml create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 3532c9ab553..ccf43706f57 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -11,7 +11,9 @@ 'base' ], 'data': [ - 'security/ir.model.access.csv' + 'security/ir.model.access.csv', + 'views/estate_property_views.xml', + 'views/estate_menus.xml' ], 'demo': [ ], diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 5982db6ab2d..ddb27a30d1b 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -7,15 +7,22 @@ class EstateProperty(models.Model): name = fields.Char('Property Name', required=True, translate=True) description = fields.Text('Property Description', required=True) postcode = fields.Char('Property postcode') - date_availability = fields.Date('Property availability date') + date_availability = fields.Date('Property availability date', copy=False, default=fields.Date.add(fields.Date.today(), months=3)) expected_price = fields.Float('Property expected price') - selling_price = fields.Float('Property selling price') - bedrooms = fields.Integer() + selling_price = fields.Float('Property selling price', readonly=True) + bedrooms = fields.Integer(default=2) + active = fields.Boolean(default=True) living_area = fields.Integer() facades = fields.Integer() garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() garden_orientation = fields.Selection( - string='Type', + string='Garden Orientation', selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) + state = fields.Selection( + string='State', + required=True, + default='new', + copy=False, + selection=[('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')]) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..579b3413f6f --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..184e974ca19 --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,19 @@ + + + + Estate Property + estate.property + list,form + +

+ List all your properties +

+

+ track thier rental state +

+

+ track thier mentainance +

+
+
+
\ No newline at end of file From f8f582cd5277c83587425acf8f62204dbac0e650 Mon Sep 17 00:00:00 2001 From: djhan Date: Wed, 19 Nov 2025 14:38:24 +0100 Subject: [PATCH 06/16] [IMP] estate: customize the view --- estate/__manifest__.py | 5 +- estate/models/estate_property.py | 23 ++++---- estate/views/estate_menus.xml | 2 +- estate/views/estate_property_views.xml | 81 +++++++++++++++++++++++++- 4 files changed, 96 insertions(+), 15 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ccf43706f57..ea863f3c9de 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -5,6 +5,9 @@ 'version': '1.0', 'category': 'Sales/Estate', 'sequence': 15, + 'description': """ + This module is here to help you manage your real estate business. + """, 'summary': 'Track all the properties you own', 'website': 'https://www.odoo.com/app/estate', 'depends': [ @@ -19,8 +22,6 @@ ], 'installable': True, 'application': True, - 'assets': { - }, 'author': 'Odoo S.A.', 'license': 'LGPL-3', } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index ddb27a30d1b..b266c0183fc 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -4,19 +4,20 @@ class EstateProperty(models.Model): _name = "estate.property" _description = "Estate properties" - name = fields.Char('Property Name', required=True, translate=True) - description = fields.Text('Property Description', required=True) - postcode = fields.Char('Property postcode') - date_availability = fields.Date('Property availability date', copy=False, default=fields.Date.add(fields.Date.today(), months=3)) - expected_price = fields.Float('Property expected price') - selling_price = fields.Float('Property selling price', readonly=True) + + name = fields.Char('Name', required=True, translate=True) + description = fields.Text('Description', required=True) + postcode = fields.Char('Postcode') + date_availability = fields.Date('Available From', copy=False, default=fields.Date.add(fields.Date.today(), months=3)) + expected_price = fields.Float('Expected Price') + selling_price = fields.Float('Selling Price', readonly=True) bedrooms = fields.Integer(default=2) active = fields.Boolean(default=True) - living_area = fields.Integer() - facades = fields.Integer() - garage = fields.Boolean() - garden = fields.Boolean() - garden_area = fields.Integer() + living_area = fields.Integer('Living Area (sqm)') + facades = fields.Integer('Facades') + garage = fields.Boolean('Garage') + garden = fields.Boolean('Garden') + garden_area = fields.Float('Garden Area (sqm)') garden_orientation = fields.Selection( string='Garden Orientation', selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')]) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 579b3413f6f..cfd8dc8a797 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -5,4 +5,4 @@ - \ No newline at end of file + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 184e974ca19..b352257ccc1 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,5 +1,84 @@ + + estate.property.search + estate.property + + + + + + + + + + + + + + + + + + + estate.property.form + estate.property + +
+ +
+

+ +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + estate.property.list + estate.property + + + + + + + + + + + + + Estate Property estate.property @@ -16,4 +95,4 @@

-
\ No newline at end of file + From 9803b98455d0741526ef5fa411f9692f87c4d365 Mon Sep 17 00:00:00 2001 From: djhan Date: Wed, 19 Nov 2025 16:03:16 +0100 Subject: [PATCH 07/16] [IMP] estate: add property types --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 1 + estate/models/estate_property_type.py | 8 ++++++ estate/security/ir.model.access.csv | 2 ++ estate/views/estate_menus.xml | 5 +++- estate/views/estate_property_type_views.xml | 29 +++++++++++++++++++++ estate/views/estate_property_views.xml | 11 ++++---- 8 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ea863f3c9de..f1d36ce59a3 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -16,6 +16,7 @@ 'data': [ 'security/ir.model.access.csv', 'views/estate_property_views.xml', + 'views/estate_property_type_views.xml', 'views/estate_menus.xml' ], 'demo': [ diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..97aee757823 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,2 @@ from . import estate_property +from . import estate_property_type \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b266c0183fc..ed0a803bf0d 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -27,3 +27,4 @@ class EstateProperty(models.Model): default='new', copy=False, selection=[('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')]) + property_type_id = fields.Many2one("estate.property.type", "Type") diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..d23aef9fd84 --- /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 properties Types" + + name = fields.Char('Name', required=True, translate=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 32389642d4f..eff4c41cdda 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +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 + diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index cfd8dc8a797..21eae23dd0b 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -4,5 +4,8 @@ + + + - + \ 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..adfe885fb82 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,29 @@ + + + + estate.property.type.form + estate.property.type + +
+ +
+

+ +

+
+
+
+
+
+ + + Estate Property Types + estate.property.type + list,form + +

+ A property type is, for example, a house or an apartment. +

+
+
+
\ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index b352257ccc1..fe111bffec2 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -6,6 +6,7 @@ + @@ -14,10 +15,8 @@ - - - + @@ -35,6 +34,7 @@ + @@ -69,6 +69,7 @@ + @@ -95,4 +96,4 @@

- + \ No newline at end of file From 4bd2716ea335b09dbe909ab3fb86f1daba3f19d6 Mon Sep 17 00:00:00 2001 From: djhan Date: Wed, 19 Nov 2025 16:25:36 +0100 Subject: [PATCH 08/16] [FIX] estate: fix lint --- estate/models/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 97aee757823..40092a2d810 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,2 +1,2 @@ from . import estate_property -from . import estate_property_type \ No newline at end of file +from . import estate_property_type From 98dc4fc4e223e726c6d9d9b72c0812644c0b37cf Mon Sep 17 00:00:00 2001 From: djhan Date: Wed, 19 Nov 2025 17:13:34 +0100 Subject: [PATCH 09/16] [IMP] estate: add tags --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 4 +++ estate/models/estate_property_tag.py | 8 ++++++ estate/security/ir.model.access.csv | 2 ++ estate/views/estate_menus.xml | 3 ++- estate/views/estate_property_tag_views.xml | 29 ++++++++++++++++++++++ estate/views/estate_property_views.xml | 9 ++++++- 8 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 estate/models/estate_property_tag.py create mode 100644 estate/views/estate_property_tag_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index f1d36ce59a3..0bbc7cc73e8 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -17,6 +17,7 @@ 'security/ir.model.access.csv', 'views/estate_property_views.xml', 'views/estate_property_type_views.xml', + 'views/estate_property_tag_views.xml', 'views/estate_menus.xml' ], 'demo': [ 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 ed0a803bf0d..b94aaa9ec2c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -28,3 +28,7 @@ class EstateProperty(models.Model): copy=False, selection=[('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')]) property_type_id = fields.Many2one("estate.property.type", "Type") + property_tags_ids = fields.Many2many("estate.property.tag", "Tags") + sales_person_id = fields.Many2one('res.users', string='Salesperson', default=lambda self: self.env.user) + buyer_id = fields.Many2one('res.partner', string='Buyer', copy=False) + diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..2b7649b7fdd --- /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 properties Tags" + + name = fields.Char('Name', required=True, translate=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index eff4c41cdda..ec12e57436d 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,4 +1,6 @@ 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 21eae23dd0b..f0591a1d1aa 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -6,6 +6,7 @@
+ - \ 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..0f82ede750c --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,29 @@ + + + + estate.property.tag.form + estate.property.tag + +
+ +
+

+ +

+
+
+
+
+
+ + + Estate Property Tags + estate.property.tag + list,form + +

+ Property Tags. +

+
+
+
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index fe111bffec2..a903283f4e0 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -31,6 +31,7 @@

+ @@ -57,6 +58,12 @@ + + + + + + @@ -96,4 +103,4 @@

- \ No newline at end of file + From b5aaaa7e445b3f052e6e2a0f93b5048b1ac98cf7 Mon Sep 17 00:00:00 2001 From: djhan Date: Thu, 20 Nov 2025 10:10:42 +0100 Subject: [PATCH 10/16] [IMP] estate: add offers --- estate/__manifest__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 2 +- estate/models/estate_property_offer.py | 14 ++++++++++ estate/security/ir.model.access.csv | 3 +-- estate/views/estate_property_offer_views.xml | 28 ++++++++++++++++++++ estate/views/estate_property_type_views.xml | 2 +- estate/views/estate_property_views.xml | 5 ++++ 8 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 estate/models/estate_property_offer.py create mode 100644 estate/views/estate_property_offer_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 0bbc7cc73e8..aa92c004563 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -18,6 +18,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' ], 'demo': [ 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 b94aaa9ec2c..68f19611978 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -31,4 +31,4 @@ class EstateProperty(models.Model): property_tags_ids = fields.Many2many("estate.property.tag", "Tags") sales_person_id = fields.Many2one('res.users', string='Salesperson', default=lambda self: self.env.user) buyer_id = fields.Many2one('res.partner', string='Buyer', copy=False) - + offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..6fe7e5aa46d --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,14 @@ +from odoo import models, fields + + +class EstatePropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Estate properties Offers" + + price = fields.Float('Price') + status = fields.Selection( + string='Status', + copy=False, + selection=[('accepted', 'Accepted'), ('refused', 'Refused')]) + partner_id = fields.Many2one('res.partner', string='Buyer', required=True) + property_id = fields.Many2one('estate.property', string='Buyer', required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index ec12e57436d..89f97c50842 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -2,5 +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..e2ee374fda1 --- /dev/null +++ b/estate/views/estate_property_offer_views.xml @@ -0,0 +1,28 @@ + + + + estate.property.offer.form + estate.property.offer + +
+ + + + + +
+
+
+ + + estate.property.offer.list + estate.property.offer + + + + + + + + +
diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml index adfe885fb82..7a191070c71 100644 --- a/estate/views/estate_property_type_views.xml +++ b/estate/views/estate_property_type_views.xml @@ -26,4 +26,4 @@

- \ No newline at end of file + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index a903283f4e0..2ffc5945c4a 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -58,6 +58,11 @@ + + + + + From 9b190ce2915963ef2bb0111332f8e0edd0fcc9f7 Mon Sep 17 00:00:00 2001 From: djhan Date: Thu, 20 Nov 2025 13:31:41 +0100 Subject: [PATCH 11/16] [IMP] estate: add computed fields --- estate/models/estate_property.py | 23 +++++++++++++++++++- estate/models/estate_property_offer.py | 15 +++++++++++-- estate/views/estate_property_offer_views.xml | 6 ++++- estate/views/estate_property_views.xml | 2 ++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 68f19611978..8be2cb5d6ba 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): @@ -32,3 +32,24 @@ class EstateProperty(models.Model): sales_person_id = fields.Many2one('res.users', string='Salesperson', default=lambda self: self.env.user) buyer_id = fields.Many2one('res.partner', string='Buyer', copy=False) offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") + total_area = fields.Float('Total Area', compute='_compute_total_area') + best_price = fields.Float('Best Offer', compute='_compute_best_price') + + @api.depends('garden_area', 'living_area') + def _compute_total_area(self): + for record in self: + record.total_area = record.garden_area + record.living_area + + @api.depends('offer_ids.price') + def _compute_best_price(self): + for record in self: + record.best_price = max(record.offer_ids, key=lambda p: p.price).price + + @api.onchange('garden') + def _onchange_garden(self): + if not self.garden: + self.garden_area = None + self.garden_orientation = None + else: + self.garden_area = 10 + self.garden_orientation = 'north' \ No newline at end of file diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 6fe7e5aa46d..fd37df848fd 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,4 @@ -from odoo import models, fields +from odoo import models, fields ,api class EstatePropertyOffer(models.Model): @@ -11,4 +11,15 @@ class EstatePropertyOffer(models.Model): copy=False, selection=[('accepted', 'Accepted'), ('refused', 'Refused')]) partner_id = fields.Many2one('res.partner', string='Buyer', required=True) - property_id = fields.Many2one('estate.property', string='Buyer', required=True) + property_id = fields.Many2one('estate.property', string='Estate Property', required=True) + validity = fields.Integer('Validity', default=7) + date_deadline = fields.Datetime('Deadline', compute='_compute_date_deadline', inverse='_inverse_date_deadline') + + @api.depends('validity', 'create_date') + def _compute_date_deadline(self): + for record in self: + record.date_deadline = fields.Date.add(record.create_date, days=record.validity) + + def _inverse_date_deadline(self): + for record in self: + record.validity = (record.date_deadline - record.create_date).days diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index e2ee374fda1..945fde8c9fc 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -9,6 +9,8 @@ + + @@ -22,7 +24,9 @@ + + - + \ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 2ffc5945c4a..0cb5291afca 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -41,6 +41,7 @@ + @@ -56,6 +57,7 @@ + From 5d4a3ff5b1958be09da307948ef8a11725b82e34 Mon Sep 17 00:00:00 2001 From: djhan Date: Thu, 20 Nov 2025 14:37:38 +0100 Subject: [PATCH 12/16] [IMP] estate: add actions --- estate/models/estate_property.py | 20 +++++++++++++++++-- estate/models/estate_property_offer.py | 21 ++++++++++++++++++-- estate/views/estate_property_offer_views.xml | 4 +++- estate/views/estate_property_views.xml | 8 ++++++-- 4 files changed, 46 insertions(+), 7 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 8be2cb5d6ba..301e77f1227 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,4 @@ -from odoo import models, fields, api +from odoo import models, fields, api, exceptions class EstateProperty(models.Model): @@ -52,4 +52,20 @@ def _onchange_garden(self): self.garden_orientation = None else: self.garden_area = 10 - self.garden_orientation = 'north' \ No newline at end of file + self.garden_orientation = 'north' + + def action_cancel_property(self): + for record in self: + if record.state == 'sold': + raise exceptions.UserError('Sold properties cannot be cancelled') + else: + record.state = 'cancelled' + return True + + def action_sold_property(self): + for record in self: + if record.state == 'cancelled': + raise exceptions.UserError('Cancelled properties cannot be sold') + else: + 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 fd37df848fd..3cb2c9753ac 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,4 @@ -from odoo import models, fields ,api +from odoo import models, fields ,api, exceptions class EstatePropertyOffer(models.Model): @@ -8,8 +8,9 @@ class EstatePropertyOffer(models.Model): price = fields.Float('Price') status = fields.Selection( string='Status', + default='new', copy=False, - selection=[('accepted', 'Accepted'), ('refused', 'Refused')]) + selection=[('accepted', 'Accepted'), ('refused', 'Refused'), ('new', 'New')]) partner_id = fields.Many2one('res.partner', string='Buyer', required=True) property_id = fields.Many2one('estate.property', string='Estate Property', required=True) validity = fields.Integer('Validity', default=7) @@ -23,3 +24,19 @@ def _compute_date_deadline(self): def _inverse_date_deadline(self): for record in self: record.validity = (record.date_deadline - record.create_date).days + + def action_accept_offer(self): + if any(record.status == 'accepted' for record in self.property_id.offer_ids): + raise exceptions.UserError('An offer is already accepted for this property') + for record in self: + record.status = 'accepted' + record.property_id.buyer_id = record.partner_id + record.property_id.selling_price = record.price + return True + + def action_refuse_offer(self): + for record in self: + if record.status == 'accepted': + raise exceptions.UserError('You cant refuse an already accepted offer') + record.status = 'refused' + return True diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml index 945fde8c9fc..4614f43d97a 100644 --- a/estate/views/estate_property_offer_views.xml +++ b/estate/views/estate_property_offer_views.xml @@ -22,10 +22,12 @@ - +