Skip to content

Commit

Permalink
[ADD] estate: add sprinkles, colored offers/tag, add stat/accepte/ref…
Browse files Browse the repository at this point in the history
…use button

- Add inline view and make editable
- Add sequence and widget
- Add conditional button on Offer and State
- Add invisible, optional, editable filled
- Add related fields in model property_type_id
- Add Offer view from property_type
- Covered chapter 11
  • Loading branch information
amya-odoo committed Aug 12, 2024
1 parent 9564242 commit 67f2f9f
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 69 deletions.
4 changes: 2 additions & 2 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
'name': "estate",
'version': '0.1',
'depends': ['base_setup'],
'depends': ['base_setup', 'mail'],
'description': "Technical practice",
'installable': True,
'application': True,

'data': [
'security/ir.model.access.csv',
'views/estate_property_views.xml',
'views/estate_property_offer_view.xml',
'views/estate_property_type.xml',
'views/estate_property_tag_view.xml',
'views/estate_property_offer_view.xml',
'views/estate_menus.xml',
],
'license': 'LGPL-3',
Expand Down
102 changes: 69 additions & 33 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -1,83 +1,119 @@
from odoo import models, fields, api
from dateutil.relativedelta import relativedelta
from datetime import date
from odoo.exceptions import UserError
from odoo.exceptions import UserError, ValidationError


class EstateProperty(models.Model):
_name = "estate.property"
_description = "Real Estate Property Data"
_inherit = ["mail.thread", "mail.activity.mixin"]
name = fields.Char(required=True)
description = fields.Char()
postcode = fields.Char()
date_availability = fields.Date(default=date.today() + relativedelta(months=3))
date_availability = fields.Date(
copy=False, default=date.today() + relativedelta(months=3)
)
expected_price = fields.Float(required=True)
selling_price = fields.Float()
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()
active = fields.Boolean(default=True)
state = fields.Selection(default='new', selection=[('new', 'New'), ('offer_recived', 'Offer Recieved'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('canceled', 'Canceled')])
garden_orientation = fields.Selection(selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West')])
property_type_id = fields.Many2one("estate.property.type", string='Property Type')
state = fields.Selection(
required=True,
copy=False,
default="new",
selection=[
("new", "New"),
("offer_recived", "Offer Recieved"),
("offer_accepted", "Offer Accepted"),
("sold", "Sold"),
("canceled", "Canceled"),
],
tracking=True,
)
garden_orientation = fields.Selection(
selection=[
("north", "North"),
("south", "South"),
("east", "East"),
("west", "West"),
]
)
_order = "id desc"
salesman_id = fields.Many2one(
'res.users', # The model this field relates to
string='Salesman', # Label for the field
default=lambda self: self.env.user.partner_id # Set default to the current user's partner
"res.users", # The model this field relates to
string="Salesman", # Label for the field
default=lambda self: self.env.user, # Set default to the current user's partner
)
buyer_id = fields.Many2one(
'res.partner', # The model this field relates to
string='Buyer', # Label for the field
copy=False # Prevent the field value from being copied when duplicating the record
"res.partner", # The model this field relates to
string="Buyer", # Label for the field
copy=False, # Prevent the field value from being copied when duplicating the record
)

tag_ids = fields.Many2many('estate.property.tag', string='Tags')
offer_ids = fields.One2many('estate.property.offer', 'property_id')
total = fields.Integer(compute='total_area')
tag_ids = fields.Many2many("estate.property.tag", string="Tags", ondelete="cascade")
offer_ids = fields.One2many("estate.property.offer", "property_id")
total = fields.Integer(compute="total_area")
best_offer = fields.Float(compute="best_offer_selete", store=True)
property_type_id = fields.Many2one("estate.property.type")

@api.depends('living_area', 'garden_area')
sql_constraints = [
(
"check_expected_price",
"CHECK(expected_price > 0)",
"The Expected Price of Property should be positive",
),
(
"check_selling_price",
"CHECK(selling_price >= 0 )",
"The Selling Price of Property should be Positive",
),
("name_uniq", "unique (name)", "Property name already exists!"),
]

@api.depends("living_area", "garden_area")
def total_area(self):
for recorde in self:
recorde.total = recorde.living_area + recorde.garden_area

best_offer = fields.Float(compute='best_offer_selete', store=True)

@api.depends('offer_ids')
@api.depends("offer_ids")
def best_offer_selete(self):
temp = 0
for offer in self.offer_ids:
if offer.price > temp:
temp = offer.price
self.best_offer = temp

@api.onchange('garden')
@api.onchange("garden")
def garden_change(self):
if self.garden:
self.garden_area = 10
self.garden_orientation = 'north'
self.garden_orientation = "north"
else:
self.garden_area = 0
self.garden_orientation = ''
self.garden_orientation = ""

def status_action_sold_button(self):
if self.state == 'canceled':
if self.state == "canceled":
raise UserError("Canceled property can't be sold")
else:
self.state = 'sold'
self.state = "sold"

def status_action_canceled_button(self):
if self.state == 'sold':
if self.state == "sold":
raise UserError("Sold property can't be canceled")
else:
self.state = 'canceled'
self.state = "canceled"

_sql_constraints = [
('check_expected_price', 'CHECK(expected_price > 0)',
'The Expected Price of Property should be positive'),
('check_selling_price', 'CHECK(selling_price >= 0 )',
'The Selling Price of Property should be Positive'),
('name_uniq', 'unique (name)', "Property name already exists!"),
]
@api.constrains("selling_price", "expexted_price")
def _check_date_end(self):
for record in self:
if record.selling_price > 0:
price_percent = (record.selling_price / record.expected_price) * 100
if price_percent < 90:
raise ValidationError("Selling Price must be at least 90%")
45 changes: 32 additions & 13 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,30 @@


class EstatePropertyOffer(models.Model):
_name = 'estate.property.offer'
_description = 'Estate Property Offer'
_name = "estate.property.offer"
_description = "Estate Property Offer"
_order = "price desc"
price = fields.Float()
status = fields.Selection(copy=False, selection=[('accepted', 'Accepted'), ('refused', 'Refused')])
partner_id = fields.Many2one('res.partner', required=True)
property_id = fields.Many2one('estate.property', required=True)
status = fields.Selection(
copy=False, selection=[("accepted", "Accepted"), ("refused", "Refused")]
)
partner_id = fields.Many2one("res.partner", required=True)
property_id = fields.Many2one("estate.property", required=True)
validity = fields.Integer(default=7)
deadline = fields.Date(compute='_compute_deadline', inverse='_inverse_deadline')
deadline = fields.Date(compute="_compute_deadline", inverse="_inverse_deadline")
property_type_id = fields.Many2one(related='property_id.property_type_id', store=True)

@api.depends('validity')
@api.ondelete(at_uninstall=False)
def _check_offer(self):
for record in self:
if record.status == "accepted":
# raise ValidationError("Accepted offer have benn deleted")
record.property_id.selling_price = 0
record.property_id.buyer_id = None
else:
pass

@api.depends("validity")
def _compute_deadline(self):
for record in self:
today = record.create_date
Expand All @@ -37,20 +51,25 @@ def _inverse_deadline(self):
else:
record.validity = 7 # Default to 7 if deadline is not set

@api.depends('property_id')
def action_status_accept(self):
self.status = 'accepted'
price_percent = (self.price / self.property_id.expected_price) * 100
self.status = "accepted"
price_percent = 0
if self.property_id.expected_price != 0:
price_percent = (self.price / self.property_id.expected_price) * 100
if price_percent > 90:
self.property_id.selling_price = self.price
self.property_id.buyer_id = self.partner_id
else:
raise ValidationError("The selling price must be at least 90%")

def aciton_status_refused(self):
self.status = 'refused'
if self.status == "accepted":
self.property_id.selling_price = 0
self.property_id.buyer_id = None
self.status = "refused"
else:
self.status = "refused"

_sql_constraints = [
('check_price', 'CHECK(price >= 0)',
'The Price of Offer should be positive'),
("check_price", "CHECK(price >= 0)", "The Price of Offer should be positive"),
]
2 changes: 2 additions & 0 deletions estate/models/estate_property_tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ class EstatePropertyTag(models.Model):
_description = 'Estate Property tag'
name = fields.Char(required=True)
_sql_constraints = [('name_uniq', 'unique (name)', "Tag name already exists!")]
_order = 'name'
color = fields.Integer()
15 changes: 14 additions & 1 deletion estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,20 @@
from odoo import fields, models
from odoo import fields, models, api


class EstatePropertyType(models.Model):
_name = "estate.property.type"
_description = "Real Estate Property Type"
name = fields.Char(required=True)
property_id = fields.One2many('estate.property', 'property_type_id')
_order = 'sequence, name'
sequence = fields.Integer('Sequence', help="Used to order stages. Lower is better.")
offers_ids = fields.One2many('estate.property.offer', 'property_type_id')
offer_count = fields.Integer(compute='_offers_count', help="Number of offers")

@api.depends('offers_ids.property_type_id')
def _offers_count(self):
for record in self:
if record.offers_ids:
record.offer_count = len(record.offers_ids)
else:
record.offer_count = 0
24 changes: 18 additions & 6 deletions estate/views/estate_property_offer_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
<field name="name">estate_property_offer</field>
<field name="model">estate.property.offer</field>
<field name="arch" type="xml">
<tree sample="1">
<tree editable="bottom" sample="1" decoration-danger="status in ('refused', 'Refused')" decoration-success="status in ('accepted', 'Accepted')">
<field name='price'/>
<field name='partner_id'/>

<field name='validity' string='Validity (days)'/>
<field name='deadline'/>
<button name="action_status_accept" type="object" icon="fa-check" />
<button name="aciton_status_refused" type="object" icon="fa-times"/>
<field name='status'/>
<button name="action_status_accept" invisible="status in ('accepted', 'refused')" title="accept" type="object" icon="fa-check" />
<button name="aciton_status_refused" invisible="status in ('accepted', 'refused')" title="refused" type="object" icon="fa-times"/>
<field name='status' column_invisible='1' />
</tree>
</field>

Expand All @@ -25,15 +25,27 @@
<field name="arch" type="xml">
<form >
<sheet>
<group>
<group >
<field name='price'/>
<field name='partner_id'/>
<field name="validity"/>
<field name="deadline"/>
<field name='status'/>
</group>
</sheet>
</form>
</field>
</record>
<record id="action_estate_property_offer" model="ir.actions.act_window">
<field name="name">Estate Property Offers</field>
<field name="res_model">estate.property.offer</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('property_type_id', '=', active_id)]</field>
</record>
<record id="action_estate_property_offer_y" model="ir.actions.act_window">
<field name="name">Estate Property Offers</field>
<field name="res_model">estate.property.offer</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('property_type_id', '=', active_id)]</field>
</record>

</odoo>
11 changes: 11 additions & 0 deletions estate/views/estate_property_tag_view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,15 @@
</p>
</field>
</record>

<record id='estate_property_tag_tree' model='ir.ui.view'>
<field name="name">estate_property_tag</field>
<field name="model">estate.property.tag</field>
<field name="arch" type="xml">
<tree editable="bottom" sample="1">
<field name='name'/>
</tree>
</field>

</record>
</odoo>
36 changes: 34 additions & 2 deletions estate/views/estate_property_type.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,55 @@
<field name="res_model">estate.property.type</field>
<field name="view_mode">tree,form</field>


<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new Property product
</p>
</field>
</record>

<record id='estate_property_form_view' model='ir.ui.view'>

<record id="estate_property_type_tree" model="ir.ui.view">
<field name="name">estate_property_type_tree</field>
<field name="model">estate.property.type</field>
<field name="arch" type="xml">
<tree sample="1">
<field name="sequence" widget="handle"/>
<field name="name"/>
<!-- <field name="offer_count"/> -->
</tree>
</field>
</record>

<record id='estate_property_form_view' model='ir.ui.view'>
<field name='name'> estate_property_type</field>
<field name='model'>estate.property.type</field>

<field name="arch" type="xml">
<form string='product Type'>
<sheet>

<button type="action" name="%(estate.action_estate_property_offer_y)d" string="Offers" class="oe_stat_button" icon="fa-ticket">
<div class="o_stat_info">
<field name="offer_count" widget="statinfo" string=""/>
<span class="o_stat_text"> Offer</span>
</div>
</button>

<h1>
<field name='name'/>
</h1>
<notebook>
<page string="Properties">
<field name="property_id">
<tree>
<field name="name"/>
<field name="expected_price"/>
<field name='state'/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
Expand Down
Loading

0 comments on commit 67f2f9f

Please sign in to comment.