From e01814d750b564383ee5a7c941e377de6529188b Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Fri, 8 May 2026 15:14:04 +0530 Subject: [PATCH 1/9] [ADD] estate: add empty module shell MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create the initial Odoo tutorial addon structure so the module is recognized in Apps and can be installed as an empty shell. This PR only adds the minimal required files (__manifest__.py and __init__.py) and does not introduce any models/views yet, following the Odoo “Chapter 2: A New Application” tutorial step. --- 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..9b79f977d17 --- /dev/null +++ b/estate/__manifest__.py @@ -0,0 +1,10 @@ +{ + 'name': 'Estate', + 'version': '0.1', + 'category': 'Tutorials', + 'summary': 'Real Estate Advertisement tutorial module (empty shell)', + 'depends': ['base'], + 'data': [], + 'application': True, + 'installable': True, +} From dd04a15adb2a5d8675e56ec3b00e281d8c18a6e6 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Wed, 13 May 2026 17:52:12 +0530 Subject: [PATCH 2/9] [ADD] estate: add author and license information to module manifest --- estate/__manifest__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/estate/__manifest__.py b/estate/__manifest__.py index 9b79f977d17..d7858141d24 100644 --- a/estate/__manifest__.py +++ b/estate/__manifest__.py @@ -3,6 +3,8 @@ 'version': '0.1', 'category': 'Tutorials', 'summary': 'Real Estate Advertisement tutorial module (empty shell)', + 'author': 'Patja', + 'license': 'LGPL-3', 'depends': ['base'], 'data': [], 'application': True, From 81f84a05071079169f1e782e2a22b9d37af5c192 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Fri, 15 May 2026 19:44:39 +0530 Subject: [PATCH 3/9] [REF] awesome_estate: renamed module and added initial model renamed 'estate' to 'awesome_estate' module and added initial property model for estate models and further implementations. And renamed to 'awesome_estate' 'cause why not, awesome anyways sounds better!!! --- awesome_estate/__init__.py | 1 + {estate => awesome_estate}/__manifest__.py | 2 +- awesome_estate/docs/chapter_2.md | 20 +++++++++ awesome_estate/docs/chapter_3.md | 41 +++++++++++++++++ awesome_estate/docs/initial.md | 44 +++++++++++++++++++ awesome_estate/models/__init__.py | 1 + .../models/awesome_estate_property.py | 31 +++++++++++++ estate/__init__.py | 0 8 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 awesome_estate/__init__.py rename {estate => awesome_estate}/__manifest__.py (89%) create mode 100644 awesome_estate/docs/chapter_2.md create mode 100644 awesome_estate/docs/chapter_3.md create mode 100644 awesome_estate/docs/initial.md create mode 100644 awesome_estate/models/__init__.py create mode 100644 awesome_estate/models/awesome_estate_property.py delete mode 100644 estate/__init__.py diff --git a/awesome_estate/__init__.py b/awesome_estate/__init__.py new file mode 100644 index 00000000000..0650744f6bc --- /dev/null +++ b/awesome_estate/__init__.py @@ -0,0 +1 @@ +from . import models diff --git a/estate/__manifest__.py b/awesome_estate/__manifest__.py similarity index 89% rename from estate/__manifest__.py rename to awesome_estate/__manifest__.py index d7858141d24..a0d14d9f22b 100644 --- a/estate/__manifest__.py +++ b/awesome_estate/__manifest__.py @@ -1,5 +1,5 @@ { - 'name': 'Estate', + 'name': 'Awesome Estate', 'version': '0.1', 'category': 'Tutorials', 'summary': 'Real Estate Advertisement tutorial module (empty shell)', diff --git a/awesome_estate/docs/chapter_2.md b/awesome_estate/docs/chapter_2.md new file mode 100644 index 00000000000..9f455848570 --- /dev/null +++ b/awesome_estate/docs/chapter_2.md @@ -0,0 +1,20 @@ + +Chapter 2: + +["base"] + +- my module needs Odoo core to be installed first + +Where base is in this repo: + +community/odoo/addons/base/ + +What base provides (high level): +- it loads fundamental UI framework pieces, and security bootstrap +- it sets up core records like languages, users, partners, currencies, companies, countries +- it also provides base security/group/access basics(Chapter 4) + +Why my module depends on it: +- without base, Odoo is missing required core models/config/security, so my module can’t install safely + +application:true suggests that is an installable app and false means its a module. diff --git a/awesome_estate/docs/chapter_3.md b/awesome_estate/docs/chapter_3.md new file mode 100644 index 00000000000..e74fbda332a --- /dev/null +++ b/awesome_estate/docs/chapter_3.md @@ -0,0 +1,41 @@ +# How are fields converted to DB? + +- `fields.Char` → varchar (if size set) or text +- `fields.Text` → text +- `fields.Integer` → int4 (PostgreSQL integer) +- `fields.Float` → numeric (with precision) or float8 (if no digits) +- `fields.Boolean` → bool +- `fields.Date` → date +- `fields.Datetime` → timestamp (without timezone — UTC) +- `fields.Selection` → varchar (stores the internal key string) +- `fields.Many2one` → int4 (foreign key) +- `fields.Binary` → bytea (if not attachment) or stored in `ir.attachment` +- `fields.Html` → text +- `fields.Monetary` → numeric (linked to a currency) + +--- + +## Blueprint / methods / required + +- `class` = blueprint +- `methods` = functions +- `required=True` translates to `NOT NULL` in SQL + +--- + +## Module namespace vs business concept + +- `awesome_estate` is the `__module__` namespace (a conventional prefix) +- `property` is the business concept inside that module + +So the technical model name becomes: `awesome_estate.property` + +--- + +## Selection: key vs label + +- __key__ / internal value (stored in DB) + - `"north"`, `"south"`, `"east"`, `"west"` + +- __label__ / display value (shown in UI) + - `"North"`, `"South"`, `"East"`, `"West"` diff --git a/awesome_estate/docs/initial.md b/awesome_estate/docs/initial.md new file mode 100644 index 00000000000..41052aad40d --- /dev/null +++ b/awesome_estate/docs/initial.md @@ -0,0 +1,44 @@ +# Notes + + +## Start odoo command: + +`./odoo-bin -d --addons-path=` + +### Breakdown: + +`./odoo-bin` : starts the Odoo server +`-d ` : which PostgreSQL database to use (for me: patja) +`--addons-path=` : comma-separated addon folders that Odoo will scan + +### it does: +- loads already-installed modules +- starts the UI and backend services + + +## Upgrade a module (Chapter - 3) + +### Command: + +`./odoo-bin -d -u --addons-path=` + +### Meaning: +`- -u ` : reload it and apply its model/data changes + +### it does: + +- after changing Python models (ORM), upgrade so database schema updates happen` +- after adding security/ACL, upgrade so access rules apply` + +### for me: + +`./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d patja -u awesome_estate` + + +## Install a module (first time) + +### Command: +`./odoo-bin -d -i --addons-path=` + +### Meaning: +`- -i `: install the module for the first time in that database diff --git a/awesome_estate/models/__init__.py b/awesome_estate/models/__init__.py new file mode 100644 index 00000000000..2419350f1e9 --- /dev/null +++ b/awesome_estate/models/__init__.py @@ -0,0 +1 @@ +from . import awesome_estate_property diff --git a/awesome_estate/models/awesome_estate_property.py b/awesome_estate/models/awesome_estate_property.py new file mode 100644 index 00000000000..4f6822396b2 --- /dev/null +++ b/awesome_estate/models/awesome_estate_property.py @@ -0,0 +1,31 @@ +from odoo import fields, models + + +class AwesomeEstateProperty(models.Model): + _name = "awesome_estate.property" + _description = "Real Estate Property" + + 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"), + ] + ) diff --git a/estate/__init__.py b/estate/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 From 432045c76f5b6e828113597f8aa261a14f056985 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Mon, 18 May 2026 18:09:41 +0530 Subject: [PATCH 4/9] [REF] awesome_estate: documentation formatting and clarity in chapters 2 and 3 --- awesome_estate/docs/chapter_2.md | 29 +++++++++-------- awesome_estate/docs/chapter_3.md | 53 ++++++++++++++++++++------------ awesome_estate/docs/initial.md | 51 +++++++++++++++--------------- 3 files changed, 77 insertions(+), 56 deletions(-) diff --git a/awesome_estate/docs/chapter_2.md b/awesome_estate/docs/chapter_2.md index 9f455848570..622ee340b0c 100644 --- a/awesome_estate/docs/chapter_2.md +++ b/awesome_estate/docs/chapter_2.md @@ -1,20 +1,25 @@ +# Chapter 2 -Chapter 2: +## Module dependency -["base"] +`base` -- my module needs Odoo core to be installed first +- My module needs Odoo core to be installed first. -Where base is in this repo: +### Where `base` lives in this repo -community/odoo/addons/base/ +`community/odoo/addons/base/` -What base provides (high level): -- it loads fundamental UI framework pieces, and security bootstrap -- it sets up core records like languages, users, partners, currencies, companies, countries -- it also provides base security/group/access basics(Chapter 4) +### What `base` provides -Why my module depends on it: -- without base, Odoo is missing required core models/config/security, so my module can’t install safely +- Fundamental UI framework pieces and security bootstrap. +- Core records like languages, users, partners, currencies, companies, and countries. +- Base security, group, and access basics (Chapter 4). -application:true suggests that is an installable app and false means its a module. +### Why my module depends on it + +Without `base`, Odoo is missing the required core models, configuration, and security layer, so my module cannot install safely. + +### Notes + +`application: true` suggests that this is an installable app, and `false` means it is a module. diff --git a/awesome_estate/docs/chapter_3.md b/awesome_estate/docs/chapter_3.md index e74fbda332a..60b4a7d9353 100644 --- a/awesome_estate/docs/chapter_3.md +++ b/awesome_estate/docs/chapter_3.md @@ -1,21 +1,21 @@ -# How are fields converted to DB? - -- `fields.Char` → varchar (if size set) or text -- `fields.Text` → text -- `fields.Integer` → int4 (PostgreSQL integer) -- `fields.Float` → numeric (with precision) or float8 (if no digits) -- `fields.Boolean` → bool -- `fields.Date` → date -- `fields.Datetime` → timestamp (without timezone — UTC) -- `fields.Selection` → varchar (stores the internal key string) -- `fields.Many2one` → int4 (foreign key) -- `fields.Binary` → bytea (if not attachment) or stored in `ir.attachment` -- `fields.Html` → text -- `fields.Monetary` → numeric (linked to a currency) +# How fields are converted to the database + +- `fields.Char` → `varchar` if a size is set, otherwise `text` +- `fields.Text` → `text` +- `fields.Integer` → `int4` (PostgreSQL integer) +- `fields.Float` → `numeric` with precision, or `float8` if no digits are set +- `fields.Boolean` → `bool` +- `fields.Date` → `date` +- `fields.Datetime` → `timestamp` without timezone (UTC) +- `fields.Selection` → `varchar` (stores the internal key string) +- `fields.Many2one` → `int4` (foreign key) +- `fields.Binary` → `bytea` if not attachment-backed, otherwise stored in `ir.attachment` +- `fields.Html` → `text` +- `fields.Monetary` → `numeric` linked to a currency --- -## Blueprint / methods / required +## Blueprint, methods, and required fields - `class` = blueprint - `methods` = functions @@ -25,17 +25,32 @@ ## Module namespace vs business concept -- `awesome_estate` is the `__module__` namespace (a conventional prefix) +- `awesome_estate` is the module namespace prefix - `property` is the business concept inside that module -So the technical model name becomes: `awesome_estate.property` +So the technical model name becomes `awesome_estate.property`. --- ## Selection: key vs label -- __key__ / internal value (stored in DB) +- **Key** / internal value stored in the database - `"north"`, `"south"`, `"east"`, `"west"` -- __label__ / display value (shown in UI) +- **Label** / display value shown in the UI - `"North"`, `"South"`, `"East"`, `"West"` + +--- + +## Chapter 3 verification + +### 1) Upgrade or install the module +`/home/odoo/odoo19/community/odoo-bin -d patja --addons-path=community/addons,enterprise,tutorials -u awesome_estate --stop-after-init` + +### 2) Check the table and columns +`psql -d patja -c "\pset pager off" -c "\d awesome_estate_property"` + +### 3) Check `required=True` becomes `NOT NULL` +`psql -d patja -c "\pset pager off" -c "SELECT column_name, is_nullable FROM information_schema.columns WHERE table_name='awesome_estate_property' AND column_name IN ('name', 'expected_price');"` + +You should see `is_nullable = NO` for `name` and `expected_price`. diff --git a/awesome_estate/docs/initial.md b/awesome_estate/docs/initial.md index 41052aad40d..d20f68537eb 100644 --- a/awesome_estate/docs/initial.md +++ b/awesome_estate/docs/initial.md @@ -1,44 +1,45 @@ # Notes +## Start Odoo command -## Start odoo command: +`odoo-bin -d --addons-path=` -`./odoo-bin -d --addons-path=` +### Breakdown -### Breakdown: +- `odoo-bin` starts the Odoo server. +- `-d ` selects which PostgreSQL database to use. +- `--addons-path=` is a comma-separated list of addon folders that Odoo scans. -`./odoo-bin` : starts the Odoo server -`-d ` : which PostgreSQL database to use (for me: patja) -`--addons-path=` : comma-separated addon folders that Odoo will scan - -### it does: -- loads already-installed modules -- starts the UI and backend services +### It does +- Loads already-installed modules. +- Starts the UI and backend services. -## Upgrade a module (Chapter - 3) +## Upgrade a module -### Command: +### Command -`./odoo-bin -d -u --addons-path=` +`odoo-bin -d -u --addons-path=` -### Meaning: -`- -u ` : reload it and apply its model/data changes +### Meaning -### it does: +`-u ` reloads the module and applies its model and data changes. -- after changing Python models (ORM), upgrade so database schema updates happen` -- after adding security/ACL, upgrade so access rules apply` +### It does -### for me: +- After changing Python models (ORM), upgrade the module so database schema changes happen. +- After adding security or ACLs, upgrade the module so access rules apply. -`./odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d patja -u awesome_estate` +### For me +`odoo-bin --addons-path=addons,../enterprise/,../tutorials/ -d patja -u awesome_estate` -## Install a module (first time) +## Install a module for the first time -### Command: -`./odoo-bin -d -i --addons-path=` +### Command -### Meaning: -`- -i `: install the module for the first time in that database +`odoo-bin -d -i --addons-path=` + +### Meaning + +`-i ` installs the module for the first time in that database. From 33506e522642c79231190e9e220e9880ffd1f9ed Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Mon, 18 May 2026 18:52:42 +0530 Subject: [PATCH 5/9] [ADD] awesome_estate: add access rights for estate.property - Added the ACL file for `estate.property` - Learned how Odoo uses `ir.model.access.csv` to grant CRUD access - Gave internal users the permissions needed to work with the model Chapter 4 - Security --- awesome_estate/__manifest__.py | 4 +- awesome_estate/docs/chapter_4.md | 93 +++++++++++++++++++++ awesome_estate/security/ir.model.access.csv | 2 + 3 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 awesome_estate/docs/chapter_4.md create mode 100644 awesome_estate/security/ir.model.access.csv diff --git a/awesome_estate/__manifest__.py b/awesome_estate/__manifest__.py index a0d14d9f22b..a775ac7bc02 100644 --- a/awesome_estate/__manifest__.py +++ b/awesome_estate/__manifest__.py @@ -6,7 +6,9 @@ 'author': 'Patja', 'license': 'LGPL-3', 'depends': ['base'], - 'data': [], + 'data': [ + 'security/ir.model.access.csv', + ], 'application': True, 'installable': True, } diff --git a/awesome_estate/docs/chapter_4.md b/awesome_estate/docs/chapter_4.md new file mode 100644 index 00000000000..b09a86836e9 --- /dev/null +++ b/awesome_estate/docs/chapter_4.md @@ -0,0 +1,93 @@ +# Security + +- module: `awesome_estate` +- model: `awesome_estate.property` +- ACL file: `tutorials/awesome_estate/security/ir.model.access.csv` +- manifest entry: `data: ['security/ir.model.access.csv']` + +If a model has no access rights, Odoo treats it as inaccessible and prints a warning in the logs. + +--- + +1. **Access rights (ACLs)** + Model-level permissions: + - read + - write + - create + - unlink + +2. **Groups** + ACLs are assigned to a group like `base.group_user`. + +3. **Record rules** + Used later to limit which records a group can see or edit. + +For Chapter 4, the important part is ACLs. + +--- + +## ACL file format + +File: `tutorials/awesome_estate/security/ir.model.access.csv` + +```csv +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_awesome_estate_property,access_awesome_estate_property,model_awesome_estate_property,base.group_user,1,1,1,1 +``` + +### What each part means + +- `id` + External ID of the access rule record. + +- `name` + Human-readable name. + +- `model_id:id` + Model the rule applies to. + For `awesome_estate.property`, the value is: + - `model_awesome_estate_property` + +- `group_id:id` + Group that gets the permissions. + Here: + - `base.group_user` + +- `perm_read` + Can read records. + +- `perm_write` + Can edit records. + +- `perm_create` + Can create records. + +- `perm_unlink` + Can delete records. + In Odoo, `unlink` means delete. + +### What this row gives + +This row gives internal users in `base.group_user` full access to the model: + +- read = 1 +- write = 1 +- create = 1 +- unlink = 1 + +--- + +## Manifest wiring + +File: `tutorials/awesome_estate/__manifest__.py` + +```python +'data': ['security/ir.model.access.csv'], +``` + +Why this matters: + +- Odoo only loads security data files if they are declared in the manifest. +- The file is loaded when the module is installed or upgraded. + +--- diff --git a/awesome_estate/security/ir.model.access.csv b/awesome_estate/security/ir.model.access.csv new file mode 100644 index 00000000000..07b5b347867 --- /dev/null +++ b/awesome_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_awesome_estate_property,access_awesome_estate_property,model_awesome_estate_property,base.group_user,1,1,1,1 From b76f7afb40e286cd21ceddb05c35c05e7303a7d7 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Wed, 20 May 2026 18:23:40 +0530 Subject: [PATCH 6/9] [ADD] awesome_estate: add chapter 5 UI, field, and docs - Added the act_window action and menu hierarchy for the property UI - Added field behavior on awesome_estate.property: readonly, copy, defaults, active, and state - Documented the chapter 5 concepts, selection keys vs labels, date defaults, and developer flags --- awesome_estate/__manifest__.py | 1 + awesome_estate/docs/chapter_5.md | 48 +++++++++++++++++++ .../models/awesome_estate_property.py | 38 +++++++++++---- .../views/awesome_estate_property_views.xml | 12 +++++ 4 files changed, 91 insertions(+), 8 deletions(-) create mode 100644 awesome_estate/docs/chapter_5.md create mode 100644 awesome_estate/views/awesome_estate_property_views.xml diff --git a/awesome_estate/__manifest__.py b/awesome_estate/__manifest__.py index a775ac7bc02..b148b3c9f73 100644 --- a/awesome_estate/__manifest__.py +++ b/awesome_estate/__manifest__.py @@ -8,6 +8,7 @@ 'depends': ['base'], 'data': [ 'security/ir.model.access.csv', + 'views/awesome_estate_property_views.xml', ], 'application': True, 'installable': True, diff --git a/awesome_estate/docs/chapter_5.md b/awesome_estate/docs/chapter_5.md new file mode 100644 index 00000000000..64a9ef48156 --- /dev/null +++ b/awesome_estate/docs/chapter_5.md @@ -0,0 +1,48 @@ +# Chapter 5 - First UI + +## Action and Menus +- **Action (`ir.actions.act_window`)**: Connects a model to the UI, specifying view modes like `list,form`. +- **Menu Hierarchy**: 3 levels deep: Root Menu -> First Level Menu -> Action Menu. +- **Manifest Order**: XML files containing these UI definitions must be added to `__manifest__.py` under `data`. Data is loaded sequentially! + +## Field Attributes +- `required=True`: Field cannot be empty. Translates to `NOT NULL` in the DB. +- `copy=False`: Prevents the field value from duplicating when a user clicks the "Duplicate" action on a record. Used for unique or situational data like `date_availability` or `selling_price`. +- `readonly=True`: Makes the field uneditable from the UI. E.g., `selling_price` updates programmatically when an offer is accepted, not by manual entry. + +## Default Values +- Pre-populates a field logically when "New" is clicked. +- Can be a literal (`default=2`) or evaluated via an anonymous function. +- **Why use `lambda self:` for logic?**: If you say `default=date.today()`, Python computes it *once* when the Odoo server boots. Using `lambda self: date.today() + relativedelta(months=3)` evaluates dynamically at the *exact moment* the record is created. + +## Reserved Fields +- **`active`**: Special boolean field. If `False`, the record is "Archived" and automatically hidden from standard searches (without deleting DB row). +- **`state`**: Selection field commonly used to drive business flow (e.g., New -> Offer Received -> Sold). + +## Python / Odoo Conventions +- **String quotes (`''` vs `""`)**: Mechanically identical in Python. By Odoo / PEP 8 convention, use single quotes `''` for internal strings (keys, backend values) and double quotes `""` for UI text or docstrings. + +## Selection Fields +Are lists of tuples acting as Key/Value pairs: `('north', 'North')` +- **Key (`'north'`)**: Backend identifier. Lower-case, internal logic, stored in DB. +- **Label (`'North'`)**: UI string. Shown to the user, can be translated easily. + +## Date Imports +- `datetime.date`: Native module for server calendar dates (`date.today()`). +- `dateutil.relativedelta`: Robust utility that cleanly handles calendar leaps when calculating logic like `months=3`. Other periods supported: `years`, `months`, `weeks`, `days`, `hours`. + +## Implementation Proof +All rules required by the Chapter 5 tutorial (readonly/copy overrides, dynamic default date, correctly formatted status options, active field implementation) have been applied exactly to specification in `awesome_estate_property.py`. + +## Developer Setup Notes (`--dev`) +When executing and testing UI/view creations regularly, use the backend server command flag `--dev=all`. It auto-reloads your codebase so you bypass server restarts. +```bash +./odoo-bin -d patja -u awesome_estate --dev=all +``` +**Common `--dev=` parameters:** +- `all`: Enables all developer configurations below. +- `reload`: Automatically bounces the python worker when Python code changes are detected. +- `qweb`: Forces QWeb templates/XML to read directly from disks instead of reading from the database caching engine. Highly recommended when editing views! +- `werkzeug`: Routes exceptions natively to the debug interactive debugger. +- `xml`: Validates XML files are structurally whole before trying to push them to PostgreSQL. + diff --git a/awesome_estate/models/awesome_estate_property.py b/awesome_estate/models/awesome_estate_property.py index 4f6822396b2..b519970dc33 100644 --- a/awesome_estate/models/awesome_estate_property.py +++ b/awesome_estate/models/awesome_estate_property.py @@ -1,19 +1,26 @@ +from datetime import date + +from dateutil.relativedelta import relativedelta + from odoo import fields, models class AwesomeEstateProperty(models.Model): - _name = "awesome_estate.property" + _name = 'awesome_estate.property' _description = "Real Estate Property" name = fields.Char(required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date() + date_availability = fields.Date( + copy=False, + default=lambda self: 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() facades = fields.Integer() @@ -21,11 +28,26 @@ class AwesomeEstateProperty(models.Model): garden = fields.Boolean() garden_area = fields.Integer() + active = fields.Boolean(default=True) + + state = fields.Selection( + [ + ('new', "New"), + ('offer_received', "Offer Received"), + ('offer_accepted', "Offer Accepted"), + ('sold', "Sold"), + ('cancelled', "Cancelled"), + ], + required=True, + copy=False, + default='new', + ) + garden_orientation = fields.Selection( [ - ("north", "North"), - ("south", "South"), - ("east", "East"), - ("west", "West"), + ('north', "North"), + ('south', "South"), + ('east', "East"), + ('west', "West"), ] ) diff --git a/awesome_estate/views/awesome_estate_property_views.xml b/awesome_estate/views/awesome_estate_property_views.xml new file mode 100644 index 00000000000..feb56fee27b --- /dev/null +++ b/awesome_estate/views/awesome_estate_property_views.xml @@ -0,0 +1,12 @@ + + + + Properties + awesome_estate.property + list,form + + + + + + From c104948efc7ed65d0dcd4e126e684723abbb35a4 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Wed, 20 May 2026 19:26:44 +0530 Subject: [PATCH 7/9] [REF] awesome_estate: fix model name formatting and clean up whitespace according to coding guidelines. --- awesome_estate/models/awesome_estate_property.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/awesome_estate/models/awesome_estate_property.py b/awesome_estate/models/awesome_estate_property.py index b519970dc33..2149635810b 100644 --- a/awesome_estate/models/awesome_estate_property.py +++ b/awesome_estate/models/awesome_estate_property.py @@ -6,30 +6,25 @@ class AwesomeEstateProperty(models.Model): - _name = 'awesome_estate.property' + _name = 'awesome.estate.property' _description = "Real Estate Property" name = fields.Char(required=True) description = fields.Text() postcode = fields.Char() - date_availability = fields.Date( copy=False, default=lambda self: date.today() + relativedelta(months=3), ) expected_price = fields.Float(required=True) selling_price = fields.Float(readonly=True, copy=False) - bedrooms = fields.Integer(default=2) living_area = fields.Integer() facades = fields.Integer() - garage = fields.Boolean() garden = fields.Boolean() garden_area = fields.Integer() - active = fields.Boolean(default=True) - state = fields.Selection( [ ('new', "New"), @@ -42,7 +37,6 @@ class AwesomeEstateProperty(models.Model): copy=False, default='new', ) - garden_orientation = fields.Selection( [ ('north', "North"), From ff6f2a0b698057224efdd142dfeb29e216882837 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Thu, 21 May 2026 12:28:54 +0530 Subject: [PATCH 8/9] [FIX] awesome_estate: correct model name in view file The XML view file was referencing the model as "awesome_estate.property" with underscores, from previous model name. Fixes the ParseError: "Invalid model name 'awesome_estate.property' in action definition" that occurred during module loading. --- awesome_estate/views/awesome_estate_property_views.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/awesome_estate/views/awesome_estate_property_views.xml b/awesome_estate/views/awesome_estate_property_views.xml index feb56fee27b..7c41cd36e9a 100644 --- a/awesome_estate/views/awesome_estate_property_views.xml +++ b/awesome_estate/views/awesome_estate_property_views.xml @@ -2,11 +2,11 @@ Properties - awesome_estate.property + awesome.estate.property list,form - + \ No newline at end of file From 571c953dcf3edb9af21928d980fb4b71ca1de952 Mon Sep 17 00:00:00 2001 From: Jay Patel Date: Fri, 22 May 2026 19:22:12 +0530 Subject: [PATCH 9/9] [ADD] awesome_estate: added list, form, and search layouts to property view. --- .../views/awesome_estate_property_views.xml | 100 ++++++++++++++++-- 1 file changed, 92 insertions(+), 8 deletions(-) diff --git a/awesome_estate/views/awesome_estate_property_views.xml b/awesome_estate/views/awesome_estate_property_views.xml index 7c41cd36e9a..0e32b14700c 100644 --- a/awesome_estate/views/awesome_estate_property_views.xml +++ b/awesome_estate/views/awesome_estate_property_views.xml @@ -1,12 +1,96 @@ - - Properties - awesome.estate.property - list,form + + + + awesome.estate.property.list + awesome.estate.property + + + + + + + + + + + + + + + + + + awesome.estate.property.form + awesome.estate.property + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + awesome.estate.property.search + awesome.estate.property + + + + + + + + + + + + + + + + + + + Properties + awesome.estate.property + list,form - - - -
\ No newline at end of file + + + + + +