-
Notifications
You must be signed in to change notification settings - Fork 3.3k
19.0 estate cebul #1371
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
cezarbulancea
wants to merge
25
commits into
odoo:19.0
Choose a base branch
from
odoo-dev:19.0-estate-cebul
base: 19.0
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+595
−0
Open
19.0 estate cebul #1371
Changes from all commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
10bb488
[ADD] estate: created manifest and init for estate module
cezarbulancea a12ad1a
[IMP] estate: Create estate_propety model.
cezarbulancea 1b4148a
[IMP] estate: Create basic fields.
cezarbulancea 97541c8
[IMP] estate: Make name and expected_price not nullable.
cezarbulancea 73c5405
[IMP] estate: Added security file for access rights.
cezarbulancea 61a59ff
[IMP] estate: Estate property view action
cezarbulancea 6466c67
[IMP] estate: Three level menu for Estate Property.
cezarbulancea bc296dd
[LINT] estate: New line at the end of all files.
cezarbulancea a347f49
[IMP] estate: Fields, Attributes And View
cezarbulancea 9c1834c
[IMP] estate: List, Form, Search view
cezarbulancea 52d7291
[IMP] estate: Many2one Fields
cezarbulancea 96dc361
[IMP] estate: Many2many tags
cezarbulancea fba2091
[IMP] estate: One2Many fields
cezarbulancea 8adef14
[IMP] estate: dependencies and inverse function
cezarbulancea c7550ba
[IMP] estate: Onchanges
cezarbulancea 767c4bb
[IMP] estate: Chapter 9
cezarbulancea bb26fa5
[IMP] estate: chapter 10
cezarbulancea acd9075
[IMP] estate: inline views
cezarbulancea 913d8c9
[IMP] estate: widgets + list order + a bit of form
cezarbulancea aa39383
[IMP] estate: finish chapter 11
cezarbulancea 25fa1b6
[IMP] estate: started chapter 12
cezarbulancea 7b2691a
[IMP] estate: finish chpater 12
cezarbulancea fdca1a8
[IMP] estate: finished chapter 13
cezarbulancea 19ef623
[IMP] estate: finish of chapter 14
cezarbulancea 1764aaa
[IMP] estate: implemented feedback
cezarbulancea File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import models |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| { | ||
| 'name': "Estate", | ||
| 'depends': ['base'], | ||
| 'application': True, | ||
| 'data': [ | ||
| 'security/ir.model.access.csv', | ||
|
|
||
| 'views/estate_property_users.xml', | ||
| 'views/estate_property_offer_view.xml', | ||
| 'views/estate_property_tag_views.xml', | ||
| 'views/estate_property_type_view.xml', | ||
| 'views/estate_property_views.xml', | ||
| 'views/estate_menus.xml', | ||
| ], | ||
| 'author': 'Odoo S.A.', | ||
| 'license': 'LGPL-3', | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| from . import estate_property | ||
| from . import estate_property_offer | ||
| from . import estate_property_tag | ||
| from . import estate_property_type | ||
| from . import res_users | ||
|
cezarbulancea marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| from odoo import api, fields, models | ||
| from odoo.exceptions import UserError, ValidationError | ||
| from odoo.tools.float_utils import float_compare, float_is_zero | ||
|
|
||
|
|
||
| class EstateProperty(models.Model): | ||
| _name = 'estate.property' | ||
| _description = "Estate Property" | ||
| _order = 'id desc' | ||
|
|
||
| name = fields.Char(required=True) | ||
| description = fields.Text() | ||
| postcode = fields.Char() | ||
| date_availability = fields.Date( | ||
| default=fields.Date.add(fields.Date.today(), months=3), | ||
| copy=False, | ||
| ) | ||
| expected_price = fields.Float(required=True) | ||
| selling_price = fields.Float(readonly=True, copy=False) | ||
| bedrooms = fields.Integer(default=2) | ||
| living_area = fields.Integer(string="Living Area (sqm)") | ||
| facades = fields.Integer() | ||
| garage = fields.Boolean() | ||
| garden = fields.Boolean() | ||
| garden_area = fields.Integer(string="Garden Area (sqm)") | ||
| garden_orientation = fields.Selection( | ||
| string="Garden Orientation", | ||
| selection=[('north', "North"), ('south', "South"), ('east', "East"), ('west', "West")], | ||
| ) | ||
| active = fields.Boolean(default=True) | ||
| state = fields.Selection( | ||
| selection=[ | ||
| ('new', "New"), | ||
| ('offer_received', "Offer Received"), | ||
| ('offer_accepted', "Offer Accepted"), | ||
| ('sold', "Sold"), | ||
| ('cancelled', "Cancelled"), | ||
| ], | ||
| required=True, | ||
| copy=False, | ||
| default='new', | ||
| ) | ||
| property_type_id = fields.Many2one('estate.property.type', string="Property Type") | ||
| salesman_id = fields.Many2one( | ||
| 'res.users', | ||
| string="Salesman", | ||
| default=lambda self: self.env.user, | ||
| ) | ||
| buyer_id = fields.Many2one( | ||
| 'res.partner', | ||
| string="Buyer", | ||
| copy=False, | ||
| ) | ||
|
cezarbulancea marked this conversation as resolved.
|
||
| tag_ids = fields.Many2many('estate.property.tag') | ||
| offer_ids = fields.One2many('estate.property.offer', 'property_id') | ||
|
|
||
| total_area = fields.Integer(compute='_compute_total_area') | ||
| best_price = fields.Float(compute='_compute_best_offer') | ||
|
|
||
| _check_expected_price = models.Constraint( | ||
| 'CHECK(expected_price > 0)', | ||
| "The expected price must be strictly positive.", | ||
| ) | ||
|
|
||
| _check_selling_price = models.Constraint( | ||
| 'CHECK(selling_price >= 0)', | ||
| "The selling price must be positive.", | ||
| ) | ||
|
|
||
| @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 _compute_best_offer(self): | ||
| for record in self: | ||
| if record.offer_ids: | ||
| record.best_price = max(record.offer_ids.mapped('price')) | ||
| continue | ||
|
|
||
| record.best_price = 0.0 | ||
|
|
||
| @api.onchange('garden') | ||
| def _onchange_property(self): | ||
| if self.garden: | ||
| self.garden_area = 10 | ||
| self.garden_orientation = 'north' | ||
| return | ||
|
|
||
| self.garden_area = None | ||
| self.garden_orientation = None | ||
|
|
||
| @api.ondelete(at_uninstall=False) | ||
| def _check_state(self): | ||
| for record in self: | ||
| if record.state not in {'new', 'canceled'}: | ||
| raise UserError(self.env._("Can't delete a property if the state is not New or Cancelled.")) | ||
|
|
||
| @api.constrains('selling_price') | ||
| def _check_selling_price(self): | ||
| for record in self: | ||
| if not float_is_zero(record.selling_price, precision_digits=2): | ||
| if float_compare( | ||
| record.selling_price, | ||
| 0.9 * record.expected_price, | ||
| precision_digits=2) < 0: | ||
| raise ValidationError( | ||
| self.env._("The selling price should be at least 90% the expected price") | ||
| ) | ||
|
|
||
| def action_cancel_property(self): | ||
| for record in self: | ||
| if record.state == 'sold': | ||
| raise UserError(self.env._("A sold property cannot be cancelled.")) | ||
|
|
||
| record.state = 'cancelled' | ||
|
|
||
| return True | ||
|
|
||
| def action_sold_property(self): | ||
| for record in self: | ||
| if record.state == 'cancelled': | ||
| raise UserError(self.env._("A cancelled property cannot be sold.")) | ||
|
|
||
| record.state = 'sold' | ||
|
|
||
| return True | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| from odoo import api, fields, models | ||
| from odoo.exceptions import UserError | ||
| from odoo.tools.float_utils import float_compare | ||
|
|
||
|
|
||
| class PropertyOffer(models.Model): | ||
| _name = 'estate.property.offer' | ||
| _description = "Estate Property Offer" | ||
| _order = 'price desc' | ||
|
|
||
| price = fields.Float() | ||
| status = fields.Selection( | ||
| selection=[ | ||
| ('accepted', "Accepted"), | ||
| ('refused', "Refused") | ||
| ], | ||
| copy=False, | ||
| ) | ||
| partner_id = fields.Many2one('res.partner', required=True) | ||
| property_id = fields.Many2one('estate.property', required=True) | ||
| validity = fields.Integer(default=7) | ||
| date_deadline = fields.Date( | ||
| compute='_compute_date_deadline', | ||
| inverse='_inverse_date_deadline', | ||
| ) | ||
| property_type_id = fields.Many2one( | ||
| 'estate.property.type', | ||
| related='property_id.property_type_id', | ||
| store=True, | ||
| ) | ||
|
|
||
| _check_price = models.Constraint( | ||
| 'CHECK(price > 0)', | ||
| "An offer price must be strictly positive", | ||
| ) | ||
|
|
||
| @api.model_create_multi | ||
| def create(self, vals_list): | ||
| for vals in vals_list: | ||
| property = self.env['estate.property'].browse(vals['property_id']) | ||
|
|
||
| if property.offer_ids: | ||
| max_offer = property.offer_ids[0].price | ||
| if float_compare(vals['price'], max_offer, precision_digits=2) <= 0: | ||
| raise UserError(self.env._("The offer must be strictly higher than %.2f", max_offer)) | ||
|
|
||
| property.state = 'offer_received' | ||
|
|
||
| return super().create(vals_list) | ||
|
|
||
| @api.depends('create_date', 'validity') | ||
| def _compute_date_deadline(self): | ||
| for record in self: | ||
| create_date = record.create_date or fields.Date.today() | ||
| record.date_deadline = fields.Date.add(create_date, days=record.validity) | ||
|
|
||
| def _inverse_date_deadline(self): | ||
| for record in self: | ||
| create_date = record.create_date or fields.Date.today() | ||
| record.validity = (record.date_deadline - fields.Date.to_date(create_date)).days | ||
|
|
||
| def action_accept_offer(self): | ||
| for record in self: | ||
| if record.status: | ||
| raise UserError( | ||
| self.env._("You can't accept an offer that has already been accepted/refused") | ||
| ) | ||
|
|
||
| record.status = 'accepted' | ||
|
|
||
| other_offers = record.property_id.offer_ids - record | ||
| other_offers.write({'status': 'refused'}) | ||
|
|
||
| record.property_id.selling_price = record.price | ||
| record.property_id.buyer_id = record.partner_id | ||
|
|
||
| record.property_id.state = 'offer_accepted' | ||
|
|
||
| return True | ||
|
|
||
| def action_refuse_offer(self): | ||
| for record in self: | ||
| if record.status: | ||
| raise UserError( | ||
| self.env._("You can't refuse an offer that has already been accepted/refused") | ||
| ) | ||
| record.status = 'refused' | ||
|
|
||
| return True | ||
|
cezarbulancea marked this conversation as resolved.
cezarbulancea marked this conversation as resolved.
cezarbulancea marked this conversation as resolved.
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class PropertyTag(models.Model): | ||
| _name = 'estate.property.tag' | ||
| _description = "Estate Property Tag" | ||
| _order = 'name' | ||
|
|
||
| name = fields.Char(required=True) | ||
| color = fields.Integer(string="Color") | ||
|
|
||
| _unique_tag_name = models.Constraint( | ||
| 'UNIQUE(name)', | ||
| "The tag name must be unique.", | ||
| ) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| from odoo import api, fields, models | ||
|
|
||
|
|
||
| class PropertyType(models.Model): | ||
| _name = 'estate.property.type' | ||
| _description = "Estate Property Type" | ||
| _order = 'sequence, name' | ||
|
|
||
| name = fields.Char(required=True) | ||
| property_ids = fields.One2many('estate.property', 'property_type_id') | ||
| sequence = fields.Integer('Sequence') | ||
|
cezarbulancea marked this conversation as resolved.
|
||
| offer_ids = fields.One2many('estate.property.offer', 'property_type_id') | ||
| offer_count = fields.Integer(compute='_compute_offer_count') | ||
|
|
||
| @api.depends('offer_ids') | ||
| def _compute_offer_count(self): | ||
| for record in self: | ||
| record.offer_count = len(record.offer_ids) | ||
|
|
||
| _unique_type_name = models.Constraint( | ||
| 'UNIQUE(name)', | ||
| "A type name must be unique.", | ||
| ) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class ResUsers(models.Model): | ||
| _inherit = 'res.users' | ||
|
|
||
| property_ids = fields.One2many( | ||
| 'estate.property', | ||
| 'salesman_id', | ||
| domain=[('state', 'in', {'new', 'offer_received'})], | ||
| ) |
|
cezarbulancea marked this conversation as resolved.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | ||
| access_estate_property,access_estate_property,model_estate_property,base.group_user,1,1,1,1 | ||
| access_estate_property_type,access_estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 | ||
| access_estate_property_tag,access_estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 | ||
| access_estate_property_offer,access_estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <menuitem id="estate_menu_root" name="Estate"> | ||
| <menuitem id="estate_advertisments_menu" name="Advertisments"> | ||
| <menuitem id="estate_model_menu_action" action="estate_property_action"/> | ||
| </menuitem> | ||
| <menuitem id="estate_settings_menu" name="Settings"> | ||
| <menuitem id="estate_type_model_menu_action" action="estate_property_type_action"/> | ||
| <menuitem id="estate_tag_model_menu_action" action="estate_property_tag_action"/> | ||
| </menuitem> | ||
| </menuitem> | ||
| </odoo> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <record id="estate_property_offer_view_list" model="ir.ui.view"> | ||
| <field name="name">estate.property.offer.list</field> | ||
| <field name="model">estate.property.offer</field> | ||
| <field name="arch" type="xml"> | ||
| <list decoration-success="status=='accepted'" | ||
| decoration-danger="status=='refused'" string="Offers" editable="bottom"> | ||
| <field name="price" width="17%"/> | ||
| <field name="partner_id" string="Partner" width="17%"/> | ||
| <field name="validity" width="17%"/> | ||
| <field name="date_deadline" string="Deadline" width="17%"/> | ||
| <button name="action_accept_offer" type="object" icon="fa-check" title="Accept" width="7.5%" invisible="status"/> | ||
| <button name="action_refuse_offer" type="object" icon="fa-times" title="Refuse" width="7.5%" invisible="status"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_offer_action" model="ir.actions.act_window"> | ||
| <field name="name">Offers</field> | ||
| <field name="res_model">estate.property.offer</field> | ||
| <field name="view_mode">list,form</field> | ||
| <field name="domain">[('property_type_id', '=', active_id)]</field> | ||
| </record> | ||
| </odoo> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <record id="estate_property_tag_view_list" model="ir.ui.view"> | ||
| <field name="name">estate.property.tag.list</field> | ||
| <field name="model">estate.property.tag</field> | ||
| <field name="arch" type="xml"> | ||
| <list string="Property tags" editable="bottom"> | ||
| <field name="name" string="Title"/> | ||
| <field name="color"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_tag_action" model="ir.actions.act_window"> | ||
| <field name="name">Property Tags</field> | ||
| <field name="res_model">estate.property.tag</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
| </odoo> |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.