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
[MIG] base_location_nuts: Migration to 10.0 #432
Conversation
@api.depends('country_id') | ||
def _labels_get(self): | ||
self.lbl_region = _('Region') | ||
self.lbl_substate = _('Substate') | ||
|
||
@api.multi | ||
def onchange_state(self, state_id): |
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.
I'm pretty sure this kind of api is not available in v10. Please check that and use @api.onchange
instead if possible.
<field name="nuts2_id"/> | ||
<field name="nuts3_id"/> | ||
<field name="nuts4_id"/> | ||
<div width="1%" cell-class="oe_form_group_cell_label" |
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.
width=1%
does something?
options="{'no_open': True, 'no_create': True}" | ||
attrs="{'readonly': [('use_parent_address','=',True)]}"/> | ||
</div> | ||
<div width="1%" cell-class="oe_form_group_cell_label" |
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.
Same on width
<field name="nuts2_id"/> | ||
<field name="nuts3_id"/> | ||
<field name="nuts4_id"/> | ||
<div width="1%" cell-class="oe_form_group_cell_label" |
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.
Same on width
options="{'no_open': True, 'no_create': True}" | ||
attrs="{'readonly': [('use_parent_address','=',True)]}"/> | ||
</div> | ||
<div width="1%" cell-class="oe_form_group_cell_label" |
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.
Same on width.
</filter> | ||
</field> | ||
</record> | ||
|
||
</data> | ||
</openerp> | ||
</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.
newline
from openerp import models, api, _ | ||
from openerp.exceptions import Warning as UserError | ||
from odoo import _, api, models | ||
from odoo.exceptions import Warning |
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.
Import it as UserError
; Warning
is deprecated.
return self._onchange_nuts(2) | ||
region = fields.Many2one(comodel_name='res.partner.nuts', | ||
string="Region") | ||
substate = fields.Many2one(comodel_name='res.partner.nuts', |
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.
Don't you need oldname
in these cols? Or any other migrations?
36bf980
to
e0a675b
Compare
Please rebase to get a green branch |
e0a675b
to
c92125d
Compare
Waiting fixes before reviewing |
base_location_nuts/README.rst
Outdated
To contribute to this module, please visit http://odoo-community.org. |
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.
https
base_location_nuts/__manifest__.py
Outdated
'views/res_partner_nuts_view.xml', | ||
'views/res_partner_view.xml', | ||
'wizard/nuts_import_view.xml', | ||
'security/ir.model.access.csv', | ||
], | ||
'images': [ | ||
'images/new_fields.png', | ||
], | ||
'author': 'Antiun Ingeniería S.L., ' |
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.
Remove Antiun
base_location_nuts/__manifest__.py
Outdated
'author': 'Antiun Ingeniería S.L., ' | ||
'Tecnativa' |
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.
Comma at the end
base_location_nuts/__manifest__.py
Outdated
'Odoo Community Association (OCA)', | ||
'website': 'http://www.antiun.com', | ||
'website': 'http://www.tecnativa.com', |
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.
https
|
||
@api.multi | ||
def _onchange_nuts(self, level): | ||
field = self["nuts%d_id" % level] |
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.
Please use getattr(self, "nuts%_id")
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.
No, he is using the right thing. Attributes can get anything from the object, while keys can only get fields, so for security this is the recommended system to access fields with variable names, and even more when the variable comes from outside the method.
Please check slide 40 of https://www.odoo.com/es_ES/slides/slide/10-rules-for-safer-code-398
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.
Well, this system can't be abused like the scenario of the slides. My fear is that this is not a documented way of accessing a field. The official way is with dot notation (and thus, getattr
), but I see in the slides that is using this method, so go on...
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.
Well, that presentation was given by @odony, so I guess that makes it somehow officially documented. Maybe a PR to docs would be good.
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.
👍 let's make it more official: odoo/odoo@464fe4a
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.
Thank your very much for the update on the documentation, Olivier!
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.
Thanks, great little addition! 👏 👏
self.nuts1_id = nuts1.id | ||
return { | ||
'domain': domain, | ||
} | ||
|
||
@api.multi | ||
def onchange_state(self, state_id): |
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 method is not used anymore. Please find the equivalent one or declare a new unique onchange (def onchange_state_id_base_location_nuts(self):
.
'res.partner.nuts', | ||
'parent_id', | ||
"Children", | ||
oldname="children") |
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.
There's no need of oldname in one2many fields, as they don't have a real column in the DB.
options="{'no_open': True, 'no_create': True}" | ||
attrs="{'readonly': [('use_parent_address','=',True)]}"/> | ||
</div> | ||
<field name="nuts1_id"/> |
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.
Why do you remove the attrs
attribute?
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.
I didn't. That change comes from a previous commit (Tecnativa@eade50c)
from openerp import models, api, _ | ||
from openerp.exceptions import Warning | ||
from odoo import _, api, models | ||
from odoo.exceptions import Warning as UserError |
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.
Old alias. Now UserError
is the valid one.
@@ -184,13 +181,14 @@ def run_import(self): | |||
nuts_to_delete = nuts_model.search( | |||
[('country_id', 'in', [x.id for x in self._countries.values()])]) | |||
# Download NUTS in english, create or update | |||
logger.info('Import NUTS 2013 English') | |||
logger.info('Importing NUTS 2013 English') |
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.
Put ...
at the end to indicate that is an operation that requires time.
Please increase test coverage for the onchanges and so on. |
I was doing some test and was getting 404 from the NUTS Eurostat server. There's some issue with Ramon not accepting https request. It does it right on http though. |
Well, change it then. |
@yajo @pedrobaeza It's all green now |
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.
Remember to squash your commits before merging
b390999
to
5980b60
Compare
Commits squashed |
Yes, @pedrobaeza, my fault for copy-pasting and not passing flake locally prior to commit 😬 |
Please put pre-commit linter in your git for avoiding these "surprises": https://github.com/OCA/maintainer-quality-tools/tree/master/git |
@pedrobaeza Thanks! |
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.
Humm complex module, some suggestions to simplify it in some parts 😊
BTW, there are some security good practices that it's good to follow, see below.
Thanks for the good job!
} | ||
dict_recursive_update(result, changes) | ||
def _onchange_nuts(self, level): | ||
field = getattr(self, 'nuts%d_id' % level) |
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.
Do not use getattr, use self["nuts%d_id" % level]
instead.
Se slides 40 and 41: https://www.odoo.com/es_ES/slides/slide/10-rules-for-safer-code-398
self.country_id = country_id | ||
if state_id and self.state_id != state_id: | ||
self.state_id = state_id | ||
if (level - 1) > 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.
😕 Why not just if level > 1
?
if state_id and self.state_id != state_id: | ||
self.state_id = state_id | ||
if (level - 1) > 0: | ||
parent_id = getattr(field, 'parent_id') |
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.
Why not parent_id = field.parent_id
?
parent_id = getattr(field, 'parent_id') | ||
if parent_id: | ||
nuts_parent_level = 'nuts%d_id' % (level - 1) | ||
parent_field = getattr(self, nuts_parent_level) |
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.
no getattr for accessing fields.
def _onchange_nuts1_id(self): | ||
return self._onchange_nuts(1) | ||
|
||
@api.multi |
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.
All these api.multi
can be dropped, now in v10 it's the default.
def onchange_state_id_base_location_nuts(self): | ||
if self.state_id: | ||
# state = self.env['res.country.state'].browse(self.state_id) | ||
result = {'value': {'country_id': self.state_id.country_id.id}} |
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.
self.country_id = self.state_id.country_id
self[field] = nuts_state | ||
result.setdefault("value", dict()) | ||
result['value'][field] = nuts_state.id | ||
return result |
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.
Remove lines 117-119, they are redundant. If you edit self
under an onchange in the new api, you don't need to return a dict with values.
parent_left = fields.Integer('Parent Left', select=True) | ||
parent_right = fields.Integer('Parent Right', select=True) | ||
child_ids = fields.One2many(comodel_name='res.partner.nuts', | ||
inverse_name='parent_id', string='Children') |
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.
Add oldname='children'
logger.info('Reading level=%s, id=%s' % | ||
(node.get('idLevel', 'N/A'), | ||
node.get('id', 'N/A'))) | ||
logger.debug( |
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.
Wrong indentation here?
@@ -36,7 +35,7 @@ | |||
<menuitem action="nuts_import_action" | |||
id="nuts_import_menu" | |||
name="Import NUTS 2013" | |||
parent="base.menu_localisation" | |||
parent="sales_team.menu_localisation" |
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.
It's sad to have to add the sales_team
dependency just for putting the menu somewhere. Do you think there's another place where we can put it and skip this big dependency just for that? 🤔 Or maybe we really need this for other reason?
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 family of modules fall into that menu historically. It's no really needed at all for anything else. There aren't much options on base views anyway... Ideas are welcomed 😄
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.
Well, on base_location there is another menu defined: https://github.com/OCA/partner-contact/blob/10.0/base_location/views/better_zip_view.xml#L61
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.
Right, @pedrobaeza , but this module doesn't depend on that one 😕 It only depended on base before...
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.
Uhm, OK, let's go this way then.
@yajo Thanks for your comments :) I've tried to implement them all. |
'Reading level=%s, id=%s', | ||
node.get('idLevel', 'N/A'), | ||
node.get('id', 'N/A')) | ||
logger.debug('Reading level=%s, id=%s', |
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.
The indentation problem I was referring to is that these are 8 spaces instead of the usual 4. (I mean from the line 195 to 196).
@chienandalu this looks almost perfect now. Could you please fix that little comment and squash all the latest migration-related commits to proceed with merge? |
This makes NUTS labels and levels to be stored in the res.country object. Now creating l10n submodules is a piece of cake! Relational fields now follow guidelines on naming. Old name attribute used for backwards compatibility wherever needed. Also some methods have been renamed, and refactored to be smarter. Most cases l10n modules will just need to fill the res.contry table, and regions and substates domains will work out of the box. In case you still need to overwrite any method, splitting in smaller methods makes it easier too. Oh! And no need for recursive dictionary updates.
d260433
to
f89cbf5
Compare
@yajo Fixed and commits squashed |
cc @Tecnativa