Skip to content

Technical Training Solution #59

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

Open
wants to merge 128 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
128 commits
Select commit Hold shift + click to select a range
5783121
Add link to Technical Training for Odoo 16.0
nim-odoo Sep 10, 2018
6a14b59
new model
goeko Nov 6, 2023
e250921
... test
goeko Nov 6, 2023
fef90a9
... ... test
goeko Nov 6, 2023
cebcd80
CAP 5 : Access Rights
goeko Nov 6, 2023
3b50f02
CAP 5 : Access Rights
goeko Nov 6, 2023
f0ffe43
CAP 5 : Access Rights
goeko Nov 6, 2023
cb105e4
CAP 5 : Access Rights
goeko Nov 6, 2023
735f2b6
CAP 5 : Access Rights
goeko Nov 6, 2023
c81c74e
CAP 5 : Access Rights
goeko Nov 6, 2023
3bb3903
CAP 6 : Views
goeko Nov 6, 2023
d4776ed
CAP 6 : Views
goeko Nov 6, 2023
6eba645
CAP 6 : Views
goeko Nov 6, 2023
e98e202
CAP 6 : Views
goeko Nov 6, 2023
d3f2f32
CAP 6 : Views
goeko Nov 6, 2023
33f5055
CAP 6 : Views
goeko Nov 6, 2023
c687ef1
CAP 6 : Views
goeko Nov 6, 2023
61ebad7
CAP 6 : Views / Menus
goeko Nov 6, 2023
655a30d
CAP 6 : Views / Menus
goeko Nov 6, 2023
0a41512
CAP 6 : Views / Menus
goeko Nov 6, 2023
eb75686
CAP 6 : Views / setup defaults
goeko Nov 6, 2023
0d012e4
CAP 6 : Views / add active and status
goeko Nov 6, 2023
3e7fa08
CAP 6 : Views / add active and status
goeko Nov 6, 2023
d47126a
CAP 6 : Views / add active and status
goeko Nov 6, 2023
6785300
...
goeko Nov 6, 2023
332d1c7
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
4fa429a
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
32ddf63
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
f21fa25
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
d835fa2
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
94a5882
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
918a9fd
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
96ea962
Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
addd5ec
... Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
c720f34
... Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
584e635
... Chapter 7: Basic Views | tree and form
goeko Nov 6, 2023
1fae471
Chapter 8
goeko Nov 6, 2023
c65e204
Chapter 8 : add property type
goeko Nov 6, 2023
7c60352
... Chapter 8 : add property type
goeko Nov 6, 2023
dafa8a6
... Chapter 8 : add property type
goeko Nov 6, 2023
600ad61
... Chapter 8 : add property type
goeko Nov 6, 2023
3df9efc
... Chapter 8 : add seller & buyer
goeko Nov 6, 2023
0ccd0f3
... Chapter 8 : add seller & buyer
goeko Nov 6, 2023
3a10215
... Chapter 8 : add seller & buyer : set different Label
goeko Nov 6, 2023
34e5a0b
... Chapter 8 : add seller & buyer : add data
goeko Nov 6, 2023
e4bc399
... Chapter 8 : add seller & buyer : add data
goeko Nov 6, 2023
2ba1884
... Chapter 8 : add seller & buyer : add data
goeko Nov 6, 2023
5416861
... Chapter 8 : add seller & buyer
goeko Nov 6, 2023
2b0be4f
... Chapter 8 : add seller & buyer
goeko Nov 6, 2023
3e5c3f2
... Chapter 8 : add seller & buyer
goeko Nov 6, 2023
8f8d870
... Chapter 8 : add seller & buyer
goeko Nov 6, 2023
4123532
... Chapter 8 : many2many : tags
goeko Nov 6, 2023
f580590
... Chapter 8 : many2many : tags
goeko Nov 6, 2023
afa76fd
... Chapter 8 : many2many : tags
goeko Nov 6, 2023
358fd5d
... Chapter 8 : many2many : tags
goeko Nov 6, 2023
78565c3
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
80c089b
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
b128b85
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
4e99c06
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
c6baa17
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
a65af89
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
ef6775b
... Chapter 8 : One2many : offer
goeko Nov 6, 2023
be96ad4
... Chapter 8 : One2many : offer
goeko Nov 7, 2023
25ab701
... Chapter 8 : One2many : offer
goeko Nov 7, 2023
1d4fa3f
... Chapter 8 : One2many : offer
goeko Nov 7, 2023
d4eade1
... Chapter 8 : One2many : offer
goeko Nov 7, 2023
abd410b
... Chapter 8 : One2many : offer
goeko Nov 7, 2023
246fb6c
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
8461d70
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
106f2d3
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
0467af5
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
4171607
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
1f25ee8
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
8cac37d
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
aefcc5f
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
2db6fa2
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
d33235d
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
355d888
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
6f10575
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
adc43ee
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
5bc4d6c
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
5dd3026
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
2a24f8f
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
526708d
... Chapter 8 : One2many : offer : Inverse Function
goeko Nov 7, 2023
82be9e7
... Chapter 9 : Onchanges
goeko Nov 7, 2023
d0c8c00
... Chapter 9 : Onchanges : garden
goeko Nov 7, 2023
ab3d96a
... Chapter 9 : Onchanges : garden
goeko Nov 7, 2023
64bfdfe
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
160dce2
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
4ff9233
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
f7a6c15
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
efab55e
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
ffecc99
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
ed439f9
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
facc39a
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
e57070a
Chapter 10 : functional buttons and status dependency
goeko Nov 7, 2023
688cf00
setup app version to 1.0.0 and odoo version to 17.0
goeko Nov 7, 2023
3fb9dbe
Chapter 11: Constraints : cp01
goeko Nov 7, 2023
fc2e9fa
Chapter 11: Constraints : cp01
goeko Nov 7, 2023
aa69006
Chapter 11: Constraints : cp01
goeko Nov 7, 2023
f1da383
Chapter 11: Constraints : cp01
goeko Nov 7, 2023
d2ece76
Chapter 11: Constraints : cp01 - activate by default
goeko Nov 7, 2023
5857125
Chapter 11: Constraints : cp01 - positve offer price
goeko Nov 7, 2023
87ad5d1
Chapter 11: Constraints : make unique
goeko Nov 7, 2023
3c4f472
Chapter 11: Constraints : make name auf type and tag unique
goeko Nov 7, 2023
f545837
Chapter 11: add menu for tags
goeko Nov 7, 2023
1e3c895
Chapter 11: Add a constraint so that the selling price cannot be lowe…
goeko Nov 7, 2023
c48bfd4
Chapter 11: fix float is zero; ... Add a constraint so that the selli…
goeko Nov 7, 2023
327e0b9
Chapter 11: add menu for tags
goeko Nov 7, 2023
77e7420
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
ce4c7b1
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
36bb1bd
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
58a276e
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
f129dc4
debug: Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
74d9d99
debug: Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
4871b3d
debug: Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
38fef5b
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
d2b8245
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
35d3a3b
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
3ce2b9b
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
c179930
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
3ee2df9
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
504635a
Chapter 12: Exercise : Add a stat button to property type.
goeko Nov 7, 2023
812c9e9
Chapter 12: Exercise : Add a stat button to property type. add comments
goeko Nov 7, 2023
20524df
Chapter 13: Exercise : Add business logic to the CRUD methods.
goeko Nov 7, 2023
be65dfe
Update README.md
goeko Nov 7, 2023
582a4ae
rename amount to price
goeko Nov 15, 2023
0f39b1e
add status to listing
goeko Nov 15, 2023
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
Empty file modified .gitignore
100644 → 100755
Empty file.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
# Odoo 12.0 - Technical Training
# Odoo 17.0 - Technical Training

The Technical Training of Odoo 17.0 is available on the
[Tutorial](https://www.odoo.com/documentation/master/developer/howtos/rdtraining.html)
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
17 changes: 17 additions & 0 deletions estate/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"name": "Real Estate", # The name that will appear in the App list
"version": "17.0.1.0.0", # Version
"application": True, # This line says the module is an App, and not a module
"depends": ["base"], # dependencies
"data": [
"security/ir.model.access.csv",
"views/estate_actions.xml", # add action bevor all other views, so their every time loaded before
"views/estate_property_views.xml",
"views/estate_property_type_views.xml",
"views/estate_property_tag_views.xml",
"views/estate_property_offer_views.xml",
"views/estate_menus.xml"
],
"installable": True,
'license': 'LGPL-3',
}
4 changes: 4 additions & 0 deletions estate/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
from . import estate_property
from . import estate_property_type
from . import estate_property_tag
from . import estate_property_offer
87 changes: 87 additions & 0 deletions estate/models/estate_property.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.float_utils import float_compare, float_is_zero

class EstateProperty(models.Model):
_name = "estate.property"
_description = "Estate Property"

name = fields.Char()
description = fields.Text()
postcode = fields.Char()
date_availability = fields.Date(default=lambda self: fields.Date.today() + relativedelta(months=+3))
Copy link
Contributor

Choose a reason for hiding this comment

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

You may also use the method defined on the field type Date:

Suggested change
date_availability = fields.Date(default=lambda self: fields.Date.today() + relativedelta(months=+3))
date_availability = fields.Date(default=lambda self: fields.Date.add(fields.Date.today(), months=3))

expected_price = fields.Float(required=True)
selling_price = fields.Float(required=True)
Comment on lines +14 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

We haven't covered it on purpose, but for your information, in odoo there is a type of field Monetary, see https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#odoo.fields.Monetary

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(
string='Type',
selection=[('north', 'North'), ('south', 'South'), ('east', 'East'), ('west', 'West') ],
help="")
state = fields.Selection(
string='State',
selection=[('new', 'New'), ('offer_received', 'Offer Received'), ('offer_accepted', 'Offer Accepted'), ('sold', 'Sold'), ('canceled', 'Canceled') ],
default='new',
help="")
active = fields.Boolean(default=1)
property_type_id = fields.Many2one("estate.property.type")
seller_id = fields.Many2one("res.partner", string="Seller")
buyer_id = fields.Many2one("res.partner", string="Buyer")
tag_ids = fields.Many2many("estate.property.tag", string="Tags")
Copy link
Contributor

Choose a reason for hiding this comment

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

In most cases it is not necessary, but not that on M2m fields we can define manually the name of the table used in between the 2 models. It is especially useful when multiple m2m fields exists between the same models. See relation in
https://www.odoo.com/documentation/17.0/developer/reference/backend/orm.html#odoo.fields.Many2many

In this particular case it's not an issue

# the name of 2nd parameter "property_id" is the var string of variable used in offer model
offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers")
# non stored -> not searchable without search method, search="_search_totalarea"
# store=True
totalarea = fields.Float(compute="_compute_totalarea")

_sql_constraints = [
('check_expected_price', 'CHECK(expected_price >= 0)', 'The Expected Price should be positive.'),
('check_selling_price', 'CHECK(selling_price >= 0)', 'The Selling Price should be positive.')
]

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

@api.onchange("garden")
def _onchange_garden(self):
if self.garden == 1:
self.garden_area = 10
self.garden_orientation = "north"
else:
self.garden_area = 0
self.garden_orientation = ""
Comment on lines +53 to +59
Copy link
Contributor

Choose a reason for hiding this comment

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

self.garden is a Boolean field, so self.garden == 1 will always be False

Suggested change
def _onchange_garden(self):
if self.garden == 1:
self.garden_area = 10
self.garden_orientation = "north"
else:
self.garden_area = 0
self.garden_orientation = ""
def _onchange_garden(self):
if self.garden:
self.garden_area = 10
self.garden_orientation = "north"
else:
self.garden_area = 0
self.garden_orientation = False


def set_status_cancel(self):
if self.state != "sold":
self.state = "canceled"

def set_status_sold(self):
if self.state != "canceled":
self.state = "sold"

@api.constrains('expected_price', 'selling_price')
def _check_selling_price(self):
for record in self:
# Skip the check if the selling price is zero (no offer validated yet)
if float_is_zero(record.selling_price, precision_digits=2):
continue

# Calculate 90% of the expected price
price_limit = record.expected_price * 0.9

# Compare the selling price to 90% of the expected price
if float_compare(record.selling_price, price_limit, precision_digits=2) < 0:
raise ValidationError("The selling price cannot be lower than 90% of the expected price.")

@api.ondelete(at_uninstall=False)
def _check_state_before_deletion(self):
for record in self:
if record.state not in ['new', 'canceled']:
raise ValidationError("You can only delete properties that are in 'New' or 'Canceled' state.")
68 changes: 68 additions & 0 deletions estate/models/estate_property_offer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models
from odoo.exceptions import UserError
from odoo.exceptions import ValidationError


class EstatePropertyOffer(models.Model):
_name = "estate.property.offer"
_description = "Estate Property Offer"

name = fields.Char()
price = fields.Float()
status = fields.Selection(
string='Type',
selection=[('accepted', 'Accepted'), ('refused', 'Refused') ],
help="")
partner_id = fields.Many2one("res.partner", string="Partner")
property_id = fields.Many2one("estate.property", string="Property")
validity = fields.Integer(default=7)
date_deadline = fields.Date(compute="_compute_date_deadline", inverse="_inverse_date_deadline", store=True)
property_type_id = fields.Many2one(related="property_id.property_type_id", store=True)

_sql_constraints = [
('check_price', 'CHECK(price >= 0)', 'The Offer Price should be positive.')
]

@api.depends("validity")
def _compute_date_deadline(self):
for record in self:
if record.create_date:
record.date_deadline = record.create_date + relativedelta(days=record.validity)
else:
record.date_deadline = fields.Date.today() + relativedelta(days=record.validity)
Comment on lines +30 to +33
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if record.create_date:
record.date_deadline = record.create_date + relativedelta(days=record.validity)
else:
record.date_deadline = fields.Date.today() + relativedelta(days=record.validity)
create_date = record.create_date or fields.Date.today()
record.date_deadline = create_date + relativedelta(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 - fields.Date.today()).days
Comment on lines +36 to +40
Copy link
Contributor

Choose a reason for hiding this comment

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

same


def estate_property_offer_accepted_action(self):
for record in self:
record.status = "accepted"
record.property_id.selling_price = record.price
record.property_id.seller_id = record.partner_id

def estate_property_offer_refused_action(self):
self.status = "refused"

@api.model
def create(self, vals):
property_id = vals.get('property_id')
if property_id:
property_obj = self.env['estate.property'].browse(property_id)

# Check if there is any existing offer with a higher price
existing_offers = self.env['estate.property.offer'].search([
('property_id', '=', property_id),
('price', '>', vals.get('price', 0))
])
if existing_offers:
raise ValidationError("You cannot create an offer with a lower price than existing offers.")

# Set the property state to 'Offer Received'
property_obj.state = 'offer_received'

return super(EstatePropertyOffer, self).create(vals)
12 changes: 12 additions & 0 deletions estate/models/estate_property_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from odoo import fields, models


class EstatePropertyTag(models.Model):
_name = "estate.property.tag"
_description = "Estate Property Tag"

name = fields.Char()

_sql_constraints = [
('check_name_unique', 'UNIQUE(name)', 'The name must be unique!')
]
18 changes: 18 additions & 0 deletions estate/models/estate_property_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from odoo import api, fields, models

class EstatePropertyType(models.Model):
_name = "estate.property.type"
_description = "Estate Property Type"

name = fields.Char()
offer_ids = fields.One2many("estate.property.offer", "property_type_id", string="Offers")
offer_count = fields.Integer(string='Offer Count', compute='_compute_offer_count')

_sql_constraints = [
('check_name_unique', 'UNIQUE(name)', 'The name must be unique!')
]

@api.depends('offer_ids')
def _compute_offer_count(self):
for record in self:
record.offer_count = len(record.offer_ids)
5 changes: 5 additions & 0 deletions estate/security/ir.model.access.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
estate.access_estate_property,access_estate_property,estate.model_estate_property,base.group_user,1,1,1,1
estate.access_estate_property_type,access_estate_property_type,estate.model_estate_property_type,base.group_user,1,1,1,1
estate.access_estate_property_tag,access_estate_property_tag,estate.model_estate_property_tag,base.group_user,1,1,1,1
estate.access_estate_property_offer,access_estate_property_offer,estate.model_estate_property_offer,base.group_user,1,1,1,1
9 changes: 9 additions & 0 deletions estate/views/estate_actions.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<odoo>
<record id="action_estate_property_offer" model="ir.actions.act_window">
<field name="name">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>
<field name="context">{'default_property_type_id': active_id}</field>
</record>
</odoo>
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 @@
<odoo>
<menuitem id="estate_property_menu_root" name="Estate Property">
<menuitem id="estate_property0_first_level_menu" name="First Level">
<menuitem id="estate_property_00_model_menu_action" action="estate_property_model_action"/>
</menuitem>
<menuitem id="estate_property1_first_level_menu" name="Settings">
<menuitem id="estate_property_type_model_menu_action" action="estate_property_type_action"/>
<menuitem id="estate_property_tag_model_menu_action" action="estate_property_tag_action"/>
</menuitem>
</menuitem>
</odoo>

25 changes: 25 additions & 0 deletions estate/views/estate_property_offer_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<odoo>
<record id="estate_property_offer_action" model="ir.actions.act_window">
<field name="name">Estate Property Offer</field>
<field name="res_model">estate.property.offer</field>
<field name="view_mode">tree,form</field>
</record>

<record id="estate_property_offer_view_tree" model="ir.ui.view">
<field name="name">estate.property.offer</field>
<field name="model">estate.property.offer</field>
<field name="arch" type="xml">
<tree string="Estate Property Offer">
<field name="name"/>
<field name="partner_id"/>
<field name="validity"/>
<field name="price"/>
<field name="date_deadline"/>
<field name="status"/>
<!-- <field name="property_type_id" invisible="1"/> <!- - make the field invisible, it do not need show to the user. leave it as learning stuff. -->
Copy link
Contributor

Choose a reason for hiding this comment

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

some time it is necessary to have fields invisible just for the purpose of using them in other fields attributes, see https://www.odoo.com/documentation/17.0/developer/reference/user_interface/view_architecture.html#python-expression

<button name="estate_property_offer_accepted_action" string="Accepted" type="object" icon="fa-check"/>
<button name="estate_property_offer_refused_action" string="Refused" type="object" icon="fa-level-down"/>
</tree>
</field>
</record>
</odoo>
7 changes: 7 additions & 0 deletions estate/views/estate_property_tag_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<odoo>
<record id="estate_property_tag_action" model="ir.actions.act_window">
<field name="name">Estate Property Tags</field>
<field name="res_model">estate.property.tag</field>
<field name="view_mode">tree,form</field>
</record>
</odoo>
29 changes: 29 additions & 0 deletions estate/views/estate_property_type_views.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<odoo>
<record id="estate_property_type_action" model="ir.actions.act_window">
<field name="name">Estate Property Types</field>
<field name="res_model">estate.property.type</field>
<field name="view_mode">tree,form</field>
</record>

<record id="view_estate_property_type_form" model="ir.ui.view">
<field name="name">estate.property.type.form</field>
<field name="model">estate.property.type</field>
<field name="arch" type="xml">
<form>
<header>
<button string="Offers"
type="action"
name="%(action_estate_property_offer)d"
class="oe_stat_button"
icon="fa-tags"
context="{'default_property_type_id': active_id}">
<field string="Offers" name="offer_count" widget="statinfo"/>
</button>
</header>
<field name="name" />
</form>
</field>
</record>


</odoo>
Loading