Skip to content

Commit 641a1a7

Browse files
committed
[IMP] awesome_owl: Implemented new components and improve UI/JS structure
Estate: - Updated models (property, offer, type) with improved logic and fields - Fixed offer views and replaced deprecated attrs with modifiers for Odoo 17+ - Updated main property views for better usability - Added cron XML for scheduled date processing - Improved manifest metadata Estate Accounting: - Added account_move extension for property invoicing - Updated estate_property accounting bridge - Added new view estate_move.xml - Updated access rights - Cleaned model imports Awesome Dashboard: - Updated dashboard JS logic - Added new SCSS styling - Improved dashboard XML structure Awesome Owl: - Updated manifest and controllers - Added new components: card, counter, todo_list (JS + XML) - Updated main.js and playground code - Added utils.js helper module
1 parent 89126d5 commit 641a1a7

31 files changed

+411
-153
lines changed

Estate/__manifest__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
'license': 'AGPL-3',
99
'data': [
1010
'security/ir.model.access.csv',
11+
'data/date_cron.xml',
1112
'views/estate_property_type_views.xml',
1213
'views/estate_property_offer_views.xml',
1314
'views/estate_property_tags_views.xml',

Estate/data/date_cron.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<odoo>
2+
<record id="ir_cron_move_sold" model="ir.cron">
3+
<field name="name">Sold if validity exceeds</field>
4+
<field name="model_id" ref="model_estate_property_offer"/>
5+
<field name="state">code</field>
6+
<field name="code">model._cron_move_sold</field>
7+
<field name="interval_number">1</field>
8+
<field name="interval_type">days</field>
9+
</record>
10+
</odoo>

Estate/models/estate_property.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
from datetime import timedelta
2-
1+
from datetime import timedelta
2+
from os import read
3+
from odoo.tools import date_utils
4+
35
from odoo import models, fields, api
46
from odoo.exceptions import ValidationError
7+
from odoo.tools.float_utils import float_compare, float_is_zero
58

69

710
class EstateProperty(models.Model):
@@ -13,7 +16,7 @@ class EstateProperty(models.Model):
1316
postcode = fields.Char()
1417
create_date = fields.Datetime()
1518
expected_price = fields.Float(required=True)
16-
selling_price = fields.Float()
19+
selling_price = fields.Float(readonly=True)
1720
bedrooms = fields.Integer()
1821
living_area = fields.Integer()
1922
facades = fields.Integer()
@@ -73,24 +76,30 @@ def _compute_date_deadline(self):
7376
if hasattr(create_date, "date"):
7477
create_date = create_date.date()
7578
record.date_deadline = create_date + timedelta(days=record.validity_days)
76-
79+
7780
def _inverse_date_deadline(self):
7881
for record in self:
7982
create_date = record.create_date or fields.Date.today()
8083
if hasattr(create_date, "date"):
8184
create_date = create_date.date()
8285
delta = (record.date_deadline - create_date).days if record.date_deadline else 0
8386
record.validity_days = delta
84-
87+
88+
@api.constrains('selling_price', 'expected_price')
89+
def _check_selling_price(self):
90+
for record in self:
91+
if not float_is_zero(record.selling_price, precision_digits=2):
92+
if float_compare(record.selling_price, 0.9 * record.expected_price, precision_digits=2) < 0:
93+
raise ValidationError("The selling price cannot be lower than 90% of the expected price.")
94+
8595
@api.onchange("garden")
8696
def _onchange_garden(self):
87-
for record in self:
88-
if record.garden:
89-
record.garden_area = 10
90-
record.garden_orientation = "north"
97+
if self.garden:
98+
self.garden_area = 10
99+
self.garden_orientation = "north"
91100
else:
92-
record.garden_area = 0
93-
record.garden_orientation = False
101+
self.garden_area = 0
102+
self.garden_orientation = False
94103

95104
@api.model
96105
def create(self, vals):
@@ -119,12 +128,6 @@ def action_back_to_new(self):
119128
for record in self:
120129
record.state = "new"
121130

122-
@api.constrains("selling_price", "expected_price")
123-
def _check_selling_price_ratio(self):
124-
for record in self:
125-
if record.selling_price < 0.9 * record.expected_price:
126-
raise ValidationError("Selling price must be at least 90% of the expected price")
127-
128131
def _unlink(self):
129132
for record in self:
130133
if record.state in ["new"]:
Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,77 @@
1+
from datetime import timedelta
12
from odoo import models, fields, api
2-
from odoo.exceptions import ValidationError
3-
3+
from odoo.exceptions import UserError
44

55
class EstatePropertyOffer(models.Model):
66
_name = "estate.property.offer"
77
_description = "Real Estate Property Offer"
88
_order = "price desc"
99

10-
price = fields.Float(required=True)
10+
price = fields.Float(string="Price", required=True)
1111
status = fields.Selection(
12-
[
13-
('accepted', 'Accepted'),
14-
('refused', 'Refused'),
15-
],
12+
[('accepted', 'Accepted'), ('refused', 'Refused')],
13+
string="Status",
14+
copy=False
1615
)
17-
property_id = fields.Many2one("estate.property", string="Property", required=True)
1816
partner_id = fields.Many2one("res.partner", string="Buyer", required=True)
17+
property_id = fields.Many2one("estate.property", string="Property", required=True)
18+
validity = fields.Integer(default=7, string="Validity (Days)")
19+
date_deadline = fields.Date(compute="_compute_date_deadline", inverse="_inverse_date_deadline", string="Deadline")
20+
21+
_check_price = models.Constraint(
22+
'CHECK(price > 0)',
23+
'The offer price must be strictly positive'
24+
)
25+
26+
@api.depends("create_date", "validity")
27+
def _compute_date_deadline(self):
28+
for record in self:
29+
base_date = record.create_date.date() if record.create_date else fields.Date.today()
30+
record.date_deadline = base_date + timedelta(days=record.validity)
31+
32+
def _inverse_date_deadline(self):
33+
for record in self:
34+
base_date = record.create_date.date() if record.create_date else fields.Date.today()
35+
if record.date_deadline:
36+
record.validity = (record.date_deadline - base_date).days
1937

2038
def action_accept_offer(self):
2139
for record in self:
40+
if record.status == 'accepted':
41+
continue
42+
2243
record.status = 'accepted'
44+
record.property_id.write({
45+
'selling_price': record.price,
46+
'buyer_id': record.partner_id.id,
47+
'state': 'offer_accepted'
48+
})
49+
50+
record.property_id.offer_ids.filtered(lambda o: o.id != record.id).write({
51+
'status': 'refused'
52+
})
53+
return True
2354

2455
def action_refuse_offer(self):
2556
for record in self:
2657
record.status = 'refused'
58+
return True
2759

28-
@api.constrains("price")
29-
def _check_price_ratio(self):
30-
for record in self:
31-
if record.price <= 0.0:
32-
raise ValidationError("Price must be greater than 0")
60+
@api.model
61+
def create(self, vals):
62+
if len(vals) > 0:
63+
property = self.env['estate.property'].browse(vals[0]['property_id'])
64+
for record in vals:
65+
if property.state == 'new':
66+
property.state = 'offer_received'
67+
if record['price'] < property.best_price:
68+
raise UserError("Offer must be higher or equal than %d" % property.best_price)
69+
return super().create(vals)
70+
71+
@api.model
72+
def _cron_move_sold(self):
73+
expired_offers = self.search([
74+
('status', '=', False),
75+
('date_deadline', '<', fields.Date.today())
76+
])
77+
expired_offers.write({'status': 'refused'})

Estate/models/estate_property_type.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
from odoo import models, fields, api
2-
from odoo.exceptions import ValidationError
32

43

54
class EstatePropertyType(models.Model):
65
_name = "estate.property.type"
76
_description = "Real Estate Property Type"
8-
_order = "name desc"
7+
_order = "sequence , name"
98

109
name = fields.Char(required=True)
1110
property_ids = fields.One2many("estate.property", "property_type_id", string="Properties")
Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,56 @@
11
<odoo>
2-
3-
<record id="estate_property_offer_tree_view" model="ir.ui.view">
2+
<record id="estate_property_offer_view_list" model="ir.ui.view">
43
<field name="name">estate.property.offer.list</field>
54
<field name="model">estate.property.offer</field>
65
<field name="arch" type="xml">
7-
<list>
8-
<field name="price" />
9-
<field name="partner_id" />
10-
<button name="action_accept_offer" string="accept" type="object" invisible="status in ['accepted', 'refused']" />
11-
<button name="action_refuse_offer" string="refuse" type="object" invisible="status in ['accepted', 'refused']" />
12-
<field name="status" />
6+
<list string="Property Offers" editable="bottom"
7+
decoration-success="status == 'accepted'"
8+
decoration-danger="status == 'refused'">
9+
<field name="price"/>
10+
<field name="partner_id"/>
11+
<field name="status" column_invisible="True"/>
12+
<button name="action_accept_offer"
13+
string="Accept"
14+
type="object"
15+
icon="fa-check"
16+
title="Accept"
17+
invisible="status"/>
18+
19+
<button name="action_refuse_offer"
20+
string="Refuse"
21+
type="object"
22+
icon="fa-times"
23+
title="Refuse"
24+
invisible="status"/>
1325
</list>
1426
</field>
1527
</record>
1628

17-
<record id="estate_property_offer_form_view" model="ir.ui.view">
29+
<record id="estate_property_offer_view_form" model="ir.ui.view">
1830
<field name="name">estate.property.offer.form</field>
1931
<field name="model">estate.property.offer</field>
2032
<field name="arch" type="xml">
21-
<form>
33+
<form string="Offer Details">
2234
<sheet>
2335
<group>
24-
<field name="price"/>
25-
<field name="partner_id"/>
26-
<field name="status"/>
27-
<button name="action_accept_offer" string="accept" type="object" invisible="status in ['accepted', 'refused']" />
28-
<button name="action_refuse_offer" string="refuse" type="object" invisible="status in ['accepted', 'refused']" />
36+
<group>
37+
<field name="price"/>
38+
<field name="partner_id"/>
39+
</group>
40+
<group>
41+
<field name="status"/>
42+
<field name="property_id" readonly="1"/>
43+
</group>
2944
</group>
3045
</sheet>
3146
</form>
3247
</field>
3348
</record>
49+
50+
<record id="action_estate_property_offer" model="ir.actions.act_window">
51+
<field name="name">Property Offers</field>
52+
<field name="res_model">estate.property.offer</field>
53+
<field name="view_mode">list,form</field>
54+
<field name="domain">[('property_id', '=', active_id)]</field>
55+
</record>
3456
</odoo>

Estate/views/estate_property_type_views.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<field name="model">estate.property.type</field>
1010
<field name="arch" type="xml">
1111
<list>
12+
<field name="sequence" widget="handle"/>
1213
<field name="name"/>
1314
</list>
1415
</field>

0 commit comments

Comments
 (0)