From 9db77c0a62fc251224ff917c83bb11989da011cb Mon Sep 17 00:00:00 2001 From: lokesh Date: Mon, 3 Aug 2026 19:03:49 +0530 Subject: [PATCH 1/9] [ADD] real_estate:created new module - Added estate property model - Defined basic property fields --- estate/__init__.py | 1 + estate/__manifest__.py | 7 +++++++ estate/models/__init__.py | 1 + estate/models/estate_property.py | 6 ++++++ 4 files changed, 15 insertions(+) create mode 100644 estate/__init__.py create mode 100644 estate/__manifest__.py 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 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..81356cc39ca --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,7 @@ +{ + 'name': 'real estate', + 'depends': [ + 'base' + ], + 'application': True, +} 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..8b030df4ccc --- /dev/null +++ b/estate/models/estate_property.py @@ -0,0 +1,6 @@ +from odoo import models + + +class TestModel(models.Model): + _name = "estate.property" + _description = "This is a dummy table" From 2ad999fca0dba2b2a7e6d0671fcb573f09b8b427 Mon Sep 17 00:00:00 2001 From: lokesh Date: Tue, 4 Aug 2026 15:07:22 +0530 Subject: [PATCH 2/9] [IMP] estate: added the security csv file - Added security file to grant permission for group user --- estate/__manifest__.py | 6 ++++++ estate/models/estate_property.py | 23 ++++++++++++++++++++++- estate/security/ir.model.access.csv | 2 ++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 estate/security/ir.model.access.csv diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 81356cc39ca..332fff9b1cb 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,7 +1,13 @@ { 'name': 'real estate', + 'author': 'Lokesh', + 'version': '1.0.0', + 'license': 'LGPL-3', 'depends': [ 'base' ], 'application': True, + 'data': [ + 'security/ir.model.access.csv', + ], } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 8b030df4ccc..764afe7c605 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,27 @@ -from odoo import models +from odoo import models, fields class TestModel(models.Model): _name = "estate.property" _description = "This is a dummy table" + + 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([ + ('north', 'North'), + ('south', 'South'), + ('east', 'East'), + ('west', 'West'), + ], + string="Direction", + default='north') diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv new file mode 100644 index 00000000000..c4f7ae7bd45 --- /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_user,estate.property.user,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file From 84049f5f2d38eec37b581003b9fbee591ad09383 Mon Sep 17 00:00:00 2001 From: lokesh Date: Wed, 5 Aug 2026 18:49:43 +0530 Subject: [PATCH 3/9] [IMP] estate: added security and view files - Added estate property view file and rendered the model fields --- awesome_dashboard/__manifest__.py | 2 +- estate/__manifest__.py | 1 + estate/security/ir.model.access.csv | 2 +- estate/views/estate_property_views.xml | 11 +++++++++++ 4 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 estate/views/estate_property_views.xml diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py index a1cd72893d7..c24c020c649 100644 --- a/awesome_dashboard/__manifest__.py +++ b/awesome_dashboard/__manifest__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- { - 'name': "Awesome Dashboard", + 'name': "Awesome Dashboard1", 'summary': """ Starting module for "Discover the JS framework, chapter 2: Build a dashboard" diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 332fff9b1cb..c399b53dec2 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -9,5 +9,6 @@ 'application': True, 'data': [ 'security/ir.model.access.csv', + 'views/estate_property_views.xml' ], } diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index c4f7ae7bd45..9dc9388f45a 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -1,2 +1,2 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink -access_estate_property_user,estate.property.user,model_estate_property,base.group_user,1,1,1,1 \ No newline at end of file +access_estate_property_user,estate.property.user,model_estate_property,base.group_user,1,1,1,1 diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml new file mode 100644 index 00000000000..4a6785e36ac --- /dev/null +++ b/estate/views/estate_property_views.xml @@ -0,0 +1,11 @@ + + + + Proprety + estate.property + list,form + + + + + From 0f1672b139d4cc5624d5211b8dce5988454cb771 Mon Sep 17 00:00:00 2001 From: lokesh Date: Thu, 6 Aug 2026 12:27:10 +0530 Subject: [PATCH 4/9] [IMP] estate: added views and menu items - Added 'estate_property_menu.xml' to render the menu items - Update the 'estate_property_views.xml' to render more fields - Update the manifest file to add 'estate_property_menu.xml' --- estate/__manifest__.py | 22 ++--- estate/models/estate_property.py | 31 +++++-- estate/views/estate_property_actions.xml | 24 +++++ estate/views/estate_property_menu.xml | 33 +++++++ estate/views/estate_property_views.xml | 109 +++++++++++++++++++++-- 5 files changed, 191 insertions(+), 28 deletions(-) create mode 100644 estate/views/estate_property_actions.xml create mode 100644 estate/views/estate_property_menu.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index c399b53dec2..13a83ca449f 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -1,14 +1,14 @@ { - 'name': 'real estate', - 'author': 'Lokesh', - 'version': '1.0.0', - 'license': 'LGPL-3', - 'depends': [ - 'base' - ], - 'application': True, - 'data': [ - 'security/ir.model.access.csv', - 'views/estate_property_views.xml' + "name": "real estate", + "author": "Lokesh", + "version": "1.0.0", + "license": "LGPL-3", + "depends": ["base"], + "application": True, + "data": [ + "security/ir.model.access.csv", + "views/estate_property_actions.xml", # the order should be like this, first we need to define the action and then we need to define the menu and then the views if the order is not maintained then error will be thrown. + "views/estate_property_views.xml", + "views/estate_property_menu.xml", ], } diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 764afe7c605..58f57a3a166 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 fields, models class TestModel(models.Model): @@ -17,11 +17,24 @@ class TestModel(models.Model): garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() - garden_orientation = fields.Selection([ - ('north', 'North'), - ('south', 'South'), - ('east', 'East'), - ('west', 'West'), - ], - string="Direction", - default='north') + garden_orientation = fields.Selection( + [ + ("north", "North"), + ("south", "South"), + ("east", "East"), + ("west", "West"), + ], + string="Direction", + default="north", + ) + active = fields.Boolean("active", default=True) + + def action_confirm(self): + print("button is clicked") + return { + "type": "ir.actions.act_window", + "name": "Properties", + "res_model": "estate.property", + "view_mode": "form", + "target": "current", + } diff --git a/estate/views/estate_property_actions.xml b/estate/views/estate_property_actions.xml new file mode 100644 index 00000000000..845a93f4029 --- /dev/null +++ b/estate/views/estate_property_actions.xml @@ -0,0 +1,24 @@ + + + + Property + estate.property + list,form + + + + + + Properties2 + estate.property + + + form + new + + diff --git a/estate/views/estate_property_menu.xml b/estate/views/estate_property_menu.xml new file mode 100644 index 00000000000..eb12d1b27f6 --- /dev/null +++ b/estate/views/estate_property_menu.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 4a6785e36ac..055131c6497 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,11 +1,104 @@ - - Proprety - estate.property - list,form - - - - + + + estate.property.form + estate.property + +
+ + + + + + + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + + estate property wizard + estate.property + +
+ + + + + + +
+
+
+
+
+ + + + estate property views + estate.property + + + + + + + + + +
From 9e3de6790a7d892a1b43aa855bd664c392592a3f Mon Sep 17 00:00:00 2001 From: lokesh Date: Wed, 2 Sep 2026 11:23:27 +0530 Subject: [PATCH 5/9] [IMP] estate: added estate_property_type table and connected the two table (estate_property and estate_property_type) using Many2one - Added different relation fields like Many2One, Many2Many and One2Many to connect two tables - Removed unnecessary lines of code - Update the 'estate_property_views.xml' to improve the UI --- estate/__manifest__.py | 11 ++++- estate/models/__init__.py | 2 +- estate/models/estate_property.py | 26 +++++++--- estate/models/estate_property_type.py | 8 +++ estate/security/ir.model.access.csv | 4 +- estate/security/securities.xml | 5 ++ estate/static/src/estate.css | 0 estate/views/estate_property_actions.xml | 16 +----- estate/views/estate_property_menu.xml | 8 +-- estate/views/estate_property_type_view.xml | 14 ++++++ estate/views/estate_property_views.xml | 57 +++++++--------------- 11 files changed, 83 insertions(+), 68 deletions(-) create mode 100644 estate/models/estate_property_type.py create mode 100644 estate/security/securities.xml create mode 100644 estate/static/src/estate.css create mode 100644 estate/views/estate_property_type_view.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 13a83ca449f..bb035f8b4ca 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,12 +3,19 @@ "author": "Lokesh", "version": "1.0.0", "license": "LGPL-3", - "depends": ["base"], + # "depends": ["base"], "application": True, + "installable": True, "data": [ + "security/securities.xml", "security/ir.model.access.csv", - "views/estate_property_actions.xml", # the order should be like this, first we need to define the action and then we need to define the menu and then the views if the order is not maintained then error will be thrown. "views/estate_property_views.xml", + "views/estate_property_actions.xml", # the order should be like this, first we need to define the views and then we need to define the action and then the menu if the order is not maintained then error will be thrown. "views/estate_property_menu.xml", ], + "assets": { + "web.assets_backend": [ + "estate/static/src/estate.css", + ], + }, } diff --git a/estate/models/__init__.py b/estate/models/__init__.py index 5e1963c9d2f..76e779e73b0 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1 +1 @@ -from . import estate_property +from . import estate_property, estate_property_type diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 58f57a3a166..96aab7f23e9 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,16 +1,30 @@ +from datetime import datetime + from odoo import fields, models class TestModel(models.Model): + today = datetime.now() + + month = today.month + 3 + year = today.year + day = today.day + + if month > 12: + year = year + 1 + month = month % 12 + + three_month_date = today.replace(year=year, month=month, day=day) + _name = "estate.property" _description = "This is a dummy table" - name = fields.Char(required=True) + name = fields.Char(translate=True, default="Unknown", required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date() + date_availability = fields.Date(copy=False, default=three_month_date.date()) expected_price = fields.Float(required=True) - selling_price = fields.Float() + selling_price = fields.Float(readonly=True, copy=False) bedrooms = fields.Integer() living_area = fields.Integer() facades = fields.Integer() @@ -27,12 +41,12 @@ class TestModel(models.Model): string="Direction", default="north", ) - active = fields.Boolean("active", default=True) + active = fields.Boolean("Active", default=True) + property_type_id = fields.Many2one("estate.property.type", string="Property_type") def action_confirm(self): - print("button is clicked") return { - "type": "ir.actions.act_window", + "type": "ir.actions.act_window", # type and name are very important "name": "Properties", "res_model": "estate.property", "view_mode": "form", diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py new file mode 100644 index 00000000000..27f87357895 --- /dev/null +++ b/estate/models/estate_property_type.py @@ -0,0 +1,8 @@ +from odoo import fields, models + + +class PropertyType(models.Model): + _name = "estate.property.type" + _description = "this is used to define the types" + + name = fields.Char(required=True) diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index 9dc9388f45a..267f7ff3075 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_user,estate.property.user,model_estate_property,base.group_user,1,1,1,1 +access_estate_property_user1,estate.property.user,model_estate_property,base.group_user,1,0,0,0 +access_estate_property_user,estate.property.user,model_estate_property,base.group_system,1,1,1,1 +access_estate_property_type_user,estate.property.type.user,model_estate_property_type,base.group_system,1,1,1,1 diff --git a/estate/security/securities.xml b/estate/security/securities.xml new file mode 100644 index 00000000000..7f759d69eb6 --- /dev/null +++ b/estate/security/securities.xml @@ -0,0 +1,5 @@ + + + Estate Administrator + + diff --git a/estate/static/src/estate.css b/estate/static/src/estate.css new file mode 100644 index 00000000000..e69de29bb2d diff --git a/estate/views/estate_property_actions.xml b/estate/views/estate_property_actions.xml index 845a93f4029..e27b62eca71 100644 --- a/estate/views/estate_property_actions.xml +++ b/estate/views/estate_property_actions.xml @@ -4,21 +4,7 @@ Property estate.property list,form - + - - - Properties2 - estate.property - - - form - new - diff --git a/estate/views/estate_property_menu.xml b/estate/views/estate_property_menu.xml index eb12d1b27f6..2de513e0a28 100644 --- a/estate/views/estate_property_menu.xml +++ b/estate/views/estate_property_menu.xml @@ -5,10 +5,10 @@ - diff --git a/estate/views/estate_property_type_view.xml b/estate/views/estate_property_type_view.xml new file mode 100644 index 00000000000..493b373d3b8 --- /dev/null +++ b/estate/views/estate_property_type_view.xml @@ -0,0 +1,14 @@ + + + + estate.property.type + +
+ + + +
+
+ +
+
\ No newline at end of file diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 055131c6497..861b8a47fd4 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -2,34 +2,26 @@ - estate.property.form + estate.property
- - - - - - +
- - + @@ -39,8 +31,6 @@ - - @@ -50,53 +40,42 @@ - - - - - -
- - estate property wizard + + estate property search view estate.property -
- - - - - - -
-
-
+ + + + +
- estate property views estate.property - - - - + + + + + + + From 9aee6a2a36012e5843e26ff36784f9e7792cbec1 Mon Sep 17 00:00:00 2001 From: lokesh Date: Wed, 2 Sep 2026 15:22:46 +0530 Subject: [PATCH 6/9] [IMP] estate: added property_type_id in the view xml - Added the 'estate_property_type.py' model and used this in the 'estate_property_views.xml' --- estate/__manifest__.py | 4 +-- estate/models/estate_property_type.py | 2 +- estate/views/estate_property_actions.xml | 10 -------- estate/views/estate_property_menu.xml | 30 ++++++++-------------- estate/views/estate_property_type_view.xml | 12 ++++++--- estate/views/estate_property_views.xml | 13 +++++----- 6 files changed, 30 insertions(+), 41 deletions(-) delete mode 100644 estate/views/estate_property_actions.xml diff --git a/estate/__manifest__.py b/estate/__manifest__.py index bb035f8b4ca..1b121b141f4 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -9,8 +9,8 @@ "data": [ "security/securities.xml", "security/ir.model.access.csv", - "views/estate_property_views.xml", - "views/estate_property_actions.xml", # the order should be like this, first we need to define the views and then we need to define the action and then the menu if the order is not maintained then error will be thrown. + "views/estate_property_views.xml", # the order should be like this, first we need to define the views and then we need to define the action and then the menu if the order is not maintained then error will be thrown. + "views/estate_property_type_view.xml", "views/estate_property_menu.xml", ], "assets": { diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index 27f87357895..b3b0d0094ee 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -5,4 +5,4 @@ class PropertyType(models.Model): _name = "estate.property.type" _description = "this is used to define the types" - name = fields.Char(required=True) + name = fields.Char(required=True, string="Type") diff --git a/estate/views/estate_property_actions.xml b/estate/views/estate_property_actions.xml deleted file mode 100644 index e27b62eca71..00000000000 --- a/estate/views/estate_property_actions.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - Property - estate.property - list,form - - - - diff --git a/estate/views/estate_property_menu.xml b/estate/views/estate_property_menu.xml index 2de513e0a28..4d13f8652f2 100644 --- a/estate/views/estate_property_menu.xml +++ b/estate/views/estate_property_menu.xml @@ -1,33 +1,25 @@ - - - - - + + - - - - diff --git a/estate/views/estate_property_type_view.xml b/estate/views/estate_property_type_view.xml index 493b373d3b8..9d168bf7334 100644 --- a/estate/views/estate_property_type_view.xml +++ b/estate/views/estate_property_type_view.xml @@ -1,14 +1,20 @@ - + + estate.property.type
- +
+
+ + Property Type + 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 861b8a47fd4..c1dac48599d 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -1,14 +1,10 @@ - - estate.property
- -
@@ -33,13 +34,27 @@ - - - - - + + + + + + + + + + + + + + + + + + +
@@ -74,11 +89,11 @@
- + + Property estate.property list,form -
From c5f70d9f311b67326f9f12dfa7078bf8f9ff13e7 Mon Sep 17 00:00:00 2001 From: lokesh Date: Wed, 9 Sep 2026 12:11:12 +0530 Subject: [PATCH 8/9] [IMP] estate: improved the search field and added new computed fields and functions I have added the available filter to allow users to isolate open properties, and i have added computed fields to dynamically calculate the fields as i have added the relation between models it is necessary to add the ondelete attribute to handle the removed or unnecessary properties 1. Property Availabilty & filtering: - Added 'state' field to 'estate.property' to track the lifecycle of a listing - updated 'estate_property_views' to include the available filter, allowing users to isolate properties open for offer 2. Computed fields: - Implemented computed fields ('total_offers', 'total_area', 'best_price') along with their respective computed functions 3. Database Integrity: - Added `ondelete='cascade'` to the 'property_tag_ids' (Many2many relation) in 'estate_property.py' model and to the 'property_id' (Many2many relation) in 'estate_property_offers' --- .gitignore | 2 + estate/models/estate_property.py | 48 +++++++++++++++++++++- estate/models/estate_property_offers.py | 2 +- estate/models/estate_property_type.py | 1 - estate/views/estate_property_type_view.xml | 7 ++-- estate/views/estate_property_views.xml | 9 +++- 6 files changed, 61 insertions(+), 8 deletions(-) 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/models/estate_property.py b/estate/models/estate_property.py index 94625fc86e8..9159efc4d68 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,6 +1,7 @@ from datetime import datetime -from odoo import fields, models +from odoo import api, fields, models +from odoo.exceptions import ValidationError class TestModel(models.Model): @@ -41,11 +42,22 @@ class TestModel(models.Model): string="Direction", default="north", ) + state = fields.Selection( + [ + ("new", "New"), + ("offer_received", "Offer Receeived"), + ("offer_accepted", "Offer Accepted"), + ("sold", "Sold"), + ("cancelled", "Cancelled"), + ] + ) active = fields.Boolean("Active", default=True) property_type_id = fields.Many2one("estate.property.type", string="Property_type") property_tag_ids = fields.Many2many( "estate.property.tag", + relation="losbo_property_propertyTag", string="Property_Tag", + ondelete="cascade", ) buyer = fields.Many2one("res.partner", string="buyer", copy=False) @@ -53,3 +65,37 @@ class TestModel(models.Model): "res.users", string="salesperson", default=lambda self: self.env.user ) offer_ids = fields.One2many("estate.property.offers", "property_id") + + total_offers = fields.Integer(compute="_compute_offers") + + total_area = fields.Float(compute="_compute_area") + best_price = fields.Integer(compute="_compute_price") + + @api.depends("offer_ids") + def _compute_offers(self): + for record in self: + count = 0 + if record.offer_ids: + for offers in record.offer_ids: + if offers.status == "accepted": + count += 1 + record.total_offers = count + + @api.constrains("name", "description") + def _check_description(self): + for record in self: + if record.name == record.description: + raise ValidationError("Fields name and description should not be equal") + + @api.depends("living_area", "garden_area") + def _compute_area(self): + for record in self: + record.total_area = record.living_area + record.garden_area + + @api.depends("offer_ids.price") + def _compute_price(self): + best_price = 0 + for records in self: + for offers in records.offer_ids: + best_price = max(offers.price, best_price) + records.best_price = best_price diff --git a/estate/models/estate_property_offers.py b/estate/models/estate_property_offers.py index 954d6a2de68..9e3e306e316 100644 --- a/estate/models/estate_property_offers.py +++ b/estate/models/estate_property_offers.py @@ -8,4 +8,4 @@ class PropertyOffer(models.Model): price = fields.Float() status = fields.Selection([("accepted", "Accepted"), ("refused", "Refused")]) partner_id = fields.Many2one("res.partner", required=True) - property_id = fields.Many2one("estate.property", required=True) + property_id = fields.Many2one("estate.property", required=True, ondelete="cascade") diff --git a/estate/models/estate_property_type.py b/estate/models/estate_property_type.py index e751128b841..b3b0d0094ee 100644 --- a/estate/models/estate_property_type.py +++ b/estate/models/estate_property_type.py @@ -6,4 +6,3 @@ class PropertyType(models.Model): _description = "this is used to define the types" name = fields.Char(required=True, string="Type") - tags = fields.Char(string="tags") diff --git a/estate/views/estate_property_type_view.xml b/estate/views/estate_property_type_view.xml index edc5aea3c87..1340b665dd9 100644 --- a/estate/views/estate_property_type_view.xml +++ b/estate/views/estate_property_type_view.xml @@ -4,11 +4,12 @@ estate.property.type -
+ - + +
diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 8d1623e40fb..4e681155168 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -6,9 +6,8 @@
-
@@ -19,12 +18,16 @@ + + + + @@ -69,6 +72,7 @@ + @@ -86,6 +90,7 @@ + From 03f32adefb8a248fb86ce29481c8de39976f80da Mon Sep 17 00:00:00 2001 From: lokesh Date: Mon, 14 Sep 2026 16:11:54 +0530 Subject: [PATCH 9/9] [FIX] estate: resolve review feedback for estate property 1> awesome_dashboard/__manifest__.py - fixed the 'name' in the __manifest__.py file of awesome_dashboard 2> estate/models/__init__.py - imported as per the odoo standard 3> estate/models/estate_property.py - changed the model name - implement better logic to calculate next 3 months date - fixed the name of property type in model - removed extra spaces - removed the accpeted check in the _compute_offers function 4> estate/views/estate_property_views.xml - fixed the string name to improve the UI --- awesome_dashboard/__manifest__.py | 36 ++++++++---------- estate/__manifest__.py | 1 + estate/models/__init__.py | 10 ++--- estate/models/estate_property.py | 46 ++++++++--------------- estate/models/estate_property_offers.py | 33 +++++++++++++++- estate/security/ir.model.access.csv | 1 + estate/views/estate_property_menu.xml | 16 +++++--- estate/views/estate_property_tag_view.xml | 10 +++++ estate/views/estate_property_views.xml | 14 ++++--- 9 files changed, 98 insertions(+), 69 deletions(-) create mode 100644 estate/views/estate_property_tag_view.xml diff --git a/awesome_dashboard/__manifest__.py b/awesome_dashboard/__manifest__.py index c24c020c649..a86d9bb991e 100644 --- a/awesome_dashboard/__manifest__.py +++ b/awesome_dashboard/__manifest__.py @@ -1,30 +1,26 @@ # -*- coding: utf-8 -*- { - 'name': "Awesome Dashboard1", - - 'summary': """ + "name": "Awesome Dashboard", + "summary": """ Starting module for "Discover the JS framework, chapter 2: Build a dashboard" """, - - 'description': """ + "description": """ Starting module for "Discover the JS framework, chapter 2: Build a dashboard" """, - - 'author': "Odoo", - 'website': "https://www.odoo.com/", - 'category': 'Tutorials', - 'version': '0.1', - 'application': True, - 'installable': True, - 'depends': ['base', 'web', 'mail', 'crm'], - - 'data': [ - 'views/views.xml', + "author": "Odoo", + "website": "https://www.odoo.com/", + "category": "Tutorials", + "version": "0.1", + "application": True, + "installable": True, + "depends": ["base", "web", "mail", "crm"], + "data": [ + "views/views.xml", ], - 'assets': { - 'web.assets_backend': [ - 'awesome_dashboard/static/src/**/*', + "assets": { + "web.assets_backend": [ + "awesome_dashboard/static/src/**/*", ], }, - 'license': 'AGPL-3' + "license": "AGPL-3", } diff --git a/estate/__manifest__.py b/estate/__manifest__.py index b143fd69227..18fa1afb8b0 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -10,6 +10,7 @@ "security/ir.model.access.csv", "views/estate_property_views.xml", # the order should be like this, first we need to define the views and then we need to define the action and then the menu if the order is not maintained then error will be thrown. "views/estate_property_type_view.xml", + "views/estate_property_tag_view.xml", "views/estate_property_menu.xml", ], "assets": { diff --git a/estate/models/__init__.py b/estate/models/__init__.py index d94b9f7ac63..5f7fb776fd7 100644 --- a/estate/models/__init__.py +++ b/estate/models/__init__.py @@ -1,6 +1,4 @@ -from . import ( - estate_property, - estate_property_offers, - estate_property_tag, - estate_property_type, -) +from . import estate_property +from . import estate_property_offers +from . import estate_property_tag +from . import estate_property_type diff --git a/estate/models/estate_property.py b/estate/models/estate_property.py index 9159efc4d68..1bc6c395a06 100644 --- a/estate/models/estate_property.py +++ b/estate/models/estate_property.py @@ -1,29 +1,20 @@ -from datetime import datetime - -from odoo import api, fields, models +from dateutil.relativedelta import relativedelta +from odoo import api +from odoo import fields +from odoo import models from odoo.exceptions import ValidationError -class TestModel(models.Model): - today = datetime.now() - - month = today.month + 3 - year = today.year - day = today.day - - if month > 12: - year = year + 1 - month = month % 12 - - three_month_date = today.replace(year=year, month=month, day=day) - +class EstateProperty(models.Model): _name = "estate.property" _description = "This is a dummy table" name = fields.Char(translate=True, default="Unknown", required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date(copy=False, default=three_month_date.date()) + date_availability = fields.Date( + copy=False, default=lambda self: fields.Date.today() + relativedelta(months=3) + ) expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) bedrooms = fields.Integer() @@ -52,34 +43,28 @@ class TestModel(models.Model): ] ) active = fields.Boolean("Active", default=True) - property_type_id = fields.Many2one("estate.property.type", string="Property_type") + property_type_id = fields.Many2one("estate.property.type", string="Property Type") property_tag_ids = fields.Many2many( "estate.property.tag", relation="losbo_property_propertyTag", string="Property_Tag", + column1="estate_property_id", + column2="estate_property_tag_id", ondelete="cascade", ) - buyer = fields.Many2one("res.partner", string="buyer", copy=False) user_id = fields.Many2one( "res.users", string="salesperson", default=lambda self: self.env.user ) offer_ids = fields.One2many("estate.property.offers", "property_id") - total_offers = fields.Integer(compute="_compute_offers") - total_area = fields.Float(compute="_compute_area") best_price = fields.Integer(compute="_compute_price") @api.depends("offer_ids") def _compute_offers(self): for record in self: - count = 0 - if record.offer_ids: - for offers in record.offer_ids: - if offers.status == "accepted": - count += 1 - record.total_offers = count + record.total_offers = len(record.offer_ids) @api.constrains("name", "description") def _check_description(self): @@ -94,8 +79,7 @@ def _compute_area(self): @api.depends("offer_ids.price") def _compute_price(self): - best_price = 0 for records in self: - for offers in records.offer_ids: - best_price = max(offers.price, best_price) - records.best_price = best_price + records.best_price = max(records.offer_ids.mapped("price"), default=0) + + # @api.onchange('') diff --git a/estate/models/estate_property_offers.py b/estate/models/estate_property_offers.py index 9e3e306e316..d1915c66922 100644 --- a/estate/models/estate_property_offers.py +++ b/estate/models/estate_property_offers.py @@ -1,4 +1,8 @@ -from odoo import fields, models +from datetime import date +from dateutil.relativedelta import relativedelta +from odoo import api +from odoo import fields +from odoo import models class PropertyOffer(models.Model): @@ -9,3 +13,30 @@ class PropertyOffer(models.Model): status = fields.Selection([("accepted", "Accepted"), ("refused", "Refused")]) partner_id = fields.Many2one("res.partner", required=True) property_id = fields.Many2one("estate.property", required=True, ondelete="cascade") + deadline = fields.Date( + default=date.today(), + copy=False, + compute="_compute_deadline", + readonly=False, + # store=True, + ) + validity_days = fields.Integer( + default=0, + copy=False, + compute="_compute_validity", + readonly=False, + # store=True + ) + + @api.depends("validity_days") + def _compute_deadline(self): + for records in self: + records.deadline = date.today() + relativedelta(days=records.validity_days) + + @api.depends("deadline") + def _compute_validity(self): + for records in self: + diff = relativedelta(records.deadline, date.today()) + records.validity_days = diff.days + + # def inverse_func(self): diff --git a/estate/security/ir.model.access.csv b/estate/security/ir.model.access.csv index a6013d437c5..2b3daeb78ff 100644 --- a/estate/security/ir.model.access.csv +++ b/estate/security/ir.model.access.csv @@ -4,3 +4,4 @@ access_estate_property_user,estate.property.user,model_estate_property,base.grou access_estate_property_type_user,estate.property.type.user,model_estate_property_type,base.group_user,1,1,1,1 access_estate_property_tag_user,estate.property.tag.user,model_estate_property_tag,base.group_user,1,1,1,1 access_estate_property_offer_user,estate.property.offer.user,model_estate_property_offers,base.group_user,1,1,1,1 +access_estate_property_tag,estate.property.tag.user,model_estate_property_tag,base.group_user,1,1,1,1 diff --git a/estate/views/estate_property_menu.xml b/estate/views/estate_property_menu.xml index 4d13f8652f2..943c120ea86 100644 --- a/estate/views/estate_property_menu.xml +++ b/estate/views/estate_property_menu.xml @@ -2,20 +2,26 @@ - - + + + + + + property tag + estate.property.tag + list,form + + + diff --git a/estate/views/estate_property_views.xml b/estate/views/estate_property_views.xml index 4e681155168..ac1da370512 100644 --- a/estate/views/estate_property_views.xml +++ b/estate/views/estate_property_views.xml @@ -12,7 +12,7 @@ - + @@ -21,7 +21,7 @@ - + @@ -51,10 +51,12 @@ - - - - + + + + + +