Skip to content

Conversation

@SurryaT10
Copy link

Initialized Estate module and created 'estate_property' model.

…nifest.

Created 'estate_property' model and fields.
@robodoo
Copy link

robodoo commented Dec 15, 2025

Pull request status dashboard

@lost-odoo
Copy link

Hello, can you please ensure that your runbot is green 😄

Copy link

@lost-odoo lost-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, I already made a small review. Not a big deal but just some nitpicking stuff that we try to avoid. 😄

@lost-odoo
Copy link

Also please don't forget to make one commit per chapter. Try to make a correct title. Don't hesitate to amend or squash your commits.

SurryaT10 added 2 commits December 18, 2025 09:51
Added estate_property_views.xml which contains list and form views

Added a separate estate_property_search_view.xml for search with filters for active and availability as well as group by based on postcode.

Also addressed code review comments.
Added estate.property.type model which specifies the type of property. Eg: House/Apartment

Added estate.property.tag model to indicate the tags(cozy, renovated) for each property

Added estate.property.offer model which indicates the offers for each property.

Also added views for each model mentioned above.
@lost-odoo
Copy link

Hey don't forget to close all the comments I did on the review when you did them 😄
Also please follow the git guidelines. ADD should only be used when you add a new module otherwise use IMP for an improvement.

lost-odoo and others added 2 commits December 18, 2025 10:39
total_area field is based on the size of both garden_area and living_area

best_offer field is based on the max price among the list of offers

Also added validity and deadline for the offers as a computed and inverse function impacting each other.
SurryaT10 added 2 commits December 19, 2025 09:19
Added Sold and Cancel buttons:
When a property is sold it cannot be canceled
When a property is canceled it cannot be sold

Added offer accept and rejected icon button:
When an offer is accepted:
 1. The selling price is automatically updated by button actions
 2. Status changes to 'Offer Accepted'
 3. Rejects all other offers

 Added  an onchange, which updates the status to 'Offer Received' when there is an offer.
Added SQL constraints for expected_price, selling_price, property_tag_name and property_type_name

Added python constraint for selling_price to be >= 90% of expected_price unless it is 0.0
Added ordering for the following:
property: Descending by ID
offer: Descending by price
tag: Name
type: Name

Added sequence ordering for type

Added color field for property tag.

Added invisible attribute for Sold, Cancel, Accept, Reject buttons

Added color decorations for list view.

Added offer count button to show the list of offers for a property type

Fixed code review changes.
SurryaT10 added 3 commits December 23, 2025 10:49
Added property_ids field for res.users model

Added the 'property_ids' field in 'Properties for Sale' page in 'Users & Companies' menu

Also removed trailing white spaces in estate.py selection fields
Added property_ids field for res.users model

Added the 'property_ids' field in 'Properties for Sale' page in 'Users & Companies' menu

Also removed trailing white spaces in estate.py selection fields
Added estate_account module

Overrided the action_mark_sold method to create an invoice when property is marked as Sold

Added 2 invoice lines:
one for 6% of selling price - brokerage fee
one for 100 - administrative fee
@SurryaT10 SurryaT10 force-pushed the 19.0-estate-sutha branch 2 times, most recently from d4377dc to 7603387 Compare December 23, 2025 15:21
Added a Kandban view for Properties
@api.model
def create(self, vals_list):
for record in vals_list:
property = self.env['estate.property'].browse(record["property_id"])

Choose a reason for hiding this comment

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

Avoid browsing in a loop, try to batch it by making the browse outside the loop


def action_mark_sold(self):
for record in self:
if record.status == "canceled":

Choose a reason for hiding this comment

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

simple quotes 😄
Same at other places

record.best_price = max(record.offer_ids.mapped('price')) if record.offer_ids else 0.0

@api.onchange('offer_ids')
def _onchange_property_status(self):

Choose a reason for hiding this comment

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

I think it should be named _onchange_offer_ids because it is offer_ids that is changing 😄

Comment on lines +62 to +65
if record.property_id.status == "offer_accepted" and record.property_id.buyer_id == record.partner_id:
record.property_id.selling_price = 0.0
record.property_id.buyer_id = False
record.property_id.status = "offer_received"

Choose a reason for hiding this comment

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

Does this make sense to reject an offer that got accepted ? Can a buyer make multiple offers ? if so then it is wrong I guess ?

def create(self, vals_list):
for record in vals_list:
property = self.env['estate.property'].browse(record["property_id"])
min_price = min(offer.price for offer in property.offer_ids) if property.offer_ids else 0

Choose a reason for hiding this comment

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

I don't think you are supposed to do that. The minimum price is 90 % of the property asked price.

Also when you do float comparisons, use float_compare.

color = fields.Integer("Color")

_unique_name = models.Constraint(
"UNIQUE(name)",

Choose a reason for hiding this comment

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

single quotes 👀

<templates>
<t t-name="card">
<field name="name" class="fw-bold"/>
<field name="status" invisible="1"/>

Choose a reason for hiding this comment

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

You could move that out of the card template and remove the invisible="1".

'depends': ['base', 'web', 'estate', 'account'],
'data': [],
'application': True,
'license': 'AGPL-3'

Choose a reason for hiding this comment

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

Do not forget auto_install to auto install this module when all its dependencies are installed.

'category': 'Tutorials',
'version': '1.0',

'depends': ['base', 'web', 'estate', 'account'],

Choose a reason for hiding this comment

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

Base and web are useless here as estate and account already depends on them 😄

self.env['account.move'].create({
'partner_id': record.buyer_id.id,
'move_type': "out_invoice",
'journal_id': self.env['account.journal'].search([('type', '=', 'sale')], limit=1).id,

Choose a reason for hiding this comment

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

Try to avoid doing search in loops even if it is unlikely to have multiple records to mark as sold at once 😄

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.

4 participants