Skip to content
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
13 changes: 13 additions & 0 deletions awesome_owl/static/src/counter/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Component, useState } from "@odoo/owl";

export class Counter extends Component {
static template = "awesome_owl.Counter";

setup() {
this.state = useState({ value: 1 });
}

increment() {
this.state.value++;
}
}
9 changes: 9 additions & 0 deletions awesome_owl/static/src/counter/counter.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates xml:space="preserve">
<t t-name="awesome_owl.Counter" owl="1">
<div class="m-2 p-2 border d-inline-block">
<span class="me-2">Counter: <t t-esc="state.value"/></span>
<button class="btn btn-primary" t-on-click="increment">Increment</button>
</div>
</t>
</templates>
4 changes: 4 additions & 0 deletions awesome_owl/static/src/playground.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { Component } from "@odoo/owl";
import { Counter } from "./counter/counter";

export class Playground extends Component {
static template = "awesome_owl.playground";


static components = { Counter };
}
8 changes: 4 additions & 4 deletions awesome_owl/static/src/playground.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<templates xml:space="preserve">

<t t-name="awesome_owl.playground">
<div class="p-3">
hello world
</div>
</t>
<p>Hello World</p>
<Counter />
<Counter />

</t>
</templates>
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
23 changes: 23 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
{
"name": "Estate Module",
"summary": """
TO BE DEF"
""",
"description": """
TO BE DEF"
""",
# any module necessary for this one to work correctly
"depends": ["base"],
"application": True,
"installable": True,
"data": [
"security/ir.model.access.csv",
"views/estate_property_views.xml",
"views/estate_property_type_views.xml",
"views/estate_property_tag_views.xml",
"views/estate_property_offer_views.xml",
"views/menus.xml",
"views/base_res_users_views.xml",

Choose a reason for hiding this comment

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

Suggested change
"views/base_res_users_views.xml",
"views/res_users_views.xml",

],
}
7 changes: 7 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from . import (
estate_property,
estate_property_type,
estate_property_tag,
estate_property_offer,
res_users,
)
176 changes: 176 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
from odoo import fields, models, api, exceptions, tools
from datetime import timedelta


class estate_property(models.Model):
_name = "estate.property"
_description = "estate.property"
_order = "sequence desc"

name = fields.Char(required=True)
sequence = fields.Integer("Sequence", default=1)
description = fields.Text()
postcode = fields.Char()
date_availability = fields.Date(
copy=False,
string="Available From",
default=lambda self: fields.Date.today() + timedelta(days=90),
)
expected_price = fields.Float(required=True)
selling_price = fields.Float(
readonly=True, copy=False, compute="_set_selling_price"
)
bedrooms = fields.Integer(default=2)
living_area = fields.Integer()
facades = fields.Integer()
garage = fields.Boolean()
garden = fields.Boolean()
garden_area = fields.Integer()
total_area = fields.Float(compute="_compute_total_area", store=True)
garden_orientation = fields.Selection(
selection=[
("north", "North"),
("south", "South"),
("east", "East"),
("west", "West"),
]
)
active = fields.Boolean(default=True)
state = fields.Selection(
required=True,
default="new",
copy=False,
selection=[
("new", "New"),
("offer_received", "Offer Received"),
("offer_accepted", "Offer Accepted"),
("sold", "Sold"),
("cancelled", "Cancelled"),
],
)
property_type_id = fields.Many2one("estate.property.type", string="Model")
sales_user_id = fields.Many2one(
"res.users", string="Salesperson", default=lambda self: self.env.user
)
buyer_partner_id = fields.Many2one("res.partner", string="Buyer", copy=False)
tags_ids = fields.Many2many("estate.property.tag", string="Tags")
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
best_price = fields.Float(compute="_get_highest_price")
has_accepted_offer = fields.Boolean(default=False, help="for testing purpouse")

# ---------------------------------------------------------------------------------------------------------
# Crud Functions

@api.ondelete(at_uninstall=False)
def _unlink_if_user_new(self):
if any(
property.state in ["offer_received", "offer_accepted", "sold"]
for property in self
):
raise exceptions.UserError(
"Only new and cancelled properties can be deleted !"
)

# ---------------------------------------------------------------------------------------------------------
# Compute Functions

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

@api.depends("offer_ids.price")
def _get_highest_price(self):
for record in self:
record.best_price = max(record.mapped("offer_ids.price"), default=0)

@api.onchange("garden")
def _onchange_garden(self):
for record in self:
if record.garden:
record.garden_area = 10
record.garden_orientation = "north"
else:
record.garden_area = 0
record.garden_orientation = ""

@api.depends("offer_ids.status", "has_accepted_offer")
def _set_selling_price(self):
for record in self:
if not len(record.offer_ids):
record.selling_price = 0
else:
if "accepted" not in set(record.mapped("offer_ids.status")):
record.selling_price = 0
record.has_accepted_offer = False
else:
id = record.mapped("offer_ids.status").index("accepted")
record.selling_price = record.mapped("offer_ids.price")[id]
record.has_accepted_offer = True

# ---------------------------------------------------------------------------------------------------------
# Public Functions

def set_state_cancelled(self):
for record in self:
if record.state != "sold":
record.state = "cancelled"
else:
raise exceptions.UserError(
(
"You can't change the offer's state to Cancelled after the offer has been sold"
)
)

return True

def set_state_sold(self):
for record in self:
if record.state != "cancelled":
record.state = "sold"
else:
raise exceptions.UserError(
(
"You can't change the offer's state to Sold after the offer has been cancelled"
)
)
return True

def _update_state(self):
ret = []
for record in self:
ret.append(record.best_price)
if record.state == "new":
record.state = "offer_received"
return ret

# ---------------------------------------------------------------------------------------------------------
# Constraints

_check_expected_price = models.Constraint(
"CHECK(expected_price > 0)",
"The expected price of a propriety needs to be strictly positive",
)

_check_selling_price = models.Constraint(
"CHECK(selling_price >= 0)",
"The selling price of a propriety needs to be positive",
)

@api.constrains(
"expected_price",
)
def _check_selling_price(self):
for record in self:
if not record.has_accepted_offer:
return True

if (
tools.float_compare(
(record.expected_price * 0.9), record.selling_price, 2
)
>= 0
):
raise exceptions.ValidationError(
"The selling price cant be lower than 90 percent of the expected price"
)
98 changes: 98 additions & 0 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from odoo import fields, models, api, exceptions, tools
from datetime import timedelta


class estate_property_offer(models.Model):
_name = "estate.property.offer"
_description = "Estate Offer"
_order = "price desc"

price = fields.Float(string="Offer Price")
status = fields.Selection(
selection=[("accepted", "Accepted"), ("refused", "Refused")],
copy=False,
string="Status",
)
partner_id = fields.Many2one("res.partner", required=True)
property_id = fields.Many2one("estate.property", required=True)
property_type_id = fields.Many2one(
related="property_id.property_type_id", store=True
)
validity = fields.Integer(default=7)
date_deadline = fields.Date(
compute="_compute_deadline", inverse="_inverse_deadline"
)

@api.depends("validity", "create_date")
def _compute_deadline(self):
for offer in self:
if offer.create_date:
offer.date_deadline = offer.create_date.date() + timedelta(
days=offer.validity
)
else:
offer.date_deadline = fields.Date.today() + timedelta(
days=offer.validity
)

def _inverse_deadline(self):
for offer in self:
if offer.create_date:
offer.validity = (offer.date_deadline - offer.create_date.date()).days
else:
offer.validity = (offer.date_deadline - fields.Date.today()).days

@api.model
def create(self, vals_list):
for values in vals_list:
prices = (
self.env["estate.property"]
.browse(values["property_id"])
._update_state()
)
if any((p := price) > values["price"] for price in prices):
raise exceptions.UserError(
("You can't create an offer that is lower than " + str(p))
)

return super().create(vals_list)

def set_status_accepted(self):
for offer in self:
if not offer.property_id.has_accepted_offer:
offer.status = "accepted"
if offer.property_id.state not in [
"offer_accepted",
"sold",
"cancelled",
]:
offer.property_id.state = "offer_accepted"
else:
raise exceptions.UserError(("You can't accept multiple offers"))
return True

def set_status_refused(self):
for offer in self:
offer.status = "refused"
return True

_check_offer_price = models.Constraint(
"CHECK(price > 0)",
"The price of an offer needs to be strictly positive",
)

@api.constrains("status", "price")
def _check_selling_price(self):
for offer in self:
if offer.status != "accepted":
return True

if (
tools.float_compare(
(offer.property_id.expected_price * 0.9), offer.price, 2
)
>= 0
):
raise exceptions.ValidationError(
"The selling price cant be lower than 90 percent of the expected price"
)
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 odoo import fields, models


class estate_property_tag(models.Model):
_name = "estate.property.tag"
_description = "estate tag"
_order = "name"

name = fields.Char(required=True)
color = fields.Integer()

_check_offer_price = models.Constraint(
"unique(name)",
"A tag with the same name already exists",
)
Loading