-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ADD] estate: adding a new real estate module #317
base: 18.0
Are you sure you want to change the base?
Conversation
…new addon named estate_property, included 2 files namely __init__.py and __manifest__.py. Also created table with name estate_property with some fields in it.
Add access file 'ir.model.access.csv' with read, write, create and unlink permissions to the group base.group_user set to 1. Also imported the same file in manifest file in data field.
… - 5) Added menu xml files and created a UI which shows list and form views from where one can create, update and delete data from database. Made selling prices in read only mode and added 3 months from today's date in avalability date section.
…(chap - 6) Add and modified list view. Costomised form view. Added search options to be searched with multiple fields. Added multiple filter like availibility using current date and state selected. Also added group by option on similar postcode data.
Added relations between models with estate_property model. Many2one relation - estate_property_type Many2Many relation - estate_property_tag One2Many relation - estate_propery_offer
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @ptpu-odoo 👋,
Great work so far!
This is the first set of the review.
Please make sure to add a new line at the end of every file.
estate/__init__.py
Outdated
@@ -0,0 +1 @@ | |||
from . import models |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the unnecessary lines and ensure there is only one empty line per file.
estate/models/estate_property.py
Outdated
@@ -0,0 +1,68 @@ | |||
from odoo import api,fields, models | |||
# import for adding months with relativedelta |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the commented-out code.
estate/models/estate_property.py
Outdated
|
||
#function calculting total area by adding living area and garden area | ||
@api.depends('living_area', 'garden_area') | ||
def _compute_total_area(self): | ||
for record in self: | ||
record.total_area = record.living_area + record.garden_area | ||
|
||
#best price calculation | ||
@api.depends('offer_ids.price') | ||
def _computer_best_price(self): | ||
for record in self: | ||
if record.offer_ids: | ||
record.best_price = max(record.offer_ids.mapped('price')) | ||
else: | ||
record.best_price = 0.0 | ||
|
||
_name = "estate.property" | ||
_description = "Estate property tables" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#function calculting total area by adding living area and garden area | |
@api.depends('living_area', 'garden_area') | |
def _compute_total_area(self): | |
for record in self: | |
record.total_area = record.living_area + record.garden_area | |
#best price calculation | |
@api.depends('offer_ids.price') | |
def _computer_best_price(self): | |
for record in self: | |
if record.offer_ids: | |
record.best_price = max(record.offer_ids.mapped('price')) | |
else: | |
record.best_price = 0.0 | |
_name = "estate.property" | |
_description = "Estate property tables" | |
_name = "estate.property" | |
_description = "Estate property tables" | |
#function calculting total area by adding living area and garden area | |
@api.depends('living_area', 'garden_area') | |
def _compute_total_area(self): | |
for record in self: | |
record.total_area = record.living_area + record.garden_area | |
#best price calculation | |
@api.depends('offer_ids.price') | |
def _computer_best_price(self): | |
for record in self: | |
if record.offer_ids: | |
record.best_price = max(record.offer_ids.mapped('price')) | |
else: | |
record.best_price = 0.0 |
The model class declaration should be followed by the name and description.
Additionally, the description should clearly explain the purpose of adding the model.
estate/models/estate_property.py
Outdated
_name = "estate.property" | ||
_description = "Estate property tables" | ||
|
||
name = fields.Char(string="Title",required=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please explain the purpose of the required
parameter in this context?
Also, what would happen if it is not used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The required parameter is applied to the name field to ensure that the user provides a value. If the field is left empty, the form cannot be saved in the database.
estate/models/estate_property.py
Outdated
name = fields.Char(string="Title",required=True) | ||
description = fields.Text(string="Description") | ||
postcode = fields.Char(string="Postcode") | ||
date_availability = fields.Date(string="Available From",copy=False, default=(fields.Date.today()+relativedelta(months=+3))) #Added 3 months |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
date_availability = fields.Date(string="Available From",copy=False, default=(fields.Date.today()+relativedelta(months=+3))) #Added 3 months | |
date_availability = fields.Date(string="Available From", copy=False, default=(fields.Date.today() + relativedelta(months=+3))) #Added 3 months |
Please ensure the entire module follows coding guidelines by adding spaces wherever necessary.
Also, could you explain the purpose of default
and copy
parameter in this context?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The default parameter is used to assign default values to the field, which the user can modify if desired.
The copy parameter is configured to determine whether the field should be copied when duplicating the item.
estate/models/estate_property.py
Outdated
required=True, | ||
default="new", | ||
copy=False, | ||
selection=[('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
selection=[('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')], | |
selection=[ | |
('new', 'New'), | |
('offer_received', 'Offer Received'), | |
('offer_accepted', 'Offer Accepted'), | |
('sold', 'Sold'), | |
('cancelled', 'Cancelled')], |
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove the unnecessary lines
estate/security/ir.model.access.csv
Outdated
estate.access_estate_property,estate.access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 | ||
estate.access_estate_property_type,estate.access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 | ||
estate.access_estate_property_tag,estate.access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1 | ||
estate.access_estate_property_offer,estate.access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please explain why there's a 1,1,1,1 at the end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"1,1,1,1" at the end represents the permissions assigned to the user for reading, writing, creating, and deleting (unlinking) items.
<record id="estate_property_tag_action" model="ir.actions.act_window"> | ||
<field name="name">Estate Property Tag</field> | ||
<field name="res_model">estate.property.tag</field> | ||
<field name="view_mode">list,form</field> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of adding view_mode here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "view_mode" parameter specifies the views to be displayed for the model. In this case, it includes both the list and form views, through which the model will be presented to the user.
<h1 class="mb32"> | ||
<field name="name" class="mb16" /> | ||
</h1> | ||
<field name="tag" widget="many2many_tags"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of adding widget="many2many_tags" here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The widget="many2many_tags" is used to display the user interface in a way that allows users to select multiple tags from a dropdown, which are then displayed as tab-style pills.
<filter string="Available" name="date_availability" domain="[('date_availability', '>=', context_today())]"/> | ||
<!-- Filter on checking the availability and if the selected state is new or offer_recievied --> | ||
<filter string="New or Offer Recieved" name="state" domain="[('date_availability', '>=', context_today()), '|', ('state', '=', 'new'),('state', '=', 'offer_received')]"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please explain, What is the purpose of adding domain
attribute here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "domain" attribute is used to define the conditions for filters, specifying the criteria on which the filter should apply to the search.
<filter string="New or Offer Recieved" name="state" domain="[('date_availability', '>=', context_today()), '|', ('state', '=', 'new'),('state', '=', 'offer_received')]"/> | ||
<!-- Group by on similar postcode and making visible the remaining (no value in postcode field) --> | ||
<group expand="1" string="Group By"> | ||
<filter string="Postcode" name="postcode" context="{'group_by':'postcode', 'residual_visible':True}"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please explain, What is the purpose of adding context
attribute here?
Also, what does the group_by
, residual_visible
do?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "context" attribute is used with filters intended to function as group-by filters. It allows us to define the parameter by which the grouping should occur and determine whether the residual values should be visible.
The "group_by" option specifies the parameter on which the grouping function will be applied, while the "residual_visible" option controls the visibility of records that do not have a value in the specified parameter field (in this case, the postcode field).
dadb606
to
5a7a42c
Compare
Implemented compute and inverse function using @api decorater. 'depends' and 'onchange' decorater is implements here. Using 'depends' decorater, deadline date is calculated using the validity field and also inverse function of it is created. Using 'onchange' decorater, 'garden_area' and 'garden_orientation' is set on selecting the garden field, and it is set to default on unselecting the garden field.
5a7a42c
to
67e11e0
Compare
Implemented Sold and Cancel buttons in the header, with functionality to update the status based on the current status of the record. Introduced icon buttons to accept or decline an offer. Upon acceptance, the selling price and buyer's name are automatically updated based on the accepted offer. Additionally, ensured that only one offer can be accepted at a time.
Added constraints for: The property expected price must be strictly positive. The property selling price must be positive. The offer price must be strictly positive. The property tag name and property type name must be unique. Additionally, a constraint has been implemented to ensure that the selling price is not lower than 90% of the expected price.
69f871b
to
5451c5e
Compare
Added real estate module for tutorial purpose