From 51a3f8830a0a5e03de20bc4591944a0bdd3d17de Mon Sep 17 00:00:00 2001 From: ngtpn Date: Tue, 18 Nov 2025 10:14:17 +0100 Subject: [PATCH 01/19] [ADD] estate: Add module --- estate/__init__.py | 0 estate/__manifest__.py | 10 ++++++++++ 2 files changed, 10 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..19d1621f0ba --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': "Real Estate", + 'version': '1.0', + 'depends': ['base'], + 'author': "ngtpn", + 'category': 'Category', + 'description': """ + Real Estate Advertisement module + """, +} From a184c4a5aaa2f45d85aadb0609dbdb812a235828 Mon Sep 17 00:00:00 2001 From: ngtpn Date: Tue, 18 Nov 2025 15:01:31 +0100 Subject: [PATCH 02/19] [IMP] estate: Add name / expected price to property model --- estate/__init__.py | 1 + estate/models/__init__.py | 1 + estate/models/estate_property.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 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..0650744f6bc 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1 @@ +from . import models 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..8ff5319e297 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,28 @@ +from odoo import fields, models + + +class Property(models.Model): + _name = "estate.property" + _description = "All properties" + + 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( + string='Garden orientation', + selection=[ + ('north', 'North'), + ('south', 'South'), + ('east', 'East'), + ('west', 'West'), + ], + ) From 6500c2ab2b841609f41fd1573de3328cf3f9fd52 Mon Sep 17 00:00:00 2001 From: ngtpn Date: Tue, 18 Nov 2025 15:24:48 +0100 Subject: [PATCH 03/19] [IMP] estate: Add access right --- estate/__manifest__.py | 3 +++ estate/security/ir.model.access.csv | 2 ++ 2 files changed, 5 insertions(+) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 19d1621f0ba..653d794bd13 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -7,4 +7,7 @@ 'description': """ Real Estate Advertisement module """, + 'data': [ + 'security/ir.model.access.csv', + ], } 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 812c7c19a999c8e14b358e168977735ae7b67d3c Mon Sep 17 00:00:00 2001 From: ngtpn Date: Tue, 18 Nov 2025 15:26:52 +0100 Subject: [PATCH 04/19] [IMP] estate: Add UIs / Update fields --- estate/__manifest__.py | 3 +++ estate/models/estate_property.py | 23 ++++++++++++++++++++--- estate/views/estate_menus.xml | 7 +++++++ estate/views/estate_property_views.xml | 7 +++++++ 4 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 estate/views/estate_menus.xml create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 653d794bd13..3b7b1a22b84 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,5 +1,6 @@ { 'name': "Real Estate", + 'license': 'LGPL-3', 'version': '1.0', 'depends': ['base'], 'author': "ngtpn", @@ -9,5 +10,7 @@ """, 'data': [ 'security/ir.model.access.csv', + 'views/estate_property_views.xml', + 'views/estate_menus.xml', ], } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 8ff5319e297..86828384650 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,5 @@ from odoo import fields, models +from dateutil.relativedelta import relativedelta class Property(models.Model): @@ -8,10 +9,13 @@ class Property(models.Model): name = fields.Char(required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date() + date_availability = fields.Date( + copy=False, + default=fields.Datetime.today() + relativedelta(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() @@ -26,3 +30,16 @@ class Property(models.Model): ('west', 'West'), ], ) + active = fields.Boolean(default=True) + state = fields.Selection( + string='State', + required=True, + default='new', + 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..346daf55f7b --- /dev/null +++ b/estate/views/estate_menus.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..57ed16dac1f --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,7 @@ + + + Properties + estate.property + list,form + + From 99bba1fa3beadab2fdd6485022f244307b47a60c Mon Sep 17 00:00:00 2001 From: ngtpn Date: Wed, 19 Nov 2025 10:01:33 +0100 Subject: [PATCH 05/19] [IMP] estate: Fix xml indentation --- estate/views/estate_menus.xml | 10 +++++----- estate/views/estate_property_views.xml | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 346daf55f7b..fc9d132180a 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,7 +1,7 @@ - - - - - + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 57ed16dac1f..4d544c18597 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 + From f5deed012b666e951fa1d0f40ec3e6382cdcd7ed Mon Sep 17 00:00:00 2001 From: ngtpn Date: Wed, 19 Nov 2025 10:02:11 +0100 Subject: [PATCH 06/19] [IMP] estate: Use date helper / Rename model --- estate/__manifest__.py | 3 ++- estate/models/estate_property.py | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 3b7b1a22b84..2a807519a79 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,11 +3,12 @@ 'license': 'LGPL-3', 'version': '1.0', 'depends': ['base'], - 'author': "ngtpn", + 'author': "Odoo S.A.", 'category': 'Category', 'description': """ Real Estate Advertisement module """, + 'application': True, 'data': [ 'security/ir.model.access.csv', 'views/estate_property_views.xml', diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 86828384650..67da8661949 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,8 +1,7 @@ from odoo import fields, models -from dateutil.relativedelta import relativedelta -class Property(models.Model): +class EstateProperty(models.Model): _name = "estate.property" _description = "All properties" @@ -11,7 +10,7 @@ class Property(models.Model): postcode = fields.Char() date_availability = fields.Date( copy=False, - default=fields.Datetime.today() + relativedelta(months=+3), + default=fields.Date.add(fields.Date.today(), months=3), ) expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) From 2ca404233368afe056c346687cda06ce95ff1a47 Mon Sep 17 00:00:00 2001 From: ngtpn Date: Wed, 19 Nov 2025 10:30:51 +0100 Subject: [PATCH 07/19] [IMP] estate: Add list / form / search UI --- estate/__manifest__.py | 7 ++- estate/views/estate_menus.xml | 2 +- estate/views/estate_property_form_views.xml | 44 +++++++++++++++++++ estate/views/estate_property_list_views.xml | 17 +++++++ estate/views/estate_property_search_views.xml | 22 ++++++++++ 5 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 estate/views/estate_property_form_views.xml create mode 100644 estate/views/estate_property_list_views.xml create mode 100644 estate/views/estate_property_search_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 2a807519a79..4d403e49f93 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,9 +1,9 @@ { - 'name': "Real Estate", + 'name': 'Real Estate', 'license': 'LGPL-3', 'version': '1.0', 'depends': ['base'], - 'author': "Odoo S.A.", + 'author': 'Odoo S.A.', 'category': 'Category', 'description': """ Real Estate Advertisement module @@ -13,5 +13,8 @@ 'security/ir.model.access.csv', 'views/estate_property_views.xml', 'views/estate_menus.xml', + 'views/estate_property_list_views.xml', + 'views/estate_property_form_views.xml', + 'views/estate_property_search_views.xml', ], } diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index fc9d132180a..9d4fd8d1c7a 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,6 +1,6 @@ - + diff --git a/estate/views/estate_property_form_views.xml b/estate/views/estate_property_form_views.xml new file mode 100644 index 00000000000..22887798fb3 --- /dev/null +++ b/estate/views/estate_property_form_views.xml @@ -0,0 +1,44 @@ + + + estate.property.form + estate.property + +
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
diff --git a/estate/views/estate_property_list_views.xml b/estate/views/estate_property_list_views.xml new file mode 100644 index 00000000000..43fae5ae820 --- /dev/null +++ b/estate/views/estate_property_list_views.xml @@ -0,0 +1,17 @@ + + + estate.property.list + estate.property + + + + + + + + + + + + + diff --git a/estate/views/estate_property_search_views.xml b/estate/views/estate_property_search_views.xml new file mode 100644 index 00000000000..c18a402c02c --- /dev/null +++ b/estate/views/estate_property_search_views.xml @@ -0,0 +1,22 @@ + + + estate.property.search + estate.property + + + + + + + + + + + + + + + + + + From 719f23ac72ebd3582dd4176bb6bcd663750ce0e2 Mon Sep 17 00:00:00 2001 From: ngtpn Date: Wed, 19 Nov 2025 11:06:34 +0100 Subject: [PATCH 08/19] [IMP] estate: Add perperty type / tag / offer --- estate/__manifest__.py | 4 +++ estate/models/__init__.py | 3 +++ estate/models/estate_property.py | 16 ++++++++++-- estate/models/estate_property_offer.py | 17 ++++++++++++ estate/models/estate_property_tag.py | 8 ++++++ estate/models/estate_property_type.py | 8 ++++++ estate/security/ir.model.access.csv | 3 +++ estate/views/estate_menus.xml | 4 +++ estate/views/estate_property_form_views.xml | 13 +++++++++- estate/views/estate_property_list_views.xml | 2 ++ .../estate_property_offer_form_views.xml | 26 +++++++++++++++++++ .../estate_property_offer_list_views.xml | 14 ++++++++++ estate/views/estate_property_search_views.xml | 1 + estate/views/estate_property_tag_views.xml | 7 +++++ estate/views/estate_property_type_views.xml | 7 +++++ 15 files changed, 130 insertions(+), 3 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_form_views.xml create mode 100644 estate/views/estate_property_offer_list_views.xml create mode 100644 estate/views/estate_property_tag_views.xml create mode 100644 estate/views/estate_property_type_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 4d403e49f93..7128f366854 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -12,9 +12,13 @@ '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_list_views.xml', 'views/estate_property_form_views.xml', 'views/estate_property_search_views.xml', + 'views/estate_property_offer_list_views.xml', + 'views/estate_property_offer_form_views.xml', ], } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..2f1821a39c1 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,4 @@ from . import estate_property +from . import estate_property_type +from . import estate_property_tag +from . import estate_property_offer diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 67da8661949..cc2df50111c 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -2,8 +2,8 @@ class EstateProperty(models.Model): - _name = "estate.property" - _description = "All properties" + _name = 'estate.property' + _description = 'All properties' name = fields.Char(required=True) description = fields.Text() @@ -42,3 +42,15 @@ class EstateProperty(models.Model): ('cancelled', 'Cancelled'), ], ) + property_type_id = fields.Many2one( + 'estate.property.type', string='Property Type' + ) + buyer_id = fields.Many2one( + 'res.partner', string='Buyer', copy=False, + ) + salesperson_id = fields.Many2one( + 'res.users', string='Salesperson', + default=lambda self: self.env.user, + ) + tag_ids = fields.Many2many('estate.property.tag', string='Tags') + offer_ids = fields.One2many('estate.property.offer', 'property_id', string='Offers') diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..e293504e6a7 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,17 @@ +from odoo import fields, models + + +class EstatePropertyOffer(models.Model): + _name = 'estate.property.offer' + _description = 'All offers' + + price = fields.Float(required=True) + status = fields.Selection( + string='Status', + selection=[ + ('accepted', 'Accepted'), + ('refused', 'Refused'), + ], + ) + partner_id = fields.Many2one('res.partner', string='Partner') + property_id = fields.Many2one('estate.property', string='Property') diff --git a/estate/models/estate_property_tag.py b/estate/models/estate_property_tag.py new file mode 100644 index 00000000000..23a0b4b5180 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyTag(models.Model): + _name = 'estate.property.tag' + _description = 'All 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..06a5e441fdf --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class EstatePropertyType(models.Model): + _name = 'estate.property.type' + _description = 'All property types' + + name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 32389642d4f..89f97c50842 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 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_menus.xml b/estate/views/estate_menus.xml index 9d4fd8d1c7a..9be236faae9 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -3,5 +3,9 @@
diff --git a/estate/views/estate_property_form_views.xml b/estate/views/estate_property_form_views.xml index 22887798fb3..ac7698e34e5 100644 --- a/estate/views/estate_property_form_views.xml +++ b/estate/views/estate_property_form_views.xml @@ -9,6 +9,12 @@ + + + + + + @@ -33,7 +39,12 @@ - + + + + + + diff --git a/estate/views/estate_property_list_views.xml b/estate/views/estate_property_list_views.xml index 43fae5ae820..bf378601786 100644 --- a/estate/views/estate_property_list_views.xml +++ b/estate/views/estate_property_list_views.xml @@ -11,6 +11,8 @@ + + diff --git a/estate/views/estate_property_offer_form_views.xml b/estate/views/estate_property_offer_form_views.xml new file mode 100644 index 00000000000..2e8417d37b2 --- /dev/null +++ b/estate/views/estate_property_offer_form_views.xml @@ -0,0 +1,26 @@ + + + estate.property.offer.form + estate.property.offer + +
+ + + + + + + + + + + + + + + + +
+
+
+
diff --git a/estate/views/estate_property_offer_list_views.xml b/estate/views/estate_property_offer_list_views.xml new file mode 100644 index 00000000000..4d8261cd6f8 --- /dev/null +++ b/estate/views/estate_property_offer_list_views.xml @@ -0,0 +1,14 @@ + + + estate.property.offer.list + estate.property.offer + + + + + + + + + + diff --git a/estate/views/estate_property_search_views.xml b/estate/views/estate_property_search_views.xml index c18a402c02c..1590db1878c 100644 --- a/estate/views/estate_property_search_views.xml +++ b/estate/views/estate_property_search_views.xml @@ -10,6 +10,7 @@ + diff --git a/estate/views/estate_property_tag_views.xml b/estate/views/estate_property_tag_views.xml new file mode 100644 index 00000000000..bbb5013739c --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,7 @@ + + + Property Tags + estate.property.tag + list,form + + diff --git a/estate/views/estate_property_type_views.xml b/estate/views/estate_property_type_views.xml new file mode 100644 index 00000000000..382925bd424 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,7 @@ + + + Property Types + estate.property.type + list,form + + From 5051e18be46d38c1c459ae5e3b4d08519f791c02 Mon Sep 17 00:00:00 2001 From: ngtpn Date: Wed, 19 Nov 2025 13:51:07 +0100 Subject: [PATCH 09/19] [IMP] estate: Compute / Inverse field value --- estate/models/estate_property.py | 31 ++++++++++++++++--- estate/models/estate_property_offer.py | 17 +++++++++- estate/views/estate_property_form_views.xml | 13 ++++++-- .../estate_property_offer_form_views.xml | 6 ++++ .../estate_property_offer_list_views.xml | 4 ++- 5 files changed, 63 insertions(+), 8 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index cc2df50111c..0628caeceb6 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 api, fields, models class EstateProperty(models.Model): @@ -14,12 +14,14 @@ class EstateProperty(models.Model): ) expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) + best_price = fields.Float(compute='_compute_best_price') bedrooms = fields.Integer(default=2) living_area = fields.Integer() + garden_area = fields.Integer() + total_area = fields.Integer(compute='_compute_total_area') facades = fields.Integer() garage = fields.Boolean() garden = fields.Boolean() - garden_area = fields.Integer() garden_orientation = fields.Selection( string='Garden orientation', selection=[ @@ -41,9 +43,9 @@ class EstateProperty(models.Model): ('sold', 'Sold'), ('cancelled', 'Cancelled'), ], - ) + ) property_type_id = fields.Many2one( - 'estate.property.type', string='Property Type' + 'estate.property.type', string='Property Type', ) buyer_id = fields.Many2one( 'res.partner', string='Buyer', copy=False, @@ -54,3 +56,24 @@ class EstateProperty(models.Model): ) tag_ids = fields.Many2many('estate.property.tag', string='Tags') offer_ids = fields.One2many('estate.property.offer', 'property_id', string='Offers') + + @api.depends('living_area', 'garden_area') + def _compute_total_area(self): + for record in self: + living_area = record.living_area or 0 + garden_area = record.garden_area or 0 + record.total_area = living_area + garden_area + + @api.depends('offer_ids') + def _compute_best_price(self): + for record in self: + record.best_price = max(record.offer_ids.mapped('price')) if self.offer_ids else 0 + + @api.onchange('garden') + def _onchange_garden(self): + if self.garden: + self.garden_area = 10 + self.garden_orientation = 'north' + else: + self.garden_area = None + self.garden_orientation = None diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index e293504e6a7..3dddfd66a42 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 api, fields, models class EstatePropertyOffer(models.Model): @@ -15,3 +15,18 @@ class EstatePropertyOffer(models.Model): ) partner_id = fields.Many2one('res.partner', string='Partner') property_id = fields.Many2one('estate.property', string='Property') + validity = fields.Integer(default=7) + date_deadline = fields.Date(compute='_compute_deadline', inverse="_inverse_deadline") + + @api.depends('create_date', 'validity') + def _compute_deadline(self): + for record in self: + created_date = record.create_date or fields.Date.today() + record.date_deadline = fields.Date.add( + created_date, days=record.validity, + ) + + def _inverse_deadline(self): + for record in self: + created_date = record.create_date.date() or fields.Date.today() + record.validity = (record.date_deadline - created_date).days diff --git a/estate/views/estate_property_form_views.xml b/estate/views/estate_property_form_views.xml index ac7698e34e5..c3eac4e9d8f 100644 --- a/estate/views/estate_property_form_views.xml +++ b/estate/views/estate_property_form_views.xml @@ -27,18 +27,27 @@ + + + - + - + + + + + + + diff --git a/estate/views/estate_property_offer_form_views.xml b/estate/views/estate_property_offer_form_views.xml index 2e8417d37b2..4dfcfa7d40c 100644 --- a/estate/views/estate_property_offer_form_views.xml +++ b/estate/views/estate_property_offer_form_views.xml @@ -18,6 +18,12 @@ + + + + + + diff --git a/estate/views/estate_property_offer_list_views.xml b/estate/views/estate_property_offer_list_views.xml index 4d8261cd6f8..16dd7f33869 100644 --- a/estate/views/estate_property_offer_list_views.xml +++ b/estate/views/estate_property_offer_list_views.xml @@ -5,8 +5,10 @@ - + + + From 9deb1644e2bd9046f4ba81389f7642c4fe5b99df Mon Sep 17 00:00:00 2001 From: ngtpn Date: Wed, 19 Nov 2025 15:01:33 +0100 Subject: [PATCH 10/19] [IMP] estate: Add actions --- estate/models/estate_property.py | 15 +++++++++++++ estate/models/estate_property_offer.py | 22 +++++++++++++++++++ estate/views/estate_property_form_views.xml | 18 +++++++++++++++ .../estate_property_offer_list_views.xml | 3 ++- 4 files changed, 57 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 0628caeceb6..f97850ec9ca 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,5 @@ from odoo import api, fields, models +from odoo.exceptions import UserError class EstateProperty(models.Model): @@ -77,3 +78,17 @@ def _onchange_garden(self): else: self.garden_area = None self.garden_orientation = None + + def action_mark_as_sold(self): + for record in self: + if record.state == 'cancelled': + raise UserError('Property is already cancelled') + + record.state = 'sold' + + def action_mark_as_cancelled(self): + for record in self: + if record.state == 'sold': + raise UserError('Property is already sold') + + record.state = 'cancelled' diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py index 3dddfd66a42..d7a1f232c24 100644 --- a/estate/models/estate_property_offer.py +++ b/estate/models/estate_property_offer.py @@ -1,4 +1,5 @@ from odoo import api, fields, models +from odoo.exceptions import UserError class EstatePropertyOffer(models.Model): @@ -30,3 +31,24 @@ def _inverse_deadline(self): for record in self: created_date = record.create_date.date() or fields.Date.today() record.validity = (record.date_deadline - created_date).days + + def action_mark_as_accepted(self): + for record in self: + if ( + record.property_id.state != 'new' + and record.property_id.state != 'offer_received' + ): + raise UserError('Cannot accept offer in this state') + + record.status = 'accepted' + record.property_id.selling_price = record.price + record.property_id.buyer_id = record.partner_id + record.property_id.state = 'offer_accepted' + + def action_mark_as_refused(self): + for record in self: + if record.status == 'accepted': + record.property_id.state = 'offer_received' + record.property_id.selling_price = None + record.property_id.buyer_id = None + record.status = 'refused' diff --git a/estate/views/estate_property_form_views.xml b/estate/views/estate_property_form_views.xml index c3eac4e9d8f..3363cf4a399 100644 --- a/estate/views/estate_property_form_views.xml +++ b/estate/views/estate_property_form_views.xml @@ -4,6 +4,21 @@ estate.property
+
+

@@ -12,6 +27,9 @@ + + + diff --git a/estate/views/estate_property_offer_list_views.xml b/estate/views/estate_property_offer_list_views.xml index 16dd7f33869..668096060a2 100644 --- a/estate/views/estate_property_offer_list_views.xml +++ b/estate/views/estate_property_offer_list_views.xml @@ -8,8 +8,9 @@ +