Skip to content
Open

plha #228

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Odoo tutorials

test
This repository hosts the code for the bases of the modules used in the
[official Odoo tutorials](https://www.odoo.com/documentation/latest/developer/tutorials.html).

Expand Down
3 changes: 3 additions & 0 deletions estate/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"python.languageServer": "None"
}
1 change: 1 addition & 0 deletions estate/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
25 changes: 25 additions & 0 deletions estate/__manifest__.py
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'

]
}
6 changes: 6 additions & 0 deletions estate/models/__init__.py
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
90 changes: 90 additions & 0 deletions estate/models/estate_property.py
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")])

Choose a reason for hiding this comment

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

Suggested change
garden_orientation = fields.Selection([("North","North"),("South","South"),("East","East"),("West","West")])
garden_orientation = fields.Selection([("north","North"),("south","South"),("east","East"),("west","West")])

Use lowercase keys for state values for consistency with Odoo's best practices.

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"


Choose a reason for hiding this comment

The 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!")
58 changes: 58 additions & 0 deletions estate/models/property_offer.py
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)

Choose a reason for hiding this comment

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

Suggested change
status = fields.Selection([("Accepted","Accepted"),("Refused","Refused")],copy=False)
status = fields.Selection([("accepted","Accepted"), ("refused","Refused")], copy=False)

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)
17 changes: 17 additions & 0 deletions estate/models/property_tag.py
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):

Choose a reason for hiding this comment

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

Suggested change
class EstatePropertyType(models.Model):
class EstatePropertyTag(models.Model):

_name = "estate.property.tags"

Choose a reason for hiding this comment

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

Suggested change
_name = "estate.property.tags"
_name = "estate.property.tag"

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")

Choose a reason for hiding this comment

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

Suggested change
properties = fields.Many2many("estate.property","tag_ids",string="properties")
property_ids = fields.Many2many("estate.property","tag_ids",string="properties")

color = fields.Integer(string="Color")
_order ="name"


_sql_constraints = [
('unique_tag_name', 'UNIQUE(name)',
'There is already a tag with this name'),
]
24 changes: 24 additions & 0 deletions estate/models/property_type.py
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"

Choose a reason for hiding this comment

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

Suggested change
_name = "estate.property.types"
_name = "estate.property.type"

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)

Choose a reason for hiding this comment

The 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")

Choose a reason for hiding this comment

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

Suggested change
properties = fields.One2many("estate.property","property_type_id",string="properties")
property_ids = fields.One2many("estate.property","property_type_id",string="properties")

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)
35 changes: 35 additions & 0 deletions estate/models/test_inheritance1.py
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")
6 changes: 6 additions & 0 deletions estate/models/users.py
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")
9 changes: 9 additions & 0 deletions estate/security/ir.model.access.csv
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
74 changes: 74 additions & 0 deletions estate/views/estate_form_view.xml
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

Choose a reason for hiding this comment

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

Suggested change
</group>
<group>

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

Choose a reason for hiding this comment

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

Suggested change
</group>
<group>

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>

Choose a reason for hiding this comment

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

Suggested change
</field>

remove this line, it's useless

</record>

</odoo>
Loading