Skip to content
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

update_JuanDanielGutierrezGomez #67

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
12 changes: 11 additions & 1 deletion estate/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,17 @@
"application": True, # This line says the module is an App, and not a module
"depends": ["base"], # dependencies
"data": [

'security/ir.model.access.csv',
# estate property

Choose a reason for hiding this comment

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

esa linea no sirve, la puedes quitar sin problema, no agrega mucha informaciom

'views/estate_property_views.xml',
# estate property offer
'views/estate_property_offer_views.xml',
# estate property type
'views/estate_property_type_views.xml',
# estate property tag
'views/estate_property_tag_views.xml',
'views/res_users.xml',
'views/estate_menus.xml',
],
"installable": True,
'license': 'LGPL-3',
Expand Down
Empty file removed estate/models.py
Empty file.
5 changes: 5 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from . import estate_property
from . import estate_property_type
from . import estate_property_tag
from . import estate_property_offer
from . import res_users
151 changes: 151 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
from datetime import datetime, timedelta
from odoo import fields, models, Command
from odoo import api
from odoo import exceptions
from odoo.exceptions import ValidationError
from odoo.exceptions import UserError
Comment on lines +2 to +6

Choose a reason for hiding this comment

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

Suggested change
from odoo import fields, models, Command
from odoo import api
from odoo import exceptions
from odoo.exceptions import ValidationError
from odoo.exceptions import UserError
from odoo import api, fields, models, Command
from odoo.exceptions import ValidationError, UserError

from odoo.tools.float_utils import float_compare, float_is_zero

class EstateProperty(models.Model):
_name = 'estate.property'
_description = "ESTATE Properties"
_order = "id desc"

name = fields.Char(string="Title", required=True, help="Property name")
description = fields.Text(string="Description", help="Property description")
postcode = fields.Text(string="Postcode", help="Property Post code")

Choose a reason for hiding this comment

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

Suggested change
postcode = fields.Text(string="Postcode", help="Property Post code")
postcode = fields.Text(help="Property Post code")

por defecto si no pones un argumento string, odoo va a poner como string el nombre del campo, poniendole mayusculas al inicio de las palabras y reemplazando los _ con espacios

date_availability = fields.Date(string="Available From",
default=lambda self: (datetime.now() + timedelta(days=90)).strftime('%Y-%m-%d'),
copy=False, help="Property Date Availability")
Comment on lines +17 to +19

Choose a reason for hiding this comment

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

podrias hacer esta parte tantito mas legible

Suggested change
date_availability = fields.Date(string="Available From",
default=lambda self: (datetime.now() + timedelta(days=90)).strftime('%Y-%m-%d'),
copy=False, help="Property Date Availability")
date_availability = fields.Date(
string="Available From",
default=lambda self: (datetime.now() + timedelta(days=90)).strftime('%Y-%m-%d'),
copy=False, help="Property Date Availability"
)


expected_price = fields.Float(string="Expected Price", required=True, help="Property Expected Price")
selling_price = fields.Float(string="Selling Price", readonly=True, copy=False, help="Property Selling Price")

bedrooms = fields.Integer(string="Bedrooms", default=2, help="Property Bedrooms")
living_area = fields.Integer(string="Living Area (sqm)", help="Property Living Area")
facades = fields.Integer(string="Facades", help="Property Facades")
garage = fields.Boolean(string="Garage", help="Property Garage")
garden = fields.Boolean(string="Garden", help="Property Garden")
garden_area = fields.Integer(string="Garden Area", help="Property Garden Area")
garden_orientation = fields.Selection(
string="Orientation",
selection=[("North", "North"), ("South", "South"), ("East", "East"), ("West", "West")],
help="Orientation help to define the garden orientation")

active = fields.Boolean(string="Active", default=True, help="Property is available")

state = fields.Selection(
string="State",
selection=[("new", "New"), ("offer_received", "Offer Received"), ("offer_accepted", "Offer Accepted"),
("sold", "Sold"), ("canceled", "Canceled")],
default="new",
help="State of the property advertisement")

# links

Choose a reason for hiding this comment

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

igual ese lo puedes quitar

property_type_id = fields.Many2one('estate.property.type', domain="[('id', '!=', False)]", string="Type")
tag_ids = fields.Many2many('estate.property.tag', string="Tag")

salesperson_id = fields.Many2one('res.users', string='Salesman', default=lambda self: self.env.user,
help="Salesperson")
buyer_id = fields.Many2one('res.partner', string="Buyer", copy=False, help="Buyer Person")

offer_ids = fields.One2many('estate.property.offer', 'property_id', string='Offers', help='List of offers')

# campos computados
total_area = fields.Integer(string="Total Area (sqm)", compute='_compute_total_area')

best_price = fields.Float(string="Best Offer", compute='_compute_best_offer')

# campo compañia si se tienen 2 o más
company_id = fields.Many2one('res.company', string="Company", required=True, default=lambda self: self.env.company,
help="Company related to this property")

# constraints

_sql_constraints = [
('check_expected_price', 'CHECK(expected_price > 0)', 'A property expected price must be strictly positive'),
('check_selling_price', 'CHECK(selling_price >= 0)', 'A property selling price must be positive'),
]

@api.depends('living_area', 'garden_area')
def _compute_total_area(self):
"""
Compute and update total area.

Choose a reason for hiding this comment

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

esta bien poner comentarios en el codigo pero aqui ya que el codigo es muy obvio realmente no ayuda mucho

"""
for record in self:
record.total_area = record.living_area + record.garden_area

@api.depends('offer_ids.price')
def _compute_best_offer(self):
"""
Compute and update best offer
"""
for record in self:
try:
record.best_price = max(record.offer_ids.mapped('price'))
except ValueError:
record.best_price = None
Comment on lines +83 to +87

Choose a reason for hiding this comment

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

nunca va a tirar error ese codigo, aqui el try catch no sirve

Suggested change
for record in self:
try:
record.best_price = max(record.offer_ids.mapped('price'))
except ValueError:
record.best_price = None
for record in self:
record.best_price = max(record.offer_ids.mapped('price'))


@api.onchange('garden')
def _onchange_garden(self):
if self.garden:
self.garden_area = 10
self.garden_orientation = 'North'
else:
self.garden_area = 0
self.garden_orientation = ''

Choose a reason for hiding this comment

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

aqui da lo mismo ponerle '' o False, pero por como lo solemos hacer en odoo, yo le pondria False

Suggested change
self.garden_orientation = ''
self.garden_orientation = False


def action_sold_property(self):
for record in self:
if record.state == 'canceled':
# cancelard propiedad
raise exceptions.UserError("canceled property cannot be sold")

Choose a reason for hiding this comment

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

podrias importar UserError directamente para hacer estas lineas mas cortas

Suggested change
raise exceptions.UserError("canceled property cannot be sold")
raise UserError("canceled property cannot be sold")

elif record.state != 'offer_accepted':
# Ya se vendio joven

Choose a reason for hiding this comment

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

ahuevo

raise exceptions.UserError("You must accept an offer before make a property as sold")
else:
record.state = 'sold'

return True

def action_prueba(self):
for record in self:
if record.state == 'canceled':
# cancelada
raise exceptions.UserError("canceled property cannot be sold")
elif record.state != 'offer_accepted':
# not se acepta ofeertas
raise exceptions.UserError("You must accept an offer before make a property as sold")
else:
record.state = 'sold'

return True
Comment on lines +98 to +122

Choose a reason for hiding this comment

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

estas 2 funciones hacen la misma cosa entonces puedes borrar una de las 2


def action_cancel_property(self):
for record in self:
if record.state == 'sold':
# venida
raise exceptions.UserError("sold property cannot be canceled")
else:
record.state = 'canceled'
return True

@api.constrains('selling_price', 'expected_price')
def _check_selling_price(self):
for property_record in self:
if not float_is_zero(property_record.selling_price, precision_digits=1):
if float_compare(property_record.selling_price, 0.9 * property_record.expected_price,
precision_digits=2) == -1:
raise ValidationError("Selling price cannot be lower than 90% of the expected price!")
else:
pass
else:
pass
Comment on lines +140 to +143

Choose a reason for hiding this comment

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

no necesitas estas lineas

Suggested change
else:
pass
else:
pass


@api.ondelete(at_uninstall=False)
def _check_property_state(self):
for property_record in self:
if property_record.state not in ['new', 'canceled']:
raise UserError("Only New or Canceled property can be deleted!")
else:
pass
Comment on lines +150 to +151

Choose a reason for hiding this comment

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

Suggested change
else:
pass

82 changes: 82 additions & 0 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
from datetime import datetime, timedelta
from datetime import date
from odoo import fields, models
from odoo import api
from odoo import exceptions
from odoo.exceptions import ValidationError

class EstatePropertyOffer(models.Model):
_name = 'estate.property.offer'
_description = "Properties Offer"
_order = "price desc"

price = fields.Float(string="Price", help="Buyer Offer")
validity = fields.Integer(string="validity (days)", default=7, help="validity")
date_deadline = fields.Date(string="Deadline", compute='_compute_date_deadline', inverse='_inverse_date_deadline', help='Validity date')

status = fields.Selection(
string="Status",
selection=[("offer_accepted", "Accept"), ("offer_refused", "Refuse"),],
copy=False,
help="State of the property advertisement")

partner_id = fields.Many2one('res.partner', string="Partner", required=True, help="Person who make the offer")
property_id = fields.Many2one('estate.property', string="Property", required=True, help="Property")

property_type_id = fields.Many2one(related='property_id.property_type_id', store=True)

# constraints
_sql_constraints = [
('check_price', 'CHECK(price >= 0)', 'An offer price must be strictly positive'),
]


@api.depends('validity')
def _compute_date_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_date_deadline(self):
for record in self:
if record.create_date:
record.validity = (record.date_deadline - record.create_date.date()).days
else:
record.validity = record.date_deadline - datetime.now().date()

def action_accept_offer(self):
for record in self:
# Reject all others offers
for offer in record.property_id.offer_ids:
offer.status = 'offer_refused'
Comment on lines +52 to +53

Choose a reason for hiding this comment

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

segun yo aqui lo puedes hacer todo de una vez, puedes probar si esta sugestion funciona !

Suggested change
for offer in record.property_id.offer_ids:
offer.status = 'offer_refused'
record.property_id.offer_ids.status = 'offer_refused'


# acceptado
record.status = 'offer_accepted'

# Actualizar campos de precios
record.property_id.state = record.status
record.property_id.selling_price = record.price
record.property_id.buyer_id = record.partner_id



Comment on lines +62 to +64

Choose a reason for hiding this comment

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

aqui hay muchas lineas vacias

Suggested change

return True

def action_refuse_offer(self):
for record in self:
record.status = 'Refused'

Comment on lines +68 to +70

Choose a reason for hiding this comment

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

Suggested change
for record in self:
record.status = 'Refused'
self.status = 'Refused'

return True

@api.model
def create(self, vals):
# Check precio mas bajo que el permitido
existing_offers = self.env['estate.property.offer'].search([('property_id', '=', vals['property_id']), ('price', '>=', vals['price'])])
if existing_offers:
raise ValidationError("The offer price cannot be lower than an existing offer.")

# Oferta recibida al crear la oferta.
self.env['estate.property'].browse(vals['property_id']).write({'state': 'offer_received'})
return super().create(vals)
15 changes: 15 additions & 0 deletions estate/models/estate_property_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from datetime import datetime, timedelta
from odoo import fields, models

class EstatePropertyTag(models.Model):
_name = 'estate.property.tag'
_description = "Properties Tag"
_order = "name"

name = fields.Char(string="Name", required=True, help="Tag name")
color = fields.Integer(string="Color", help="Tag color")

# constraints
_sql_constraints = [
('unique_property_tag_name', 'UNIQUE(name)', 'A property cannot have duplicate tags.'),
]
33 changes: 33 additions & 0 deletions estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from datetime import datetime, timedelta
from odoo import fields, models
from odoo import api

class EstatePropertyType(models.Model):
_name = 'estate.property.type'
_description = "Properties type"
_order = "name"

name = fields.Char(string="Name", required=True, help="Property type")

property_ids = fields.One2many('estate.property', 'property_type_id', string='Properties', help='Type properties')

sequence = fields.Integer('Sequence', default=1, help="Used to order stages. Lower is better.")

offer_ids = fields.One2many('estate.property.offer', 'property_type_id', string="Offers")

offer_count = fields.Integer(string="Offers Count", default=0, compute="_compute_offer_count")


# constraints
_sql_constraints = [
('unique_property_type_name', 'UNIQUE(name)', 'A property cannot have duplicate types.'),
]

@api.depends('offer_ids')
def _compute_offer_count(self):
for property_type_record in self:
property_type_record.offer_count = len(property_type_record.offer_ids)

def get_offer_count(self):
# Recuperar valor
return self.offer_count
Comment on lines +31 to +33

Choose a reason for hiding this comment

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

Suggested change
def get_offer_count(self):
# Recuperar valor
return self.offer_count

no vi que estas llamando esta funcion en ningun otro lado

11 changes: 11 additions & 0 deletions estate/models/res_users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from datetime import datetime, timedelta
from datetime import date
from odoo import fields, models
from odoo import api
from odoo import exceptions
from odoo.exceptions import ValidationError
Comment on lines +1 to +6

Choose a reason for hiding this comment

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

Suggested change
from datetime import datetime, timedelta
from datetime import date
from odoo import fields, models
from odoo import api
from odoo import exceptions
from odoo.exceptions import ValidationError
from odoo import fields, models

mejor solo importar lo necesario


class ResUsers(models.Model):
_inherit = "res.users"

property_ids = fields.One2many('estate.property', 'salesperson_id', string='Properties', domain="[('active', '=', True), '|', ('state', '=', 'new'), ('state', '=', 'offer_received')]", help='List of properties')
12 changes: 12 additions & 0 deletions estate/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
id,name,model_id/id,group_id/id,perm_read,perm_write,perm_create,perm_unlink
1,Real Estate Base Access,model_estate_property,base.group_user,1,0,0,0
2,Real Estate Base Access,model_estate_property_type,base.group_user,1,0,0,0
3,Real Estate Base Access,model_estate_property_tag,base.group_user,1,0,0,0
4,Real Estate Base Access,model_estate_property_offer,base.group_user,1,1,1,1
5,Real Estate Manager Access,model_estate_property,base.group_system,1,1,1,1
6,Real Estate Manager Access,model_estate_property_type,base.group_system,1,1,1,1
7,Real Estate Manager Access,model_estate_property_tag,base.group_system,1,1,1,1
8,Agent Access for Properties,model_estate_property,base.group_system,1,1,1,0
9,Agent Access for Types and Tags,model_estate_property_type,base.group_system,1,0,0,0
10,Agent Access for Tags,model_estate_property_tag,base.group_system,1,0,0,0
11,Prevent Delete for Properties,model_estate_property,,0,0,0,0
12 changes: 12 additions & 0 deletions estate/views/estate_menus.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<menuitem id="test_menu_root" name="Estate">
<menuitem id="test_first_level_menu" name="Advertisements">
<menuitem id="estate_property_menu_action" action="estate_property_action"/>
</menuitem>
<menuitem id="test_second_level_menu" name="Ajustes">
<menuitem id="estate_property_type_menu" action="estate_property_type_action"/>
<menuitem id="estate_property_tag_action" action="action_estate_property_tag"/>
</menuitem>
</menuitem>
</odoo>
19 changes: 19 additions & 0 deletions estate/views/estate_property_offer_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Estate Property Lista vista -->
<record id="estate_property_offer_view_tree" model="ir.ui.view">
<field name="name">estate.property.offer.tree</field>
<field name="model">estate.property.offer</field>
<field name="arch" type="xml">
<tree string="Offers" editable="top" decoration-success="status=='offer_accepted'" decoration-danger="status=='offer_refused'">
<field name="price" />
<field name="partner_id" />
<field name="validity" />
<field name="date_deadline" />
<button name="action_accept_offer" string="Accept" type="object" icon="fa-check" invisible="status"/>
<button name="action_refuse_offer" string="Refuse" type="object" icon="fa-times" invisible="status"/>
<field name="status" invisible="1"/>
</tree>
</field>
</record>
</odoo>
Loading