-
Notifications
You must be signed in to change notification settings - Fork 2.8k
19.0 app traning raibr #1074
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
base: 19.0
Are you sure you want to change the base?
19.0 app traning raibr #1074
Changes from all commits
9078a4d
b46dc7d
9d3e35d
afbf975
c79e559
27d7a39
fbb6c5e
06b0b67
e76dbf5
23dc969
7d28247
fcbae9f
90bef7f
c81eb7e
b5928f0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -127,3 +127,4 @@ dmypy.json | |
|
|
||
| # Pyre type checker | ||
| .pyre/ | ||
| .DS_Store | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| My first change on odoo | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
|
||
| from . import models |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
| { | ||
| 'name': 'Real Estate Advertisement', | ||
| 'version': '1.0', | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You don't have to provide the version because it is |
||
| 'author': 'Odoo', | ||
| 'category': 'Sales/Real Estate', | ||
| 'sequence': 15, | ||
| 'summary': 'Manage property listings and real estate advertisements', | ||
| 'description': """ | ||
| Real Estate Advertisement Management | ||
| ==================================== | ||
| This module allows you to manage real estate properties, including: | ||
| * Property listings with detailed information | ||
| * Property types and tags | ||
| * Property offers and negotiations | ||
| * Sales tracking | ||
| """, | ||
| 'depends': ['base'], | ||
| '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/estate_menus.xml', | ||
| ], | ||
| 'installable': True, | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| 'application': True, | ||
| 'license': 'LGPL-3', | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
|
||
| from . import estate_property | ||
| from . import estate_property_type | ||
| from . import estate_property_tag | ||
| from . import estate_property_offer |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,106 @@ | ||||||||||||||||||||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||||||||||||||||||||
|
|
||||||||||||||||||||
| 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 = "Real Estate Property" | ||||||||||||||||||||
| _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." | ||||||||||||||||||||
| ) | ||||||||||||||||||||
|
Comment on lines
+11
to
+16
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here too, it can be on one line each. |
||||||||||||||||||||
|
|
||||||||||||||||||||
| name = fields.Char(required=True) | ||||||||||||||||||||
| description = fields.Text() | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to at least put the string parameter to every fields if possible. Even if the name of the field is implied. |
||||||||||||||||||||
| postcode = fields.Char() | ||||||||||||||||||||
| date_availability = fields.Date() | ||||||||||||||||||||
| expected_price = fields.Float(required=True) | ||||||||||||||||||||
| selling_price = fields.Float() | ||||||||||||||||||||
| bedrooms = fields.Integer() | ||||||||||||||||||||
| living_area = fields.Integer() | ||||||||||||||||||||
| facades = fields.Integer() | ||||||||||||||||||||
| garage = fields.Boolean() | ||||||||||||||||||||
| garden = fields.Boolean() | ||||||||||||||||||||
| garden_area = fields.Integer() | ||||||||||||||||||||
| garden_orientation = fields.Selection( | ||||||||||||||||||||
| selection=[ | ||||||||||||||||||||
| ("north", "North"), | ||||||||||||||||||||
| ("south", "South"), | ||||||||||||||||||||
| ("east", "East"), | ||||||||||||||||||||
| ("west", "West"), | ||||||||||||||||||||
| ] | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| state = fields.Selection( | ||||||||||||||||||||
| selection=[ | ||||||||||||||||||||
| ("new", "New"), | ||||||||||||||||||||
| ("offer_received", "Offer Received"), | ||||||||||||||||||||
| ("offer_accepted", "Offer Accepted"), | ||||||||||||||||||||
| ("sold", "Sold"), | ||||||||||||||||||||
| ("cancelled", "Cancelled"), | ||||||||||||||||||||
| ], | ||||||||||||||||||||
| default="new", | ||||||||||||||||||||
| required=True, | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| buyer_id = fields.Many2one("res.partner", string="Buyer") | ||||||||||||||||||||
| property_type_id = fields.Many2one("estate.property.type", string="Property Type") | ||||||||||||||||||||
| tag_ids = fields.Many2many("estate.property.tag", string="Tags") | ||||||||||||||||||||
| offer_ids = fields.One2many("estate.property.offer", "property_id", string="Offers") | ||||||||||||||||||||
| total_area = fields.Integer(compute="_compute_total_area") | ||||||||||||||||||||
| best_price = fields.Float(compute="_compute_best_price", string="Best Offer Price") | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @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_price(self): | ||||||||||||||||||||
| for record in self: | ||||||||||||||||||||
| if record.offer_ids: | ||||||||||||||||||||
| record.best_price = max(record.offer_ids.mapped("price")) | ||||||||||||||||||||
| else: | ||||||||||||||||||||
| record.best_price = 0.0 | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @api.onchange("garden") | ||||||||||||||||||||
| def _onchange_garden(self): | ||||||||||||||||||||
| if self.garden: | ||||||||||||||||||||
| self.garden_area = 10 | ||||||||||||||||||||
| self.garden_orientation = "north" | ||||||||||||||||||||
| else: | ||||||||||||||||||||
| self.garden_area = 0 | ||||||||||||||||||||
| self.garden_orientation = False | ||||||||||||||||||||
|
|
||||||||||||||||||||
| @api.constrains("selling_price", "expected_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, | ||||||||||||||||||||
| record.expected_price * 0.9, | ||||||||||||||||||||
| precision_digits=2, | ||||||||||||||||||||
| ) | ||||||||||||||||||||
| < 0 | ||||||||||||||||||||
| ): | ||||||||||||||||||||
|
Comment on lines
+82
to
+89
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you put this on one line, it shouldn't be too long.
Suggested change
|
||||||||||||||||||||
| raise ValidationError( | ||||||||||||||||||||
| "The selling price cannot be lower than 90% of the expected price." | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here also it should be translated. |
||||||||||||||||||||
| ) | ||||||||||||||||||||
|
|
||||||||||||||||||||
| def action_sold(self): | ||||||||||||||||||||
| for record in self: | ||||||||||||||||||||
| if record.state == "cancelled": | ||||||||||||||||||||
| raise UserError("Cancelled property cannot be sold.") | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||||||||||||||||||||
| record.state = "sold" | ||||||||||||||||||||
| return True | ||||||||||||||||||||
|
|
||||||||||||||||||||
| def action_cancel(self): | ||||||||||||||||||||
| for record in self: | ||||||||||||||||||||
| if record.state == "sold": | ||||||||||||||||||||
| raise UserError("Sold property cannot be cancelled.") | ||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And here |
||||||||||||||||||||
| record.state = "cancelled" | ||||||||||||||||||||
| return True | ||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
|
||
| from datetime import timedelta | ||
| from odoo import api, fields, models | ||
| from odoo.exceptions import UserError | ||
|
|
||
|
|
||
| class EstatePropertyOffer(models.Model): | ||
| _name = "estate.property.offer" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should only use double quotes for non technical fields and single quotes for technical fields. |
||
| _description = "Real Estate Property Offer" | ||
| _order = "price desc" | ||
|
|
||
| price = fields.Float(required=True) | ||
| _check_price = models.Constraint( | ||
| "Check(price > 0)", "The offer price must be strictly positive." | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Splitting this on multiple lines doesn't provide more readability. You can keep this on a single line. |
||
| ) | ||
| status = fields.Selection( | ||
| selection=[("accepted", "Accepted"), ("refused", "Refused")], copy=False | ||
| ) | ||
| partner_id = fields.Many2one("res.partner", string="Partner", required=True) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is good practice to name your parameters. So here you should add |
||
| property_id = fields.Many2one("estate.property", string="Property", required=True) | ||
| validity = fields.Integer(default=7, string="Validity (days)") | ||
| date_deadline = fields.Date( | ||
| compute="_compute_date_deadline", | ||
| inverse="_inverse_date_deadline", | ||
| store=True, | ||
| string="Deadline", | ||
| ) | ||
|
|
||
| @api.depends("validity") | ||
| def _compute_date_deadline(self): | ||
| for record in self: | ||
| record.date_deadline = fields.Date.today() + timedelta(days=record.validity) | ||
|
|
||
| def _inverse_date_deadline(self): | ||
| for record in self: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Instead of Same thing at other places |
||
| if record.date_deadline: | ||
| record.validity = (record.date_deadline - fields.Date.today()).days | ||
|
|
||
| def action_accept(self): | ||
| for record in self: | ||
| if record.property_id.offer_ids.filtered( | ||
| lambda o: o.status == "accepted" and o.id != record.id | ||
| ): | ||
|
Comment on lines
+42
to
+44
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It doesn't provide more readability to split this into multiple lines. |
||
| raise UserError("Only one offer can be accepted per property.") | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should make this string translatable. You can use this : |
||
| record.status = "accepted" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget about using single quotes here as it is a technical string. |
||
| record.property_id.buyer_id = record.partner_id | ||
| record.property_id.selling_price = record.price | ||
| return True | ||
|
|
||
| def action_refuse(self): | ||
| for record in self: | ||
| record.status = "refused" | ||
| return True | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
|
||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class EstatePropertyTag(models.Model): | ||
| _name = "estate.property.tag" | ||
| _description = "Real Estate Property Tag" | ||
| _order = "name" | ||
|
|
||
| _check_unique_name = models.Constraint( | ||
| "UNIQUE(name)", "The tag name must be unique." | ||
| ) | ||
|
Comment on lines
+11
to
+13
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here on a single line 😄 |
||
|
|
||
| name = fields.Char(required=True) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| # Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
|
||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class EstatePropertyType(models.Model): | ||
| _name = "estate.property.type" | ||
| _description = "Real Estate Property Type" | ||
| _order = "name" | ||
| _check_unique_name = models.Constraint( | ||
| "UNIQUE(name)", "The type name must be unique." | ||
| ) | ||
|
Comment on lines
+10
to
+12
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here too |
||
|
|
||
| name = fields.Char(required=True) | ||
| 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 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget to add a final new lines. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <!-- Main menu --> | ||
| <menuitem id="estate_menu_root" name="Real Estate"/> | ||
|
|
||
| <!-- Properties menu --> | ||
| <menuitem id="estate_property_menu" | ||
| name="Advertisements" | ||
| parent="estate_menu_root"/> | ||
|
|
||
| <menuitem id="estate_property_menu_action" | ||
| name="Properties" | ||
| parent="estate_property_menu" | ||
| action="estate_property_action"/> | ||
|
|
||
| <!-- Settings menu --> | ||
| <menuitem id="estate_settings_menu" | ||
| name="Settings" | ||
| parent="estate_menu_root"/> | ||
|
|
||
| <menuitem id="estate_property_type_menu_action" | ||
| name="Property Types" | ||
| parent="estate_settings_menu" | ||
| action="estate_property_type_action"/> | ||
|
|
||
| <menuitem id="estate_property_tag_menu_action" | ||
| name="Property Tags" | ||
| parent="estate_settings_menu" | ||
| action="estate_property_tag_action"/> | ||
|
|
||
| <menuitem id="estate_property_offer_menu_action" | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like there is a spacing issue here 😄 |
||
| name="Property Offers" | ||
| parent="estate_settings_menu" | ||
| action="estate_property_offer_action"/> | ||
| </odoo> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <!-- Tree View --> | ||
| <record id="estate_property_offer_view_tree" model="ir.ui.view"> | ||
| <field name="name">estate.property.offer.view.tree</field> | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Try to use list instead of tree . I know that you can find in examples |
||
| <field name="model">estate.property.offer</field> | ||
| <field name="arch" type="xml"> | ||
| <list> | ||
| <field name="price"/> | ||
| <field name="partner_id"/> | ||
| <field name="validity"/> | ||
| <field name="date_deadline"/> | ||
| <field name="status"/> | ||
| <button name="action_accept" type="object" icon="fa-check" title="Accept"/> | ||
| <button name="action_refuse" type="object" icon="fa-times" title="Refuse"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Form View --> | ||
| <record id="estate_property_offer_view_form" model="ir.ui.view"> | ||
| <field name="name">estate.property.offer.view.form</field> | ||
| <field name="model">estate.property.offer</field> | ||
| <field name="arch" type="xml"> | ||
| <form> | ||
| <sheet> | ||
| <group> | ||
| <field name="price"/> | ||
| <field name="partner_id"/> | ||
| <field name="property_id"/> | ||
| <field name="validity"/> | ||
| <field name="date_deadline"/> | ||
| <field name="status"/> | ||
| </group> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Action --> | ||
| <record id="estate_property_offer_action" model="ir.actions.act_window"> | ||
| <field name="name">Property Offers</field> | ||
| <field name="res_model">estate.property.offer</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
| </odoo> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| <?xml version="1.0" encoding="utf-8"?> | ||
| <odoo> | ||
| <!-- List view --> | ||
| <record id="estate_property_tag_view_tree" model="ir.ui.view"> | ||
| <field name="name">estate.property.tag.view.tree</field> | ||
| <field name="model">estate.property.tag</field> | ||
| <field name="arch" type="xml"> | ||
| <list string="Property Tags"> | ||
| <field name="name"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Form view --> | ||
| <record id="estate_property_tag_view_form" model="ir.ui.view"> | ||
| <field name="name">estate.property.tag.view.form</field> | ||
| <field name="model">estate.property.tag</field> | ||
| <field name="arch" type="xml"> | ||
| <form string="Property Tag"> | ||
| <sheet> | ||
| <group> | ||
| <field name="name"/> | ||
| </group> | ||
| </sheet> | ||
| </form> | ||
| </field> | ||
| </record> | ||
|
|
||
| <!-- Action --> | ||
| <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> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it still useful to keep that ? 🤔