-
Notifications
You must be signed in to change notification settings - Fork 2.7k
MALER Onboarding #995
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?
MALER Onboarding #995
Changes from all commits
4b94903
732cd24
abf17f4
755ef94
77b28ab
f790264
2ca3c10
5108d34
950aa6a
ebd00a8
eab30ee
bfdee5e
91f5f42
dd92e48
b327775
fe1800b
5124c90
31dfe65
155c968
a315476
5b0378c
83fd657
452451c
b808568
0c70ac5
2314ab9
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 |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import models |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| { | ||
| 'name': 'estate', | ||
| 'depends': [ | ||
| 'base', | ||
| ], | ||
| 'application': 'True', | ||
| 'author': 'Odoo S.A.', | ||
| 'license': 'LGPL-3', | ||
| 'data': [ | ||
| 'security/ir.model.access.csv', | ||
|
|
||
| 'views/estate_property_offer_views.xml', | ||
| 'views/estate_property_tag_views.xml', | ||
| 'views/estate_property_type_views.xml', | ||
| 'views/estate_property_views.xml', | ||
| 'views/inherited_user_views.xml', | ||
| 'views/estate_menus.xml', | ||
| ], | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| from . import estate_property | ||
| from . import estate_property_type | ||
| from . import estate_property_tag | ||
| from . import estate_property_offer | ||
| from . import inherited_user | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,103 @@ | ||||||||||||||||||||||||||
| from odoo import api, models, fields | ||||||||||||||||||||||||||
| from odoo.exceptions import UserError | ||||||||||||||||||||||||||
| import datetime | ||||||||||||||||||||||||||
| from dateutil.relativedelta import relativedelta | ||||||||||||||||||||||||||
| from odoo.tools.float_utils import float_compare | ||||||||||||||||||||||||||
|
Comment on lines
+1
to
+5
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. You must also place built-in imports before external imports and external imports before internal imports. A built-in import is when you import code that comes with Python by default (such as datetime). An external import occurs when you import code from outside your project (such as dateutil). And an internal import occurs when you import a code that is present in your project, but in another file.
Suggested change
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
|
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. A blank line is missing here. You should have two blank lines above a class. It is a python convention coming from the pip8. |
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| class EstateProperty(models.Model): | ||||||||||||||||||||||||||
| _name = "estate.property" | ||||||||||||||||||||||||||
| _description = "test description" | ||||||||||||||||||||||||||
| _order = "id desc" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| name = fields.Char('Name', required=True) | ||||||||||||||||||||||||||
| description = fields.Text('Description') | ||||||||||||||||||||||||||
| postcode = fields.Char('Postcode') | ||||||||||||||||||||||||||
| date_availability = fields.Date('Date availability', copy=False, default=datetime.date.today() + relativedelta(months=+3)) | ||||||||||||||||||||||||||
| expected_price = fields.Float('Expected price', required=True) | ||||||||||||||||||||||||||
| selling_price = fields.Float('Selling price', readonly=True, copy=False) | ||||||||||||||||||||||||||
| bedrooms = fields.Integer('Bedrooms', default=2) | ||||||||||||||||||||||||||
| living_area = fields.Integer('Living area (sqm)') | ||||||||||||||||||||||||||
| facades = fields.Integer('Facades') | ||||||||||||||||||||||||||
| garage = fields.Boolean('Garage') | ||||||||||||||||||||||||||
| garden = fields.Boolean('Garden') | ||||||||||||||||||||||||||
| garden_area = fields.Integer('Garden area (sqm)') | ||||||||||||||||||||||||||
| garden_orientation = fields.Selection( | ||||||||||||||||||||||||||
| string='Orientation', | ||||||||||||||||||||||||||
| selection=[('north', 'North'), ('east', 'East'), ('south', 'South'), ('west', 'West')], | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| active = fields.Boolean('Active', default=True) | ||||||||||||||||||||||||||
| state = fields.Selection( | ||||||||||||||||||||||||||
| string='state', | ||||||||||||||||||||||||||
| selection=[('new', 'New'), ('offerreceived', 'Offer Received'), ('offeraccepted', 'Offer Accepted'), ('sold', 'Sold'), ('cancelled', 'Cancelled')], | ||||||||||||||||||||||||||
| default='new', | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
| total_area = fields.Integer('Total area (sqm)', compute='_compute_total_area') | ||||||||||||||||||||||||||
| best_offer = fields.Float('Best price', compute='_compute_best_offer') | ||||||||||||||||||||||||||
| property_type_id = fields.Many2one('estate.property.type', string="Property Type") | ||||||||||||||||||||||||||
| salesperson_id = fields.Many2one('res.users', string='Salesman', default=lambda self: self.env.user) | ||||||||||||||||||||||||||
| buyer_id = fields.Many2one('res.partner', string='Buyer', copy=False) | ||||||||||||||||||||||||||
| tag_ids = fields.Many2many('estate.property.tag', string="Property Tags") | ||||||||||||||||||||||||||
| offer_ids = fields.One2many('estate.property.offer', 'property_id', string="Offers") | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @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: | ||||||||||||||||||||||||||
| record.best_offer = max(record.offer_ids.mapped('price')) if record.offer_ids else 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 = None | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| def action_set_cancelled(self): | ||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||
| if record.state == 'sold': | ||||||||||||||||||||||||||
| raise UserError('A sold property cannot be cancelled') | ||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||
| record.state = 'cancelled' | ||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||
|
Comment on lines
+63
to
+68
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, your action is used on a form. That means that you are updating only one record. So you do not need to iterate
Suggested change
|
||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| def action_set_sold(self): | ||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||
| if record.state == 'cancelled': | ||||||||||||||||||||||||||
| raise UserError('A cancelled property cannot be sold') | ||||||||||||||||||||||||||
| elif record.state != 'offeraccepted': | ||||||||||||||||||||||||||
| raise UserError('There is no accepted offer on this property') | ||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||
| record.state = 'sold' | ||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| _check_expected_price = models.Constraint( | ||||||||||||||||||||||||||
| 'CHECK(expected_price > 0)', | ||||||||||||||||||||||||||
| 'The expected price must be striclty positive', | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| _check_selling_price = models.Constraint( | ||||||||||||||||||||||||||
| 'CHECK(selling_price >= 0)', | ||||||||||||||||||||||||||
| 'The selling price must be positive', | ||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @api.constrains('selling_price') | ||||||||||||||||||||||||||
| def check_selling_price(self): | ||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||
| expected_minimum = record.expected_price * 0.9 | ||||||||||||||||||||||||||
| if float_compare(record.selling_price, expected_minimum, precision_digits=2) < 0: | ||||||||||||||||||||||||||
| raise UserError(r'The selling price should be at least 90% of the expexted price') | ||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||
| record.state = "offeraccepted" | ||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||
| @api.ondelete(at_uninstall=False) | ||||||||||||||||||||||||||
| def unlink_property(self): | ||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||
| if record.state != 'new' and record.state != 'canceled': | ||||||||||||||||||||||||||
|
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. Do not hesitate to use the
Suggested change
|
||||||||||||||||||||||||||
| raise UserError("Only new and canceled properties can be deleted") | ||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,67 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from odoo import api, models, fields | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. Should be sorted alphabetically.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from odoo.exceptions import UserError | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class EstatePropertyOffer(models.Model): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _name = "estate.property.offer" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _description = "test description" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _order = "price desc" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| price = fields.Float('Price') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status = fields.Selection( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| string='Status', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| selection=[('accepted', 'Accepted'), ('refused', 'Refused')], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| copy=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| partner_id = fields.Many2one('res.partner', string='Partner', required=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| property_id = fields.Many2one('estate.property', string='Property', required=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| validity = fields.Integer('Validity', default=7) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| date_deadline = fields.Date('Deadline', compute='_compute_deadline', inverse='inverse_deadline') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| property_type_id = fields.Many2one(related='property_id.property_type_id', store=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @api.depends('validity') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _compute_deadline(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for records in self: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| records.date_deadline = fields.Datetime.add(fields.Date.today(), days=records.validity) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def inverse_deadline(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for records in self: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| records.validity = (records.date_deadline - fields.Date.today()).days | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def action_accept(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| record.status = 'accepted' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not record.property_id.buyer_id: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| record.property_id.buyer_id = record.partner_id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| record.property_id.selling_price = record.price | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise UserError('An offer has already been accepted') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def action_decline(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for record in self: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if record.status == 'accepted': | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise UserError('This offer has already been accepted') | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| record.status = 'refused' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _check_offer_price = models.Constraint( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'CHECK(price > 0)', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 'The offer price must be strictly positive' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| @api.model | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def create(self, vals): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for val in vals: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| property_id = self.env['estate.property'].browse(val['property_id']) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if property_id.state == "sold": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise UserError("You can't create an offer for a sold property") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for offer in property_id.offer_ids: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if offer.price > val['price']: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise UserError("You can't create a lower offer than the highest one") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offers = super().create(vals) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| offers.property_id.state = 'offerreceived' | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return offers | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+55
to
+67
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 shouldn't do sql request inside a loop 😃. It will do a lot of requests to your db as the create method can be used to create multiple records. Get first all the needed ids and then make a request with all of them with_prefetch(), which will allow you to get records by their id with browse inside the loop without doing any requests to the data base. Here also you can see that I used EstateProperties instead of estate_properties, that's an Odoo convention. When a variable represent a model we have to use the same convention than for the name of a python class. As offer_ids is a list you can use min. Also _id should be added at the end of a variable only if it is assigned to a relational field or to an integer. Here property_id is linked to a record of estate.property so you can name it property.
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class EstatePropertyTag(models.Model): | ||
| _name = "estate.property.tag" | ||
| _description = "test description" | ||
| _order = "name" | ||
|
|
||
| name = fields.Char('Name', required=True) | ||
| color = fields.Integer('Color') | ||
|
|
||
| _check_name = models.Constraint( | ||
| 'UNIQUE (name)', | ||
| 'The name must be unique', | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| from odoo import api, fields, models | ||
|
|
||
|
|
||
| class EstatePropertyType(models.Model): | ||
| _name = "estate.property.type" | ||
| _description = "test description" | ||
| _order = "sequence, name" | ||
|
|
||
| name = fields.Char('Name', required=True) | ||
| sequence = fields.Integer('Sequence', default=1, help="Used to order stages.") | ||
| property_ids = fields.One2many('estate.property', 'property_type_id', string="Properties") | ||
| offer_ids = fields.One2many('estate.property.offer', 'property_type_id', string="Offers") | ||
| offer_count = fields.Integer('Number of offers', compute='_compute_offers') | ||
|
|
||
| @api.depends('offer_ids') | ||
| def _compute_offers(self): | ||
| for record in self: | ||
| record.offer_count = len(record.offer_ids) | ||
|
|
||
| _check_name = models.Constraint( | ||
| 'UNIQUE (name)', | ||
| 'The name must be unique', | ||
| ) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| from odoo import fields, models | ||
|
|
||
|
|
||
| class InheritedUser(models.Model): | ||
|
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. The class and file should be named ResUser and res_user.py, respectively. |
||
| _inherit = "res.users" | ||
|
|
||
| property_ids = fields.One2many('estate.property', 'salesperson_id', string="Related Properties", domain=[('state', 'in', ['new', 'offerreceived'])]) | ||
| 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. The blank line a the end of the file is missing. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| from . import test_estate_property |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,39 @@ | ||||||||||
| from odoo.tests.common import TransactionCase | ||||||||||
| from odoo.exceptions import UserError | ||||||||||
| from odoo.tests import Form, tagged | ||||||||||
|
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.
Suggested change
|
||||||||||
|
|
||||||||||
|
|
||||||||||
| @tagged('post_install', '-at_install') | ||||||||||
| class EstateTestCase(TransactionCase): | ||||||||||
|
|
||||||||||
| @classmethod | ||||||||||
| def setUpClass(cls): | ||||||||||
| super().setUpClass() | ||||||||||
|
|
||||||||||
| cls.properties = cls.env['estate.property'].create({'name': 'testAdd', 'expected_price': '190000'}) | ||||||||||
| cls.partner = cls.env['res.partner'].create({'name': 'eric'}) | ||||||||||
|
|
||||||||||
| def test_creation_estate(self): | ||||||||||
| self.env['estate.property.offer'].create({'price': 180000, 'partner_id': self.partner.id, 'property_id': self.properties.id, 'status': 'accepted'}) | ||||||||||
| self.properties.state = 'sold' | ||||||||||
|
|
||||||||||
| with self.assertRaises(UserError): | ||||||||||
| self.env['estate.property.offer'].create({'price': 180000, 'partner_id': self.partner.id, 'property_id': self.properties.id}) | ||||||||||
|
|
||||||||||
| def test_sell_property(self): | ||||||||||
| self.properties.state = 'new' | ||||||||||
|
|
||||||||||
| with self.assertRaises(UserError): | ||||||||||
| self.properties.action_set_sold() | ||||||||||
|
|
||||||||||
| def test_garden_onchange(self): | ||||||||||
| property_form = Form(self.env['estate.property']) | ||||||||||
| property_form.garden = True | ||||||||||
| property_form.garden_area = 20 | ||||||||||
| property_form.garden_orientation = 'east' | ||||||||||
|
|
||||||||||
| property_form.garden = False | ||||||||||
| property_form.garden = True | ||||||||||
|
|
||||||||||
| self.assertEqual(property_form.garden_area, 10) | ||||||||||
| self.assertEqual(property_form.garden_orientation, 'north') | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0"?> | ||
| <odoo> | ||
| <menuitem id="estate_root_menu" name="Estate"> | ||
| <menuitem id="estate_first_level_menu" name="Menu"> | ||
| <menuitem id="estate_model_menu_action" action="estate_property_action"/> | ||
| </menuitem> | ||
| <menuitem id="estate_settings_menu" name="Settings"> | ||
| <menuitem id="estate_type_menu_action" action="estate_property_type_action"/> | ||
| <menuitem id="estate_tag_menu_action" action="estate_property_tag_action"/> | ||
| </menuitem> | ||
| </menuitem> | ||
| </odoo> | ||
|
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. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| <?xml version="1.0"?> | ||
| <odoo> | ||
| <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> | ||
|
|
||
| <record id="estate_property_offer_view" model="ir.ui.view"> | ||
| <field name="name">property type offer</field> | ||
| <field name="model">estate.property.offer</field> | ||
| <field name="arch" type="xml"> | ||
| <list editable="bottom" decoration-success="status=='accepted'" decoration-danger="status=='refused'"> | ||
| <field name="price"/> | ||
| <field name="partner_id"/> | ||
| <field name="validity"/> | ||
| <field name="date_deadline"/> | ||
| <button name="action_accept" string="Accept" type="object" icon="fa-check" invisible="status in ('accepted', 'refused')"/> | ||
| <button name="action_decline" string="Refuse" type="object" icon="fa-times" invisible="status in ('accepted', 'refused')"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
| </odoo> | ||
|
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. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| <?xml version="1.0"?> | ||
| <odoo> | ||
| <record id="estate_property_tag_action" model="ir.actions.act_window"> | ||
| <field name="name">Tags</field> | ||
| <field name="res_model">estate.property.tag</field> | ||
| <field name="view_mode">list,form</field> | ||
| </record> | ||
|
|
||
| <record id="estate_property_tag_view_list" model="ir.ui.view"> | ||
| <field name="name">tags.list</field> | ||
| <field name="model">estate.property.tag</field> | ||
| <field name="arch" type="xml"> | ||
| <list editable="bottom"> | ||
| <field name="name"/> | ||
| </list> | ||
| </field> | ||
| </record> | ||
| </odoo> | ||
|
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 |
||
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.
Should be sorted alphabetically 😃.