-
Notifications
You must be signed in to change notification settings - Fork 2.3k
[ADD] estate: Chapters 1-11 #873
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
base: 18.0
Are you sure you want to change the base?
Changes from 3 commits
0ab67dd
86d10e7
77a96c0
3d385e6
9399362
774b1fd
13be7a5
3e070f0
e206e1f
56b79fb
f120840
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models | ||
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,17 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'name': "estate", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'depends':['base'], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'application': True, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'data':['security/ir.model.access.csv', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'views/estate_property_views.xml', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'views/estate_property_tag_views.xml', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'views/estate_property_offer_views.xml', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'views/estate_property_type_views.xml', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'views/estate_property_menus.xml', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
'views/inherited_model_view.xml' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indentation is super important for readability so we always indent files in a pythonish way even in file types that don't require it.
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import estate_property, estate_property_type, estate_property_tag, estate_property_offer, inherited_model | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing EOL (End Of Line character (empty last line at the end of your file)) |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,119 @@ | ||||||||||||||
from odoo import models, fields, api | ||||||||||||||
from odoo.exceptions import UserError, ValidationError | ||||||||||||||
from odoo.tools import float_compare, float_is_zero | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The guidelines for the imports notably asks to sort all import (sources and imported elements alphabtically) so:
Suggested change
|
||||||||||||||
|
||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The runbot ci/style probably says that but we always have two blank lines between the imports and the models
Suggested change
|
||||||||||||||
class TestModel(models.Model): | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The class name of a model is always its
Suggested change
|
||||||||||||||
_name = "estate_property" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||
_description = "Basic fields in estate property" | ||||||||||||||
_order = "id desc" | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't checked if ci/style flags this but only ever one blank line everywhere except between the imports and the models. Other occurences of this lower in the diff 👍 |
||||||||||||||
name = fields.Char(required = True) | ||||||||||||||
description = fields.Text() | ||||||||||||||
postcode = fields.Char() | ||||||||||||||
date_availability = fields.Date(copy = False, default = fields.Date.add(fields.Date.today(), months = 3)) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably flagged by ci/style but i'll still say it, no spaces around the operators in a field definition 👍
Suggested change
Other occurences of this lower in the diff 👍 |
||||||||||||||
expected_price = fields.Float(required = True)# | ||||||||||||||
selling_price = fields.Float(readonly=True, copy = False) # | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
bedrooms = fields.Integer(default = 2) | ||||||||||||||
living_area = fields.Integer() | ||||||||||||||
facades = fields.Integer()# | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||
garage = fields.Boolean() | ||||||||||||||
garden = fields.Boolean() | ||||||||||||||
garden_area = fields.Integer() | ||||||||||||||
garden_orientation = fields.Selection( | ||||||||||||||
string='Garden Orientation', | ||||||||||||||
selection=[('North', 'North'),('South', 'South'), ('East', 'East'), ('West', 'West')]) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the
Suggested change
There is also another small detail here is that when you define a field on multiple lines, even the last lines takes a coma so that if someone was to add a line, he wouldn't apply a diff to yours to add his. |
||||||||||||||
active = fields.Boolean('Active', default = True) | ||||||||||||||
# New, Offer Received, Offer Accepted, Sold and Cancelled | ||||||||||||||
state = fields.Selection( | ||||||||||||||
string='State', | ||||||||||||||
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 commentThe reason will be displayed to describe this comment to others. Learn more. Related to my last comment, here there are multiple words technical values so they should look like that:
Suggested change
|
||||||||||||||
required = True, | ||||||||||||||
default = "New") | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Last line takes a coma and the closing parenthesis of the definition should be aligned with the field's name:
Suggested change
|
||||||||||||||
property_type_id = fields.Many2one("estate_property_type", string = "Property Type") | ||||||||||||||
salesperson = fields.Many2one('res.users', string='Salesman', default=lambda self: self.env.user) | ||||||||||||||
buyer = fields.Many2one('res.partner', string='Buyer', copy = False) | ||||||||||||||
tag_ids = fields.Many2many("estate_property_tag", string="Property Tags") | ||||||||||||||
offer_ids = fields.One2many(comodel_name="estate_property_offer", inverse_name = "property_id") | ||||||||||||||
total_area = fields.Integer(compute = "_compute_total_area") | ||||||||||||||
best_price = fields.Float(compute = "_compute_best_offer") | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Too many blank lines Other occurences of this lower in the diff 👍 |
||||||||||||||
@api.depends('living_area', 'garden_area') | ||||||||||||||
def _compute_total_area(self): | ||||||||||||||
for property in self: | ||||||||||||||
property.total_area = property.living_area + property.garden_area | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
@api.depends('offer_ids') | ||||||||||||||
def _compute_best_offer(self): | ||||||||||||||
for property in self: | ||||||||||||||
if len(property.offer_ids) > 0: | ||||||||||||||
property.best_price = max(property.offer_ids.mapped('price')) | ||||||||||||||
else: | ||||||||||||||
property.best_price = 0.0 | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
@api.onchange("garden") | ||||||||||||||
def _onchange_garden(self): | ||||||||||||||
if self.garden: | ||||||||||||||
self.garden_orientation = "North" | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you will have changed the technical value of the
Suggested change
Other occurences of this lower in the diff 👍 |
||||||||||||||
self.garden_area = 10 | ||||||||||||||
else: | ||||||||||||||
self.garden_area = 0 | ||||||||||||||
self.garden_orientation = '' | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It'd be better to set it as
Suggested change
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
def sell(self): | ||||||||||||||
for record in self: | ||||||||||||||
if record.state == 'Cancelled': | ||||||||||||||
raise UserError("Cancelled properties cannot be sold!") | ||||||||||||||
|
||||||||||||||
else: | ||||||||||||||
record.state = "Sold" | ||||||||||||||
return True | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
def cancel(self): | ||||||||||||||
for record in self: | ||||||||||||||
if record.state == 'Sold': | ||||||||||||||
raise UserError("Sold properties cannot be cancelled!") | ||||||||||||||
|
||||||||||||||
else: | ||||||||||||||
record.state = "Cancelled" | ||||||||||||||
return True | ||||||||||||||
|
||||||||||||||
_sql_constraints = [ | ||||||||||||||
('strictly_positive_expected_price', | ||||||||||||||
'CHECK(expected_price > 0)', | ||||||||||||||
'The expected price should be strictly positive'), | ||||||||||||||
|
||||||||||||||
('positive_seling_price', | ||||||||||||||
'CHECK(selling_price >= 0)', | ||||||||||||||
'The selling price should be positive'), | ||||||||||||||
|
||||||||||||||
] | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
@api.constrains('expected_price', 'selling_price') | ||||||||||||||
def filter_bad_offers(self): | ||||||||||||||
for property in self: | ||||||||||||||
if not float_is_zero(property.selling_price, precision_digits = 6) and float_compare(property.selling_price, 0.9*property.expected_price, precision_digits=6) < 0: | ||||||||||||||
raise ValidationError('The selling price is below the 90% threshold of the expected price') | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Depends on the team you will join but we tend to always wrap user messages in between douoble quotes. At least in R&D Accounting. But whatever the team you will join, you will be asked to be consistent with your use of single and double quotes so as you used doubles quotes for all teh other errors before this one, I'd suggest you do the same here 👍
Suggested change
|
||||||||||||||
return True | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
@api.ondelete(at_uninstall=False) | ||||||||||||||
def _unlink_if_offer_not_new_not_cancelled(self): | ||||||||||||||
if any(property.state not in ["New", "Cancelled"] for property in self): | ||||||||||||||
raise UserError("Can't delete an offer which is not cancelled or new!") | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
||||||||||||||
|
Original file line number | Diff line number | Diff line change | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,112 @@ | ||||||||||||||||||||
from odoo import models, fields, api | ||||||||||||||||||||
from datetime import datetime | ||||||||||||||||||||
from odoo.exceptions import UserError | ||||||||||||||||||||
from odoo.tools import float_compare | ||||||||||||||||||||
Comment on lines
+1
to
+4
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here is an instance of two blocks of imports. You have external ones and odoo ones so your imports should look like this:
Suggested change
|
||||||||||||||||||||
|
||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing one blank space |
||||||||||||||||||||
class EstatePropertyOffer(models.Model): | ||||||||||||||||||||
_name = "estate_property_offer" | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
_order = "price desc" | ||||||||||||||||||||
|
||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. too many blank spaces, more of this lower in the diff 👍 |
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
name = fields.Char(required = True, default = "Offer") | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. no space around operators for fields attributes |
||||||||||||||||||||
price = fields.Float() | ||||||||||||||||||||
state = fields.Selection( | ||||||||||||||||||||
string='State', | ||||||||||||||||||||
selection=[('Accepted', 'Accepted'),('Refused','Refused')], | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technical values in Selection fields' selection in lowercase |
||||||||||||||||||||
copy = False) | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||
partner_id = fields.Many2one('res.partner', string='Partner',required = True) | ||||||||||||||||||||
property_id = fields.Many2one('estate_property',required = True, ondelete='cascade') | ||||||||||||||||||||
date_deadline = fields.Date(compute = '_compute_deadline', inverse = '_compute_validity') | ||||||||||||||||||||
validity = fields.Integer(default = 7) | ||||||||||||||||||||
|
||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can but we don't usually leave blank space inside the field definitions part of the model 👍 |
||||||||||||||||||||
property_state = fields.Selection( | ||||||||||||||||||||
related='property_id.state', | ||||||||||||||||||||
readonly=True, | ||||||||||||||||||||
) | ||||||||||||||||||||
|
||||||||||||||||||||
property_type_id = fields.Many2one( | ||||||||||||||||||||
related='property_id.property_type_id', | ||||||||||||||||||||
stored = True | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. coma on last line of a multi-line field definition 👍 |
||||||||||||||||||||
) | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
@api.depends('validity') | ||||||||||||||||||||
def _compute_deadline(self): | ||||||||||||||||||||
for property in self: | ||||||||||||||||||||
if not property.create_date: | ||||||||||||||||||||
property.date_deadline = fields.Date.add(fields.Date.today(), days = property.validity) | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
same just below 😉 |
||||||||||||||||||||
|
||||||||||||||||||||
else: | ||||||||||||||||||||
property.date_deadline = fields.Date.add(property.create_date, days = property.validity) | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
def _compute_validity(self): | ||||||||||||||||||||
for property in self: | ||||||||||||||||||||
if not property.create_date: | ||||||||||||||||||||
|
||||||||||||||||||||
property.validity = (property.date_deadline - fields.Date.today()).days | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
else: | ||||||||||||||||||||
property.validity = (datetime.combine(property.date_deadline, datetime.min.time()) - property.create_date).days | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
def action_confirm(self): | ||||||||||||||||||||
for record in self: | ||||||||||||||||||||
if record.property_id.state not in ["Cancelled", "Sold", "Offer Accepted"]: | ||||||||||||||||||||
record.state = 'Accepted' | ||||||||||||||||||||
record.property_id.buyer = record.partner_id | ||||||||||||||||||||
record.property_id.selling_price = record.price | ||||||||||||||||||||
record.property_id.state = "Offer Accepted" | ||||||||||||||||||||
elif record.property_id.state == "Offer Accepted": | ||||||||||||||||||||
if record.state != "Accepted": | ||||||||||||||||||||
raise UserError("Only one offer can be accepted!") | ||||||||||||||||||||
|
||||||||||||||||||||
else: | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The
Suggested change
|
||||||||||||||||||||
raise UserError("Property not available!") | ||||||||||||||||||||
|
||||||||||||||||||||
return True | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't need a return value for this method. Doesn't hurt, but doesn't help either 😄
Suggested change
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
def action_reject(self): | ||||||||||||||||||||
for record in self: | ||||||||||||||||||||
if record.property_id.state not in ["Cancelled", "Sold"]: | ||||||||||||||||||||
if record.state == 'Accepted': | ||||||||||||||||||||
record.property_id.state = "Offer Received" | ||||||||||||||||||||
record.property_id.buyer = '' | ||||||||||||||||||||
record.property_id.selling_price = 0.0 | ||||||||||||||||||||
record.state = 'Refused' | ||||||||||||||||||||
|
||||||||||||||||||||
else: | ||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. To clarify a bit, I don't think anyone will ever ask you to do it so if you don't it's fine. There are places where it's really better and some not so much. Just keep in mind you spend 99% of your time in code that is not yours so it's always better when it's easy to understand 👍 |
||||||||||||||||||||
raise UserError("Property not available!") | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
return True | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
_sql_constraints = [ | ||||||||||||||||||||
('strictly_positive_offer_price', | ||||||||||||||||||||
'CHECK(price > 0)', | ||||||||||||||||||||
'The offer price should be strictly positive') | ||||||||||||||||||||
|
||||||||||||||||||||
] | ||||||||||||||||||||
|
||||||||||||||||||||
|
||||||||||||||||||||
@api.model | ||||||||||||||||||||
def create(self, vals): | ||||||||||||||||||||
|
||||||||||||||||||||
property_object = self.env["estate_property"].browse(vals['property_id']) | ||||||||||||||||||||
if float_compare(property_object.best_price, vals['price'], precision_digits=6) > 0: | ||||||||||||||||||||
raise UserError(f"Offer must be higher than {property_object.best_price}!") | ||||||||||||||||||||
|
||||||||||||||||||||
offer = super().create(vals) | ||||||||||||||||||||
offer.property_id.state = 'Offer Received' | ||||||||||||||||||||
return offer |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from odoo import models, fields | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this file is shorter, i'll just leave the list of the things i saw here and let you look after what it means in terms changes to be made 😄
|
||
|
||
class EstatePropertyTag(models.Model): | ||
_name = "estate_property_tag" | ||
_order = "name" | ||
name = fields.Char(required = True) | ||
color = fields.Integer() | ||
|
||
|
||
|
||
_sql_constraints = [ | ||
('is_tag_unique', 'UNIQUE(name)', 'Tag name must be unique!') | ||
] |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,24 @@ | ||||||
from odoo import models, fields, api | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This one i'll let you do by yourself with the comments i wrote before. There's a bunch of repeating stuff 😄 |
||||||
|
||||||
class EstatePropertyType(models.Model): | ||||||
_name = "estate_property_type" | ||||||
_order = "sequence,name" | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
||||||
name = fields.Char(required = True) | ||||||
property_ids = fields.One2many(comodel_name="estate_property", inverse_name = "property_type_id") | ||||||
sequence = fields.Integer('Sequence', default=1) | ||||||
offer_ids = fields.One2many(comodel_name="estate_property_offer", inverse_name = "property_type_id") | ||||||
offer_count = fields.Integer(compute = "_compute_offer_count") | ||||||
|
||||||
|
||||||
|
||||||
_sql_constraints = [ | ||||||
('is_property_type_unique', 'UNIQUE(name)', 'Property type name must be unique!') | ||||||
] | ||||||
|
||||||
|
||||||
@api.depends('offer_ids') | ||||||
def _compute_offer_count(self): | ||||||
for property_type in self: | ||||||
property_type.offer_count = len(property_type.offer_ids) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from odoo import fields, models | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And this one too is pretty straight forward with what i wrote before 😄 |
||
|
||
class InheritedModel(models.Model): | ||
_inherit = "res.users" | ||
|
||
property_ids = fields.One2many(comodel_name="estate_property", inverse_name = "salesperson", domain = [('state', 'in', ['New', 'Offer Received'])]) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink | ||
estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1 | ||
estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1 | ||
estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1 | ||
estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<?xml version="1.0"?> | ||
<odoo> | ||
<menuitem id="test_menu_root" name="Real Estate"> | ||
<menuitem id="test_first_level_menu" name="Advertisements"> | ||
<menuitem id="test_model_menu_action" action="test_model_action"/> | ||
</menuitem> | ||
<menuitem id="estate_property_type_settings_menu" name="Settings"> | ||
<menuitem id="property_type_action" action="estate_property_type_properties"/> | ||
<menuitem id="estate_property_tag_menu_tags" action="estate_property_tag_action"/> | ||
</menuitem> | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Useless blank line 👍 |
||
</menuitem> | ||
</odoo> |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,72 @@ | ||||||||||||||||||||||||||
<?xml version="1.0"?> | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Lots of blank lines that shouldn't be here in this file. 😄 |
||||||||||||||||||||||||||
<odoo> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<record id="estate_property_offer_action" model="ir.actions.act_window"> | ||||||||||||||||||||||||||
<field name="name">Offers</field> | ||||||||||||||||||||||||||
<field name="res_model">estate_property_offer</field> | ||||||||||||||||||||||||||
<field name="view_mode">list,form</field> | ||||||||||||||||||||||||||
<field name="domain">[('property_type_id', '=', active_id)]</field> | ||||||||||||||||||||||||||
</record> | ||||||||||||||||||||||||||
Comment on lines
+5
to
+10
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<record id="estate_property_offer_list_view" model="ir.ui.view"> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<field name="name">List View</field> | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to make it a bit more specific 👍
Suggested change
|
||||||||||||||||||||||||||
<field name="model">estate_property_offer</field> | ||||||||||||||||||||||||||
<field name="arch" type="xml"> | ||||||||||||||||||||||||||
<list string="Offer List" editable="bottom" decoration-success = "state == 'Accepted'" decoration-danger = "(state == 'Refused') or (state != 'Accepted' and property_state in ('Offer Accepted', 'Cancelled', 'Sold'))"> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<field name="price" string = "Price"/> | ||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. operators spacing 😄 |
||||||||||||||||||||||||||
<field name="partner_id" string = "Partner"/> | ||||||||||||||||||||||||||
<field name="validity" string = "Validity (days)"/> | ||||||||||||||||||||||||||
<field name="date_deadline" string = "Deadline"/> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<button name="action_confirm" string="Accept" type="object" icon="fa-check" invisible="(state in ('Accepted','Refused')) or property_state in ('Cancelled', 'Offer Accepted', 'Sold')"/> | ||||||||||||||||||||||||||
<button name="action_reject" string="Reject" type="object" icon="fa-times" invisible="(state in ('Accepted','Refused')) or property_state in ('Cancelled', 'Offer Accepted', 'Sold')"/> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
</list> | ||||||||||||||||||||||||||
</field> | ||||||||||||||||||||||||||
</record> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<record id="estate_property_offer_form_view" model="ir.ui.view"> | ||||||||||||||||||||||||||
<field name="name">Form View</field> | ||||||||||||||||||||||||||
<field name="model">estate_property_offer</field> | ||||||||||||||||||||||||||
<field name="arch" type="xml"> | ||||||||||||||||||||||||||
<form string="Property Form"> | ||||||||||||||||||||||||||
<sheet> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<div class="estate_property_offer_oe_title"> | ||||||||||||||||||||||||||
<h1> <field name="name" nolabel="1"/> </h1> | ||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
<group> | ||||||||||||||||||||||||||
<field name="price" string = "Price"/> | ||||||||||||||||||||||||||
<field name="partner_id" string = "Partner"/> | ||||||||||||||||||||||||||
<field name="validity" string = "Validity (days)"/> | ||||||||||||||||||||||||||
<field name="date_deadline" string = "Deadline"/> | ||||||||||||||||||||||||||
<field name="state" string = "State"/> | ||||||||||||||||||||||||||
Comment on lines
+46
to
+50
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. always indent by gorups of 4 spaces ( |
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
</group> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
</sheet> | ||||||||||||||||||||||||||
</form> | ||||||||||||||||||||||||||
</field> | ||||||||||||||||||||||||||
</record> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
</odoo> | ||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
|
||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. missing EOL |
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.
For multiple reasons, the main one being that we always want to keep the changes history as clean as possible, we always end files with a blank line so that if someone edits your file and add a line at the end, it doesn't modify your last line to add the line break character.