Skip to content
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: create a new module for real estate management #326

Draft
wants to merge 5 commits into
base: 18.0
Choose a base branch
from

Conversation

aych-odoo
Copy link

@aych-odoo aych-odoo commented Feb 6, 2025

Created a new Real Estate module for managing real estate properties as part of the training.

  • Properties can be added with a specified property type and assigned multiple tags.
  • Properties have a salesperson and a buyer assigned to them.
  • Offers can be made on properties, and the best price is automatically computed from the submitted offers.

@robodoo
Copy link

robodoo commented Feb 6, 2025

Pull request status dashboard

@aych-odoo aych-odoo changed the title test [ADD] estate: new module added Feb 6, 2025
Day 1:
  Chapter 2: created directory structure along with manifest file for estate module
  Chapter 3: created estate_properties model
Day 2:
  Chapter 4: created ir.model.access.csv to enable CRUD operation on property
  Chapter 5: created basic action and menu for estate property
  Chapter 6: created basic views for estate property i.e. list, form, search
  Chapter 7: created property type model and defined Many2one relation.
Copy link

@maad-odoo maad-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello 👋,

Added few comments and suggestions please have a look into it.
PR message is missing and commit messages can be improved.

Thank You :)

estate/__init__.py Show resolved Hide resolved
estate/__manifest__.py Show resolved Hide resolved
estate/models/__init__.py Show resolved Hide resolved
estate/models/estate_property.py Outdated Show resolved Hide resolved
estate/models/estate_property.py Show resolved Hide resolved
estate/models/estate_property_offer.py Show resolved Hide resolved
estate/views/estate_property_menu_views.xml Outdated Show resolved Hide resolved
estate/views/estate_property_views.xml Outdated Show resolved Hide resolved
estate/views/estate_property_views.xml Outdated Show resolved Hide resolved
estate/views/estate_property_views.xml Outdated Show resolved Hide resolved
Added the estate.property.offer model with One2many relation to estate.property,
allowing offers to be managed from the property form view.
Introduced the estate.property.tag model with a Many2many relation,
enabling tag creation via Settings -> Property Tags and
assignment through the Many2many widget.

Added computed fields:
total_area (sum of garden_area and living_area) and
best_price (highest offer price).
Implemented an onchange handler for the garden field to set or
reset related fields automatically.
@aych-odoo aych-odoo changed the title [ADD] estate: new module added [ADD] estate: create a new module which tracks properties Feb 7, 2025
@aych-odoo aych-odoo changed the title [ADD] estate: create a new module which tracks properties [ADD] estate: create a new module for real estate management Feb 7, 2025
Day 4:
Added 'sold' and 'cancel' actions to the property form view,
allowing properties to be marked as sold or canceled with proper validations.
Implemented logic to automatically set the selling price and buyer,
when an offer is accepted.
Added SQL constraints to ensure all price-related fields remain positive,
with selling_price required to be greater than 90% of expected_price.
Enforced unique constraints to prevent duplicate property tags and types.
Added default sorting across all estate models,
with sequence-based sorting for property types.
Enhanced the property, offers list view with color coding and
adjusted button visibility based on the property's status.
Day 5:
Added an Offers stat button in the property types view, which displays all
offers made on properties under the selected type.
Implemented restrictions on property deletion, allowing deletion only when the
property's state is New or Cancelled.
Extended res.users model with property_ids, enabling properties to be viewed
in the user profile.
Developed the estate_account module to facilitate invoicing,
ensuring an invoice is generated when a property is sold,
even if the user lacks access to the invoicing module.
Created a Kanban view for properties, grouped by property type.
Created Manager and Agent user groups with distinct access rights,
along with a security rule limiting Agents to viewing only the properties they
have created.
… property

Day 6:
Restricted property visibility for Agents to only those belonging to
their company by implementing a multi-company rule.
Updated access control to ensure that only users with the Manager role
can view the settings menu in the estate module.
Added demo data for the property, property_type, and property_offer models
to facilitate testing and development.
Integrated a chatter feature in the property model to track changes in the
property name.
Copy link

@maad-odoo maad-odoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hii 👋

Here is an another quick review

Comment on lines +111 to +119
class User(models.Model):
_inherit = "res.users"

property_ids = fields.One2many(
string="Properties",
comodel_name="estate.property",
inverse_name="salesperson_id",
domain="[('state', 'in', ['new', 'offer_received'])]"
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add this in a different file

record.validity = (record.date_deadline - record.create_date.date()).days

def action_accept_offer(self):
if any([x.status == "accepted" for x in self.property_id.offer_ids]):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if any([x.status == "accepted" for x in self.property_id.offer_ids]):
if any([property.status == "accepted" for property in self.property_id.offer_ids]):

copy=False
)
active = fields.Boolean(default=True)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary diff


total_area = fields.Integer(string="Total Area (sqm)", compute="_compute_total_area")
best_price = fields.Float(string="Best Price", compute="_compute_best_price")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary diff

def action_sell_property(self):
if self.state == "cancelled":
raise UserError("Cancelled property cannot be sold")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unnecessary diff

Comment on lines +37 to +40
<field name="name" width="200px" />
<field name="property_type_id" width="150px" />
<field name="postcode" width="150px" />
<field name="tag_ids" widget="many2many_tags" width="200px" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid using hard-coded style rules as this might not work for every screen size or for every case.

Comment on lines +60 to +67
<div> Expected Price: <field name="expected_price" />
</div>
<div t-if="record.state.raw_value == 'offer_received'"> Best Offer: <field
name="best_price" />
</div>
<div t-if="record.state.raw_value == 'offer_accepted'"> Selling Price: <field
name="selling_price" />
</div>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<div> Expected Price: <field name="expected_price" />
</div>
<div t-if="record.state.raw_value == 'offer_received'"> Best Offer: <field
name="best_price" />
</div>
<div t-if="record.state.raw_value == 'offer_accepted'"> Selling Price: <field
name="selling_price" />
</div>
<div>
Expected Price: <field name="expected_price" />
</div>
<div t-if="record.state.raw_value == 'offer_received'">
Best Offer: <field name="best_price" />
</div>
<div t-if="record.state.raw_value == 'offer_accepted'">
Selling Price: <field name="selling_price" />
</div>

Indentation

Comment on lines +83 to +84
<button name="action_sell_property" type="object" string="Sold"
invisible="state in ['offer_accepted', 'sold', 'cancelled']" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<button name="action_sell_property" type="object" string="Sold"
invisible="state in ['offer_accepted', 'sold', 'cancelled']" />
<button name="action_sell_property"
invisible="state in ['offer_accepted', 'sold', 'cancelled']"
type="object"
string="Sold"
/>

Comment on lines +85 to +90
<button name="action_sell_property" type="object" string="Sold"
invisible="state in ['new', 'offer_received', 'sold', 'cancelled']"
class="btn-primary" />
<!-- Cancel button-->
<button name="action_cancel_property" type="object" string="Cancel"
invisible="state in ['sold', 'cancelled']" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Refer to above comment ☝️

if not self.buyer_id.id:
raise UserError("Property without buyer cannot be sold")

self.env["estate.property"].check_access("write")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Put this in try.. expect block to avoid error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants