From 6c73646aa3cc96613a7ff6ff949a439ae438c743 Mon Sep 17 00:00:00 2001 From: Shijakov Date: Mon, 20 Jul 2026 14:45:23 +0200 Subject: [PATCH 1/8] Create basis for Real Estate 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..4cd6ae67fa9 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': "Real Estate", + 'version': '1.0', + 'depends': ['base'], + 'author': "Author Name", + 'category': 'Category', + 'description': """ + Description text + """, +} \ No newline at end of file From fa054848460941aee254602ef27cb6a455020bc0 Mon Sep 17 00:00:00 2001 From: Shijakov Date: Mon, 20 Jul 2026 15:50:48 +0200 Subject: [PATCH 2/8] Make 'Real Estate' an application module --- estate/__manifest__.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 4cd6ae67fa9..4fff962889d 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -2,9 +2,5 @@ 'name': "Real Estate", 'version': '1.0', 'depends': ['base'], - 'author': "Author Name", - 'category': 'Category', - 'description': """ - Description text - """, + 'application': True, } \ No newline at end of file From cdb95285942aa6a293dee7f574ee3923c73c4b2e Mon Sep 17 00:00:00 2001 From: Shijakov Date: Mon, 20 Jul 2026 17:08:36 +0200 Subject: [PATCH 3/8] Create model for Estate Property --- .gitignore | 2 ++ estate/__init__.py | 3 +++ estate/models/__init__.py | 1 + estate/models/estate_property.py | 40 ++++++++++++++++++++++++++++++++ 4 files changed, 46 insertions(+) create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py diff --git a/.gitignore b/.gitignore index b6e47617de1..c42b4c7a405 100644 --- a/.gitignore +++ b/.gitignore @@ -127,3 +127,5 @@ dmypy.json # Pyre type checker .pyre/ + +.vscode \ No newline at end of file diff --git a/estate/__init__.py b/estate/__init__.py index e69de29bb2d..ab69f6ee4e6 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1,3 @@ +from . import models + +from odoo import api, SUPERUSER_ID \ No newline at end of file diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..f4c8fd6db6d --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1 @@ +from . import estate_property \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py new file mode 100644 index 00000000000..b9554c53676 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,40 @@ +from odoo import fields, models + +class Property(models.Model): + _name = "estate.property" + _description = "Real Estate Properties" + + name = fields.Char(required=True) + + description = fields.Text() + + postcode = fields.Char() + + date_availability = fields.Date('Available From') + + expected_price = fields.Float(required=True) + + selling_price = fields.Float() + + bedrooms = fields.Integer() + + living_area = fields.Integer() + + facades = fields.Integer() + + garage = fields.Boolean() + + garden = fields.Boolean() + + garden_area = fields.Integer() + + garden_orientation = fields.Selection( + selection=[ + ('north', 'North'), + ('south', 'South'), + ('west', 'West'), + ('east', 'East'), + ], + ) + + best_offer = fields.Float() \ No newline at end of file From cc9e725bc119febb42ed7313d9fc4c03977b1819 Mon Sep 17 00:00:00 2001 From: Shijakov Date: Wed, 22 Jul 2026 09:54:40 +0200 Subject: [PATCH 4/8] Add security to Estate Property --- 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 4fff962889d..8dd7f5bf0a6 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,4 +3,7 @@ 'version': '1.0', 'depends': ['base'], 'application': True, + 'data': [ + 'security/ir.model.access.csv', + ], } \ No newline at end of file diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..11214b63262 --- /dev/null +++ b/estate/security/ir.model.access.csv @@ -0,0 +1,2 @@ +id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink +estate_property_access_right_user,estate_property_access_right,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file From 6314636357c6f71eab02ba7baed336a99047d252 Mon Sep 17 00:00:00 2001 From: Shijakov Date: Wed, 22 Jul 2026 10:47:09 +0200 Subject: [PATCH 5/8] Add menu items for Real Estate and action for Estate Properties --- estate/__manifest__.py | 2 ++ estate/views/estate_menus.xml | 8 ++++++++ estate/views/estate_property_views.xml | 8 ++++++++ 3 files changed, 18 insertions(+) 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 8dd7f5bf0a6..2f749ed7bfa 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -5,5 +5,7 @@ 'application': True, 'data': [ 'security/ir.model.access.csv', + 'views/estate_property_views.xml', + 'views/estate_menus.xml', ], } \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml new file mode 100644 index 00000000000..8990e2775aa --- /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..affda3b8abc --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,8 @@ + + + + Properties + estate.property + list,form + + \ No newline at end of file From 179fc7b5cff59af50e89e273df7beee9d115f66f Mon Sep 17 00:00:00 2001 From: Shijakov Date: Wed, 22 Jul 2026 11:10:35 +0200 Subject: [PATCH 6/8] Modify some fields with default, copy and required ; add status and active fields --- estate/models/estate_property.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b9554c53676..0c121762b61 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,22 +1,23 @@ from odoo import fields, models +from dateutil.relativedelta import relativedelta class Property(models.Model): _name = "estate.property" _description = "Real Estate Properties" - name = fields.Char(required=True) + name = fields.Char(string='Title', required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date('Available From') + date_availability = fields.Date('Available From', copy=False, default=(fields.Date.today() + relativedelta(months=3))) expected_price = fields.Float(required=True) - selling_price = fields.Float() + selling_price = fields.Float(readonly=True, copy=False) - bedrooms = fields.Integer() + bedrooms = fields.Integer(default=2) living_area = fields.Integer() @@ -37,4 +38,20 @@ class Property(models.Model): ], ) - best_offer = fields.Float() \ No newline at end of file + best_offer = fields.Float() + + active = fields.Boolean(default=True) + + state = fields.Selection( + string='Status', + selection=[ + ('new', 'New'), + ('received', 'Offer Received'), + ('accepted', 'Offer Accepted'), + ('sold', 'Sold'), + ('cancelled', 'Cancelled'), + ], + required=True, + copy=False, + default="new" + ) From ca368c139903928078848dfd97bb0783ec770691 Mon Sep 17 00:00:00 2001 From: Shijakov Date: Wed, 22 Jul 2026 14:41:19 +0200 Subject: [PATCH 7/8] Add form, list and search view to Estate Properties --- estate/models/estate_property.py | 2 +- estate/views/estate_property_views.xml | 75 ++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 0c121762b61..f63e6f2496a 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -19,7 +19,7 @@ class Property(models.Model): bedrooms = fields.Integer(default=2) - living_area = fields.Integer() + living_area = fields.Integer(string="Living Area (sqm)") facades = fields.Integer() diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index affda3b8abc..03a0a53b0b2 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,5 +1,80 @@ + + estate.property.list + estate.property + + + + + + + + + + + + + + + estate.property.form + estate.property + +
+ +

+ +

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + estate.property.search + estate.property + + + + + + + + + + + + + + + + Properties estate.property From 437fc2570b2693df665fa16b29caaa23592bebeb Mon Sep 17 00:00:00 2001 From: Shijakov Date: Wed, 22 Jul 2026 17:28:54 +0200 Subject: [PATCH 8/8] Add relational fields to new estate models on estate properties --- estate/__manifest__.py | 3 ++ estate/models/__init__.py | 5 ++- estate/models/estate_property.py | 10 ++++++ estate/models/estate_property_offer.py | 20 ++++++++++++ estate/models/estate_property_tag.py | 7 ++++ estate/models/estate_property_type.py | 7 ++++ estate/security/ir.model.access.csv | 5 ++- estate/views/estate_menus.xml | 7 +++- estate/views/estate_property_offer_views.xml | 34 ++++++++++++++++++++ estate/views/estate_property_tag_views.xml | 22 +++++++++++++ estate/views/estate_property_type_views.xml | 22 +++++++++++++ estate/views/estate_property_views.xml | 24 +++++++++++++- 12 files changed, 162 insertions(+), 4 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_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 2f749ed7bfa..636169c9d0a 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -5,6 +5,9 @@ 'application': True, 'data': [ 'security/ir.model.access.csv', + 'views/estate_property_tag_views.xml', + 'views/estate_property_type_views.xml', + 'views/estate_property_offer_views.xml', 'views/estate_property_views.xml', 'views/estate_menus.xml', ], diff --git a/estate/models/__init__.py b/estate/models/__init__.py index f4c8fd6db6d..09b2099fe84 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1,4 @@ -from . import estate_property \ No newline at end of file +from . import estate_property +from . import estate_property_type +from . import estate_property_tag +from . import estate_property_offer \ No newline at end of file diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index f63e6f2496a..13649956ee9 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -55,3 +55,13 @@ class Property(models.Model): copy=False, default="new" ) + + property_type_id = fields.Many2one(comodel_name="estate.property.type") + + salesman_id = fields.Many2one(comodel_name="res.users", default=lambda self: self.env.uid) + + buyer_id = fields.Many2one(comodel_name="res.partner", copy=False) + + tag_ids = fields.Many2many(comodel_name="estate.property.tag") + + offer_ids = fields.One2many(comodel_name="estate.property.offer", inverse_name="property_id") diff --git a/estate/models/estate_property_offer.py b/estate/models/estate_property_offer.py new file mode 100644 index 00000000000..2ddb07a7096 --- /dev/null +++ b/estate/models/estate_property_offer.py @@ -0,0 +1,20 @@ +from odoo import fields, models + +class PropertyOffer(models.Model): + _name = "estate.property.offer" + _description = "Real Estate Property Offers" + + price = fields.Float() + + status = fields.Selection( + selection=[ + ('new', 'New'), + ('accepted', 'Accepted'), + ('refused', 'Refused'), + ], + copy=False, + ) + + partner_id = fields.Many2one(comodel_name='res.partner', required=True) + + property_id = fields.Many2one(comodel_name='estate.property', required=True) \ 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..0020f143aa4 --- /dev/null +++ b/estate/models/estate_property_tag.py @@ -0,0 +1,7 @@ +from odoo import fields, models + +class PropertyTag(models.Model): + _name = "estate.property.tag" + _description = "Real Estate Property Tags" + + name = fields.Char(required=True) \ 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..7c65dbc6f3a --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,7 @@ +from odoo import fields, models + +class PropertyType(models.Model): + _name = "estate.property.type" + _description = "Real Estate Property Types" + + name = fields.Char(required=True) \ No newline at end of file diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 11214b63262..8ba61db81b0 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,5 @@ id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink -estate_property_access_right_user,estate_property_access_right,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file +estate_property_access_right_user,estate_property_access_right,model_estate_property,base.group_user,1,1,1,1 +estate_property_type_access_right_user,estate_property_type_access_right,model_estate_property_type,base.group_user,1,1,1,1 +estate_property_tag_access_right_user,estate_property_tag_access_right,model_estate_property_tag,base.group_user,1,1,1,1 +estate_property_offer_access_right_user,estate_property_offer_access_right,model_estate_property_offer,base.group_user,1,1,1,1 \ No newline at end of file diff --git a/estate/views/estate_menus.xml b/estate/views/estate_menus.xml index 8990e2775aa..70af6400349 100644 --- a/estate/views/estate_menus.xml +++ b/estate/views/estate_menus.xml @@ -1,8 +1,13 @@ - + + + + + + \ No newline at end of file diff --git a/estate/views/estate_property_offer_views.xml b/estate/views/estate_property_offer_views.xml new file mode 100644 index 00000000000..dda0e0d7eb1 --- /dev/null +++ b/estate/views/estate_property_offer_views.xml @@ -0,0 +1,34 @@ + + + + estate.property.offer.form + estate.property.offer + +
+ + + + + + + + + + + +
+
+
+ + + estate.property.offer.list + estate.property.offer + + + + + + + + +
\ 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..d294c895450 --- /dev/null +++ b/estate/views/estate_property_tag_views.xml @@ -0,0 +1,22 @@ + + + + estate.property.tag.form + estate.property.tag + +
+ +

+ +

+
+
+
+
+ + + Property Tags + estate.property.tag + list,form + +
\ 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..315f78ea255 --- /dev/null +++ b/estate/views/estate_property_type_views.xml @@ -0,0 +1,22 @@ + + + + estate.property.type.form + estate.property.type + +
+ +

+ +

+
+
+
+
+ + + Property Types + estate.property.type + list,form + +
\ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 03a0a53b0b2..339f14da56e 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -6,6 +6,7 @@ + @@ -16,7 +17,7 @@
- + estate.property.form estate.property @@ -26,8 +27,11 @@ + + + @@ -50,6 +54,23 @@ + + + + + + + + + + @@ -62,6 +83,7 @@ +