-
Notifications
You must be signed in to change notification settings - Fork 2.8k
19.0 estate stfra #1075
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 estate stfra #1075
Conversation
…ta in list view and create/edit property data in form view The model was created and access rights provided but there was no interaction with the model. This is implemented through xml as its is mre convinient for complex data. There is one menu to acces the list view of the properties and a form views is displayed whend creating or editing a property. Some fields have now a default value, some are read-only, some are requiered and some cannot be copied when duplicated. The fields active and state were added for properties display in the list view by default and for it to have a different state depending on the stage respectively.
f327195 to
ab1280b
Compare
…the estate module. The views created were basic one and need some custumization to be use in a business application. List view: the following fields have been added: Title, Postcode, bedrooms, Living Area (sqm), Expected Price, Selling Price, Available From Form view: It is now composed of groups and a notebook with a page description Search view: Search has now other predifened shorcuts (Title, Postcode, expectedPrice, Bedrooms, Living Area, Facades), a predefined filter "Available" (that looks for properties with the state New or Offer received) and a Group by filter on the postcodes
…: buyer, salesperson, property type, list of tags and list of offers. Buyer Can be any individual (res.partner) Salesperson Has to be an employe (res.user) Property type New model with the name of the type (estate.property.type) Tags New model with the name of the tag (estate.property.tag) Offers New model with the buyer, price, status and property id (estate.property.offer) All those new models have list and form view but the offer model is only accessible from the porperty form (as each offer is linked to a property) A new menu setting has been added to allow the creation of new tags and types.
ushyme
left a comment
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.
Good work so far; I just have one small remark.
… area in estate property and validity and deadline in property offer). Best price is computed on the maximum price of all the offers linked to the property. Total area is computed as the sum of the lving area and garden area. Validity is the number days that have passed since the creation of the offer during wich it remains valid. Deadline is the date until wich the offer remains valid. It is computed based on validity and when changed, updates validity.
|
Runbot is still red 😃 |
Previewsly made pull request could not pass because of the linting issues.
ee173b0 to
5dafd8b
Compare
…s offers. The state of a property and its offer could only be changed manually which is not safe way of handling those status. Now buttons have been added : sold and cancel for the property and accept and refuse for the offers. An error pop-up is shown when trying to perfom an illegal action.
… on the models. Estate property model: - SQL constraints: check that theexpected price is stricly positive and selling price positive. - Python constraint: check that the selling price is at least 90% of the expected price when one of them is modified. Estate property offer model: - SQL constraint: check that the price is strictly positive. Estate property tag model: - SQL constraint: check that the name tag is unique. Estate property type model: - SQL constraint: check that the name type is unique.
…ttons. State are now displayed in a status bar. The buttons (Sold/cancel on properties and Accept/Refuse on offers) are now dynamic and only appeares when needed. Offers can be created and edited in place. Tags have colors. Property type can only be created and edited from the settings. Offers related to a property type can be acces from its form.
…ndart creation method of offers and the view form of an user. The new delete method with the decorator 'ondelete()' prevent the deletion of a property that is not in the state 'New' or 'Cancelled'. The new creation method prevent user from creatin an offer with a lower amount than an existing offer and change the state of the property to 'Offer recieved' when it was 'New'. The list of available properties is now displayed in a new page on the user form view.
The state of property didn't change when a new offer was made and it still had no offer. Now property state goes from 'New' to 'Offer received' when an offer is made.
…voicing module to estate module. Estate Accounting module depends on Estate and Account module to directly create an invoice the customer when a property is sold. The invoice has 3 lines: - property price - 6% fee - Addimistrative fee
ushyme
left a comment
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.
Almost there! Also, all your XML files are missing a newline at the end of the file.
| def action_refuse(self): | ||
| for record in self: | ||
| record.status = 'refused' | ||
| record.property_id.property_buyer_id = None | ||
| record.property_id.selling_price = 0 |
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.
This currently clears the property's selling price even if you are refusing a random low offer. It should only clear the property fields if the currently accepted offer is the one being refused.
| def action_refuse(self): | |
| for record in self: | |
| record.status = 'refused' | |
| record.property_id.property_buyer_id = None | |
| record.property_id.selling_price = 0 | |
| def action_refuse(self): | |
| for record in self: | |
| if record.status == 'accepted': | |
| record.property_id.selling_price = 0 | |
| record.property_id.property_buyer_id = False | |
| record.status = 'refused' |
estate/security/ir.model.access.csv
Outdated
| access_real_estate_platform,estate_property,model_estate_property,base.group_user,1,1,1,1 | ||
| access_real_estate_type,estate_property_type,model_estate_property_type,base.group_user,1,1,1,1 | ||
| access_real_estate_tag,estate_property_tag,model_estate_property_tag,base.group_user,1,1,1,1 | ||
| access_real_estate_offer,estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 No newline at end of file |
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.
| access_real_estate_offer,estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 | |
| access_real_estate_offer,estate_property_offer,model_estate_property_offer,base.group_user,1,1,1,1 | |
missing new line at the end of the file.
this goes for most of your other non-python files as well
| <field name="arch" type="xml"> | ||
| <form string="Estate Property"> | ||
| <header> | ||
| <button name="action_sold" type="object" string="Sold" invisible="state in ['new', 'offer_received', 'sold', 'cancelled']" class="btn btn-primary"/> |
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.
| <button name="action_sold" type="object" string="Sold" invisible="state in ['new', 'offer_received', 'sold', 'cancelled']" class="btn btn-primary"/> | |
| <button name="action_sold" type="object" string="Sold" invisible="state != 'offer_accepted'" class="btn btn-primary"/> |
estate/models/estate_property.py
Outdated
| self.garden_orientation = 'north' | ||
| else: | ||
| self.garden_area = 0 | ||
| self.garden_orientation = '' |
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.
Use False (or None) to clear a selection field. Using an empty string '' works but isn't standard practice in Odoo.
| self.garden_orientation = '' | |
| self.garden_orientation = False |
estate/models/res_users.py
Outdated
|
|
||
| class ResUsers(models.Model): | ||
| _inherit = "res.users" | ||
| _name = "res.users" |
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.
| _name = "res.users" |
Not needed when you are inheriting a standard Odoo model using _inherit.
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.
You can delete this file. You have already defined these exact access rights in the estate module. estate_account depends on estate, so it inherits these rights automatically. You only need this file if you are adding new models or modifying rights.
| invoice_vals_list = [ | ||
| { | ||
| 'partner_id': self.property_buyer_id.id, | ||
| 'move_type': 'out_invoice', | ||
| 'invoice_line_ids': [ | ||
| Command.create({ | ||
| 'name': self.name, | ||
| 'quantity': 1, | ||
| 'price_unit': self.selling_price | ||
| }), | ||
| Command.create({ | ||
| 'name': "6%", | ||
| 'quantity': 1, | ||
| 'price_unit': self.selling_price * 0.06 | ||
| }), | ||
| Command.create({ | ||
| 'name': "Administrative fees", | ||
| 'quantity': 1, | ||
| 'price_unit': 100.0 | ||
| }), | ||
| ] | ||
| } | ||
| ] |
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.
| invoice_vals_list = [ | |
| { | |
| 'partner_id': self.property_buyer_id.id, | |
| 'move_type': 'out_invoice', | |
| 'invoice_line_ids': [ | |
| Command.create({ | |
| 'name': self.name, | |
| 'quantity': 1, | |
| 'price_unit': self.selling_price | |
| }), | |
| Command.create({ | |
| 'name': "6%", | |
| 'quantity': 1, | |
| 'price_unit': self.selling_price * 0.06 | |
| }), | |
| Command.create({ | |
| 'name': "Administrative fees", | |
| 'quantity': 1, | |
| 'price_unit': 100.0 | |
| }), | |
| ] | |
| } | |
| ] | |
| invoice_vals_list = [] | |
| for record in self: | |
| invoice_vals_list.append({ | |
| 'partner_id': record.property_buyer_id.id, | |
| 'move_type': 'out_invoice', | |
| 'invoice_line_ids': [ | |
| Command.create({ | |
| 'name': record.name, | |
| 'quantity': 1, | |
| 'price_unit': record.selling_price | |
| }), | |
| Command.create({ | |
| 'name': "6%", | |
| 'quantity': 1, | |
| 'price_unit': record.selling_price * 0.06 | |
| }), | |
| Command.create({ | |
| 'name': "Administrative fees", | |
| 'quantity': 1, | |
| 'price_unit': 100.0 | |
| }), | |
| ] | |
| }) |
The current implementation will raise an error if action_sold is called on multiple records. You should build invoice_vals_list for all records.
Kanban view cards are grouped by type and display the name of the property the expected price, the best price (when an offer is recieved) and the selling price (when an offer is accepted).
8a66f91 to
290cf64
Compare

No description provided.