diff --git a/estate/__init__.py b/estate/__init__.py
new file mode 100644
index 00000000000..0650744f6bc
--- /dev/null
+++ b/estate/__init__.py
@@ -0,0 +1 @@
+from . import models
diff --git a/estate/__manifest__.py b/estate/__manifest__.py
new file mode 100644
index 00000000000..1447e04f863
--- /dev/null
+++ b/estate/__manifest__.py
@@ -0,0 +1,30 @@
+{
+ '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': [
+ "data/estate.tag.csv",
+ "data/estate.property.csv",
+ "security/ir.model.access.csv",
+ "views/estate_property_views.xml",
+ "views/estate_menu_views.xml",
+ ],
+ '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/__init__.py b/estate/models/__init__.py
new file mode 100644
index 00000000000..1a1271f8598
--- /dev/null
+++ b/estate/models/__init__.py
@@ -0,0 +1,2 @@
+from . import estate_tag
+from . import estate_property
diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py
new file mode 100644
index 00000000000..f0cb88f3a96
--- /dev/null
+++ b/estate/models/estate_property.py
@@ -0,0 +1,51 @@
+# 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
+ )
+
+ 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, readonly=True)
+
+ 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.',
+ )
diff --git a/estate/models/estate_tag.py b/estate/models/estate_tag.py
new file mode 100644
index 00000000000..9d629fc2827
--- /dev/null
+++ b/estate/models/estate_tag.py
@@ -0,0 +1,40 @@
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+from random import randint
+
+
+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", 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.')
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
diff --git a/estate/static/description/icon.png b/estate/static/description/icon.png
new file mode 100644
index 00000000000..12da2f0de3c
Binary files /dev/null and b/estate/static/description/icon.png differ
diff --git a/estate/views/estate_menu_views.xml b/estate/views/estate_menu_views.xml
new file mode 100644
index 00000000000..b7e754dfff6
--- /dev/null
+++ b/estate/views/estate_menu_views.xml
@@ -0,0 +1,19 @@
+
+
+
+
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
+
+