Skip to content

Conversation

@jugurtha-gaci
Copy link

Create the estate module

@robodoo
Copy link

robodoo commented Oct 20, 2025

Pull request status dashboard

@Mathilde411 Mathilde411 changed the title [ADD] estate: create the app JUGAC Onboarding Oct 20, 2025
@Mathilde411 Mathilde411 self-requested a review October 20, 2025 11:57
@Mathilde411 Mathilde411 self-assigned this Oct 20, 2025
Copy link

@Mathilde411 Mathilde411 left a comment

Choose a reason for hiding this comment

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

Small comments :)

@Mathilde411 Mathilde411 self-requested a review October 21, 2025 11:18
@Mathilde411 Mathilde411 removed their assignment Oct 21, 2025
Copy link

@Mathilde411 Mathilde411 left a comment

Choose a reason for hiding this comment

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

Good work :)
Please look at your runbot and make it green.
Also take a look at the naming conventions: https://www.odoo.com/documentation/19.0/contributing/development/coding_guidelines.html#xml-ids-and-naming

Comment on lines 39 to 45
state = fields.Selection(
selection=[
('new', 'New'),
('received', 'Received'),
('accepted', 'Accepted')
]
)

Choose a reason for hiding this comment

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

Suggested change
state = fields.Selection(
selection=[
('new', 'New'),
('received', 'Received'),
('accepted', 'Accepted')
]
)
state = fields.Selection(
selection=[
('new', 'New'),
('received', 'Received'),
('accepted', 'Accepted')
], required=True, default='new'
)

state should always be set, and new by default

Choose a reason for hiding this comment

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

This again

buyer_id = fields.Many2one("res.partner")
salesman_id = fields.Many2one("res.users")
tag_ids = fields.Many2many("estate.property.tag")
offer_ids = fields.One2many("estate.property.offer", "partner_id") No newline at end of file

Choose a reason for hiding this comment

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

Missing newline


class EstateProperty(models.Model):
_name = "estate.property"
_description = "Table that stores the estate properties"

Choose a reason for hiding this comment

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

Suggested change
_description = "Table that stores the estate properties"
_description = "Estate Property"

_description is the human-readable name of the model, not an actual description. It' a misnomer.


</menuitem>
</data>
</odoo> No newline at end of file

Choose a reason for hiding this comment

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

Missing newline

</field>
</record>
</data>
</odoo> No newline at end of file

Choose a reason for hiding this comment

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

Missing newline

</field>
</record>

</odoo> No newline at end of file

Choose a reason for hiding this comment

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

Missing newline

@@ -0,0 +1 @@
from . import models No newline at end of file

Choose a reason for hiding this comment

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

Missing newline

Comment on lines 60 to 70
<list string="Estate offers">
<group>
<field name="price"/>
</group>
<group>
<field name="partner_id"/>
</group>
<group>
<field name="status"/>
</group>
</list>

Choose a reason for hiding this comment

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

Suggested change
<list string="Estate offers">
<group>
<field name="price"/>
</group>
<group>
<field name="partner_id"/>
</group>
<group>
<field name="status"/>
</group>
</list>
<list string="Estate offers">
<field name="price"/>
<field name="partner_id"/>
<field name="status"/>
</list>

No groups needed in a list view

Comment on lines 74 to 76
<group> <field name="salesman_id"/> </group>
<group> <field name="buyer_id"/> </group>
<group> <field name="buyer_id"/> </group>

Choose a reason for hiding this comment

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

Same here, only one group needed

Copy link

@Mathilde411 Mathilde411 left a comment

Choose a reason for hiding this comment

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

Did you test everything ? Ifeel like some parts would outright not work at all.
Good work overall though. :)

from . import estate_type
from . import estate_tag
from . import estate_offer
from . import users

Choose a reason for hiding this comment

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

Suggested change
from . import users
from . import res_users

Model name is res.users, so here the file name should be res_users.py

Comment on lines +37 to +40
@api.depends("date_deadline")
def _inverse_validity(self):
for record in self:
record.validity = (record.date_deadline - record.create_date).days

Choose a reason for hiding this comment

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

What happens here if I put False in date_deadline ? date_deadline is not required

Comment on lines +51 to +54
def action_refuse(self):
for record in self:
record.status = 'refused'
return True

Choose a reason for hiding this comment

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

Suggested change
def action_refuse(self):
for record in self:
record.status = 'refused'
return True
def action_refuse(self):
record.status = 'refused'
return True

This works

Comment on lines +56 to +68
@api.model
def create(self, vals_list):

for offer in self:
if offer.price > vals_list.price:
raise UserError('The offer price should be greater than those already received')

res = super().create(vals_list)

if res.property_id.state != 'received':
res.property_id.state = 'received'

return res

Choose a reason for hiding this comment

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

Suggested change
@api.model
def create(self, vals_list):
for offer in self:
if offer.price > vals_list.price:
raise UserError('The offer price should be greater than those already received')
res = super().create(vals_list)
if res.property_id.state != 'received':
res.property_id.state = 'received'
return res
@api.model_create_multi
def create(self, vals_list):
for offer in self:
if offer.price > vals_list.price:
raise UserError('The offer price should be greater than those already received')
res = super().create(vals_list)
if res.property_id.state != 'received':
res.property_id.state = 'received'
return res

Did you test this ? vals_list should be a List[Dict[str, Any]], so this wouldn't work.
To make sure mark it as model_create_multi. it makes sure that vals_list is always that.

Comment on lines 39 to 45
state = fields.Selection(
selection=[
('new', 'New'),
('received', 'Received'),
('accepted', 'Accepted')
]
)

Choose a reason for hiding this comment

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

This again

Comment on lines +81 to +87
def action_set_sold(self):
for record in self:
if record.state == 'canceled':
raise UserError('A canceled property cannot be sold')
else:
record.state = 'sold'
return True

Choose a reason for hiding this comment

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

Suggested change
def action_set_sold(self):
for record in self:
if record.state == 'canceled':
raise UserError('A canceled property cannot be sold')
else:
record.state = 'sold'
return True
def action_set_sold(self):
for record in self:
if record.state == 'canceled':
raise UserError('A canceled property cannot be sold')
record.state = 'sold'
return True

else not needed here. The exception will break the flow anyways

Comment on lines +89 to +95
def action_set_canceled(self):
for record in self:
if record.state == 'sold':
raise UserError('A sold property cannot be canceled')
else:
record.state = 'canceled'
return True

Choose a reason for hiding this comment

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

Suggested change
def action_set_canceled(self):
for record in self:
if record.state == 'sold':
raise UserError('A sold property cannot be canceled')
else:
record.state = 'canceled'
return True
def action_set_canceled(self):
for record in self:
if record.state == 'sold':
raise UserError('A sold property cannot be canceled')
record.state = 'canceled'
return True

ditto

Comment on lines +102 to +112
@api.constrains('selling_price')
def _check_selling_price(self):
for record in self:
if record.state in ("new", "received"):
return

if float_compare(record.selling_price, (record.expected_price * 0.9), 2) < 0:
raise ValidationError("The selling price cannot be lower than 90%% of the expected price")

if float_is_zero(record.selling_price, 2):
raise ValidationError("The selling price should be positive")

Choose a reason for hiding this comment

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

Suggested change
@api.constrains('selling_price')
def _check_selling_price(self):
for record in self:
if record.state in ("new", "received"):
return
if float_compare(record.selling_price, (record.expected_price * 0.9), 2) < 0:
raise ValidationError("The selling price cannot be lower than 90%% of the expected price")
if float_is_zero(record.selling_price, 2):
raise ValidationError("The selling price should be positive")
@api.constrains('selling_price')
def _check_selling_price(self):
for record in self.filtered(lambda p: p.state not in ("new", "received")):
if float_compare(record.selling_price, (record.expected_price * 0.9), 2) < 0:
raise ValidationError("The selling price cannot be lower than 90%% of the expected price")
if float_is_zero(record.selling_price, 2):
raise ValidationError("The selling price should be positive")

This is more odooesque

Comment on lines +24 to +26
if created_invoice:
res = super().action_set_sold()
return res

Choose a reason for hiding this comment

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

What are you trying to do here ?

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