From 9658532b64f0d26faeaf53bf9ad8686719627e1c Mon Sep 17 00:00:00 2001 From: Astremy <43485551+Astremy@users.noreply.github.com> Date: Mon, 16 Feb 2026 14:14:00 +0100 Subject: [PATCH 1/5] [ADD] Real Estate: Creation of the module definition --- estate/__init__.py | 0 estate/__manifest__.py | 25 +++++++++++++++++++++++++ 2 files changed, 25 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..9f9659f45eb --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +{ + 'name': "Real Estate", + + 'summary': """ + Server framework 101: A New Application" + """, + + 'description': """ + Starting module for "Server framework 101: A New Application" + """, + + 'author': "Odoo", + 'website': "https://www.odoo.com/", + 'category': 'Tutorials', + 'version': '0.1', + 'application': True, + 'installable': True, + 'depends': ['base'], + + 'data': [], + 'assets': { + }, + 'license': 'LGPL-3' +} From 64e5ae64bdb731994f18d7f032022ed7dbf0fca4 Mon Sep 17 00:00:00 2001 From: "Astremy (luleg)" <43485551+Astremy@users.noreply.github.com> Date: Mon, 16 Feb 2026 15:21:29 +0100 Subject: [PATCH 2/5] [IMP] Real Estate: Add basic property model --- estate/__init__.py | 1 + estate/models/__init__.py | 2 ++ estate/models/estate_property.py | 42 ++++++++++++++++++++++++++++++++ estate/models/estate_tag.py | 40 ++++++++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 estate/models/__init__.py create mode 100644 estate/models/estate_property.py create mode 100644 estate/models/estate_tag.py diff --git a/estate/__init__.py b/estate/__init__.py index e69de29bb2d..9a7e03eded3 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -0,0 +1 @@ +from . import models \ No newline at end of file diff --git a/estate/models/__init__.py b/estate/models/__init__.py new file mode 100644 index 00000000000..f835427dd99 --- /dev/null +++ b/estate/models/__init__.py @@ -0,0 +1,2 @@ +from . import estate_tag +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..cd575efe598 --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class Property(models.Model): + _name = "estate.property" + _description = "Real Estate Property" + _order = "expecting_price, selling_price, sequence, id" + + name = fields.Char("Name", required=True, translate=True) + + property_type = fields.Selection( + [ + ("house", "House"), + ("apartment", "Apartment"), + ("land", "Land") + ], + required=True + ) + + currency_id = fields.Many2one('res.currency', 'Currency', readonly=True) + expecting_price = fields.Monetary("Expecting Price", required=True) + selling_price = fields.Monetary("Selling Price", default=0) + + bedroom_number = fields.Integer("Bedrooms", default=0) + area = fields.Integer("Living Area (sqm)", required=True) + + sequence = fields.Integer(default=10) + + tag_ids = fields.Many2many("estate.tag", string="Tags") + + _check_bedroom_number = models.Constraint( + 'CHECK(bedroom_number >= 0)', + 'The number of bedrooms can\'t be negative.', + ) + + _check_area = models.Constraint( + 'CHECK(area >= 0)', + 'The area can\'t be negative.', + ) \ No newline at end of file diff --git a/estate/models/estate_tag.py b/estate/models/estate_tag.py new file mode 100644 index 00000000000..e8fcd7e05ad --- /dev/null +++ b/estate/models/estate_tag.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Part of Odoo. See LICENSE file for full copyright and licensing details. + +from odoo import fields, models + + +class EstateTagCategory(models.Model): + _name = "estate.tag.category" + _description = "Estate Tag Category" + _order = "sequence" + + def _default_sequence(self): + """ + Here we use a _default method instead of ordering on 'sequence, id' to + prevent adding a new related stored field in the 'event.tag' model that + would hold the category id. + """ + return (self.search([], order="sequence desc", limit=1).sequence or 0) + 1 + + name = fields.Char("Name", required=True, translate=True) + sequence = fields.Integer('Sequence', default=_default_sequence) + tag_ids = fields.Many2many("estate.tag", "category_id", string="Tags") + +class EstateTag(models.Model): + _name = "estate.tag" + _description = "Estate Tag" + _order = "category_sequence, sequence, id" + + def _default_color(self): + return randint(1, 11) + + name = fields.Char("Name", required=True, translate=True) + sequence = fields.Integer("Sequence", default=0) + category_id = fields.Many2one("estate.tag.category", string="Category", required=True, index=True, ondelete='cascade') + category_sequence = fields.Integer(related="category_id.sequence", string='Category Sequence', store=True) + color = fields.Integer( + string='Color Index', default=lambda self: self._default_color(), + help='Tag color. No color means no display in kanban or front-end, to distinguish internal tags from public categorization tags.') + + From 5af7058dc53bcf4abfb0d5f7c519f5631e90a545 Mon Sep 17 00:00:00 2001 From: "Astremy (luleg)" <43485551+Astremy@users.noreply.github.com> Date: Mon, 16 Feb 2026 16:18:11 +0100 Subject: [PATCH 3/5] [IMP] real estate: Set base data and access rights --- estate/__manifest__.py | 6 +++++- estate/data/estate.property.csv | 3 +++ estate/data/estate.tag.csv | 3 +++ estate/models/estate_tag.py | 4 +++- estate/security/ir.model.access.csv | 4 ++++ 5 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 estate/data/estate.property.csv create mode 100644 estate/data/estate.tag.csv create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 9f9659f45eb..ebba413ee6a 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -18,7 +18,11 @@ 'installable': True, 'depends': ['base'], - 'data': [], + 'data': [ + "data/estate.tag.csv", + "data/estate.property.csv", + "security/ir.model.access.csv" + ], 'assets': { }, 'license': 'LGPL-3' diff --git a/estate/data/estate.property.csv b/estate/data/estate.property.csv new file mode 100644 index 00000000000..edefbd91839 --- /dev/null +++ b/estate/data/estate.property.csv @@ -0,0 +1,3 @@ +"id","name","expecting_price","area","property_type" +estate_tag_1,"Odoo Farm 2",300000,2000,"house" +estate_tag_2,"Odoo LLN",1000000,40000,"apartment" \ No newline at end of file diff --git a/estate/data/estate.tag.csv b/estate/data/estate.tag.csv new file mode 100644 index 00000000000..2632941d0cb --- /dev/null +++ b/estate/data/estate.tag.csv @@ -0,0 +1,3 @@ +"id","name","color" +estate_property_1,"Leased",5 +estate_property_2,"Empty",8 \ No newline at end of file diff --git a/estate/models/estate_tag.py b/estate/models/estate_tag.py index e8fcd7e05ad..93fccad4f35 100644 --- a/estate/models/estate_tag.py +++ b/estate/models/estate_tag.py @@ -3,6 +3,8 @@ from odoo import fields, models +from random import randint + class EstateTagCategory(models.Model): _name = "estate.tag.category" @@ -31,7 +33,7 @@ def _default_color(self): name = fields.Char("Name", required=True, translate=True) sequence = fields.Integer("Sequence", default=0) - category_id = fields.Many2one("estate.tag.category", string="Category", required=True, index=True, ondelete='cascade') + category_id = fields.Many2one("estate.tag.category", string="Category", index=True, ondelete='cascade') category_sequence = fields.Integer(related="category_id.sequence", string='Category Sequence', store=True) color = fields.Integer( string='Color Index', default=lambda self: self._default_color(), diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..e5d581ea24f --- /dev/null +++ b/estate/security/ir.model.access.csv @@ -0,0 +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_tag,access_estate_tag,model_estate_tag,base.group_user,1,1,1,1 +access_estate_tag_category,access_estate_tag_category,model_estate_tag_category,base.group_user,1,1,1,1 \ No newline at end of file From c2dfc5d5a44e5801241c68fd39de828a719a3606 Mon Sep 17 00:00:00 2001 From: "Astremy (luleg)" <43485551+Astremy@users.noreply.github.com> Date: Mon, 16 Feb 2026 16:32:33 +0100 Subject: [PATCH 4/5] [LINT] real estate: Fix styling errors --- estate/__init__.py | 2 +- estate/__manifest__.py | 1 - estate/models/__init__.py | 2 +- estate/models/estate_property.py | 5 ++--- estate/models/estate_tag.py | 8 +++----- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/estate/__init__.py b/estate/__init__.py index 9a7e03eded3..0650744f6bc 100644 --- a/estate/__init__.py +++ b/estate/__init__.py @@ -1 +1 @@ -from . import models \ No newline at end of file +from . import models diff --git a/estate/__manifest__.py b/estate/__manifest__.py index ebba413ee6a..5c28bec050e 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- { 'name': "Real Estate", diff --git a/estate/models/__init__.py b/estate/models/__init__.py index f835427dd99..1a1271f8598 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,2 +1,2 @@ from . import estate_tag -from . import estate_property \ No newline at end of file +from . import estate_property diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index cd575efe598..b5f01db6f1d 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import fields, models @@ -10,7 +9,7 @@ class Property(models.Model): _order = "expecting_price, selling_price, sequence, id" name = fields.Char("Name", required=True, translate=True) - + property_type = fields.Selection( [ ("house", "House"), @@ -39,4 +38,4 @@ class Property(models.Model): _check_area = models.Constraint( 'CHECK(area >= 0)', 'The area can\'t be negative.', - ) \ No newline at end of file + ) diff --git a/estate/models/estate_tag.py b/estate/models/estate_tag.py index 93fccad4f35..9d629fc2827 100644 --- a/estate/models/estate_tag.py +++ b/estate/models/estate_tag.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import fields, models @@ -10,7 +9,7 @@ class EstateTagCategory(models.Model): _name = "estate.tag.category" _description = "Estate Tag Category" _order = "sequence" - + def _default_sequence(self): """ Here we use a _default method instead of ordering on 'sequence, id' to @@ -23,11 +22,12 @@ def _default_sequence(self): sequence = fields.Integer('Sequence', default=_default_sequence) tag_ids = fields.Many2many("estate.tag", "category_id", string="Tags") + class EstateTag(models.Model): _name = "estate.tag" _description = "Estate Tag" _order = "category_sequence, sequence, id" - + def _default_color(self): return randint(1, 11) @@ -38,5 +38,3 @@ def _default_color(self): color = fields.Integer( string='Color Index', default=lambda self: self._default_color(), help='Tag color. No color means no display in kanban or front-end, to distinguish internal tags from public categorization tags.') - - From 4c46b9306b4af243ab496595352c46c6c9e35572 Mon Sep 17 00:00:00 2001 From: "Astremy (luleg)" <43485551+Astremy@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:15:29 +0100 Subject: [PATCH 5/5] [IMP] Real Estate: Add estate application page with list and form view. --- estate/__manifest__.py | 4 +- estate/models/estate_property.py | 12 +++- estate/static/description/icon.png | Bin 0 -> 12880 bytes estate/views/estate_menu_views.xml | 19 +++++++ estate/views/estate_property_views.xml | 73 +++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) create mode 100644 estate/static/description/icon.png create mode 100644 estate/views/estate_menu_views.xml create mode 100644 estate/views/estate_property_views.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 5c28bec050e..1447e04f863 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -20,7 +20,9 @@ 'data': [ "data/estate.tag.csv", "data/estate.property.csv", - "security/ir.model.access.csv" + "security/ir.model.access.csv", + "views/estate_property_views.xml", + "views/estate_menu_views.xml", ], 'assets': { }, diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index b5f01db6f1d..f0cb88f3a96 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -19,9 +19,19 @@ class Property(models.Model): required=True ) + active = fields.Boolean("Active", default=True) + + stage = fields.Selection([ + ("new", "New"), + ("offer_received", "Offer Received"), + ("offer_accepted","Offer Accepted"), + ("sold", "Sold"), + ("cancelled","Cancelled") + ], default="new") + currency_id = fields.Many2one('res.currency', 'Currency', readonly=True) expecting_price = fields.Monetary("Expecting Price", required=True) - selling_price = fields.Monetary("Selling Price", default=0) + selling_price = fields.Monetary("Selling Price", default=0, readonly=True) bedroom_number = fields.Integer("Bedrooms", default=0) area = fields.Integer("Living Area (sqm)", required=True) diff --git a/estate/static/description/icon.png b/estate/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..12da2f0de3c0395f06b44460dd393d9d0ecf3415 GIT binary patch literal 12880 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 w8Y)OQ*pZkGENK2 + + + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..114cac0f011 --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,73 @@ + + + + estate.property.view.search + estate.property + + + + + + + + + + + + + estate.property.form + estate.property + +
+
+ +
+ +
+
+
+

+ +

+
+ + + + + + + + + + + + +
+
+
+
+ + + estate.property.view.list + estate.property + + + + + + + + + + + + + + + Properties + estate.property + list,form + +