2
0

[IMP] account_chart_update: Include field selection

With this option, you can select which fields do you want to compare for updating.

Use case: you have specific accounts in taxes, and you don't want to lose them,
but you want to update their groups through the wizard. Before this, the update
was all or nothing. Now, you have total control!
This commit is contained in:
Pedro M. Baeza 2018-09-22 03:28:30 +02:00 committed by Luis J. Salvatierra
parent e206a37bdd
commit 9e63f90527
8 changed files with 238 additions and 41 deletions

View File

@ -1,6 +1,4 @@
# © 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com)
# © 2010 Pexego Sistemas Informáticos S.L.(http://www.pexego.es)
# © 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import models
from . import wizard from . import wizard

View File

@ -8,7 +8,7 @@
{ {
'name': "Detect changes and update the Account Chart from a template", 'name': "Detect changes and update the Account Chart from a template",
"summary": "Wizard to update a company's account chart from a template", "summary": "Wizard to update a company's account chart from a template",
'version': "11.0.1.0.1", 'version': "11.0.1.1.0",
'author': "Tecnativa, " 'author': "Tecnativa, "
"BCIM, " "BCIM, "
"Okia, " "Okia, "

View File

@ -23,6 +23,11 @@ msgstr ""
msgid "<span states=\"init,ready\"> or </span>" msgid "<span states=\"init,ready\"> or </span>"
msgstr "" msgstr ""
#. module: account_chart_update
#: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_account_field_ids
msgid "Account fields"
msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_account_account_id #: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_account_account_id
msgid "Account template" msgid "Account template"
@ -85,7 +90,7 @@ msgid "Create/Update"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:616 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:679
#, python-format #, python-format
msgid "Created account %s." msgid "Created account %s."
msgstr "" msgstr ""
@ -107,19 +112,19 @@ msgid "Created on"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:717 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:780
#, python-format #, python-format
msgid "Created or updated fiscal position %s." msgid "Created or updated fiscal position %s."
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:583 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:646
#, python-format #, python-format
msgid "Created tax %s." msgid "Created tax %s."
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:578 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:641
#, python-format #, python-format
msgid "Deactivated tax %s." msgid "Deactivated tax %s."
msgstr "" msgstr ""
@ -135,7 +140,7 @@ msgid "Determines where the tax is selectable. Note : 'None' means a tax can't b
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:453 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:516
#, python-format #, python-format
msgid "Differences in these fields: %s." msgid "Differences in these fields: %s."
msgstr "" msgstr ""
@ -149,13 +154,13 @@ msgid "Display Name"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:625 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:688
#, python-format #, python-format
msgid "Exception creating account %s." msgid "Exception creating account %s."
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:647 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:710
#, python-format #, python-format
msgid "Exception writing account %s." msgid "Exception writing account %s."
msgstr "" msgstr ""
@ -175,6 +180,21 @@ msgstr ""
msgid "Existing taxes are updated. Taxes are searched by name." msgid "Existing taxes are updated. Taxes are searched by name."
msgstr "" msgstr ""
#. module: account_chart_update
#: model:ir.ui.view,arch_db:account_chart_update.view_update_multi_chart
msgid "Field options"
msgstr ""
#. module: account_chart_update
#: model:ir.model,name:account_chart_update.model_ir_model_fields
msgid "Fields"
msgstr ""
#. module: account_chart_update
#: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_fp_field_ids
msgid "Fiscal position fields"
msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_fiscal_position_fiscal_position_id #: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_fiscal_position_fiscal_position_id
msgid "Fiscal position template" msgid "Fiscal position template"
@ -201,6 +221,16 @@ msgstr ""
msgid "For records searched by name (taxes, fiscal positions), the template name will be matched against the record name on this language." msgid "For records searched by name (taxes, fiscal positions), the template name will be matched against the record name on this language."
msgstr "" msgstr ""
#. module: account_chart_update
#: model:ir.ui.view,arch_db:account_chart_update.view_update_multi_chart
msgid "General options"
msgstr ""
#. module: account_chart_update
#: model:ir.ui.view,arch_db:account_chart_update.view_update_multi_chart
msgid "Here you can select the fields you want to check if they have been updated in the templates."
msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_account_id #: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_account_id
#: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_fiscal_position_id #: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_fiscal_position_id
@ -264,7 +294,7 @@ msgid "Messages and Errors"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:477 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:540
#, python-format #, python-format
msgid "Name or description not found." msgid "Name or description not found."
msgstr "" msgstr ""
@ -297,13 +327,13 @@ msgid "Next"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:520 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:583
#, python-format #, python-format
msgid "No account found with this code." msgid "No account found with this code."
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:554 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:617
#, python-format #, python-format
msgid "No fiscal position found with this name." msgid "No fiscal position found with this name."
msgstr "" msgstr ""
@ -326,7 +356,7 @@ msgid "Notes"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:245 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:296
#, python-format #, python-format
msgid "One or more errors detected!\n" msgid "One or more errors detected!\n"
"\n" "\n"
@ -339,7 +369,7 @@ msgid "Other options"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:670 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:733
#, python-format #, python-format
msgid "Post-updated tax %s." msgid "Post-updated tax %s."
msgstr "" msgstr ""
@ -390,7 +420,12 @@ msgid "Tax Scope"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:458 #: model:ir.model.fields,field_description:account_chart_update.field_wizard_update_charts_accounts_tax_field_ids
msgid "Tax fields"
msgstr ""
#. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:521
#, python-format #, python-format
msgid "Tax is disabled." msgid "Tax is disabled."
msgstr "" msgstr ""
@ -427,7 +462,7 @@ msgid "This wizard will update your accounts, taxes and fiscal positions accordi
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:504 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:567
#, python-format #, python-format
msgid "To deactivate: not in the template" msgid "To deactivate: not in the template"
msgstr "" msgstr ""
@ -487,7 +522,7 @@ msgid "Update taxes"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:638 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:701
#, python-format #, python-format
msgid "Updated account %s." msgid "Updated account %s."
msgstr "" msgstr ""
@ -503,7 +538,7 @@ msgid "Updated fiscal positions"
msgstr "" msgstr ""
#. module: account_chart_update #. module: account_chart_update
#: code:addons/account_chart_update/wizard/wizard_chart_update.py:591 #: code:addons/account_chart_update/wizard/wizard_chart_update.py:654
#, python-format #, python-format
msgid "Updated tax %s." msgid "Updated tax %s."
msgstr "" msgstr ""

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from . import ir_model_fields

View File

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Copyright 2018 Tecnativa - Pedro M. Baeza
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from odoo import models
class IrModelFields(models.Model):
_inherit = 'ir.model.fields'
def name_get(self):
"""Return special label when showing fields in chart update wizard."""
if self.env.context.get('account_chart_update'):
res = []
for record in self:
res.append((record.id, "%s (%s)" % (
record.field_description, record.name,
)))
return res
return super(IrModelFields, self).name_get()

View File

@ -135,9 +135,21 @@ class TestAccountChartUpdate(common.HttpCase):
@mute_logger('odoo.sql_db') @mute_logger('odoo.sql_db')
def test_chart_update(self): def test_chart_update(self):
# Test no changes
wizard = self.wizard_obj.create(self.wizard_vals) wizard = self.wizard_obj.create(self.wizard_vals)
wizard.action_find_records() wizard.action_find_records()
# Test ir.model.fields name_get
field = wizard.fp_field_ids[:1]
name = field.with_context(account_chart_update=True).name_get()[0]
self.assertEqual(name[0], field.id)
self.assertEqual(
name[1], "%s (%s)" % (field.field_description, field.name),
)
name = field.name_get()[0]
self.assertEqual(name[0], field.id)
self.assertEqual(
name[1], "%s (%s)" % (field.field_description, field.model),
)
# Test no changes
self.assertEqual(wizard.state, 'ready') self.assertEqual(wizard.state, 'ready')
self.assertFalse(wizard.tax_ids) self.assertFalse(wizard.tax_ids)
self.assertFalse(wizard.account_ids) self.assertFalse(wizard.account_ids)
@ -254,6 +266,32 @@ class TestAccountChartUpdate(common.HttpCase):
self.assertEqual(self.fp.account_ids.account_dest_id, new_account) self.assertEqual(self.fp.account_ids.account_dest_id, new_account)
self.assertEqual(self.fp.tax_ids.tax_dest_id, self.tax) self.assertEqual(self.fp.tax_ids.tax_dest_id, self.tax)
wizard.unlink() wizard.unlink()
# Exclude fields from check
self.tax_template.description = "Test description 2"
self.account_template.name = "Other name 2"
self.fp_template.note = "Test note 2"
wizard = self.wizard_obj.create(self.wizard_vals)
wizard.action_find_records()
wizard.tax_field_ids -= self.env['ir.model.fields'].search([
('model', '=', 'account.tax.template'),
('name', '=', 'description'),
])
wizard.account_field_ids -= self.env['ir.model.fields'].search([
('model', '=', 'account.account.template'),
('name', '=', 'name'),
])
wizard.fp_field_ids -= self.env['ir.model.fields'].search([
('model', '=', 'account.fiscal.position.template'),
('name', '=', 'note'),
])
wizard.action_find_records()
self.assertFalse(wizard.tax_ids)
self.assertFalse(wizard.account_ids)
self.assertFalse(wizard.fiscal_position_ids)
self.tax_template.description = "Test description"
self.account_template.name = "Other name"
self.fp_template.note = "Test note"
wizard.unlink()
# Remove objects # Remove objects
new_tax_tmpl.unlink() new_tax_tmpl.unlink()
wizard = self.wizard_obj.create(self.wizard_vals) wizard = self.wizard_obj.create(self.wizard_vals)

View File

@ -96,6 +96,57 @@ class WizardUpdateChartsAccounts(models.TransientModel):
string='Deactivated taxes', string='Deactivated taxes',
compute="_compute_deleted_taxes_count") compute="_compute_deleted_taxes_count")
log = fields.Text(string='Messages and Errors', readonly=True) log = fields.Text(string='Messages and Errors', readonly=True)
tax_field_ids = fields.Many2many(
comodel_name="ir.model.fields",
relation="wizard_update_charts_tax_fields_rel",
string="Tax fields",
domain=lambda self: self._domain_tax_field_ids(),
default=lambda self: self._default_tax_field_ids(),
)
account_field_ids = fields.Many2many(
comodel_name="ir.model.fields",
relation="wizard_update_charts_account_fields_rel",
string="Account fields",
domain=lambda self: self._domain_account_field_ids(),
default=lambda self: self._default_account_field_ids(),
)
fp_field_ids = fields.Many2many(
comodel_name="ir.model.fields",
relation="wizard_update_charts_fp_fields_rel",
string="Fiscal position fields",
domain=lambda self: self._domain_fp_field_ids(),
default=lambda self: self._default_fp_field_ids(),
)
def _domain_per_name(self, name):
return [
('model', '=', name),
('name', 'not in', tuple(self.fields_to_ignore(name))),
]
def _domain_tax_field_ids(self):
return self._domain_per_name('account.tax.template')
def _domain_account_field_ids(self):
return self._domain_per_name('account.account.template')
def _domain_fp_field_ids(self):
return self._domain_per_name('account.fiscal.position.template')
def _default_tax_field_ids(self):
return [(4, x.id) for x in self.env['ir.model.fields'].search(
self._domain_tax_field_ids()
)]
def _default_account_field_ids(self):
return [(4, x.id) for x in self.env['ir.model.fields'].search(
self._domain_account_field_ids()
)]
def _default_fp_field_ids(self):
return [(4, x.id) for x in self.env['ir.model.fields'].search(
self._domain_fp_field_ids()
)]
@api.model @api.model
def _get_lang_selection_options(self): def _get_lang_selection_options(self):
@ -355,7 +406,7 @@ class WizardUpdateChartsAccounts(models.TransientModel):
@api.model @api.model
@tools.ormcache("name") @tools.ormcache("name")
def fields_to_ignore(self, template, name): def fields_to_ignore(self, name):
"""Get fields that will not be used when checking differences. """Get fields that will not be used when checking differences.
:param str template: A template record. :param str template: A template record.
@ -364,11 +415,16 @@ class WizardUpdateChartsAccounts(models.TransientModel):
""" """
specials_mapping = { specials_mapping = {
"account.tax.template": { "account.tax.template": {
"chart_template_id",
"children_tax_ids", "children_tax_ids",
}, },
"account.account.template": { "account.account.template": {
"chart_template_id",
"code", "code",
}, },
"account.fiscal.position.template": {
"chart_template_id",
},
} }
specials = ({"display_name", "__last_update", "company_id"} | specials = ({"display_name", "__last_update", "company_id"} |
specials_mapping.get(name, set())) specials_mapping.get(name, set()))
@ -387,9 +443,16 @@ class WizardUpdateChartsAccounts(models.TransientModel):
Fields that are different in both records, and the expected value. Fields that are different in both records, and the expected value.
""" """
result = dict() result = dict()
ignore = self.fields_to_ignore(template, template._name) ignore = self.fields_to_ignore(template._name)
to_include = []
if template._name == 'account.tax.template':
to_include = self.tax_field_ids.mapped('name')
elif template._name == 'account.account.template':
to_include = self.account_field_ids.mapped('name')
elif template._name == 'account.fiscal.position.template':
to_include = self.fp_field_ids.mapped('name')
for key, field in template._fields.items(): for key, field in template._fields.items():
if key in ignore: if key in ignore or key not in to_include:
continue continue
expected = t = None expected = t = None
# Translate template records to reals for comparison # Translate template records to reals for comparison

View File

@ -32,23 +32,62 @@
/> />
<field name="lang" attrs="{'invisible':[('state','!=','init')]}" /> <field name="lang" attrs="{'invisible':[('state','!=','init')]}" />
</group> </group>
<group attrs="{'invisible':[('state','!=','init')]}"> <notebook attrs="{'invisible':[('state','!=','init')]}">
<group string="Update records?"> <page string="General options" name="page_general_options">
<field name="update_tax" /> <group>
<field name="update_account" /> <group string="Update records?">
<field name="update_fiscal_position" /> <field name="update_tax" />
</group> <field name="update_account" />
<group string="Other options" attrs="{'invisible':[('state','!=','init')]}"> <field name="update_fiscal_position" />
<field name="continue_on_errors" /> </group>
</group> <group string="Other options" attrs="{'invisible':[('state','!=','init')]}">
</group> <field name="continue_on_errors" />
</group>
<group attrs="{'invisible':[('state','!=','init')]}"> </group>
<h5> <group>
<p>If you leave these options set, the wizard will not just create new records, but also update records with changes (i.e. different tax amount)</p> <h5>
<p>Note: Only the changed fields are updated.</p> <p>If you leave these options set, the wizard will not just create new records, but also update records with changes (i.e. different tax amount)</p>
</h5> <p>Note: Only the changed fields are updated.</p>
</group> </h5>
</group>
</page>
<page string="Field options"
attrs="{'invisible': [('update_tax', '=', False), ('update_account', '=', False), ('update_fiscal_position', '=', False)]}"
>
<h3>
<p>Here you can select the fields you want to check if they have been updated in the templates.</p>
</h3>
<notebook>
<page string="Taxes"
name="page_fields_taxes"
attrs="{'invisible': [('update_tax', '=', False)]}"
>
<field name="tax_field_ids"
widget="many2many_checkboxes"
context="{'account_chart_update': True}"
/>
</page>
<page string="Accounts"
name="page_fields_accounts"
attrs="{'invisible': [('update_account', '=', False)]}"
>
<field name="account_field_ids"
widget="many2many_checkboxes"
context="{'account_chart_update': True}"
/>
</page>
<page string="Fiscal positions"
name="page_fields_fps"
attrs="{'invisible': [('update_fiscal_position', '=', False)]}"
>
<field name="fp_field_ids"
widget="many2many_checkboxes"
context="{'account_chart_update': True}"
/>
</page>
</notebook>
</page>
</notebook>
<group attrs="{'invisible':[('state','!=','ready'),]}" <group attrs="{'invisible':[('state','!=','ready'),]}"
string="Records to create/update"> string="Records to create/update">
<notebook colspan="4"> <notebook colspan="4">