-
Notifications
You must be signed in to change notification settings - Fork 2.5k
plha #228
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?
plha #228
Changes from all commits
0df9ae8
3c8218b
96643d5
455e8d9
686616c
46ce22f
d219fa8
837033e
10fcaec
08f0d77
7b04592
536301c
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,3 @@ | ||
{ | ||
"python.languageServer": "None" | ||
} |
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,25 @@ | ||
{ 'name': 'real estate app plh', | ||
'depends': [ | ||
'base',], | ||
'application': True, | ||
'data':[ | ||
'security/ir.model.access.csv', | ||
'views/estate_property_views_action.xml', | ||
'views/estate_menus.xml', | ||
'views/estate_list_view.xml', | ||
'views/estate_form_view.xml', | ||
'views/estate_kanban_view.xml', | ||
'views/estate_search_view.xml', | ||
'views/type_actions.xml', | ||
'views/type_menus.xml', | ||
'views/type_views.xml', | ||
'views/tag_actions.xml', | ||
'views/tag_menus.xml', | ||
'views/tag_views.xml', | ||
'views/offer_actions.xml', | ||
# 'views/offer_menus.xml', | ||
'views/offer_views.xml', | ||
'views/user_views.xml' | ||
|
||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from . import estate_property | ||
from . import property_type | ||
from . import property_tag | ||
from . import property_offer | ||
from . import users | ||
from . import test_inheritance1 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from odoo import api,fields, models,exceptions | ||
from datetime import date, timedelta | ||
|
||
class EstateProperty(models.Model): | ||
_name = "estate.property" | ||
_description = "reals estate properties" | ||
|
||
name = fields.Char('Property Name',required=True) | ||
offer_ids=fields.One2many("estate.property.offer","property_id",string="Offers Received") | ||
tag_ids=fields.Many2many("estate.property.tags",string="Tags") | ||
buyer_id=fields.Many2one("res.partner",string="Buyer") | ||
salesperson_id=fields.Many2one("res.users",string="Sales Person",default=lambda self: self.env.user) | ||
property_type_id = fields.Many2one("estate.property.types", string="Property Type") | ||
description = fields.Text('The Descritption') | ||
postcode = fields.Char() | ||
date_availability = fields.Date(default=date.today()+ timedelta(days=90),copy=False) | ||
expected_price = fields.Float(required=True) | ||
selling_price = fields.Float(copy=False,readonly=True) | ||
bedrooms = fields.Integer(default=2) | ||
living_area = fields.Integer() | ||
facades = fields.Integer() | ||
garage = fields.Boolean() | ||
garden = fields.Boolean() | ||
garden_area= fields.Integer() | ||
garden_orientation = fields.Selection([("North","North"),("South","South"),("East","East"),("West","West")]) | ||
active = fields.Boolean(default=True) | ||
state = fields.Selection([("New","New"),("Offer Received","Offer Received"),("Offer Accepted","Offer Accepted"),("Sold","Sold"),("Cancelled","Cancelled")],copy=False,default="New") | ||
total_area= fields.Integer(compute = "_compute_total_area",default=0) | ||
best_price=fields.Float(compute="_compute_best_price") | ||
_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. remove extra line |
||
|
||
|
||
@api.depends("living_area","garden_area") | ||
def _compute_total_area(self): | ||
for record in self: | ||
record.total_area=record.garden_area+record.living_area | ||
|
||
@api.depends("offer_ids.price") | ||
def _compute_best_price(self): | ||
for record in self: | ||
if record.offer_ids: | ||
record.best_price=max(record.mapped('offer_ids.price')) | ||
else : record.best_price=0 | ||
|
||
@api.onchange("garden") | ||
def _onchange_garden(self): | ||
if self.garden==True: | ||
self.garden_area=10 | ||
self.garden_orientation="North" | ||
if self.garden==False: | ||
self.garden_area=0 | ||
self.garden_orientation=None | ||
|
||
def action_sold(self): | ||
if self.state=="Cancelled": | ||
raise exceptions.UserError("impossible car la propriété est cancelled") | ||
else : | ||
self.state="Sold" | ||
return True | ||
|
||
def action_cancelled(self): | ||
if self.state=="Sold": | ||
raise exceptions.UserError("impossible car la propriété est sold") | ||
else : | ||
for record in self: | ||
record.state="Cancelled" | ||
return True | ||
|
||
|
||
|
||
_sql_constraints = [ | ||
('expected_price_positive', 'CHECK(expected_price >= 0)', | ||
'The price hase to be positive'), | ||
('selling_price_positiv','CHECK(selling_price >= 0)','the selling price has to be positive') | ||
] | ||
|
||
@api.constrains('selling_price','expected_price') | ||
def _check_selling_price_90(self): | ||
for record in self: | ||
if record.selling_price<0.9*(record.expected_price): | ||
raise exceptions.ValidationError("the selling prise is lower than 90 pourcent of the expected price") | ||
|
||
|
||
|
||
@api.ondelete(at_uninstall=False) | ||
def _unlink_if_user_inactive(self): | ||
if self.state not in ["New","Cancelled"]: | ||
raise exceptions.UserError("Can't delete a property not new or cancelled!") |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,58 @@ | ||||||
from odoo import api,fields, models,exceptions | ||||||
from datetime import date, timedelta | ||||||
|
||||||
class EstatePropertyOffer(models.Model): | ||||||
_name = "estate.property.offer" | ||||||
_description = "reals estate properties offer" | ||||||
|
||||||
property_offer_id= fields.Char('Property Offer ID') | ||||||
price = fields.Float('Le Prix') | ||||||
status = fields.Selection([("Accepted","Accepted"),("Refused","Refused")],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",required=True) | ||||||
property_id=fields.Many2one("estate.property",required=True) | ||||||
validity= fields.Integer(default=7) | ||||||
date_deadline=fields.Date(compute="_compute_deadline",inverse="_inverse_deadline",string="Date Limite") | ||||||
offer_type_id=fields.Many2one(related="property_id.property_type_id") | ||||||
|
||||||
_order="price desc" | ||||||
|
||||||
|
||||||
@api.depends("validity") | ||||||
def _compute_deadline(self): | ||||||
for record in self: | ||||||
if record.create_date: | ||||||
record.date_deadline=record.create_date+timedelta(days=record.validity) | ||||||
else : record.date_deadline=date.today()+timedelta(days=record.validity) | ||||||
|
||||||
def _inverse_deadline(self): | ||||||
for record in self: | ||||||
date_crea = fields.Date.to_date(record.create_date or fields.Date.today()) | ||||||
record.validity=(record.date_deadline-date_crea).days | ||||||
|
||||||
def offer_accepted(self): | ||||||
if "Accepted" in self.property_id.offer_ids.mapped('status'): | ||||||
raise exceptions.UserError("An other offer has already been accepted") | ||||||
else : | ||||||
for record in self: | ||||||
record.status="Accepted" | ||||||
record.property_id.buyer_id=record.partner_id | ||||||
record.property_id.selling_price=record.price | ||||||
return True | ||||||
|
||||||
def offer_declined(self): | ||||||
for record in self: | ||||||
record.status="Refused" | ||||||
return True | ||||||
|
||||||
_sql_constraints = [ | ||||||
('offer_price_positive', 'CHECK(price >= 0)', | ||||||
'The offer price hase to be positive'), | ||||||
] | ||||||
|
||||||
@api.model_create_multi | ||||||
def create(self, vals): | ||||||
for val in vals: | ||||||
if val['price'] < self.env['estate.property'].browse(val['property_id']).best_price: | ||||||
raise exceptions.UserError("Can't make an offer this low") | ||||||
self.env['estate.property'].browse(val['property_id']).state="Offer Received" | ||||||
return super().create(vals) |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,17 @@ | ||||||
from odoo import fields, models | ||||||
from datetime import date, timedelta | ||||||
|
||||||
class EstatePropertyType(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.
Suggested change
|
||||||
_name = "estate.property.tags" | ||||||
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
a record represents only one tag |
||||||
_description = "common characteristics of the properties" | ||||||
|
||||||
name = fields.Char('Property Tag Name',required=True) | ||||||
properties = fields.Many2many("estate.property","tag_ids",string="properties") | ||||||
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
|
||||||
color = fields.Integer(string="Color") | ||||||
_order ="name" | ||||||
|
||||||
|
||||||
_sql_constraints = [ | ||||||
('unique_tag_name', 'UNIQUE(name)', | ||||||
'There is already a tag with this name'), | ||||||
] |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,24 @@ | ||||||
from odoo import api,fields, models | ||||||
from datetime import date, timedelta | ||||||
|
||||||
class EstatePropertyType(models.Model): | ||||||
_name = "estate.property.types" | ||||||
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
Each record in this file represents a single estate property type, so the name should be clear and not misleading. |
||||||
_description = "reals estate properties" | ||||||
|
||||||
name = fields.Char('Property Type Name',required=True) | ||||||
property_type_id= fields.Char('Property Type ID',required=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. what is this field, why do you need it? |
||||||
properties = fields.One2many("estate.property","property_type_id",string="properties") | ||||||
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
|
||||||
offer_ids=fields.One2many("estate.property.offer","offer_type_id",string="offers") | ||||||
offer_count=fields.Integer(compute="_compute_offer_count",default=0) | ||||||
_order ="sequence" | ||||||
sequence=fields.Integer('Sequence',default=1,help="Used to order porperties") | ||||||
|
||||||
_sql_constraints = [ | ||||||
('unique_type_name', 'UNIQUE(name)', | ||||||
'There is already a type with this name'), | ||||||
] | ||||||
|
||||||
@api.depends("offer_ids") | ||||||
def _compute_offer_count(self): | ||||||
for record in self: | ||||||
record.offer_count=len(record.offer_ids) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
from odoo import api,fields, models,exceptions | ||
|
||
class Inheritance0(models.Model): | ||
_name = 'inheritance.0' | ||
_description = 'Inheritance Zero' | ||
|
||
name = fields.Char() | ||
|
||
def call(self): | ||
return self.check("model 0") | ||
|
||
def check(self, s): | ||
return "This is {} record {}".format(s, self.name) | ||
|
||
class Inheritance1(models.Model): | ||
_name = 'inheritance.1' | ||
_inherit = 'inheritance.0' | ||
_description = 'Inheritance One' | ||
|
||
family_name=fields.Char() | ||
|
||
def call(self): | ||
return self.check("model 1") | ||
|
||
class Inheritance2(models.Model): | ||
_name = 'inheritance.2' | ||
_inherits = {'inheritance.0':'inher0_id'} | ||
_description = 'Inheritance two' | ||
|
||
inher0_id=fields.Many2one("inheritance.0",required=True,ondelete="cascade") | ||
|
||
address=fields.Char() | ||
|
||
def call(self): | ||
return self.check("model 1") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from odoo import api,fields, models,exceptions | ||
from datetime import date, timedelta | ||
|
||
class EstateUsers(models.Model): | ||
_inherit = 'res.users' | ||
property_ids=fields.One2many("estate.property","salesperson_id") |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
estate.access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 | ||
estate.access_estate_property_types,access_estate_property_types,model_estate_property_types,base.group_user,1,1,1,1 | ||
estate.access_estate_property_tags,access_estate_property_tags,model_estate_property_tags,base.group_user,1,1,1,1 | ||
estate.access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 | ||
res.users.access,res.users,model_res_users,base.group_user,1,1,1,1 | ||
estate.access_inheritance_0,access_inheritance_0,model_inheritance_0,base.group_user,1,1,1,1 | ||
estate.access_inheritance_1,access_inheritance_1,model_inheritance_1,base.group_user,1,1,1,1 | ||
estate.access_inheritance_2,access_inheritance_2,model_inheritance_2,base.group_user,1,1,1,1 |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
@@ -0,0 +1,74 @@ | ||||||
<?xml version="1.0"?> | ||||||
<odoo> | ||||||
<record id="estate_property_view_form" model="ir.ui.view"> | ||||||
<field name="name">estate.property.view.form</field> | ||||||
<field name="model">estate.property</field> | ||||||
<field name="type">form</field> | ||||||
<field name="arch" type="xml"> | ||||||
<form string="Test"> | ||||||
|
||||||
<sheet> | ||||||
<header> | ||||||
<field name="state" widget="statusbar" statusbar_visible="New,Offer Received,Offer Accepted,Sold" options="{'clickable': True}"/> | ||||||
<button name="action_sold" type="object" string="SOLD" invisible="state=='Sold'or state=='Cancelled'"/> | ||||||
<button name="action_cancelled" type="object" string="CANCELLED" invisible="state=='Sold'or state=='Cancelled'"/> | ||||||
</header> | ||||||
|
||||||
<group> | ||||||
|
||||||
|
||||||
|
||||||
<group> | ||||||
<field name="name"/> | ||||||
</group> | ||||||
<group> | ||||||
Comment on lines
+23
to
+24
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
there is no need of putting each one of them in a group |
||||||
<field name="expected_price"/> | ||||||
</group> | ||||||
</group> | ||||||
<group> | ||||||
<group> | ||||||
<field name="date_availability"/> | ||||||
</group> | ||||||
<group> | ||||||
Comment on lines
+31
to
+32
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 here |
||||||
<field name="selling_price"/> | ||||||
</group> | ||||||
</group> | ||||||
<notebook> | ||||||
<page string="Description"> | ||||||
<group> | ||||||
<field name="description"/> | ||||||
<field name="tag_ids" widget="many2many_tags" options="{'color_field':'color'}" /> | ||||||
<field name="bedrooms"/> | ||||||
<field name="property_type_id" options="{'no_create': True}"/> | ||||||
<field name="buyer_id"/> | ||||||
<field name="salesperson_id"/> | ||||||
<field name="living_area"/> | ||||||
<field name="total_area"/> | ||||||
<field name="facades"/> | ||||||
<field name="garage"/> | ||||||
<field name="garden"/> | ||||||
<field name="garden_area" invisible="not garden"/> | ||||||
<field name="garden_orientation" invisible="not garden"/> | ||||||
<field name="best_price"/> | ||||||
</group> | ||||||
</page> | ||||||
<page string="Other Info"> | ||||||
<group> | ||||||
<field name="buyer_id"/> | ||||||
<field name="salesperson_id"/> | ||||||
</group> | ||||||
|
||||||
</page> | ||||||
<page string="Offers"> | ||||||
<group> | ||||||
<field name="offer_ids" readonly="state=='Sold' or state=='Cancelled'"/> | ||||||
</group> | ||||||
|
||||||
</page> | ||||||
</notebook> | ||||||
</sheet> | ||||||
</form> | ||||||
</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.
Suggested change
remove this line, it's useless |
||||||
</record> | ||||||
|
||||||
</odoo> |
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.
Use lowercase keys for state values for consistency with Odoo's best practices.