From e9da8fe0ea015eb7c4e98d8829da2be51b6b3f95 Mon Sep 17 00:00:00 2001 From: Joaquin Gutierrez Date: Tue, 1 Oct 2013 18:28:19 +0200 Subject: [PATCH 01/86] [MIG]: account_char_update: Migration to version 7.0 [FIX]: Changed types to orm.Model, orm.TransientModel and orm.AbstractModel. [FIX]: Fix deletion method for some fields of objects. [FIX]: Contributions have been written in the standard format of the community. [FIX]: Changes in the form to work as a real wizard. [FIX]: Remove 'init_xml' keys, because it's no longer needed in v7. [FIX]: Rename 'demo_xml' key to the new standard 'demo'. [FIX]: Change imports calls. [FIX]: Remove __author__ variables in files, because authors are put on manifest file (__openerp__.py). [FIX]: Update view definitions to version 7.0 [FIX]: Rename variables to OpenERP standard. [FIX]: Increased compatibility with standard PEP8. [IMP]: User Invitu add the method call _reopen to keep open the wizard. [MRG]: User Invitu add frech language. --- account_chart_update/__init__.py | 25 + account_chart_update/__openerp__.py | 69 + account_chart_update/wizard/__init__.py | 25 + .../wizard/wizard_chart_update.py | 1351 +++++++++++++++++ .../wizard/wizard_chart_update_view.xml | 176 +++ 5 files changed, 1646 insertions(+) create mode 100644 account_chart_update/__init__.py create mode 100644 account_chart_update/__openerp__.py create mode 100644 account_chart_update/wizard/__init__.py create mode 100644 account_chart_update/wizard/wizard_chart_update.py create mode 100644 account_chart_update/wizard/wizard_chart_update_view.xml diff --git a/account_chart_update/__init__.py b/account_chart_update/__init__.py new file mode 100644 index 00000000000..36d5407d08f --- /dev/null +++ b/account_chart_update/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +""" +Account Chart Update Wizard +""" +import wizard diff --git a/account_chart_update/__openerp__.py b/account_chart_update/__openerp__.py new file mode 100644 index 00000000000..79b16c0879c --- /dev/null +++ b/account_chart_update/__openerp__.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2013 Joaquin Gutierrez (http://www.gutierrezweb.es) +# Pedro Manuel Baeza +# $Id$ +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +# 2013/09/08 - Joaquín Gutierrez: Adaptación a la versión +# +############################################################################## + +{ + 'name': "Detect changes and update the Account Chart from a template", + 'version': "1.0", + 'author': "Zikzakmedia SL", + 'website': "www.zikzakmedia.com", + 'depends': ["account"], + 'category': "Generic Modules/Accounting", + 'contributors': ['Joaquin Gutierrez', 'Pedro M. Baeza'], + 'description': """ +Adds a wizard to update a company account chart from a chart template. +====================================================================== + +This is a pretty useful tool to update OpenERP instalations after tax reforms +on the oficial charts of accounts, or to apply fixes performed on the chart +template. + +The wizard: +- Allows the user to compare a chart and a template showing differences + on accounts, taxes, tax codes and fiscal positions. +- It may create the new account, taxes, tax codes and fiscal positions detected + on the template. +- It can also update (overwrite) the accounts, taxes, tax codes and fiscal + positions that got modified on the template. + +The wizard lets the user select what kind of objects must be checked/updated, +and whether old records must be checked for changes and updated. +It will display all the accounts to be created / updated with some information +about the detected differences, and allow the user to exclude records +individually. +Any problem found while updating will be shown on the last step. +""", + 'license': "AGPL-3", + "depends": [ + "account", + "base", + ], + "demo" : [], + "data": [ + 'wizard/wizard_chart_update_view.xml', + ], + "active": False, + "installable": True +} diff --git a/account_chart_update/wizard/__init__.py b/account_chart_update/wizard/__init__.py new file mode 100644 index 00000000000..8d0cfc9ed96 --- /dev/null +++ b/account_chart_update/wizard/__init__.py @@ -0,0 +1,25 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +""" +Account Chart Update Wizard +""" +import wizard_chart_update diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py new file mode 100644 index 00000000000..e4801373f0b --- /dev/null +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -0,0 +1,1351 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## +""" +Account Chart Update Wizard +""" + +from openerp.osv import fields, orm +from openerp.tools.translate import _ +import logging + + +def _reopen(self, res_id, model): + return { + 'type': 'ir.actions.act_window', + 'view_mode': 'form', + 'view_type': 'form', + 'res_id': res_id, + 'res_model': self._name, + 'target': 'new', + # save original model in context, because selecting the list of available + # templates requires a model in context + 'context': { + 'default_model': model, + }, + } + + +class WizardLog: + """ + ******************************************************************* + Small helper class to store the messages and errors on the wizard. + ******************************************************************* + """ + def __init__(self): + self.messages = [] + self.errors = [] + + """ + Adds a message to the log. + """ + def add(self, message, is_error=False): + logger = logging.getLogger("account_chart_update") + if is_error: + logger.warning(u"Log line: %s" % message) + self.errors.append(message) + else: + logger.debug(u"Log line: %s" % message) + self.messages.append(message) + + """ + Returns whether errors where logged. + """ + def has_errors(self): + return self.errors + + def __call__(self): + return "".join(self.messages) + + def __str__(self): + return "".join(self.messages) + + def get_errors_str(self): + return "".join(self.errors) + + +class wizard_update_charts_accounts(orm.TransientModel): + _name = 'wizard.update.charts.accounts' + + """ + Gets the available languages for the selection. + """ + def _get_lang_selection_options(self, cr, uid, context={}): + obj = self.pool.get('res.lang') + ids = obj.search(cr, uid, [], context=context) + res = obj.read(cr, uid, ids, ['code', 'name'], context) + return [(r['code'], r['name']) for r in res] + [('', '')] + + _columns = { + 'state': fields.selection([ + ('init', 'Step 1'), + ('ready', 'Step 2'), + ('done', 'Wizard Complete') + ], 'Status', readonly=True), + 'company_id': fields.many2one('res.company', 'Company', required=True, ondelete='set null'), + 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True, ondelete='set null'), + 'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code. Make sure it is the same number as existing accounts."), + 'lang': fields.selection(_get_lang_selection_options, 'Language', size=5, help="For records searched by name (taxes, tax codes, fiscal positions), the template name will be matched against the record name on this language."), + 'update_tax_code': fields.boolean('Update tax codes', help="Existing tax codes are updated. Tax codes are searched by name."), + 'update_tax': fields.boolean('Update taxes', help="Existing taxes are updated. Taxes are searched by name."), + 'update_account': fields.boolean('Update accounts', help="Existing accounts are updated. Accounts are searched by code."), + 'update_fiscal_position': fields.boolean('Update fiscal positions', help="Existing fiscal positions are updated. Fiscal positions are searched by name."), + 'update_children_accounts_parent': fields.boolean("Update children accounts parent", + help="Update the parent of accounts that seem (based on the code) to be children of the newly created ones. If you had an account 430 with a child 4300000, and a 4300 account is created, the 4300000 parent will be set to 4300."), + 'continue_on_errors': fields.boolean("Continue on errors", help="If set, the wizard will continue to the next step even if there are minor errors (for example the parent account of a new account couldn't be set)."), + 'tax_code_ids': fields.one2many('wizard.update.charts.accounts.tax.code', 'update_chart_wizard_id', 'Tax codes', ondelete='cascade'), + 'tax_ids': fields.one2many('wizard.update.charts.accounts.tax', 'update_chart_wizard_id', 'Taxes', ondelete='cascade'), + 'account_ids': fields.one2many('wizard.update.charts.accounts.account', 'update_chart_wizard_id', 'Accounts', ondelete='cascade'), + 'fiscal_position_ids': fields.one2many('wizard.update.charts.accounts.fiscal.position', 'update_chart_wizard_id', 'Fiscal positions', ondelete='cascade'), + 'new_tax_codes': fields.integer('New tax codes', readonly=True), + 'new_taxes': fields.integer('New taxes', readonly=True), + 'new_accounts': fields.integer('New accounts', readonly=True), + 'new_fps': fields.integer('New fiscal positions', readonly=True), + 'updated_tax_codes': fields.integer('Updated tax codes', readonly=True), + 'updated_taxes': fields.integer('Updated taxes', readonly=True), + 'updated_accounts': fields.integer('Updated accounts', readonly=True), + 'updated_fps': fields.integer('Updated fiscal positions', readonly=True), + 'log': fields.text('Messages and Errors', readonly=True) + } + """ + Redefine the search to search by company name. + """ + def name_search(self, cr, user, name, + args=None, operator='ilike', context=None, limit=80): + if not name: + name = '%' + if not args: + args = [] + if not context: + context = {} + args = args[:] + ids = [] + ids = self.search( + cr, user, [('company_id', operator, name)] + args, limit=limit) + return self.name_get(cr, user, ids, context=context) + + """ + Use the company name and template as name. + """ + def name_get(self, cr, uid, ids, context=None): + if context is None: + context = {} + if not len(ids): + return [] + records = self.browse(cr, uid, ids, context) + res = [] + for record in records: + res.append((record.id, record.company_id.name + + ' - ' + record.chart_template_id.name)) + return res + + """ + Returns the default chart template. + """ + def _get_chart(self, cr, uid, context=None): + if context is None: + context = {} + ids = self.pool.get( + 'account.chart.template').search(cr, uid, [], context=context) + if ids: + return ids[0] + return False + + """ + Returns the default code size for the accounts. + To figure out the number of digits of the accounts it look at the + code size of the default receivable account of the company + (or user's company if any company is given). + """ + def _get_code_digits(self, cr, uid, context=None, company_id=None): + if context is None: + context = {} + property_obj = self.pool.get('ir.property') + account_obj = self.pool.get('account.account') + if not company_id: + user = self.pool.get('res.users').browse(cr, uid, uid, context) + company_id = user.company_id.id + property_ids = property_obj.search( + cr, + uid, + [('name', '=', 'property_account_receivable'), + ('company_id', '=', company_id), + ('res_id', '=', False), + ('value_reference', '!=', False) + ]) + if not property_ids: + # Try to get a generic (no-company) property + property_ids = property_obj.search( + cr, + uid, + [('name', '=', 'property_account_receivable'), + ('res_id', '=', False), + ('value_reference', '!=', False) + ]) + number_digits = 6 + if property_ids: + prop = property_obj.browse( + cr, uid, property_ids[0], context=context) + account_id = prop.value_reference.id + + if account_id: + code = account_obj.read( + cr, uid, account_id, ['code'], context)['code'] + number_digits = len(code) + return number_digits + + _defaults = { + 'state': 'init', + 'company_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, [uid], context)[0].company_id.id, + 'chart_template_id': _get_chart, + 'update_tax_code': True, + 'update_tax': True, + 'update_account': True, + 'update_fiscal_position': True, + 'update_children_accounts_parent': True, + 'continue_on_errors': False, + 'lang': lambda self, cr, uid, context: context and context.get('lang') or None, + } + + """ + Update the code size when the company changes + """ + def onchange_company_id(self, cr, uid, ids, company_id, context=None): + res = { + 'value': { + 'code_digits': self._get_code_digits( + cr, + uid, + context=context, + company_id=company_id), + } + } + return res + + """ + Initial action that sets the initial state. + """ + def action_init(self, cr, uid, ids, context=None): + if context is None: + context = {} + wizard = self.browse(cr, uid, ids[0], context=context) + self.write(cr, uid, ids, {'state': 'init'}, context) + view_wizard = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_chart_update', 'view_update_multi_chart') + view_wizard_id = view_wizard and view_wizard[1] or False, + res = { + 'type': 'ir.actions.act_window', + 'name': _("Update Chart of Accounts from a Chart Template "), + 'res_model': 'wizard.update.charts.accounts', + 'view_type': 'form', + 'view_mode': 'form', + 'res_id': wizard.id, + 'view_id': view_wizard_id, + 'context': context, + 'target': 'new', + } + return res + + return True + + ########################################################################## + # Helper methods + ########################################################################## + """ + Adds a tax template -> tax id to the mapping. + """ + def _map_tax_template(self, cr, uid, wizard, tax_template_mapping, tax_template, context=None): + if tax_template and not tax_template_mapping.get(tax_template.id): + taxes = self.pool.get('account.tax') + tax_ids = taxes.search(cr, uid, [ + ('name', '=', tax_template.name), + ('company_id', '=', wizard.company_id.id) + ], context=context) + if tax_ids: + tax_template_mapping[tax_template.id] = tax_ids[0] + + """ + Adds a tax code template -> tax code id to the mapping. + """ + def _map_tax_code_template(self, cr, uid, wizard, tax_code_template_mapping, tax_code_template, context=None): + if tax_code_template and not tax_code_template_mapping.get(tax_code_template.id): + tax_codes = self.pool.get('account.tax.code') + root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id + tax_code_name = (tax_code_template.id == root_tax_code_id) and wizard.company_id.name or tax_code_template.name + tax_code_ids = tax_codes.search(cr, uid, [ + ('name', '=', tax_code_name), + ('company_id', '=', wizard.company_id.id) + ]) + if tax_code_ids: + tax_code_template_mapping[ + tax_code_template.id] = tax_code_ids[0] + + """ + Adds an account template -> account id to the mapping + """ + def _map_account_template(self, cr, uid, wizard, account_template_mapping, account_template, context=None): + if account_template and not account_template_mapping.get(account_template.id): + accounts = self.pool.get('account.account') + code = account_template.code or '' + if account_template.type != 'view': + if len(code) > 0 and len(code) <= wizard.code_digits: + code = '%s%s' % ( + code, '0' * (wizard.code_digits - len(code))) + account_ids = accounts.search(cr, uid, [ + ('code', '=', code), + ('company_id', '=', wizard.company_id.id) + ], context=context) + if account_ids: + account_template_mapping[account_template.id] = account_ids[0] + """ + Adds a fiscal position template -> fiscal position id to the mapping. + """ + def _map_fp_template(self, cr, uid, wizard, fp_template_mapping, fp_template, context=None): + if fp_template and not fp_template_mapping.get(fp_template.id): + fiscalpositions = self.pool.get('account.fiscal.position') + fp_ids = fiscalpositions.search(cr, uid, [ + ('name', '=', fp_template.name), + ('company_id', '=', wizard.company_id.id) + ], context=context) + if fp_ids: + fp_template_mapping[fp_template.id] = fp_ids[0] + + """ + Search for, and load, tax code templates to create/update. + """ + def _find_tax_codes(self, cr, uid, wizard, context=None): + new_tax_codes = 0 + updated_tax_codes = 0 + tax_code_template_mapping = {} + + taxes_codes_templates = self.pool.get('account.tax.code.template') + taxcodes = self.pool.get('account.tax.code') + wiz_taxcodes = self.pool.get('wizard.update.charts.accounts.tax.code') + + # Remove previous tax codes + wiz_taxcodes.unlink( + cr, uid, wiz_taxcodes.search(cr, uid, [])) + + # + # Search for new / updated tax codes + # + root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id + children_tax_code_template = taxes_codes_templates.search(cr, uid, [( + 'parent_id', 'child_of', [root_tax_code_id])], order='id') + for tax_code_template in taxes_codes_templates.browse(cr, uid, children_tax_code_template): + # Ensure the tax code template is on the map (search for the mapped + # tax code id). + self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template, context) + + tax_code_id = tax_code_template_mapping.get(tax_code_template.id) + if not tax_code_id: + new_tax_codes += 1 + wiz_taxcodes.create(cr, uid, { + 'tax_code_id': tax_code_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'new', + }, context) + elif wizard.update_tax_code: + # + # Check the tax code for changes. + # + modified = False + notes = "" + tax_code = taxcodes.browse( + cr, uid, tax_code_id, context=context) + + if tax_code.code != tax_code_template.code: + notes += _("The code field is different.\n") + modified = True + if tax_code.info != tax_code_template.info: + notes += _("The info field is different.\n") + modified = True + if tax_code.sign != tax_code_template.sign: + notes += _("The sign field is different.\n") + modified = True + + # TODO: We could check other account fields for changes... + + if modified: + # + # Tax code to update. + # + updated_tax_codes += 1 + wiz_taxcodes.create(cr, uid, { + 'tax_code_id': tax_code_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'updated', + 'update_tax_code_id': tax_code_id, + 'notes': notes, + }, context) + + return { + 'new': new_tax_codes, + 'updated': updated_tax_codes, + 'mapping': tax_code_template_mapping + } + """ + Search for, and load, tax templates to create/update. + """ + def _find_taxes(self, cr, uid, wizard, context=None): + new_taxes = 0 + updated_taxes = 0 + tax_template_mapping = {} + + taxes = self.pool.get('account.tax') + wiz_taxes = self.pool.get('wizard.update.charts.accounts.tax') + + delay_wiz_tax = [] + # Remove previous taxes + wiz_taxes.unlink(cr, uid, wiz_taxes.search(cr, uid, [])) + + # + # Search for new / updated taxes + # + for tax_template in wizard.chart_template_id.tax_template_ids: + # Ensure the tax template is on the map (search for the mapped tax + # id). + self._map_tax_template( + cr, uid, wizard, tax_template_mapping, tax_template, context) + + tax_id = tax_template_mapping.get(tax_template.id) + if not tax_id: + new_taxes += 1 + vals_wiz = { + 'tax_id': tax_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'new', + } + if not tax_template.parent_id: + wiz_taxes.create(cr, uid, vals_wiz, context) + else: + delay_wiz_tax.append(vals_wiz) + elif wizard.update_tax: + # + # Check the tax for changes. + # + modified = False + notes = "" + tax = taxes.browse(cr, uid, tax_id, context=context) + if tax.sequence != tax_template.sequence: + notes += _("The sequence field is different.\n") + modified = True + if tax.amount != tax_template.amount: + notes += _("The amount field is different.\n") + modified = True + if tax.type != tax_template.type: + notes += _("The type field is different.\n") + modified = True + if tax.applicable_type != tax_template.applicable_type: + notes += _("The applicable type field is different.\n") + modified = True + if tax.domain != tax_template.domain: + notes += _("The domain field is different.\n") + modified = True + if tax.child_depend != tax_template.child_depend: + notes += _("The child depend field is different.\n") + modified = True + if tax.python_compute != tax_template.python_compute: + notes += _("The python compute field is different.\n") + modified = True + # if tax.tax_group != tax_template.tax_group: + # notes += _("The tax group field is different.\n") + # modified = True + if tax.base_sign != tax_template.base_sign: + notes += _("The base sign field is different.\n") + modified = True + if tax.tax_sign != tax_template.tax_sign: + notes += _("The tax sign field is different.\n") + modified = True + if tax.include_base_amount != tax_template.include_base_amount: + notes += _("The include base amount field is different.\n") + modified = True + if tax.type_tax_use != tax_template.type_tax_use: + notes += _("The type tax use field is different.\n") + modified = True + # TODO: We could check other tax fields for changes... + + if modified: + # + # Tax code to update. + # + updated_taxes += 1 + wiz_taxes.create(cr, uid, { + 'tax_id': tax_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'updated', + 'update_tax_id': tax_id, + 'notes': notes, + }, context) + + for delay_vals_wiz in delay_wiz_tax: + wiz_taxes.create(cr, uid, delay_vals_wiz, context) + + return {'new': new_taxes, 'updated': updated_taxes, 'mapping': tax_template_mapping} + + """ + Search for, and load, account templates to create/update. + """ + def _find_accounts(self, cr, uid, wizard, context=None): + new_accounts = 0 + updated_accounts = 0 + account_template_mapping = {} + + accounts = self.pool.get('account.account') + accounts_template = self.pool.get('account.account.template') + wiz_accounts = self.pool.get( + 'wizard.update.charts.accounts.account') + + # Remove previous accounts + wiz_accounts.unlink( + cr, uid, wiz_accounts.search(cr, uid, [])) + + # + # Search for new / updated accounts + # + root_account_id = wizard.chart_template_id.account_root_id.id + children_acc_template = accounts_template.search(cr, uid, [( + 'parent_id', 'child_of', [root_account_id])], context=context) + children_acc_template.sort() + for account_template in accounts_template.browse(cr, uid, children_acc_template, context=context): + # Ensure the account template is on the map (search for the mapped + # account id). + self._map_account_template(cr, uid, wizard, account_template_mapping, account_template, context) + + account_id = account_template_mapping.get(account_template.id) + if not account_id: + new_accounts += 1 + wiz_accounts.create(cr, uid, { + 'account_id': account_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'new', + }, context) + elif wizard.update_account: + # + # Check the account for changes. + # + modified = False + notes = "" + account = accounts.browse( + cr, uid, account_id, context=context) + + if account.name != account_template.name and account.name != wizard.company_id.name: + notes += _("The name is different.\n") + modified = True + if account.type != account_template.type: + notes += _("The type is different.\n") + modified = True + if account.user_type != account_template.user_type: + notes += _("The user type is different.\n") + modified = True + if account.reconcile != account_template.reconcile: + notes += _("The reconcile is different.\n") + modified = True + + # TODO: We could check other account fields for changes... + + if modified: + # + # Account to update. + # + updated_accounts += 1 + wiz_accounts.create(cr, uid, { + 'account_id': account_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'updated', + 'update_account_id': account_id, + 'notes': notes, + }, context) + + return {'new': new_accounts, 'updated': updated_accounts, 'mapping': account_template_mapping} + + """ + Search for, and load, fiscal position templates to create/update. + """ + def _find_fiscal_positions(self, cr, uid, wizard, context=None): + new_fps = 0 + updated_fps = 0 + fp_template_mapping = {} + + fiscalpostitions_template = self.pool.get('account.fiscal.position.template') + fiscalpositions = self.pool.get('account.fiscal.position') + wiz_fiscalpositions = self.pool.get( + 'wizard.update.charts.accounts.fiscal.position') + + # Remove previous fiscal positions + wiz_fiscalpositions.unlink(cr, uid, wiz_fiscalpositions.search(cr, uid, [])) + + # + # Search for new / updated fiscal positions + # + fp_template_ids = fiscalpostitions_template.search(cr, uid, [('chart_template_id', '=', wizard.chart_template_id.id)], context=context) + for fp_template in fiscalpostitions_template.browse(cr, uid, fp_template_ids, context=context): + # Ensure the fiscal position template is on the map (search for the + # mapped fiscal position id). + self._map_fp_template( + cr, uid, wizard, fp_template_mapping, fp_template, context) + + fp_id = fp_template_mapping.get(fp_template.id) + if not fp_id: + # + # New fiscal position template. + # + new_fps += 1 + wiz_fiscalpositions.create(cr, uid, { + 'fiscal_position_id': fp_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'new', + }, context) + elif wizard.update_fiscal_position: + # + # Check the fiscal position for changes. + # + modified = False + notes = "" + fp = fiscalpositions.browse(cr, uid, fp_id, context=context) + + # + # Check fiscal position taxes for changes. + # + if fp_template.tax_ids and fp.tax_ids: + for fp_tax_template in fp_template.tax_ids: + found = False + for fp_tax in fp.tax_ids: + if fp_tax.tax_src_id.name == fp_tax_template.tax_src_id.name: + if fp_tax_template.tax_dest_id and fp_tax.tax_dest_id: + if fp_tax.tax_dest_id.name == fp_tax_template.tax_dest_id.name: + found = True + break + elif not fp_tax_template.tax_dest_id and not fp_tax.tax_dest_id: + found = True + break + if not found: + if fp_tax_template.tax_dest_id: + notes += _("Tax mapping not found on the fiscal position instance: %s -> %s.\n") % (fp_tax_template.tax_src_id.name, fp_tax_template.tax_dest_id.name) + else: + notes += _("Tax mapping not found on the fiscal position instance: %s -> None.\n") % fp_tax_template.tax_src_id.name + modified = True + elif fp_template.tax_ids and not fp.tax_ids: + notes += _("The template has taxes the fiscal position instance does not.\n") + modified = True + + # + # Check fiscal position accounts for changes. + # + if fp_template.account_ids and fp.account_ids: + for fp_account_template in fp_template.account_ids: + found = False + for fp_account in fp.account_ids: + if fp_account.account_src_id.name == fp_account_template.account_src_id.name: + if fp_account.account_dest_id.name == fp_account_template.account_dest_id.name: + found = True + break + if not found: + notes += _("Account mapping not found on the fiscal position instance: %s -> %s.\n") % (fp_account_template.account_src_id.name, fp_account_template.account_dest_id.name) + modified = True + elif fp_template.account_ids and not fp.account_ids: + notes += _("The template has accounts the fiscal position instance does not.\n") + modified = True + + if modified: + # + # Fiscal position template to update. + # + updated_fps += 1 + wiz_fiscalpositions.create(cr, uid, { + 'fiscal_position_id': fp_template.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'updated', + 'update_fiscal_position_id': fp_id, + 'notes': notes, + }, context) + + return {'new': new_fps, 'updated': updated_fps, 'mapping': fp_template_mapping} + + """ + Searchs for records to update/create and shows them + """ + def action_find_records(self, cr, uid, ids, context=None): + if context is None: + context = {} + wizard = self.browse(cr, uid, ids[0], context=context) + + if wizard.lang: + context['lang'] = wizard.lang + elif context.get('lang'): + del context['lang'] + + # + # Search for, and load, the records to create/update. + # + tax_codes_res = self._find_tax_codes(cr, uid, wizard, context=context) + taxes_res = self._find_taxes(cr, uid, wizard, context=context) + accounts_res = self._find_accounts(cr, uid, wizard, context=context) + fps_res = self._find_fiscal_positions(cr, uid, wizard, context=context) + + # + # Write the results, and go to the next step. + # + self.write(cr, uid, [wizard.id], { + 'state': 'ready', + 'new_tax_codes': tax_codes_res.get('new', 0), + 'new_taxes': taxes_res.get('new', 0), + 'new_accounts': accounts_res.get('new', 0), + 'new_fps': fps_res.get('new', 0), + 'updated_tax_codes': tax_codes_res.get('updated', 0), + 'updated_taxes': taxes_res.get('updated', 0), + 'updated_accounts': accounts_res.get('updated', 0), + 'updated_fps': fps_res.get('updated', 0), + }, context) + + return _reopen(self, wizard.id, 'wizard.update.chart.accounts') + """ + Search for, and load, tax code templates to create/update. + """ + def _update_tax_codes(self, cr, uid, wizard, log, context=None): + taxcodes = self.pool.get('account.tax.code') + root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id + new_tax_codes = 0 + updated_tax_codes = 0 + tax_code_template_mapping = {} + + for wiz_tax_code in wizard.tax_code_ids: + tax_code_template = wiz_tax_code.tax_code_id + tax_code_name = (root_tax_code_id == tax_code_template.id) and wizard.company_id.name or tax_code_template.name + + # Ensure the parent tax code template is on the map. + self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template.parent_id, context) + + # + # Values + # + vals = { + 'name': tax_code_name, + 'code': tax_code_template.code, + 'info': tax_code_template.info, + 'parent_id': tax_code_template.parent_id and tax_code_template_mapping.get(tax_code_template.parent_id.id), + 'company_id': wizard.company_id.id, + 'sign': tax_code_template.sign, + } + + tax_code_id = None + modified = False + + if wiz_tax_code.type == 'new': + # + # Create the tax code + # + tax_code_id = taxcodes.create(cr, uid, vals) + log.add(_("Created tax code %s.\n") % tax_code_name) + new_tax_codes += 1 + modified = True + elif wizard.update_tax_code and wiz_tax_code.update_tax_code_id: + # + # Update the tax code + # + tax_code_id = wiz_tax_code.update_tax_code_id.id + taxcodes.write(cr, uid, [tax_code_id], vals) + log.add(_("Updated tax code %s.\n") % tax_code_name) + updated_tax_codes += 1 + modified = True + else: + tax_code_id = wiz_tax_code.update_tax_code_id and wiz_tax_code.update_tax_code_id.id + modified = False + + # Store the tax codes on the map + tax_code_template_mapping[tax_code_template.id] = tax_code_id + + if modified: + # + # Detect errors + # + if tax_code_template.parent_id and not tax_code_template_mapping.get(tax_code_template.parent_id.id): + log.add(_("Tax code %s: The parent tax code %s can not be set.\n") % (tax_code_name, tax_code_template.parent_id.name), True) + + return { + 'new': new_tax_codes, + 'updated': updated_tax_codes, + 'mapping': tax_code_template_mapping + } + + """ + Search for, and load, tax templates to create/update. + """ + def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context=None): + taxes = self.pool.get('account.tax') + + new_taxes = 0 + updated_taxes = 0 + tax_template_mapping = {} + taxes_pending_for_accounts = {} + + for wiz_tax in wizard.tax_ids: + tax_template = wiz_tax.tax_id + + # Ensure the parent tax template is on the map. + self._map_tax_template(cr, uid, wizard, tax_template_mapping, + tax_template.parent_id, context) + + # + # Ensure the referenced tax codes are on the map. + # + tax_code_templates_to_find = [ + tax_template.base_code_id, + tax_template.tax_code_id, + tax_template.ref_base_code_id, + tax_template.ref_tax_code_id + ] + for tax_code_template in [tmpl for tmpl in tax_code_templates_to_find if tmpl]: + self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template) + + # + # Values + # + vals_tax = { + 'name': tax_template.name, + 'sequence': tax_template.sequence, + 'amount': tax_template.amount, + 'type': tax_template.type, + 'applicable_type': tax_template.applicable_type, + 'domain': tax_template.domain, + 'parent_id': tax_template.parent_id and tax_template_mapping.get(tax_template.parent_id.id), + 'child_depend': tax_template.child_depend, + 'python_compute': tax_template.python_compute, + 'python_compute_inv': tax_template.python_compute_inv, + 'python_applicable': tax_template.python_applicable, + #'tax_group': tax_template.tax_group, + 'base_code_id': tax_template.base_code_id and tax_code_template_mapping.get(tax_template.base_code_id.id), + 'tax_code_id': tax_template.tax_code_id and tax_code_template_mapping.get(tax_template.tax_code_id.id), + 'base_sign': tax_template.base_sign, + 'tax_sign': tax_template.tax_sign, + 'ref_base_code_id': tax_template.ref_base_code_id and tax_code_template_mapping.get(tax_template.ref_base_code_id.id), + 'ref_tax_code_id': tax_template.ref_tax_code_id and tax_code_template_mapping.get(tax_template.ref_tax_code_id.id), + 'ref_base_sign': tax_template.ref_base_sign, + 'ref_tax_sign': tax_template.ref_tax_sign, + 'include_base_amount': tax_template.include_base_amount, + 'description': tax_template.description, + 'company_id': wizard.company_id.id, + 'type_tax_use': tax_template.type_tax_use + } + + tax_id = None + modified = False + + if wiz_tax.type == 'new': + # + # Create a new tax. + # + tax_id = taxes.create(cr, uid, vals_tax) + log.add(_("Created tax %s.\n") % tax_template.name) + new_taxes += 1 + modified = True + elif wizard.update_tax and wiz_tax.update_tax_id: + # + # Update a tax. + # + tax_id = wiz_tax.update_tax_id.id + taxes.write(cr, uid, [tax_id], vals_tax) + log.add(_("Updated tax %s.\n") % tax_template.name) + updated_taxes += 1 + modified = True + else: + tax_id = wiz_tax.update_tax_id and wiz_tax.update_tax_id.id + + # Update the tax template map + tax_template_mapping[tax_template.id] = tax_id + + if modified: + # + # Add to the dict of taxes waiting for accounts. + # + taxes_pending_for_accounts[tax_id] = { + 'account_collected_id': tax_template.account_collected_id and tax_template.account_collected_id.id or False, + 'account_paid_id': tax_template.account_paid_id and tax_template.account_paid_id.id or False, + } + + # + # Detect errors + # + if tax_template.parent_id and not tax_template_mapping.get(tax_template.parent_id.id): + log.add(_("Tax %s: The parent tax %s can not be set.\n") % (tax_template.name, tax_template.parent_id.name), True) + if tax_template.base_code_id and not tax_code_template_mapping.get(tax_template.base_code_id.id): + log.add(_("Tax %s: The tax code for the base %s can not be set.\n") % (tax_template.name, tax_template.base_code_id.name), True) + if tax_template.tax_code_id and not tax_code_template_mapping.get(tax_template.tax_code_id.id): + log.add(_("Tax %s: The tax code for the tax %s can not be set.\n") % (tax_template.name, tax_template.tax_code_id.name), True) + if tax_template.ref_base_code_id and not tax_code_template_mapping.get(tax_template.ref_base_code_id.id): + log.add(_("Tax %s: The tax code for the base refund %s can not be set.\n") % (tax_template.name, tax_template.ref_base_code_id.name), True) + if tax_template.ref_tax_code_id and not tax_code_template_mapping.get(tax_template.ref_tax_code_id.id): + log.add(_("Tax %s: The tax code for the tax refund %s can not be set.\n") % (tax_template.name, tax_template.ref_tax_code_id.name), True) + + return { + 'new': new_taxes, + 'updated': updated_taxes, + 'mapping': tax_template_mapping, + 'pending': taxes_pending_for_accounts + } + + """ + Updates the parent_id of accounts that seem to be children of the + given account (accounts that start with the same code and are brothers + of the first account). + """ + def _update_children_accounts_parent(self, cr, uid, wizard, log, parent_account_id, context=None): + account_account = self.pool.get('account.account') + parent_account = account_account.browse( + cr, uid, parent_account_id, context=context) + + if not parent_account.parent_id or not parent_account.code: + return False + + children_ids = account_account.search(cr, uid, [ + ('company_id', '=', + parent_account.company_id and parent_account.company_id.id), + ('parent_id', '=', parent_account.parent_id.id), + ('code', '=like', "%s%%" % parent_account.code), + ('id', '!=', parent_account.id), + ], context=context) + + if children_ids: + try: + account_account.write(cr, uid, children_ids, {'parent_id': + parent_account.id}, context=context) + except orm.except_orm, ex: + log.add(_("Exception setting the parent of account %s children: %s - %s.\n") % (parent_account.code, ex.name, ex.value), True) + + return True + + """ + Search for, and load, account templates to create/update. + """ + def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=None): + accounts = self.pool.get('account.account') + root_account_id = wizard.chart_template_id.account_root_id.id + + # Disable the parent_store computing on account_account during the batch + # processing, we will force _parent_store_compute afterwards. + self.pool._init = True + new_accounts = 0 + updated_accounts = 0 + account_template_mapping = {} + + for wiz_account in wizard.account_ids: + account_template = wiz_account.account_id + + # Ensure the parent account template is on the map. + self._map_account_template(cr, uid, wizard, account_template_mapping, account_template.parent_id, context) + + # + # Ensure the related tax templates are on the map. + # + for tax_template in account_template.tax_ids: + self._map_tax_template(cr, uid, wizard, tax_template_mapping, + tax_template, context) + + # Get the tax ids + tax_ids = [tax_template_mapping[tax_template.id] for tax_template in account_template.tax_ids if tax_template_mapping[tax_template.id]] + + # + # Calculate the account code (we need to add zeros to non-view + # account codes) + # + code = account_template.code or '' + if account_template.type != 'view': + if len(code) > 0 and len(code) <= wizard.code_digits: + code = '%s%s' % ( + code, '0' * (wizard.code_digits - len(code))) + + # + # Values + # + vals = { + 'name': (root_account_id == account_template.id) and wizard.company_id.name or account_template.name, + #'sign': account_template.sign, + 'currency_id': account_template.currency_id and account_template.currency_id.id or False, + 'code': code, + 'type': account_template.type, + 'user_type': account_template.user_type and account_template.user_type.id or False, + 'reconcile': account_template.reconcile, + 'shortcut': account_template.shortcut, + 'note': account_template.note, + 'parent_id': account_template.parent_id and account_template_mapping.get(account_template.parent_id.id) or False, + 'tax_ids': [(6, 0, tax_ids)], + 'company_id': wizard.company_id.id, + } + + account_id = None + modified = False + + if wiz_account.type == 'new': + # + # Create the account + # + try: + account_id = accounts.create(cr, uid, vals) + log.add(_("Created account %s.\n") % code) + new_accounts += 1 + modified = True + except orm.except_orm, ex: + log.add(_("Exception creating account %s: %s - %s.\n") + % (code, ex.name, ex.value), True) + elif wizard.update_account and wiz_account.update_account_id: + # + # Update the account + # + account_id = wiz_account.update_account_id.id + try: + accounts.write(cr, uid, [account_id], vals) + log.add(_("Updated account %s.\n") % code) + updated_accounts += 1 + modified = True + except orm.except_orm, ex: + log.add(_("Exception writing account %s: %s - %s.\n") + % (code, ex.name, ex.value), True) + else: + account_id = wiz_account.update_account_id and wiz_account.update_account_id.id + + # Store the account on the map + account_template_mapping[account_template.id] = account_id + + if modified: + # + # Detect errors + # + if account_template.parent_id and not account_template_mapping.get(account_template.parent_id.id): + log.add(_("Account %s: The parent account %s can not be set.\n") % (code, account_template.parent_id.code), True) + + # + # Set this account as the parent of the accounts that seem to + # be its children (brothers starting with the same code). + # + if wizard.update_children_accounts_parent: + self._update_children_accounts_parent( + cr, uid, wizard, log, account_id, context=context) + + # + # Reenable the parent_store computing on account_account + # and force the recomputation. + # + self.pool._init = False + self.pool.get('account.account')._parent_store_compute(cr) + + return { + 'new': new_accounts, + 'updated': updated_accounts, + 'mapping': account_template_mapping + } + + """ + Updates the taxes (created or updated on previous steps) to set + the references to the accounts (the taxes where created/updated first, + when the referenced accounts where still not available). + """ + def _update_taxes_pending_for_accounts(self, cr, uid, wizard, log, taxes_pending_for_accounts, account_template_mapping, context=None): + taxes = self.pool.get('account.tax') + accounts_template = self.pool.get('account.account.template') + + for key, value in taxes_pending_for_accounts.items(): + # + # Ensure the related account templates are on the map. + # + if value['account_collected_id']: + account_template = accounts_template.browse( + cr, uid, value['account_collected_id'], context=context) + self._map_account_template(cr, uid, wizard, account_template_mapping, account_template, context) + if value['account_paid_id']: + account_template = accounts_template.browse( + cr, uid, value['account_paid_id'], context=context) + self._map_account_template(cr, uid, wizard, account_template_mapping, account_template, context) + + if value['account_collected_id'] or value['account_paid_id']: + if account_template_mapping.get(value['account_collected_id']) and account_template_mapping.get(value['account_paid_id']): + vals = { + 'account_collected_id': account_template_mapping[value['account_collected_id']], + 'account_paid_id': account_template_mapping[value['account_paid_id']], + } + taxes.write(cr, uid, [key], vals) + else: + tax = taxes.browse(cr, uid, key) + if not account_template_mapping.get(value['account_collected_id']): + log.add(_("Tax %s: The collected account can not be set.\n") % (tax.name), True) + if not account_template_mapping.get(value['account_paid_id']): + log.add(_("Tax %s: The paid account can not be set.\n") + % (tax.name), True) + + """ + Search for, and load, fiscal position templates to create/update. + """ + def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, account_template_mapping, context=None): + fiscalpositions = self.pool.get('account.fiscal.position') + fiscalpositions_taxes = self.pool.get('account.fiscal.position.tax') + fiscalpositions_account = self.pool.get('account.fiscal.position.account') + + new_fps = 0 + updated_fps = 0 + + for wiz_fp in wizard.fiscal_position_ids: + fp_template = wiz_fp.fiscal_position_id + fp_id = None + modified = False + if wiz_fp.type == 'new': + # + # Create a new fiscal position + # + vals_fp = { + 'company_id': wizard.company_id.id, + 'name': fp_template.name, + } + fp_id = fiscalpositions.create(cr, uid, vals_fp) + new_fps += 1 + modified = True + elif wizard.update_fiscal_position and wiz_fp.update_fiscal_position_id: + # + # Update the given fiscal position (remove the tax and account + # mappings, that will be regenerated later) + # + fp_id = wiz_fp.update_fiscal_position_id.id + updated_fps += 1 + modified = True + # Remove the tax mappings + fp_tax_ids = fiscalpositions_taxes.search( + cr, uid, [('position_id', '=', fp_id)]) + fiscalpositions_taxes.unlink(cr, uid, fp_tax_ids) + # Remove the account mappings + fp_account_ids = fiscalpositions_account.search( + cr, uid, [('position_id', '=', fp_id)]) + fiscalpositions_account.unlink(cr, uid, fp_account_ids) + else: + fp_id = wiz_fp.update_fiscal_position_id and wiz_fp.update_fiscal_position_id.id + + if modified: + # + # (Re)create the tax mappings + # + for fp_tax in fp_template.tax_ids: + # + # Ensure the related tax templates are on the map. + # + self._map_tax_template(cr, uid, wizard, tax_template_mapping, fp_tax.tax_src_id, context) + if fp_tax.tax_dest_id: + self._map_tax_template(cr, uid, wizard, tax_template_mapping, fp_tax.tax_dest_id, context) + + # + # Create the fp tax mapping + # + vals_tax = { + 'tax_src_id': tax_template_mapping.get(fp_tax.tax_src_id.id), + 'tax_dest_id': fp_tax.tax_dest_id and tax_template_mapping.get(fp_tax.tax_dest_id.id), + 'position_id': fp_id, + } + fiscalpositions_taxes.create(cr, uid, vals_tax) + + # + # Check for errors + # + if not tax_template_mapping.get(fp_tax.tax_src_id.id): + log.add(_("Fiscal position %s: The source tax %s can not be set.\n") % (fp_template.name, fp_tax.tax_src_id.code), True) + if fp_tax.tax_dest_id and not tax_template_mapping.get(fp_tax.tax_dest_id.id): + log.add(_("Fiscal position %s: The destination tax %s can not be set.\n") % (fp_template.name, fp_tax.tax_dest_id.name), True) + # + # (Re)create the account mappings + # + for fp_account in fp_template.account_ids: + # + # Ensure the related account templates are on the map. + # + self._map_account_template(cr, uid, wizard, account_template_mapping, fp_account.account_src_id, context) + if fp_account.account_dest_id: + self._map_account_template(cr, uid, wizard, account_template_mapping, fp_account.account_dest_id, context) + + # + # Create the fp account mapping + # + vals_account = { + 'account_src_id': account_template_mapping.get(fp_account.account_src_id.id), + 'account_dest_id': fp_account.account_dest_id and account_template_mapping.get(fp_account.account_dest_id.id), + 'position_id': fp_id, + } + fiscalpositions_account.create(cr, uid, vals_account) + + # + # Check for errors + # + if not account_template_mapping.get(fp_account.account_src_id.id): + log.add(_("Fiscal position %s: The source account %s can not be set.\n") % (fp_template.name, fp_account.account_src_id.code), True) + if fp_account.account_dest_id and not account_template_mapping.get(fp_account.account_dest_id.id): + log.add(_("Fiscal position %s: The destination account %s can not be set.\n") % (fp_template.name, fp_account.account_dest_id.code), True) + + log.add(_("Created or updated fiscal position %s.\n") + % fp_template.name) + return {'new': new_fps, 'updated': updated_fps} + + """ + Action that creates/updates the selected elements. + """ + def action_update_records(self, cr, uid, ids, context=None): + if context is None: + context = {} + wizard = self.browse(cr, uid, ids[0], context=context) + + if wizard.lang: + context['lang'] = wizard.lang + elif context.get('lang'): + del context['lang'] + + log = WizardLog() + + # + # Create or update the records. + # + tax_codes_res = self._update_tax_codes( + cr, uid, wizard, log, context=context) + taxes_res = self._update_taxes( + cr, uid, wizard, log, tax_codes_res['mapping'], context=context) + accounts_res = self._update_accounts( + cr, uid, wizard, log, taxes_res['pending'], context=context) + self._update_taxes_pending_for_accounts(cr, uid, wizard, log, taxes_res['pending'], accounts_res['mapping'], context=context) + fps_res = self._update_fiscal_positions(cr, uid, wizard, log, taxes_res['mapping'], accounts_res['mapping'], context=context) + + # + # Check if errors where detected and wether we should stop. + # + if log.has_errors() and not wizard.continue_on_errors: + raise orm.except_orm(_('Error'), _( + "One or more errors detected!\n\n%s") % log.get_errors_str()) + + # + # Store the data and go to the next step. + # + self.write(cr, uid, [wizard.id], { + 'state': 'done', + 'new_tax_codes': tax_codes_res.get('new', 0), + 'new_taxes': taxes_res.get('new', 0), + 'new_accounts': accounts_res .get('new', 0), + 'new_fps': fps_res.get('new', 0), + 'updated_tax_codes': tax_codes_res.get('updated', 0), + 'updated_taxes': taxes_res.get('updated', 0), + 'updated_accounts': accounts_res.get('updated', 0), + 'updated_fps': fps_res.get('updated', 0), + 'log': log(), + }, context) + + return _reopen(self, wizard.id, 'wizard.update.chart.accounts') + +wizard_update_charts_accounts() + + +class wizard_update_charts_accounts_tax_code(orm.TransientModel): + """ + ****************************************************************** + Tax code that needs to be updated (new or updated in the template). + ****************************************************************** + """ + _name = 'wizard.update.charts.accounts.tax.code' + _columns = { + 'tax_code_id': fields.many2one('account.tax.code.template', 'Tax code template', required=True, ondelete='set null'), + 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'type': fields.selection([ + ('new', 'New template'), + ('updated', 'Updated template'), + ], 'Type'), + 'update_tax_code_id': fields.many2one('account.tax.code', 'Tax code to update', required=False, ondelete='set null'), + 'notes': fields.text('Notes'), + } + _defaults = { + } + +wizard_update_charts_accounts_tax_code() + + +class wizard_update_charts_accounts_tax(orm.TransientModel): + """ + ************************************************************** + Tax that needs to be updated (new or updated in the template). + ************************************************************** + """ + _name = 'wizard.update.charts.accounts.tax' + _columns = { + 'tax_id': fields.many2one('account.tax.template', 'Tax template', required=True, ondelete='set null'), + 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'type': fields.selection([ + ('new', 'New template'), + ('updated', 'Updated template'), + ], 'Type'), + 'update_tax_id': fields.many2one('account.tax', 'Tax to update', required=False, ondelete='set null'), + 'notes': fields.text('Notes'), + } + + _defaults = { + } + +wizard_update_charts_accounts_tax() + + +class wizard_update_charts_accounts_account(orm.TransientModel): + """ + ****************************************************************** + Account that needs to be updated (new or updated in the template). + ******************************************************************* + """ + _name = 'wizard.update.charts.accounts.account' + # The chart of accounts can have a lot of accounts, so we need an higher + # limit for the objects in memory to let the wizard create all the items + # at once. + _max_count = 4096 + _columns = { + 'account_id': fields.many2one('account.account.template', 'Account template', required=True, ondelete='set null'), + 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'type': fields.selection([ + ('new', 'New template'), + ('updated', 'Updated template'), + ], 'Type'), + 'update_account_id': fields.many2one('account.account', 'Account to update', required=False, ondelete='set null'), + 'notes': fields.text('Notes'), + } + + _defaults = { + } + +wizard_update_charts_accounts_account() + + +class wizard_update_charts_accounts_fiscal_position(orm.TransientModel): + """ + ************************************************************************** + Fiscal position that needs to be updated (new or updated in the template). + ************************************************************************** + """ + _name = 'wizard.update.charts.accounts.fiscal.position' + _columns = { + 'fiscal_position_id': fields.many2one('account.fiscal.position.template', 'Fiscal position template', required=True, ondelete='set null'), + 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'type': fields.selection([ + ('new', 'New template'), + ('updated', 'Updated template'), + ], 'Type'), + 'update_fiscal_position_id': fields.many2one('account.fiscal.position', 'Fiscal position to update', required=False, ondelete='set null'), + 'notes': fields.text('Notes'), + } + _defaults = { + } + + +wizard_update_charts_accounts_fiscal_position() + +# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_chart_update/wizard/wizard_chart_update_view.xml b/account_chart_update/wizard/wizard_chart_update_view.xml new file mode 100644 index 00000000000..66e76dbc461 --- /dev/null +++ b/account_chart_update/wizard/wizard_chart_update_view.xml @@ -0,0 +1,176 @@ + + + + + + + + Update Chart of Accounts from a Chart Template + + wizard.update.charts.accounts + + +
+
+ +
+ +

+

This wizard will update your accounts, taxes and fiscal positions according to the selected chart template

+ +

+
+ + + + + + + + + + + + + + + + + + + + +
+

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)

+

Note:Not all the fields are tested for changes, just the main ones

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + +
+
+
+ + + + + + + +
+ + + + + + +
+
+
+ + + + + + + +
+ + + + + + +
+
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+ +
+
+ + + Update Chart of Accounts from a Chart Template + + ir.actions.act_window + wizard.update.charts.accounts + form + form + new + + + + +
+
From dcfd81d0e1493cf609b384a46a9fc92e7bc9423d Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Tue, 15 Oct 2013 16:28:59 +0200 Subject: [PATCH 02/86] [IMP] account_chart_update: Menu path to avoid needing multi-company permission. --- account_chart_update/__openerp__.py | 2 +- account_chart_update/wizard/wizard_chart_update_view.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/account_chart_update/__openerp__.py b/account_chart_update/__openerp__.py index 79b16c0879c..860606f0cac 100644 --- a/account_chart_update/__openerp__.py +++ b/account_chart_update/__openerp__.py @@ -31,7 +31,7 @@ 'website': "www.zikzakmedia.com", 'depends': ["account"], 'category': "Generic Modules/Accounting", - 'contributors': ['Joaquin Gutierrez', 'Pedro M. Baeza'], + 'contributors': ['Joaquín Gutierrez', 'Pedro M. Baeza', 'invitu'], 'description': """ Adds a wizard to update a company account chart from a chart template. ====================================================================== diff --git a/account_chart_update/wizard/wizard_chart_update_view.xml b/account_chart_update/wizard/wizard_chart_update_view.xml index 66e76dbc461..1705eb45df2 100644 --- a/account_chart_update/wizard/wizard_chart_update_view.xml +++ b/account_chart_update/wizard/wizard_chart_update_view.xml @@ -170,7 +170,7 @@ new - + From 83c5c74a7a1e8a26892f5f0fcb198099fbd00310 Mon Sep 17 00:00:00 2001 From: Invitu Date: Fri, 18 Oct 2013 06:44:19 -1000 Subject: [PATCH 03/86] [IMP] small improvement : calling reopen method in action_init + indentation --- .../wizard/wizard_chart_update.py | 101 +++++++----------- 1 file changed, 36 insertions(+), 65 deletions(-) diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index e4801373f0b..0ce1274ee77 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -96,9 +96,9 @@ def _get_lang_selection_options(self, cr, uid, context={}): _columns = { 'state': fields.selection([ - ('init', 'Step 1'), - ('ready', 'Step 2'), - ('done', 'Wizard Complete') + ('init', 'Step 1'), + ('ready', 'Step 2'), + ('done', 'Wizard completed') ], 'Status', readonly=True), 'company_id': fields.many2one('res.company', 'Company', required=True, ondelete='set null'), 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True, ondelete='set null'), @@ -125,9 +125,7 @@ def _get_lang_selection_options(self, cr, uid, context={}): 'updated_fps': fields.integer('Updated fiscal positions', readonly=True), 'log': fields.text('Messages and Errors', readonly=True) } - """ - Redefine the search to search by company name. - """ + def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): if not name: @@ -183,29 +181,24 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): if not company_id: user = self.pool.get('res.users').browse(cr, uid, uid, context) company_id = user.company_id.id - property_ids = property_obj.search( - cr, - uid, - [('name', '=', 'property_account_receivable'), - ('company_id', '=', company_id), - ('res_id', '=', False), - ('value_reference', '!=', False) - ]) + property_ids = property_obj.search(cr, uid, [ + ('name', '=', 'property_account_receivable'), + ('company_id', '=', company_id), + ('res_id', '=', False), + ('value_reference', '!=', False) + ]) if not property_ids: # Try to get a generic (no-company) property - property_ids = property_obj.search( - cr, - uid, - [('name', '=', 'property_account_receivable'), - ('res_id', '=', False), - ('value_reference', '!=', False) - ]) - number_digits = 6 + property_ids = property_obj.search(cr, uid, [ + ('name', '=', 'property_account_receivable'), + ('res_id', '=', False), + ('value_reference', '!=', False) + ]) + number_digits = 6 if property_ids: prop = property_obj.browse( cr, uid, property_ids[0], context=context) account_id = prop.value_reference.id - if account_id: code = account_obj.read( cr, uid, account_id, ['code'], context)['code'] @@ -231,13 +224,9 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): def onchange_company_id(self, cr, uid, ids, company_id, context=None): res = { 'value': { - 'code_digits': self._get_code_digits( - cr, - uid, - context=context, - company_id=company_id), - } - } + 'code_digits': self._get_code_digits(cr, uid, context=context, company_id=company_id), + } + } return res """ @@ -248,22 +237,7 @@ def action_init(self, cr, uid, ids, context=None): context = {} wizard = self.browse(cr, uid, ids[0], context=context) self.write(cr, uid, ids, {'state': 'init'}, context) - view_wizard = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'account_chart_update', 'view_update_multi_chart') - view_wizard_id = view_wizard and view_wizard[1] or False, - res = { - 'type': 'ir.actions.act_window', - 'name': _("Update Chart of Accounts from a Chart Template "), - 'res_model': 'wizard.update.charts.accounts', - 'view_type': 'form', - 'view_mode': 'form', - 'res_id': wizard.id, - 'view_id': view_wizard_id, - 'context': context, - 'target': 'new', - } - return res - - return True + return _reopen(self, wizard.id, 'wizard.update.chart.accounts') ########################################################################## # Helper methods @@ -397,13 +371,11 @@ def _find_tax_codes(self, cr, uid, wizard, context=None): }, context) return { - 'new': new_tax_codes, - 'updated': updated_tax_codes, - 'mapping': tax_code_template_mapping - } - """ - Search for, and load, tax templates to create/update. - """ + 'new': new_tax_codes, + 'updated': updated_tax_codes, + 'mapping': tax_code_template_mapping + } + def _find_taxes(self, cr, uid, wizard, context=None): new_taxes = 0 updated_taxes = 0 @@ -924,8 +896,7 @@ def _update_children_accounts_parent(self, cr, uid, wizard, log, parent_account_ if children_ids: try: - account_account.write(cr, uid, children_ids, {'parent_id': - parent_account.id}, context=context) + account_account.write(cr, uid, children_ids, {'parent_id': parent_account.id}, context=context) except orm.except_orm, ex: log.add(_("Exception setting the parent of account %s children: %s - %s.\n") % (parent_account.code, ex.name, ex.value), True) @@ -1110,7 +1081,7 @@ def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, a vals_fp = { 'company_id': wizard.company_id.id, 'name': fp_template.name, - } + } fp_id = fiscalpositions.create(cr, uid, vals_fp) new_fps += 1 modified = True @@ -1261,8 +1232,8 @@ class wizard_update_charts_accounts_tax_code(orm.TransientModel): 'tax_code_id': fields.many2one('account.tax.code.template', 'Tax code template', required=True, ondelete='set null'), 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), 'type': fields.selection([ - ('new', 'New template'), - ('updated', 'Updated template'), + ('new', 'New template'), + ('updated', 'Updated template'), ], 'Type'), 'update_tax_code_id': fields.many2one('account.tax.code', 'Tax code to update', required=False, ondelete='set null'), 'notes': fields.text('Notes'), @@ -1284,8 +1255,8 @@ class wizard_update_charts_accounts_tax(orm.TransientModel): 'tax_id': fields.many2one('account.tax.template', 'Tax template', required=True, ondelete='set null'), 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), 'type': fields.selection([ - ('new', 'New template'), - ('updated', 'Updated template'), + ('new', 'New template'), + ('updated', 'Updated template'), ], 'Type'), 'update_tax_id': fields.many2one('account.tax', 'Tax to update', required=False, ondelete='set null'), 'notes': fields.text('Notes'), @@ -1312,8 +1283,8 @@ class wizard_update_charts_accounts_account(orm.TransientModel): 'account_id': fields.many2one('account.account.template', 'Account template', required=True, ondelete='set null'), 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), 'type': fields.selection([ - ('new', 'New template'), - ('updated', 'Updated template'), + ('new', 'New template'), + ('updated', 'Updated template'), ], 'Type'), 'update_account_id': fields.many2one('account.account', 'Account to update', required=False, ondelete='set null'), 'notes': fields.text('Notes'), @@ -1336,9 +1307,9 @@ class wizard_update_charts_accounts_fiscal_position(orm.TransientModel): 'fiscal_position_id': fields.many2one('account.fiscal.position.template', 'Fiscal position template', required=True, ondelete='set null'), 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), 'type': fields.selection([ - ('new', 'New template'), - ('updated', 'Updated template'), - ], 'Type'), + ('new', 'New template'), + ('updated', 'Updated template'), + ], 'Type'), 'update_fiscal_position_id': fields.many2one('account.fiscal.position', 'Fiscal position to update', required=False, ondelete='set null'), 'notes': fields.text('Notes'), } From f88d415142bdfdfc4f241571a2d3e3363bcb14a5 Mon Sep 17 00:00:00 2001 From: Yann Papouin Date: Wed, 27 Nov 2013 15:36:05 +0100 Subject: [PATCH 04/86] FIX: wrong dict passed in _update_accounts --- account_chart_update/wizard/wizard_chart_update.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index 0ce1274ee77..604836ab929 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -1189,7 +1189,7 @@ def action_update_records(self, cr, uid, ids, context=None): taxes_res = self._update_taxes( cr, uid, wizard, log, tax_codes_res['mapping'], context=context) accounts_res = self._update_accounts( - cr, uid, wizard, log, taxes_res['pending'], context=context) + cr, uid, wizard, log, taxes_res['mapping'], context=context) self._update_taxes_pending_for_accounts(cr, uid, wizard, log, taxes_res['pending'], accounts_res['mapping'], context=context) fps_res = self._update_fiscal_positions(cr, uid, wizard, log, taxes_res['mapping'], accounts_res['mapping'], context=context) From 3e5d4a173cb2969cad1cb8bb723a4d57eb837ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Tue, 7 Jan 2014 12:48:24 +0100 Subject: [PATCH 05/86] [IMP] attempt to match tax code on code if no match on name was found --- account_chart_update/__openerp__.py | 11 ++++++++--- account_chart_update/wizard/wizard_chart_update.py | 9 +++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/account_chart_update/__openerp__.py b/account_chart_update/__openerp__.py index 860606f0cac..fc619522f6e 100644 --- a/account_chart_update/__openerp__.py +++ b/account_chart_update/__openerp__.py @@ -26,12 +26,17 @@ { 'name': "Detect changes and update the Account Chart from a template", - 'version': "1.0", + 'version': "1.1", 'author': "Zikzakmedia SL", 'website': "www.zikzakmedia.com", 'depends': ["account"], 'category': "Generic Modules/Accounting", - 'contributors': ['Joaquín Gutierrez', 'Pedro M. Baeza', 'invitu'], + 'contributors': [ + 'Joaquín Gutierrez', + 'Pedro M. Baeza', + 'invitu', + 'Stéphane Bidoul', + ], 'description': """ Adds a wizard to update a company account chart from a chart template. ====================================================================== @@ -60,7 +65,7 @@ "account", "base", ], - "demo" : [], + "demo": [], "data": [ 'wizard/wizard_chart_update_view.xml', ], diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index 604836ab929..7389cbf2dba 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -267,6 +267,15 @@ def _map_tax_code_template(self, cr, uid, wizard, tax_code_template_mapping, tax ('name', '=', tax_code_name), ('company_id', '=', wizard.company_id.id) ]) + if not tax_code_ids: + # if we could not match no tax code template name, + # try to match on tax code template code, if any + tax_code_code = tax_code_template.code + if tax_code_code: + tax_code_ids = tax_codes.search(cr, uid, [ + ('code', '=', tax_code_code), + ('company_id', '=', wizard.company_id.id) + ]) if tax_code_ids: tax_code_template_mapping[ tax_code_template.id] = tax_code_ids[0] From e3de4cbc1de95d13cbe3c20fa365ee1bc461e062 Mon Sep 17 00:00:00 2001 From: "Pedro M. Baeza" Date: Fri, 21 Mar 2014 02:01:05 +0100 Subject: [PATCH 06/86] [FIX] account_chart_update: Selection of operations to do now is working. [FIX] account_chart_update: Adapted to work with inherited account chart templates. [FIX] account_chart_update: Remove required=True for chart_template_id on DB and put on screen to avoid error when removing chart templates. [FIX] account_chart_update: Change method to compare taxes of fiscal positions to match with the one comparing taxes. [FIX] account_chart_update: Change method to compare accounts of fiscal positions to match with the one comparing accounts. [IMP] account_chart_update: Wizard now shows in tree view modification notes. [IMP] account_chart_update: For new data to be created, it is marked on notes the reason for the creation (just for clarity). [IMP] account_chart_update: Tabs for operations that are not going to be performed are hidden. [IMP] account_chart_update: Some PEP8 here and there. [IMP] account_chart_update: Enhance a little the mapping searches (there's more room to improve). [IMP] account_chart_update: Now it takes into account name and description for mapping taxes. --- .../wizard/wizard_chart_update.py | 757 ++++++++++-------- .../wizard/wizard_chart_update_view.xml | 233 +++--- 2 files changed, 505 insertions(+), 485 deletions(-) diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index 7389cbf2dba..be17b466956 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -101,8 +101,10 @@ def _get_lang_selection_options(self, cr, uid, context={}): ('done', 'Wizard completed') ], 'Status', readonly=True), 'company_id': fields.many2one('res.company', 'Company', required=True, ondelete='set null'), - 'chart_template_id': fields.many2one('account.chart.template', 'Chart Template', required=True, ondelete='set null'), - 'code_digits': fields.integer('# of Digits', required=True, help="No. of Digits to use for account code. Make sure it is the same number as existing accounts."), + 'chart_template_id': fields.many2one( + 'account.chart.template', 'Chart Template', ondelete='cascade', + required=True), + 'code_digits': fields.integer('# of digits', required=True, help="No. of digits to use for account code. Make sure it is the same number as existing accounts."), 'lang': fields.selection(_get_lang_selection_options, 'Language', size=5, help="For records searched by name (taxes, tax codes, fiscal positions), the template name will be matched against the record name on this language."), 'update_tax_code': fields.boolean('Update tax codes', help="Existing tax codes are updated. Tax codes are searched by name."), 'update_tax': fields.boolean('Update taxes', help="Existing taxes are updated. Taxes are searched by name."), @@ -242,108 +244,141 @@ def action_init(self, cr, uid, ids, context=None): ########################################################################## # Helper methods ########################################################################## - """ - Adds a tax template -> tax id to the mapping. - """ - def _map_tax_template(self, cr, uid, wizard, tax_template_mapping, tax_template, context=None): - if tax_template and not tax_template_mapping.get(tax_template.id): - taxes = self.pool.get('account.tax') - tax_ids = taxes.search(cr, uid, [ - ('name', '=', tax_template.name), - ('company_id', '=', wizard.company_id.id) - ], context=context) - if tax_ids: - tax_template_mapping[tax_template.id] = tax_ids[0] - """ - Adds a tax code template -> tax code id to the mapping. - """ - def _map_tax_code_template(self, cr, uid, wizard, tax_code_template_mapping, tax_code_template, context=None): - if tax_code_template and not tax_code_template_mapping.get(tax_code_template.id): - tax_codes = self.pool.get('account.tax.code') - root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id - tax_code_name = (tax_code_template.id == root_tax_code_id) and wizard.company_id.name or tax_code_template.name - tax_code_ids = tax_codes.search(cr, uid, [ - ('name', '=', tax_code_name), - ('company_id', '=', wizard.company_id.id) - ]) - if not tax_code_ids: - # if we could not match no tax code template name, - # try to match on tax code template code, if any - tax_code_code = tax_code_template.code - if tax_code_code: - tax_code_ids = tax_codes.search(cr, uid, [ - ('code', '=', tax_code_code), - ('company_id', '=', wizard.company_id.id) - ]) - if tax_code_ids: - tax_code_template_mapping[ - tax_code_template.id] = tax_code_ids[0] - - """ - Adds an account template -> account id to the mapping - """ - def _map_account_template(self, cr, uid, wizard, account_template_mapping, account_template, context=None): - if account_template and not account_template_mapping.get(account_template.id): - accounts = self.pool.get('account.account') - code = account_template.code or '' - if account_template.type != 'view': - if len(code) > 0 and len(code) <= wizard.code_digits: - code = '%s%s' % ( - code, '0' * (wizard.code_digits - len(code))) - account_ids = accounts.search(cr, uid, [ - ('code', '=', code), - ('company_id', '=', wizard.company_id.id) - ], context=context) - if account_ids: - account_template_mapping[account_template.id] = account_ids[0] - """ - Adds a fiscal position template -> fiscal position id to the mapping. - """ - def _map_fp_template(self, cr, uid, wizard, fp_template_mapping, fp_template, context=None): - if fp_template and not fp_template_mapping.get(fp_template.id): - fiscalpositions = self.pool.get('account.fiscal.position') - fp_ids = fiscalpositions.search(cr, uid, [ - ('name', '=', fp_template.name), - ('company_id', '=', wizard.company_id.id) - ], context=context) - if fp_ids: - fp_template_mapping[fp_template.id] = fp_ids[0] - - """ - Search for, and load, tax code templates to create/update. - """ - def _find_tax_codes(self, cr, uid, wizard, context=None): + def _map_tax_template(self, cr, uid, wizard, tax_templ_mapping, + tax_templ, context=None): + """ + Adds a tax template -> tax id to the mapping. + """ + if not tax_templ: + return False + if tax_templ_mapping.get(tax_templ.id): + return tax_templ_mapping[tax_templ.id] + # In other case + tax_obj = self.pool['account.tax'] + criteria = ['|', + ('name', '=', tax_templ.name), + ('description', '=', tax_templ.name)] + if tax_templ.description: + criteria = (['|', '|'] + criteria + + [('description', '=', tax_templ.description), + ('name', '=', tax_templ.description)]) + tax_ids = tax_obj.search(cr, uid, criteria, context=context) + tax_templ_mapping[tax_templ.id] = tax_ids and tax_ids[0] or False + return tax_templ_mapping[tax_templ.id] + + def _map_tax_code_template(self, cr, uid, wizard, + tax_code_templ_mapping, tax_code_template, + context=None): + """ + Adds a tax code template -> tax code id to the mapping. + """ + if not tax_code_template: + return False + if not wizard.chart_template_id: + return False + if tax_code_templ_mapping.get(tax_code_template.id): + return tax_code_templ_mapping[tax_code_template.id] + # In other case + tax_code_obj = self.pool['account.tax.code'] + root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id + tax_code_name = ((tax_code_template.id == root_tax_code_id) and + wizard.company_id.name or tax_code_template.name) + tax_code_ids = tax_code_obj.search(cr, uid, [ + ('name', '=', tax_code_name), + ('company_id', '=', wizard.company_id.id) + ], context=context) + if not tax_code_ids: + # if we could not match no tax code template name, + # try to match on tax code template code, if any + tax_code_code = tax_code_template.code + if tax_code_code: + tax_code_ids = tax_code_obj.search(cr, uid, [ + ('code', '=', tax_code_code), + ('company_id', '=', wizard.company_id.id) + ], context=context) + tax_code_templ_mapping[tax_code_template.id] = (tax_code_ids and + tax_code_ids[0] or + False) + return tax_code_templ_mapping[tax_code_template.id] + + def _map_account_template(self, cr, uid, wizard, acc_templ_mapping, + acc_templ, context=None): + """ + Adds an account template -> account id to the mapping + """ + if not acc_templ: + return False + if acc_templ_mapping.get(acc_templ.id): + return acc_templ_mapping[acc_templ.id] + # In other case + acc_obj = self.pool['account.account'] + code = acc_templ.code or '' + if acc_templ.type != 'view': + if code and len(code) <= wizard.code_digits: + code = '%s%s' % (code, '0' * (wizard.code_digits - len(code))) + acc_ids = acc_obj.search(cr, uid, [ + ('code', '=', code), + ('company_id', '=', wizard.company_id.id) + ], context=context) + acc_templ_mapping[acc_templ.id] = acc_ids and acc_ids[0] or False + return acc_templ_mapping[acc_templ.id] + + def _map_fp_template(self, cr, uid, wizard, fp_templ_mapping, fp_template, context=None): + """ + Adds a fiscal position template -> fiscal position id to the mapping. + """ + if not fp_template: + return False + if fp_templ_mapping.get(fp_template.id): + return fp_templ_mapping[fp_template.id] + # In other case + fp_obj = self.pool['account.fiscal.position'] + fp_ids = fp_obj.search(cr, uid, + [('name', '=', fp_template.name), + ('company_id', '=', wizard.company_id.id)], + context=context) + fp_templ_mapping[fp_template.id] = fp_ids and fp_ids[0] or False + return fp_templ_mapping[fp_template.id] + + def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, + context=None): + """ + Search for, and load, tax code templates to create/update. + + @param chart_template_ids: IDs of the chart templates to look on, + calculated once in the calling method. + """ + if not wizard.chart_template_id: + return {} new_tax_codes = 0 updated_tax_codes = 0 tax_code_template_mapping = {} - - taxes_codes_templates = self.pool.get('account.tax.code.template') - taxcodes = self.pool.get('account.tax.code') - wiz_taxcodes = self.pool.get('wizard.update.charts.accounts.tax.code') - + tax_code_templ_obj = self.pool['account.tax.code.template'] + tax_code_obj = self.pool['account.tax.code'] + wiz_tax_code_obj = self.pool['wizard.update.charts.accounts.tax.code'] # Remove previous tax codes - wiz_taxcodes.unlink( - cr, uid, wiz_taxcodes.search(cr, uid, [])) - - # + wiz_tax_code_obj.unlink(cr, uid, wiz_tax_code_obj.search(cr, uid, [])) # Search for new / updated tax codes # root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id - children_tax_code_template = taxes_codes_templates.search(cr, uid, [( - 'parent_id', 'child_of', [root_tax_code_id])], order='id') - for tax_code_template in taxes_codes_templates.browse(cr, uid, children_tax_code_template): + children_tax_code_template = tax_code_templ_obj.search(cr, uid, [( + 'parent_id', 'child_of', [root_tax_code_id])], order='id', + context=context) + for tax_code_template in tax_code_templ_obj.browse(cr, uid, + children_tax_code_template, context=context): # Ensure the tax code template is on the map (search for the mapped # tax code id). - self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template, context) - - tax_code_id = tax_code_template_mapping.get(tax_code_template.id) + tax_code_id = self._map_tax_code_template(cr, uid, wizard, + tax_code_template_mapping, + tax_code_template, context=context) if not tax_code_id: new_tax_codes += 1 - wiz_taxcodes.create(cr, uid, { + wiz_tax_code_obj.create(cr, uid, { 'tax_code_id': tax_code_template.id, 'update_chart_wizard_id': wizard.id, 'type': 'new', + 'notes': _('Name or code not found.'), }, context) elif wizard.update_tax_code: # @@ -351,9 +386,8 @@ def _find_tax_codes(self, cr, uid, wizard, context=None): # modified = False notes = "" - tax_code = taxcodes.browse( + tax_code = tax_code_obj.browse( cr, uid, tax_code_id, context=context) - if tax_code.code != tax_code_template.code: notes += _("The code field is different.\n") modified = True @@ -363,59 +397,62 @@ def _find_tax_codes(self, cr, uid, wizard, context=None): if tax_code.sign != tax_code_template.sign: notes += _("The sign field is different.\n") modified = True - # TODO: We could check other account fields for changes... - if modified: # # Tax code to update. # updated_tax_codes += 1 - wiz_taxcodes.create(cr, uid, { + wiz_tax_code_obj.create(cr, uid, { 'tax_code_id': tax_code_template.id, 'update_chart_wizard_id': wizard.id, 'type': 'updated', 'update_tax_code_id': tax_code_id, 'notes': notes, }, context) - return { 'new': new_tax_codes, 'updated': updated_tax_codes, 'mapping': tax_code_template_mapping } - def _find_taxes(self, cr, uid, wizard, context=None): + def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): + """ + Search for, and load, tax templates to create/update. + + @param chart_template_ids: IDs of the chart templates to look on, + calculated once in the calling method. + """ new_taxes = 0 updated_taxes = 0 - tax_template_mapping = {} - - taxes = self.pool.get('account.tax') - wiz_taxes = self.pool.get('wizard.update.charts.accounts.tax') - + tax_templ_mapping = {} + tax_obj = self.pool['account.tax'] + tax_templ_obj = self.pool['account.tax.template'] + wiz_taxes_obj = self.pool['wizard.update.charts.accounts.tax'] delay_wiz_tax = [] # Remove previous taxes - wiz_taxes.unlink(cr, uid, wiz_taxes.search(cr, uid, [])) - - # + wiz_taxes_ids = wiz_taxes_obj.search(cr, uid, [], context=context) + wiz_taxes_obj.unlink(cr, uid, wiz_taxes_ids, context=context) # Search for new / updated taxes - # - for tax_template in wizard.chart_template_id.tax_template_ids: - # Ensure the tax template is on the map (search for the mapped tax - # id). - self._map_tax_template( - cr, uid, wizard, tax_template_mapping, tax_template, context) - - tax_id = tax_template_mapping.get(tax_template.id) + tax_templ_ids = tax_templ_obj.search( + cr, uid, [('chart_template_id', 'in', chart_template_ids)], + context=context) + for tax_templ in tax_templ_obj.browse(cr, uid, tax_templ_ids, + context=context): + # Ensure tax template is on the map (search for the mapped tax id) + tax_id = self._map_tax_template(cr, uid, wizard, + tax_templ_mapping, + tax_templ, context=context) if not tax_id: new_taxes += 1 vals_wiz = { - 'tax_id': tax_template.id, + 'tax_id': tax_templ.id, 'update_chart_wizard_id': wizard.id, 'type': 'new', + 'notes': _('Name or description not found.'), } - if not tax_template.parent_id: - wiz_taxes.create(cr, uid, vals_wiz, context) + if not tax_templ.parent_id: + wiz_taxes_obj.create(cr, uid, vals_wiz, context) else: delay_wiz_tax.append(vals_wiz) elif wizard.update_tax: @@ -424,99 +461,107 @@ def _find_taxes(self, cr, uid, wizard, context=None): # modified = False notes = "" - tax = taxes.browse(cr, uid, tax_id, context=context) - if tax.sequence != tax_template.sequence: + tax = tax_obj.browse(cr, uid, tax_id, context=context) + if tax.sequence != tax_templ.sequence: notes += _("The sequence field is different.\n") modified = True - if tax.amount != tax_template.amount: + if tax.amount != tax_templ.amount: notes += _("The amount field is different.\n") modified = True - if tax.type != tax_template.type: + if tax.type != tax_templ.type: notes += _("The type field is different.\n") modified = True - if tax.applicable_type != tax_template.applicable_type: + if tax.applicable_type != tax_templ.applicable_type: notes += _("The applicable type field is different.\n") modified = True - if tax.domain != tax_template.domain: + if tax.domain != tax_templ.domain: notes += _("The domain field is different.\n") modified = True - if tax.child_depend != tax_template.child_depend: + if tax.child_depend != tax_templ.child_depend: notes += _("The child depend field is different.\n") modified = True - if tax.python_compute != tax_template.python_compute: + if tax.python_compute != tax_templ.python_compute: notes += _("The python compute field is different.\n") modified = True - # if tax.tax_group != tax_template.tax_group: + # if tax.tax_group != tax_templ.tax_group: # notes += _("The tax group field is different.\n") # modified = True - if tax.base_sign != tax_template.base_sign: + if tax.base_sign != tax_templ.base_sign: notes += _("The base sign field is different.\n") modified = True - if tax.tax_sign != tax_template.tax_sign: + if tax.tax_sign != tax_templ.tax_sign: notes += _("The tax sign field is different.\n") modified = True - if tax.include_base_amount != tax_template.include_base_amount: + if tax.include_base_amount != tax_templ.include_base_amount: notes += _("The include base amount field is different.\n") modified = True - if tax.type_tax_use != tax_template.type_tax_use: + if tax.type_tax_use != tax_templ.type_tax_use: notes += _("The type tax use field is different.\n") modified = True # TODO: We could check other tax fields for changes... - if modified: # # Tax code to update. # updated_taxes += 1 - wiz_taxes.create(cr, uid, { - 'tax_id': tax_template.id, + wiz_taxes_obj.create(cr, uid, { + 'tax_id': tax_templ.id, 'update_chart_wizard_id': wizard.id, 'type': 'updated', 'update_tax_id': tax_id, 'notes': notes, }, context) - for delay_vals_wiz in delay_wiz_tax: - wiz_taxes.create(cr, uid, delay_vals_wiz, context) + wiz_taxes_obj.create(cr, uid, delay_vals_wiz, context) - return {'new': new_taxes, 'updated': updated_taxes, 'mapping': tax_template_mapping} + return {'new': new_taxes, 'updated': updated_taxes, 'mapping': tax_templ_mapping} """ Search for, and load, account templates to create/update. """ def _find_accounts(self, cr, uid, wizard, context=None): + """ + Search for, and load, account templates to create/update. + """ + if not wizard.chart_template_id: + return {} new_accounts = 0 updated_accounts = 0 - account_template_mapping = {} - - accounts = self.pool.get('account.account') - accounts_template = self.pool.get('account.account.template') - wiz_accounts = self.pool.get( - 'wizard.update.charts.accounts.account') - + acc_templ_mapping = {} + acc_obj = self.pool['account.account'] + acc_templ_obj = self.pool['account.account.template'] + wiz_accounts = self.pool['wizard.update.charts.accounts.account'] # Remove previous accounts - wiz_accounts.unlink( - cr, uid, wiz_accounts.search(cr, uid, [])) - - # + wiz_accounts_ids = wiz_accounts.search(cr, uid, [], context=context) + wiz_accounts.unlink(cr, uid, wiz_accounts_ids, context=context) # Search for new / updated accounts # root_account_id = wizard.chart_template_id.account_root_id.id - children_acc_template = accounts_template.search(cr, uid, [( - 'parent_id', 'child_of', [root_account_id])], context=context) - children_acc_template.sort() - for account_template in accounts_template.browse(cr, uid, children_acc_template, context=context): + acc_templ_criteria = [('chart_template_id', + '=', + wizard.chart_template_id.id)] + if root_account_id: + acc_templ_criteria = (['|'] + acc_templ_criteria + + ['&', ('parent_id', 'child_of', [root_account_id]), + ('chart_template_id', '=', False)]) + acc_ids = acc_templ_obj.search(cr, uid, acc_templ_criteria, + context=context) + acc_ids.sort() + for acc_templ in acc_templ_obj.browse(cr, uid, acc_ids, + context=context): # Ensure the account template is on the map (search for the mapped # account id). - self._map_account_template(cr, uid, wizard, account_template_mapping, account_template, context) - - account_id = account_template_mapping.get(account_template.id) + account_id = self._map_account_template(cr, uid, wizard, + acc_templ_mapping, + acc_templ, + context=context) if not account_id: new_accounts += 1 wiz_accounts.create(cr, uid, { - 'account_id': account_template.id, + 'account_id': acc_templ.id, 'update_chart_wizard_id': wizard.id, 'type': 'new', + 'notes': _('Code not found.'), }, context) elif wizard.update_account: # @@ -524,141 +569,150 @@ def _find_accounts(self, cr, uid, wizard, context=None): # modified = False notes = "" - account = accounts.browse( - cr, uid, account_id, context=context) - - if account.name != account_template.name and account.name != wizard.company_id.name: + account = acc_obj.browse(cr, uid, account_id, context=context) + if account.name != acc_templ.name and account.name != wizard.company_id.name: notes += _("The name is different.\n") modified = True - if account.type != account_template.type: + if account.type != acc_templ.type: notes += _("The type is different.\n") modified = True - if account.user_type != account_template.user_type: + if account.user_type != acc_templ.user_type: notes += _("The user type is different.\n") modified = True - if account.reconcile != account_template.reconcile: + if account.reconcile != acc_templ.reconcile: notes += _("The reconcile is different.\n") modified = True - # TODO: We could check other account fields for changes... - if modified: # # Account to update. # updated_accounts += 1 wiz_accounts.create(cr, uid, { - 'account_id': account_template.id, + 'account_id': acc_templ.id, 'update_chart_wizard_id': wizard.id, 'type': 'updated', 'update_account_id': account_id, 'notes': notes, }, context) + return { + 'new': new_accounts, + 'updated': updated_accounts, + 'mapping': acc_templ_mapping + } - return {'new': new_accounts, 'updated': updated_accounts, 'mapping': account_template_mapping} - - """ - Search for, and load, fiscal position templates to create/update. - """ - def _find_fiscal_positions(self, cr, uid, wizard, context=None): + def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, + context=None): + """ + Search for, and load, fiscal position templates to create/update. + + @param chart_template_ids: IDs of the chart templates to look on, + calculated once in the calling method. + """ new_fps = 0 updated_fps = 0 - fp_template_mapping = {} - - fiscalpostitions_template = self.pool.get('account.fiscal.position.template') - fiscalpositions = self.pool.get('account.fiscal.position') - wiz_fiscalpositions = self.pool.get( - 'wizard.update.charts.accounts.fiscal.position') - + fp_templ_mapping = {} + tax_templ_mapping = {} + acc_templ_mapping = {} + fp_templ_obj = self.pool['account.fiscal.position.template'] + fp_obj = self.pool['account.fiscal.position'] + wiz_fp = self.pool['wizard.update.charts.accounts.fiscal.position'] # Remove previous fiscal positions - wiz_fiscalpositions.unlink(cr, uid, wiz_fiscalpositions.search(cr, uid, [])) - - # + wiz_fp.unlink(cr, uid, wiz_fp.search(cr, uid, [])) # Search for new / updated fiscal positions - # - fp_template_ids = fiscalpostitions_template.search(cr, uid, [('chart_template_id', '=', wizard.chart_template_id.id)], context=context) - for fp_template in fiscalpostitions_template.browse(cr, uid, fp_template_ids, context=context): + fp_template_ids = fp_templ_obj.search(cr, uid, + [('chart_template_id', + 'in', + chart_template_ids)], + context=context) + for fp_templ in fp_templ_obj.browse(cr, uid, fp_template_ids, + context=context): # Ensure the fiscal position template is on the map (search for the # mapped fiscal position id). - self._map_fp_template( - cr, uid, wizard, fp_template_mapping, fp_template, context) - - fp_id = fp_template_mapping.get(fp_template.id) + fp_id = self._map_fp_template(cr, uid, wizard, fp_templ_mapping, + fp_templ, context=context) if not fp_id: # # New fiscal position template. # new_fps += 1 - wiz_fiscalpositions.create(cr, uid, { - 'fiscal_position_id': fp_template.id, + wiz_fp.create(cr, uid, { + 'fiscal_position_id': fp_templ.id, 'update_chart_wizard_id': wizard.id, 'type': 'new', - }, context) - elif wizard.update_fiscal_position: - # - # Check the fiscal position for changes. - # - modified = False - notes = "" - fp = fiscalpositions.browse(cr, uid, fp_id, context=context) - - # - # Check fiscal position taxes for changes. - # - if fp_template.tax_ids and fp.tax_ids: - for fp_tax_template in fp_template.tax_ids: - found = False - for fp_tax in fp.tax_ids: - if fp_tax.tax_src_id.name == fp_tax_template.tax_src_id.name: - if fp_tax_template.tax_dest_id and fp_tax.tax_dest_id: - if fp_tax.tax_dest_id.name == fp_tax_template.tax_dest_id.name: - found = True - break - elif not fp_tax_template.tax_dest_id and not fp_tax.tax_dest_id: + 'notes': _('Name not found.'), + }, context=context) + continue + # Check the fiscal position for changes + modified = False + notes = "" + fp = fp_obj.browse(cr, uid, fp_id, context=context) + # Check fiscal position taxes for changes. + if fp_templ.tax_ids and fp.tax_ids: + for fp_tax_templ in fp_templ.tax_ids: + found = False + tax_src_id = self._map_tax_template(cr, uid, wizard, + tax_templ_mapping, + fp_tax_templ.tax_src_id, + context=None) + tax_dest_id = self._map_tax_template(cr, uid, wizard, + tax_templ_mapping, + fp_tax_templ.tax_dest_id, + context=None) + for fp_tax in fp.tax_ids: + if fp_tax.tax_src_id.id == tax_src_id: + if not fp_tax.tax_dest_id: + if not tax_dest_id: found = True break - if not found: - if fp_tax_template.tax_dest_id: - notes += _("Tax mapping not found on the fiscal position instance: %s -> %s.\n") % (fp_tax_template.tax_src_id.name, fp_tax_template.tax_dest_id.name) else: - notes += _("Tax mapping not found on the fiscal position instance: %s -> None.\n") % fp_tax_template.tax_src_id.name - modified = True - elif fp_template.tax_ids and not fp.tax_ids: - notes += _("The template has taxes the fiscal position instance does not.\n") - modified = True - - # - # Check fiscal position accounts for changes. - # - if fp_template.account_ids and fp.account_ids: - for fp_account_template in fp_template.account_ids: - found = False - for fp_account in fp.account_ids: - if fp_account.account_src_id.name == fp_account_template.account_src_id.name: - if fp_account.account_dest_id.name == fp_account_template.account_dest_id.name: + if fp_tax.tax_dest_id.id == tax_dest_id: found = True break - if not found: - notes += _("Account mapping not found on the fiscal position instance: %s -> %s.\n") % (fp_account_template.account_src_id.name, fp_account_template.account_dest_id.name) - modified = True - elif fp_template.account_ids and not fp.account_ids: - notes += _("The template has accounts the fiscal position instance does not.\n") - modified = True - - if modified: - # - # Fiscal position template to update. - # - updated_fps += 1 - wiz_fiscalpositions.create(cr, uid, { - 'fiscal_position_id': fp_template.id, - 'update_chart_wizard_id': wizard.id, - 'type': 'updated', - 'update_fiscal_position_id': fp_id, - 'notes': notes, - }, context) - - return {'new': new_fps, 'updated': updated_fps, 'mapping': fp_template_mapping} + if not found: + notes += _("Tax mapping not found on the fiscal position instance: %s -> %s.\n") % ( + fp_tax_templ.tax_src_id.name, + fp_tax_templ.tax_dest_id and fp_tax_templ.tax_dest_id.name or _('None')) + modified = True + elif fp_templ.tax_ids and not fp.tax_ids: + notes += _("The template has taxes the fiscal position instance does not.\n") + modified = True + # Check fiscal position accounts for changes + if fp_templ.account_ids and fp.account_ids: + for fp_acc_templ in fp_templ.account_ids: + found = False + acc_src_id = self._map_account_template( + cr, uid, wizard, acc_templ_mapping, + fp_acc_templ.account_src_id, context=context) + acc_dest_id = self._map_account_template( + cr, uid, wizard, acc_templ_mapping, + fp_acc_templ.account_dest_id, context=context) + for fp_acc in fp.account_ids: + if (fp_acc.account_src_id.id == acc_src_id and + fp_acc.account_dest_id.id == acc_dest_id): + found = True + break + if not found: + notes += _("Account mapping not found on the fiscal " + "position instance: %s -> %s.\n") % \ + (fp_acc_templ.account_src_id.name, + fp_acc_templ.account_dest_id.name) + modified = True + elif fp_templ.account_ids and not fp.account_ids: + notes += _("The template has accounts the fiscal position " + "instance does not.\n") + modified = True + if modified: + # Fiscal position template to update + updated_fps += 1 + wiz_fp.create(cr, uid, { + 'fiscal_position_id': fp_templ.id, + 'update_chart_wizard_id': wizard.id, + 'type': 'updated', + 'update_fiscal_position_id': fp_id, + 'notes': notes, + }, context=context) + return {'new': new_fps, 'updated': updated_fps, 'mapping': fp_templ_mapping} """ Searchs for records to update/create and shows them @@ -667,21 +721,34 @@ def action_find_records(self, cr, uid, ids, context=None): if context is None: context = {} wizard = self.browse(cr, uid, ids[0], context=context) - if wizard.lang: context['lang'] = wizard.lang elif context.get('lang'): del context['lang'] - - # + # Defaults when calculations are not done + tax_codes_res = {} + taxes_res = {} + accounts_res = {} + fps_res = {} + # Get all chart templates involved + wiz_obj = self.pool['wizard.multi.charts.accounts'] + chart_template_ids = wiz_obj._get_chart_parent_ids( + cr, uid, wizard.chart_template_id, context=context) # Search for, and load, the records to create/update. - # - tax_codes_res = self._find_tax_codes(cr, uid, wizard, context=context) - taxes_res = self._find_taxes(cr, uid, wizard, context=context) - accounts_res = self._find_accounts(cr, uid, wizard, context=context) - fps_res = self._find_fiscal_positions(cr, uid, wizard, context=context) - - # + if wizard.update_tax_code: + tax_codes_res = self._find_tax_codes(cr, uid, wizard, + chart_template_ids, + context=context) + if wizard.update_tax: + taxes_res = self._find_taxes(cr, uid, wizard, chart_template_ids, + context=context) + if wizard.update_account: + accounts_res = self._find_accounts(cr, uid, wizard, + context=context) + if wizard.update_fiscal_position: + fps_res = self._find_fiscal_positions(cr, uid, wizard, + chart_template_ids, + context=context) # Write the results, and go to the next step. # self.write(cr, uid, [wizard.id], { @@ -706,15 +773,14 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): new_tax_codes = 0 updated_tax_codes = 0 tax_code_template_mapping = {} - for wiz_tax_code in wizard.tax_code_ids: tax_code_template = wiz_tax_code.tax_code_id tax_code_name = (root_tax_code_id == tax_code_template.id) and wizard.company_id.name or tax_code_template.name - # Ensure the parent tax code template is on the map. - self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template.parent_id, context) - - # + self._map_tax_code_template(cr, uid, wizard, + tax_code_template_mapping, + tax_code_template.parent_id, + context=context) # Values # vals = { @@ -725,10 +791,8 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): 'company_id': wizard.company_id.id, 'sign': tax_code_template.sign, } - tax_code_id = None modified = False - if wiz_tax_code.type == 'new': # # Create the tax code @@ -749,17 +813,14 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): else: tax_code_id = wiz_tax_code.update_tax_code_id and wiz_tax_code.update_tax_code_id.id modified = False - # Store the tax codes on the map tax_code_template_mapping[tax_code_template.id] = tax_code_id - if modified: # # Detect errors # if tax_code_template.parent_id and not tax_code_template_mapping.get(tax_code_template.parent_id.id): log.add(_("Tax code %s: The parent tax code %s can not be set.\n") % (tax_code_name, tax_code_template.parent_id.name), True) - return { 'new': new_tax_codes, 'updated': updated_tax_codes, @@ -770,21 +831,19 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): Search for, and load, tax templates to create/update. """ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context=None): - taxes = self.pool.get('account.tax') - + """ + Search for, and load, tax templates to create/update. + """ + taxes = self.pool['account.tax'] new_taxes = 0 updated_taxes = 0 tax_template_mapping = {} taxes_pending_for_accounts = {} - for wiz_tax in wizard.tax_ids: tax_template = wiz_tax.tax_id - # Ensure the parent tax template is on the map. self._map_tax_template(cr, uid, wizard, tax_template_mapping, tax_template.parent_id, context) - - # # Ensure the referenced tax codes are on the map. # tax_code_templates_to_find = [ @@ -794,9 +853,9 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context tax_template.ref_tax_code_id ] for tax_code_template in [tmpl for tmpl in tax_code_templates_to_find if tmpl]: - self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template) - - # + self._map_tax_code_template(cr, uid, wizard, + tax_code_template_mapping, + tax_code_template, context=context) # Values # vals_tax = { @@ -825,10 +884,8 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context 'company_id': wizard.company_id.id, 'type_tax_use': tax_template.type_tax_use } - tax_id = None modified = False - if wiz_tax.type == 'new': # # Create a new tax. @@ -848,10 +905,8 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context modified = True else: tax_id = wiz_tax.update_tax_id and wiz_tax.update_tax_id.id - # Update the tax template map tax_template_mapping[tax_template.id] = tax_id - if modified: # # Add to the dict of taxes waiting for accounts. @@ -860,8 +915,6 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context 'account_collected_id': tax_template.account_collected_id and tax_template.account_collected_id.id or False, 'account_paid_id': tax_template.account_paid_id and tax_template.account_paid_id.id or False, } - - # # Detect errors # if tax_template.parent_id and not tax_template_mapping.get(tax_template.parent_id.id): @@ -874,7 +927,6 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context log.add(_("Tax %s: The tax code for the base refund %s can not be set.\n") % (tax_template.name, tax_template.ref_base_code_id.name), True) if tax_template.ref_tax_code_id and not tax_code_template_mapping.get(tax_template.ref_tax_code_id.id): log.add(_("Tax %s: The tax code for the tax refund %s can not be set.\n") % (tax_template.name, tax_template.ref_tax_code_id.name), True) - return { 'new': new_taxes, 'updated': updated_taxes, @@ -917,31 +969,23 @@ def _update_children_accounts_parent(self, cr, uid, wizard, log, parent_account_ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=None): accounts = self.pool.get('account.account') root_account_id = wizard.chart_template_id.account_root_id.id - # Disable the parent_store computing on account_account during the batch # processing, we will force _parent_store_compute afterwards. self.pool._init = True new_accounts = 0 updated_accounts = 0 account_template_mapping = {} - for wiz_account in wizard.account_ids: account_template = wiz_account.account_id - # Ensure the parent account template is on the map. self._map_account_template(cr, uid, wizard, account_template_mapping, account_template.parent_id, context) - - # # Ensure the related tax templates are on the map. # for tax_template in account_template.tax_ids: self._map_tax_template(cr, uid, wizard, tax_template_mapping, tax_template, context) - # Get the tax ids tax_ids = [tax_template_mapping[tax_template.id] for tax_template in account_template.tax_ids if tax_template_mapping[tax_template.id]] - - # # Calculate the account code (we need to add zeros to non-view # account codes) # @@ -950,8 +994,6 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=N if len(code) > 0 and len(code) <= wizard.code_digits: code = '%s%s' % ( code, '0' * (wizard.code_digits - len(code))) - - # # Values # vals = { @@ -968,10 +1010,8 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=N 'tax_ids': [(6, 0, tax_ids)], 'company_id': wizard.company_id.id, } - account_id = None modified = False - if wiz_account.type == 'new': # # Create the account @@ -999,79 +1039,74 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=N % (code, ex.name, ex.value), True) else: account_id = wiz_account.update_account_id and wiz_account.update_account_id.id - # Store the account on the map account_template_mapping[account_template.id] = account_id - if modified: # # Detect errors # if account_template.parent_id and not account_template_mapping.get(account_template.parent_id.id): log.add(_("Account %s: The parent account %s can not be set.\n") % (code, account_template.parent_id.code), True) - - # # Set this account as the parent of the accounts that seem to # be its children (brothers starting with the same code). # if wizard.update_children_accounts_parent: self._update_children_accounts_parent( cr, uid, wizard, log, account_id, context=context) - - # # Reenable the parent_store computing on account_account # and force the recomputation. # self.pool._init = False self.pool.get('account.account')._parent_store_compute(cr) - return { 'new': new_accounts, 'updated': updated_accounts, 'mapping': account_template_mapping } - """ - Updates the taxes (created or updated on previous steps) to set - the references to the accounts (the taxes where created/updated first, - when the referenced accounts where still not available). - """ - def _update_taxes_pending_for_accounts(self, cr, uid, wizard, log, taxes_pending_for_accounts, account_template_mapping, context=None): - taxes = self.pool.get('account.tax') - accounts_template = self.pool.get('account.account.template') - + def _update_taxes_pending_for_accounts(self, cr, uid, wizard, log, + taxes_pending_for_accounts, + acc_templ_mapping, context=None): + """ + Updates the taxes (created or updated on previous steps) to set + the references to the accounts (the taxes where created/updated first, + when the referenced accounts where still not available). + """ + taxes = self.pool['account.tax'] + accounts_template = self.pool['account.account.template'] for key, value in taxes_pending_for_accounts.items(): # # Ensure the related account templates are on the map. # if value['account_collected_id']: - account_template = accounts_template.browse( + acc_templ = accounts_template.browse( cr, uid, value['account_collected_id'], context=context) - self._map_account_template(cr, uid, wizard, account_template_mapping, account_template, context) + self._map_account_template(cr, uid, wizard, acc_templ_mapping, + acc_templ, context=context) if value['account_paid_id']: - account_template = accounts_template.browse( + acc_templ = accounts_template.browse( cr, uid, value['account_paid_id'], context=context) - self._map_account_template(cr, uid, wizard, account_template_mapping, account_template, context) - + self._map_account_template(cr, uid, wizard, acc_templ_mapping, + acc_templ, context=context) if value['account_collected_id'] or value['account_paid_id']: - if account_template_mapping.get(value['account_collected_id']) and account_template_mapping.get(value['account_paid_id']): + if acc_templ_mapping.get(value['account_collected_id']) and acc_templ_mapping.get(value['account_paid_id']): vals = { - 'account_collected_id': account_template_mapping[value['account_collected_id']], - 'account_paid_id': account_template_mapping[value['account_paid_id']], + 'account_collected_id': acc_templ_mapping[value['account_collected_id']], + 'account_paid_id': acc_templ_mapping[value['account_paid_id']], } taxes.write(cr, uid, [key], vals) else: tax = taxes.browse(cr, uid, key) - if not account_template_mapping.get(value['account_collected_id']): + if not acc_templ_mapping.get(value['account_collected_id']): log.add(_("Tax %s: The collected account can not be set.\n") % (tax.name), True) - if not account_template_mapping.get(value['account_paid_id']): + if not acc_templ_mapping.get(value['account_paid_id']): log.add(_("Tax %s: The paid account can not be set.\n") % (tax.name), True) - """ - Search for, and load, fiscal position templates to create/update. - """ - def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, account_template_mapping, context=None): + def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, acc_templ_mapping, context=None): + """ + Search for, and load, fiscal position templates to create/update. + """ fiscalpositions = self.pool.get('account.fiscal.position') fiscalpositions_taxes = self.pool.get('account.fiscal.position.tax') fiscalpositions_account = self.pool.get('account.fiscal.position.account') @@ -1148,27 +1183,29 @@ def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, a for fp_account in fp_template.account_ids: # # Ensure the related account templates are on the map. - # - self._map_account_template(cr, uid, wizard, account_template_mapping, fp_account.account_src_id, context) + self._map_account_template(cr, uid, wizard, + acc_templ_mapping, + fp_account.account_src_id, + context=context) if fp_account.account_dest_id: - self._map_account_template(cr, uid, wizard, account_template_mapping, fp_account.account_dest_id, context) - - # + self._map_account_template(cr, uid, wizard, + acc_templ_mapping, + fp_account.account_dest_id, + context=context) # Create the fp account mapping # vals_account = { - 'account_src_id': account_template_mapping.get(fp_account.account_src_id.id), - 'account_dest_id': fp_account.account_dest_id and account_template_mapping.get(fp_account.account_dest_id.id), + 'account_src_id': acc_templ_mapping.get(fp_account.account_src_id.id), + 'account_dest_id': fp_account.account_dest_id and acc_templ_mapping.get(fp_account.account_dest_id.id), 'position_id': fp_id, } fiscalpositions_account.create(cr, uid, vals_account) # # Check for errors - # - if not account_template_mapping.get(fp_account.account_src_id.id): + if not acc_templ_mapping.get(fp_account.account_src_id.id): log.add(_("Fiscal position %s: The source account %s can not be set.\n") % (fp_template.name, fp_account.account_src_id.code), True) - if fp_account.account_dest_id and not account_template_mapping.get(fp_account.account_dest_id.id): + if fp_account.account_dest_id and not acc_templ_mapping.get(fp_account.account_dest_id.id): log.add(_("Fiscal position %s: The destination account %s can not be set.\n") % (fp_template.name, fp_account.account_dest_id.code), True) log.add(_("Created or updated fiscal position %s.\n") @@ -1182,34 +1219,43 @@ def action_update_records(self, cr, uid, ids, context=None): if context is None: context = {} wizard = self.browse(cr, uid, ids[0], context=context) - if wizard.lang: context['lang'] = wizard.lang elif context.get('lang'): del context['lang'] - log = WizardLog() - - # + # Defaults when calculations are not done + tax_codes_res = {'mapping': {}} + taxes_res = {'mapping': {}, 'pending': {}} + accounts_res = {'mapping': {}} + fps_res = {} # Create or update the records. - # - tax_codes_res = self._update_tax_codes( - cr, uid, wizard, log, context=context) - taxes_res = self._update_taxes( - cr, uid, wizard, log, tax_codes_res['mapping'], context=context) - accounts_res = self._update_accounts( - cr, uid, wizard, log, taxes_res['mapping'], context=context) - self._update_taxes_pending_for_accounts(cr, uid, wizard, log, taxes_res['pending'], accounts_res['mapping'], context=context) - fps_res = self._update_fiscal_positions(cr, uid, wizard, log, taxes_res['mapping'], accounts_res['mapping'], context=context) - - # + if wizard.update_tax_code: + tax_codes_res = self._update_tax_codes(cr, uid, wizard, log, + context=context) + if wizard.update_tax: + taxes_res = self._update_taxes(cr, uid, wizard, log, + tax_codes_res['mapping'], + context=context) + if wizard.update_account: + accounts_res = self._update_accounts(cr, uid, wizard, log, + taxes_res['mapping'], + context=context) + if wizard.update_tax and wizard.update_account: + self._update_taxes_pending_for_accounts(cr, uid, wizard, log, + taxes_res['pending'], + accounts_res['mapping'], + context=context) + if wizard.update_fiscal_position: + fps_res = self._update_fiscal_positions(cr, uid, wizard, log, + taxes_res['mapping'], + accounts_res['mapping'], + context=context) # Check if errors where detected and wether we should stop. # if log.has_errors() and not wizard.continue_on_errors: raise orm.except_orm(_('Error'), _( "One or more errors detected!\n\n%s") % log.get_errors_str()) - - # # Store the data and go to the next step. # self.write(cr, uid, [wizard.id], { @@ -1223,8 +1269,7 @@ def action_update_records(self, cr, uid, ids, context=None): 'updated_accounts': accounts_res.get('updated', 0), 'updated_fps': fps_res.get('updated', 0), 'log': log(), - }, context) - + }, context=context) return _reopen(self, wizard.id, 'wizard.update.chart.accounts') wizard_update_charts_accounts() diff --git a/account_chart_update/wizard/wizard_chart_update_view.xml b/account_chart_update/wizard/wizard_chart_update_view.xml index 1705eb45df2..b0b93d39796 100644 --- a/account_chart_update/wizard/wizard_chart_update_view.xml +++ b/account_chart_update/wizard/wizard_chart_update_view.xml @@ -4,121 +4,93 @@ - - Update Chart of Accounts from a Chart Template - - wizard.update.charts.accounts - - -
-
- -
- -

-

This wizard will update your accounts, taxes and fiscal positions according to the selected chart template

- -

-
- - - - - - - - - - - - - - - - - - + + Update Chart of Accounts from a Chart Template + + wizard.update.charts.accounts + + +
+ +
+ +

+

This wizard will update your accounts, taxes and fiscal positions according to the selected chart template

+

+
+ + + + + + + + + + + + + + + + + + - -
-

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)

-

Note:Not all the fields are tested for changes, just the main ones

-
-
- - - - - - - - - - - - - - - - - - - + +
+

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)

+

Note: Not all the fields are tested for changes, just the main ones

+
+
+ + + + + + + + + + + + - - - - - - - -
- - - - - - -
-
-
- - - - - - - -
- - - - - - -
-
-
- - - - - - - -
- - - - - - -
-
-
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
@@ -143,22 +115,25 @@
-
-
-
-
-
-
- -
-
+
+
+
+
+
+
+
+
+ +
+
Update Chart of Accounts from a Chart Template From 35ff8d96712f6c96ffefcd2d49751f573e4a8649 Mon Sep 17 00:00:00 2001 From: Nicolas Bessi Date: Mon, 30 Jun 2014 11:12:36 +0200 Subject: [PATCH 07/86] Set all addons to uninstallable --- account_chart_update/__init__.py | 5 +- account_chart_update/__openerp__.py | 18 +- account_chart_update/wizard/__init__.py | 5 +- .../wizard/wizard_chart_update.py | 794 ++++++++++++------ .../wizard/wizard_chart_update_view.xml | 151 ---- 5 files changed, 535 insertions(+), 438 deletions(-) delete mode 100644 account_chart_update/wizard/wizard_chart_update_view.xml diff --git a/account_chart_update/__init__.py b/account_chart_update/__init__.py index 36d5407d08f..d04374b714a 100644 --- a/account_chart_update/__init__.py +++ b/account_chart_update/__init__.py @@ -2,7 +2,8 @@ ############################################################################## # # Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) -# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. +# (http://www.pexego.es) # @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) # # This program is free software: you can redistribute it and/or modify @@ -22,4 +23,4 @@ """ Account Chart Update Wizard """ -import wizard +from . import wizard diff --git a/account_chart_update/__openerp__.py b/account_chart_update/__openerp__.py index fc619522f6e..1ebdbfc8610 100644 --- a/account_chart_update/__openerp__.py +++ b/account_chart_update/__openerp__.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) -# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L.(http://www.pexego.es) # Copyright (c) 2013 Joaquin Gutierrez (http://www.gutierrezweb.es) # Pedro Manuel Baeza # $Id$ @@ -26,7 +26,7 @@ { 'name': "Detect changes and update the Account Chart from a template", - 'version': "1.1", + 'version': "1.2", 'author': "Zikzakmedia SL", 'website': "www.zikzakmedia.com", 'depends': ["account"], @@ -41,23 +41,25 @@ Adds a wizard to update a company account chart from a chart template. ====================================================================== -This is a pretty useful tool to update OpenERP instalations after tax reforms -on the oficial charts of accounts, or to apply fixes performed on the chart +This is a pretty useful tool to update OpenERP installations after tax reforms +on the official charts of accounts, or to apply fixes performed on the chart template. The wizard: + - Allows the user to compare a chart and a template showing differences - on accounts, taxes, tax codes and fiscal positions. + on accounts, taxes, tax codes and fiscal positions. - It may create the new account, taxes, tax codes and fiscal positions detected - on the template. + on the template. - It can also update (overwrite) the accounts, taxes, tax codes and fiscal - positions that got modified on the template. + positions that got modified on the template. The wizard lets the user select what kind of objects must be checked/updated, -and whether old records must be checked for changes and updated. +and whether old records must be checked for changes and updates. It will display all the accounts to be created / updated with some information about the detected differences, and allow the user to exclude records individually. + Any problem found while updating will be shown on the last step. """, 'license': "AGPL-3", diff --git a/account_chart_update/wizard/__init__.py b/account_chart_update/wizard/__init__.py index 8d0cfc9ed96..787022f15da 100644 --- a/account_chart_update/wizard/__init__.py +++ b/account_chart_update/wizard/__init__.py @@ -2,7 +2,8 @@ ############################################################################## # # Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) -# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. +# (http://www.pexego.es) # @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) # # This program is free software: you can redistribute it and/or modify @@ -22,4 +23,4 @@ """ Account Chart Update Wizard """ -import wizard_chart_update +from . import wizard_chart_update diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index be17b466956..1cd817503ac 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -2,7 +2,7 @@ ############################################################################## # # Copyright (c) 2010 Zikzakmedia S.L. (http://www.zikzakmedia.com) -# Copyright (c) 2010 Pexego Sistemas Informáticos S.L. (http://www.pexego.es) +# Copyright (c) 2010 Pexego Sistemas Informáticos S.L.(http://www.pexego.es) # @authors: Jordi Esteve (Zikzakmedia), Borja López Soilán (Pexego) # # This program is free software: you can redistribute it and/or modify @@ -36,7 +36,8 @@ def _reopen(self, res_id, model): 'res_id': res_id, 'res_model': self._name, 'target': 'new', - # save original model in context, because selecting the list of available + # save original model in context, + # because selecting the list of available # templates requires a model in context 'context': { 'default_model': model, @@ -54,10 +55,10 @@ def __init__(self): self.messages = [] self.errors = [] - """ - Adds a message to the log. - """ def add(self, message, is_error=False): + """ + Adds a message to the log. + """ logger = logging.getLogger("account_chart_update") if is_error: logger.warning(u"Log line: %s" % message) @@ -66,10 +67,10 @@ def add(self, message, is_error=False): logger.debug(u"Log line: %s" % message) self.messages.append(message) - """ - Returns whether errors where logged. - """ def has_errors(self): + """ + Returns whether errors where logged. + """ return self.errors def __call__(self): @@ -85,10 +86,10 @@ def get_errors_str(self): class wizard_update_charts_accounts(orm.TransientModel): _name = 'wizard.update.charts.accounts' - """ - Gets the available languages for the selection. - """ - def _get_lang_selection_options(self, cr, uid, context={}): + def _get_lang_selection_options(self, cr, uid, context=None): + """ + Gets the available languages for the selection. + """ obj = self.pool.get('res.lang') ids = obj.search(cr, uid, [], context=context) res = obj.read(cr, uid, ids, ['code', 'name'], context) @@ -100,36 +101,111 @@ def _get_lang_selection_options(self, cr, uid, context={}): ('ready', 'Step 2'), ('done', 'Wizard completed') ], 'Status', readonly=True), - 'company_id': fields.many2one('res.company', 'Company', required=True, ondelete='set null'), + 'company_id': fields.many2one( + 'res.company', + 'Company', + required=True, + ondelete='set null' + ), 'chart_template_id': fields.many2one( - 'account.chart.template', 'Chart Template', ondelete='cascade', - required=True), - 'code_digits': fields.integer('# of digits', required=True, help="No. of digits to use for account code. Make sure it is the same number as existing accounts."), - 'lang': fields.selection(_get_lang_selection_options, 'Language', size=5, help="For records searched by name (taxes, tax codes, fiscal positions), the template name will be matched against the record name on this language."), - 'update_tax_code': fields.boolean('Update tax codes', help="Existing tax codes are updated. Tax codes are searched by name."), - 'update_tax': fields.boolean('Update taxes', help="Existing taxes are updated. Taxes are searched by name."), - 'update_account': fields.boolean('Update accounts', help="Existing accounts are updated. Accounts are searched by code."), - 'update_fiscal_position': fields.boolean('Update fiscal positions', help="Existing fiscal positions are updated. Fiscal positions are searched by name."), - 'update_children_accounts_parent': fields.boolean("Update children accounts parent", - help="Update the parent of accounts that seem (based on the code) to be children of the newly created ones. If you had an account 430 with a child 4300000, and a 4300 account is created, the 4300000 parent will be set to 4300."), - 'continue_on_errors': fields.boolean("Continue on errors", help="If set, the wizard will continue to the next step even if there are minor errors (for example the parent account of a new account couldn't be set)."), - 'tax_code_ids': fields.one2many('wizard.update.charts.accounts.tax.code', 'update_chart_wizard_id', 'Tax codes', ondelete='cascade'), - 'tax_ids': fields.one2many('wizard.update.charts.accounts.tax', 'update_chart_wizard_id', 'Taxes', ondelete='cascade'), - 'account_ids': fields.one2many('wizard.update.charts.accounts.account', 'update_chart_wizard_id', 'Accounts', ondelete='cascade'), - 'fiscal_position_ids': fields.one2many('wizard.update.charts.accounts.fiscal.position', 'update_chart_wizard_id', 'Fiscal positions', ondelete='cascade'), + 'account.chart.template', + 'Chart Template', + ondelete='cascade', + required=True + ), + 'code_digits': fields.integer( + '# of digits', + required=True, + help="No. of digits to use for account code. " + "Make sure it is the same number as existing accounts." + ), + 'lang': fields.selection( + _get_lang_selection_options, + 'Language', + size=5, + help="For records searched by name " + "(taxes, tax codes, fiscal positions), " + "the template name will be matched against the record " + "name on this language." + ), + 'update_tax_code': fields.boolean( + 'Update tax codes', + help="Existing tax codes are updated." + " Tax codes are searched by name." + ), + 'update_tax': fields.boolean( + 'Update taxes', + help="Existing taxes are updated. Taxes are searched by name." + ), + 'update_account': fields.boolean( + 'Update accounts', + help="Existing accounts are updated. " + "Accounts are searched by code." + ), + 'update_fiscal_position': fields.boolean( + 'Update fiscal positions', + help="Existing fiscal positions are updated. " + "Fiscal positions are searched by name." + ), + 'update_children_accounts_parent': fields.boolean( + "Update children accounts parent", + help="Update the parent of accounts that seem (based on the code)" + " to be children of the newly created ones." + " If you had an account 430 with a child 4300000, and a 4300 " + "account is created, the 4300000 parent will be set to 4300." + ), + 'continue_on_errors': fields.boolean( + "Continue on errors", + help="If set, the wizard will continue to the next step even if " + "there are minor errors (for example the parent account " + "of a new account couldn't be set)." + ), + 'tax_code_ids': fields.one2many( + 'wizard.update.charts.accounts.tax.code', + 'update_chart_wizard_id', + 'Tax codes', + ondelete='cascade' + ), + 'tax_ids': fields.one2many( + 'wizard.update.charts.accounts.tax', + 'update_chart_wizard_id', + 'Taxes', + ondelete='cascade' + ), + 'account_ids': fields.one2many( + 'wizard.update.charts.accounts.account', + 'update_chart_wizard_id', + 'Accounts', + ondelete='cascade' + ), + 'fiscal_position_ids': fields.one2many( + 'wizard.update.charts.accounts.fiscal.position', + 'update_chart_wizard_id', + 'Fiscal positions', + ondelete='cascade' + ), 'new_tax_codes': fields.integer('New tax codes', readonly=True), 'new_taxes': fields.integer('New taxes', readonly=True), 'new_accounts': fields.integer('New accounts', readonly=True), 'new_fps': fields.integer('New fiscal positions', readonly=True), - 'updated_tax_codes': fields.integer('Updated tax codes', readonly=True), + 'updated_tax_codes': fields.integer( + 'Updated tax codes', + readonly=True + ), 'updated_taxes': fields.integer('Updated taxes', readonly=True), 'updated_accounts': fields.integer('Updated accounts', readonly=True), - 'updated_fps': fields.integer('Updated fiscal positions', readonly=True), + 'updated_fps': fields.integer( + 'Updated fiscal positions', + readonly=True + ), 'log': fields.text('Messages and Errors', readonly=True) } def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=80): + """ + Redefine the search to search by company name. + """ if not name: name = '%' if not args: @@ -142,10 +218,10 @@ def name_search(self, cr, user, name, cr, user, [('company_id', operator, name)] + args, limit=limit) return self.name_get(cr, user, ids, context=context) - """ - Use the company name and template as name. - """ def name_get(self, cr, uid, ids, context=None): + """ + Use the company name and template as name. + """ if context is None: context = {} if not len(ids): @@ -157,10 +233,10 @@ def name_get(self, cr, uid, ids, context=None): ' - ' + record.chart_template_id.name)) return res - """ - Returns the default chart template. - """ def _get_chart(self, cr, uid, context=None): + """ + Returns the default chart template. + """ if context is None: context = {} ids = self.pool.get( @@ -169,13 +245,13 @@ def _get_chart(self, cr, uid, context=None): return ids[0] return False - """ - Returns the default code size for the accounts. - To figure out the number of digits of the accounts it look at the - code size of the default receivable account of the company - (or user's company if any company is given). - """ def _get_code_digits(self, cr, uid, context=None, company_id=None): + """ + Returns the default code size for the accounts. + To figure out the number of digits of the accounts it look at the + code size of the default receivable account of the company + (or user's company if any company is given). + """ if context is None: context = {} property_obj = self.pool.get('ir.property') @@ -209,7 +285,9 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): _defaults = { 'state': 'init', - 'company_id': lambda self, cr, uid, context: self.pool.get('res.users').browse(cr, uid, [uid], context)[0].company_id.id, + 'company_id': lambda self, cr, uid, context: + self.pool.get('res.users').browse( + cr, uid, [uid], context)[0].company_id.id, 'chart_template_id': _get_chart, 'update_tax_code': True, 'update_tax': True, @@ -217,24 +295,26 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): 'update_fiscal_position': True, 'update_children_accounts_parent': True, 'continue_on_errors': False, - 'lang': lambda self, cr, uid, context: context and context.get('lang') or None, + 'lang': lambda self, cr, uid, context: + context and context.get('lang') or None, } - """ - Update the code size when the company changes - """ def onchange_company_id(self, cr, uid, ids, company_id, context=None): + """ + Update the code size when the company changes + """ res = { 'value': { - 'code_digits': self._get_code_digits(cr, uid, context=context, company_id=company_id), + 'code_digits': self._get_code_digits( + cr, uid, context=context, company_id=company_id), } } return res - """ - Initial action that sets the initial state. - """ def action_init(self, cr, uid, ids, context=None): + """ + Initial action that sets the initial state. + """ if context is None: context = {} wizard = self.browse(cr, uid, ids[0], context=context) @@ -317,14 +397,15 @@ def _map_account_template(self, cr, uid, wizard, acc_templ_mapping, if acc_templ.type != 'view': if code and len(code) <= wizard.code_digits: code = '%s%s' % (code, '0' * (wizard.code_digits - len(code))) - acc_ids = acc_obj.search(cr, uid, [ - ('code', '=', code), - ('company_id', '=', wizard.company_id.id) - ], context=context) + acc_ids = acc_obj.search(cr, uid, + [('code', '=', code), + ('company_id', '=', wizard.company_id.id)], + context=context) acc_templ_mapping[acc_templ.id] = acc_ids and acc_ids[0] or False return acc_templ_mapping[acc_templ.id] - def _map_fp_template(self, cr, uid, wizard, fp_templ_mapping, fp_template, context=None): + def _map_fp_template(self, cr, uid, wizard, fp_templ_mapping, + fp_template, context=None): """ Adds a fiscal position template -> fiscal position id to the mapping. """ @@ -345,7 +426,7 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, context=None): """ Search for, and load, tax code templates to create/update. - + @param chart_template_ids: IDs of the chart templates to look on, calculated once in the calling method. """ @@ -360,18 +441,20 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, # Remove previous tax codes wiz_tax_code_obj.unlink(cr, uid, wiz_tax_code_obj.search(cr, uid, [])) # Search for new / updated tax codes - # root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id children_tax_code_template = tax_code_templ_obj.search(cr, uid, [( 'parent_id', 'child_of', [root_tax_code_id])], order='id', context=context) - for tax_code_template in tax_code_templ_obj.browse(cr, uid, - children_tax_code_template, context=context): + for tax_code_template in tax_code_templ_obj.browse( + cr, uid, + children_tax_code_template, context=context): # Ensure the tax code template is on the map (search for the mapped # tax code id). - tax_code_id = self._map_tax_code_template(cr, uid, wizard, - tax_code_template_mapping, - tax_code_template, context=context) + tax_code_id = self._map_tax_code_template( + cr, uid, wizard, + tax_code_template_mapping, + tax_code_template, context=context + ) if not tax_code_id: new_tax_codes += 1 wiz_tax_code_obj.create(cr, uid, { @@ -381,9 +464,6 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, 'notes': _('Name or code not found.'), }, context) elif wizard.update_tax_code: - # - # Check the tax code for changes. - # modified = False notes = "" tax_code = tax_code_obj.browse( @@ -399,9 +479,6 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, modified = True # TODO: We could check other account fields for changes... if modified: - # - # Tax code to update. - # updated_tax_codes += 1 wiz_tax_code_obj.create(cr, uid, { 'tax_code_id': tax_code_template.id, @@ -419,7 +496,7 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): """ Search for, and load, tax templates to create/update. - + @param chart_template_ids: IDs of the chart templates to look on, calculated once in the calling method. """ @@ -456,9 +533,6 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): else: delay_wiz_tax.append(vals_wiz) elif wizard.update_tax: - # - # Check the tax for changes. - # modified = False notes = "" tax = tax_obj.browse(cr, uid, tax_id, context=context) @@ -500,9 +574,7 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): modified = True # TODO: We could check other tax fields for changes... if modified: - # # Tax code to update. - # updated_taxes += 1 wiz_taxes_obj.create(cr, uid, { 'tax_id': tax_templ.id, @@ -514,11 +586,10 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): for delay_vals_wiz in delay_wiz_tax: wiz_taxes_obj.create(cr, uid, delay_vals_wiz, context) - return {'new': new_taxes, 'updated': updated_taxes, 'mapping': tax_templ_mapping} + return {'new': new_taxes, + 'updated': updated_taxes, + 'mapping': tax_templ_mapping} - """ - Search for, and load, account templates to create/update. - """ def _find_accounts(self, cr, uid, wizard, context=None): """ Search for, and load, account templates to create/update. @@ -535,15 +606,16 @@ def _find_accounts(self, cr, uid, wizard, context=None): wiz_accounts_ids = wiz_accounts.search(cr, uid, [], context=context) wiz_accounts.unlink(cr, uid, wiz_accounts_ids, context=context) # Search for new / updated accounts - # root_account_id = wizard.chart_template_id.account_root_id.id acc_templ_criteria = [('chart_template_id', '=', wizard.chart_template_id.id)] if root_account_id: - acc_templ_criteria = (['|'] + acc_templ_criteria + - ['&', ('parent_id', 'child_of', [root_account_id]), - ('chart_template_id', '=', False)]) + acc_templ_criteria = ( + ['|'] + acc_templ_criteria + + ['&', ('parent_id', 'child_of', [root_account_id]), + ('chart_template_id', '=', False)] + ) acc_ids = acc_templ_obj.search(cr, uid, acc_templ_criteria, context=context) acc_ids.sort() @@ -564,13 +636,12 @@ def _find_accounts(self, cr, uid, wizard, context=None): 'notes': _('Code not found.'), }, context) elif wizard.update_account: - # # Check the account for changes. - # modified = False notes = "" account = acc_obj.browse(cr, uid, account_id, context=context) - if account.name != acc_templ.name and account.name != wizard.company_id.name: + if (account.name != acc_templ.name and + account.name != wizard.company_id.name): notes += _("The name is different.\n") modified = True if account.type != acc_templ.type: @@ -584,9 +655,7 @@ def _find_accounts(self, cr, uid, wizard, context=None): modified = True # TODO: We could check other account fields for changes... if modified: - # # Account to update. - # updated_accounts += 1 wiz_accounts.create(cr, uid, { 'account_id': acc_templ.id, @@ -595,17 +664,15 @@ def _find_accounts(self, cr, uid, wizard, context=None): 'update_account_id': account_id, 'notes': notes, }, context) - return { - 'new': new_accounts, + return {'new': new_accounts, 'updated': updated_accounts, - 'mapping': acc_templ_mapping - } + 'mapping': acc_templ_mapping} def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, context=None): """ Search for, and load, fiscal position templates to create/update. - + @param chart_template_ids: IDs of the chart templates to look on, calculated once in the calling method. """ @@ -626,15 +693,13 @@ def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, chart_template_ids)], context=context) for fp_templ in fp_templ_obj.browse(cr, uid, fp_template_ids, - context=context): + context=context): # Ensure the fiscal position template is on the map (search for the # mapped fiscal position id). fp_id = self._map_fp_template(cr, uid, wizard, fp_templ_mapping, fp_templ, context=context) if not fp_id: - # # New fiscal position template. - # new_fps += 1 wiz_fp.create(cr, uid, { 'fiscal_position_id': fp_templ.id, @@ -651,14 +716,18 @@ def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, if fp_templ.tax_ids and fp.tax_ids: for fp_tax_templ in fp_templ.tax_ids: found = False - tax_src_id = self._map_tax_template(cr, uid, wizard, - tax_templ_mapping, - fp_tax_templ.tax_src_id, - context=None) - tax_dest_id = self._map_tax_template(cr, uid, wizard, - tax_templ_mapping, - fp_tax_templ.tax_dest_id, - context=None) + tax_src_id = self._map_tax_template( + cr, uid, wizard, + tax_templ_mapping, + fp_tax_templ.tax_src_id, + context=None + ) + tax_dest_id = self._map_tax_template( + cr, uid, wizard, + tax_templ_mapping, + fp_tax_templ.tax_dest_id, + context=None + ) for fp_tax in fp.tax_ids: if fp_tax.tax_src_id.id == tax_src_id: if not fp_tax.tax_dest_id: @@ -670,12 +739,18 @@ def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, found = True break if not found: - notes += _("Tax mapping not found on the fiscal position instance: %s -> %s.\n") % ( - fp_tax_templ.tax_src_id.name, - fp_tax_templ.tax_dest_id and fp_tax_templ.tax_dest_id.name or _('None')) + msg = (fp_tax_templ.tax_dest_id and + fp_tax_templ.tax_dest_id.name or + _('None')) + notes += _("Tax mapping not found on the fiscal " + "position instance: %s -> %s.\n") % ( + fp_tax_templ.tax_src_id.name, + msg + ) modified = True elif fp_templ.tax_ids and not fp.tax_ids: - notes += _("The template has taxes the fiscal position instance does not.\n") + notes += _("The template has taxes the fiscal " + "position instance does not.\n") modified = True # Check fiscal position accounts for changes if fp_templ.account_ids and fp.account_ids: @@ -693,10 +768,11 @@ def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, found = True break if not found: - notes += _("Account mapping not found on the fiscal " - "position instance: %s -> %s.\n") % \ - (fp_acc_templ.account_src_id.name, - fp_acc_templ.account_dest_id.name) + notes += _( + "Account mapping not found on the fiscal " + "position instance: %s -> %s.\n") \ + % (fp_acc_templ.account_src_id.name, + fp_acc_templ.account_dest_id.name) modified = True elif fp_templ.account_ids and not fp.account_ids: notes += _("The template has accounts the fiscal position " @@ -712,12 +788,14 @@ def _find_fiscal_positions(self, cr, uid, wizard, chart_template_ids, 'update_fiscal_position_id': fp_id, 'notes': notes, }, context=context) - return {'new': new_fps, 'updated': updated_fps, 'mapping': fp_templ_mapping} + return {'new': new_fps, + 'updated': updated_fps, + 'mapping': fp_templ_mapping} - """ - Searchs for records to update/create and shows them - """ def action_find_records(self, cr, uid, ids, context=None): + """ + Searchs for records to update/create and shows them + """ if context is None: context = {} wizard = self.browse(cr, uid, ids[0], context=context) @@ -750,7 +828,6 @@ def action_find_records(self, cr, uid, ids, context=None): chart_template_ids, context=context) # Write the results, and go to the next step. - # self.write(cr, uid, [wizard.id], { 'state': 'ready', 'new_tax_codes': tax_codes_res.get('new', 0), @@ -764,10 +841,11 @@ def action_find_records(self, cr, uid, ids, context=None): }, context) return _reopen(self, wizard.id, 'wizard.update.chart.accounts') - """ - Search for, and load, tax code templates to create/update. - """ + def _update_tax_codes(self, cr, uid, wizard, log, context=None): + """ + Search for, and load, tax code templates to create/update. + """ taxcodes = self.pool.get('account.tax.code') root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id new_tax_codes = 0 @@ -775,62 +853,64 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): tax_code_template_mapping = {} for wiz_tax_code in wizard.tax_code_ids: tax_code_template = wiz_tax_code.tax_code_id - tax_code_name = (root_tax_code_id == tax_code_template.id) and wizard.company_id.name or tax_code_template.name + tax_code_name = ((root_tax_code_id == tax_code_template.id) and + wizard.company_id.name or tax_code_template.name) # Ensure the parent tax code template is on the map. self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template.parent_id, context=context) # Values - # + p_id = tax_code_template.parent_id.id vals = { 'name': tax_code_name, 'code': tax_code_template.code, 'info': tax_code_template.info, - 'parent_id': tax_code_template.parent_id and tax_code_template_mapping.get(tax_code_template.parent_id.id), + 'parent_id': (tax_code_template.parent_id and + tax_code_template_mapping.get(p_id)), 'company_id': wizard.company_id.id, 'sign': tax_code_template.sign, } tax_code_id = None modified = False if wiz_tax_code.type == 'new': - # # Create the tax code - # tax_code_id = taxcodes.create(cr, uid, vals) log.add(_("Created tax code %s.\n") % tax_code_name) new_tax_codes += 1 modified = True elif wizard.update_tax_code and wiz_tax_code.update_tax_code_id: - # # Update the tax code - # tax_code_id = wiz_tax_code.update_tax_code_id.id taxcodes.write(cr, uid, [tax_code_id], vals) log.add(_("Updated tax code %s.\n") % tax_code_name) updated_tax_codes += 1 modified = True else: - tax_code_id = wiz_tax_code.update_tax_code_id and wiz_tax_code.update_tax_code_id.id + tax_code_id = (wiz_tax_code.update_tax_code_id and + wiz_tax_code.update_tax_code_id.id) modified = False # Store the tax codes on the map tax_code_template_mapping[tax_code_template.id] = tax_code_id if modified: - # # Detect errors - # - if tax_code_template.parent_id and not tax_code_template_mapping.get(tax_code_template.parent_id.id): - log.add(_("Tax code %s: The parent tax code %s can not be set.\n") % (tax_code_name, tax_code_template.parent_id.name), True) + p_id = tax_code_template.parent_id.id + if (tax_code_template.parent_id and + not tax_code_template_mapping.get(p_id)): + log.add( + _("Tax code %s: The parent tax code %s " + "can not be set.\n") % ( + tax_code_name, tax_code_template.parent_id.name), + True + ) return { 'new': new_tax_codes, 'updated': updated_tax_codes, 'mapping': tax_code_template_mapping } - """ - Search for, and load, tax templates to create/update. - """ - def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context=None): + def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, + context=None): """ Search for, and load, tax templates to create/update. """ @@ -845,19 +925,18 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context self._map_tax_template(cr, uid, wizard, tax_template_mapping, tax_template.parent_id, context) # Ensure the referenced tax codes are on the map. - # tax_code_templates_to_find = [ tax_template.base_code_id, tax_template.tax_code_id, tax_template.ref_base_code_id, tax_template.ref_tax_code_id ] - for tax_code_template in [tmpl for tmpl in tax_code_templates_to_find if tmpl]: + for tax_code_template in \ + [tmpl for tmpl in tax_code_templates_to_find if tmpl]: self._map_tax_code_template(cr, uid, wizard, tax_code_template_mapping, tax_code_template, context=context) # Values - # vals_tax = { 'name': tax_template.name, 'sequence': tax_template.sequence, @@ -865,18 +944,35 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context 'type': tax_template.type, 'applicable_type': tax_template.applicable_type, 'domain': tax_template.domain, - 'parent_id': tax_template.parent_id and tax_template_mapping.get(tax_template.parent_id.id), + 'parent_id': ( + tax_template.parent_id and + tax_template_mapping.get(tax_template.parent_id.id) + ), 'child_depend': tax_template.child_depend, 'python_compute': tax_template.python_compute, 'python_compute_inv': tax_template.python_compute_inv, 'python_applicable': tax_template.python_applicable, - #'tax_group': tax_template.tax_group, - 'base_code_id': tax_template.base_code_id and tax_code_template_mapping.get(tax_template.base_code_id.id), - 'tax_code_id': tax_template.tax_code_id and tax_code_template_mapping.get(tax_template.tax_code_id.id), + 'base_code_id': ( + tax_template.base_code_id and + tax_code_template_mapping.get(tax_template.base_code_id.id) + ), + 'tax_code_id': ( + tax_template.tax_code_id and + tax_code_template_mapping.get(tax_template.tax_code_id.id) + ), 'base_sign': tax_template.base_sign, 'tax_sign': tax_template.tax_sign, - 'ref_base_code_id': tax_template.ref_base_code_id and tax_code_template_mapping.get(tax_template.ref_base_code_id.id), - 'ref_tax_code_id': tax_template.ref_tax_code_id and tax_code_template_mapping.get(tax_template.ref_tax_code_id.id), + 'ref_base_code_id': ( + tax_template.ref_base_code_id and + tax_code_template_mapping.get( + tax_template.ref_base_code_id.id + ) + ), + 'ref_tax_code_id': ( + tax_template.ref_tax_code_id and + tax_code_template_mapping.get( + tax_template.ref_tax_code_id.id) + ), 'ref_base_sign': tax_template.ref_base_sign, 'ref_tax_sign': tax_template.ref_tax_sign, 'include_base_amount': tax_template.include_base_amount, @@ -887,17 +983,13 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context tax_id = None modified = False if wiz_tax.type == 'new': - # # Create a new tax. - # tax_id = taxes.create(cr, uid, vals_tax) log.add(_("Created tax %s.\n") % tax_template.name) new_taxes += 1 modified = True elif wizard.update_tax and wiz_tax.update_tax_id: - # # Update a tax. - # tax_id = wiz_tax.update_tax_id.id taxes.write(cr, uid, [tax_id], vals_tax) log.add(_("Updated tax %s.\n") % tax_template.name) @@ -908,25 +1000,67 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context # Update the tax template map tax_template_mapping[tax_template.id] = tax_id if modified: - # # Add to the dict of taxes waiting for accounts. - # taxes_pending_for_accounts[tax_id] = { - 'account_collected_id': tax_template.account_collected_id and tax_template.account_collected_id.id or False, - 'account_paid_id': tax_template.account_paid_id and tax_template.account_paid_id.id or False, + 'account_collected_id': ( + tax_template.account_collected_id and + tax_template.account_collected_id.id or False + ), + 'account_paid_id': ( + tax_template.account_paid_id and + tax_template.account_paid_id.id or False + ), } # Detect errors - # - if tax_template.parent_id and not tax_template_mapping.get(tax_template.parent_id.id): - log.add(_("Tax %s: The parent tax %s can not be set.\n") % (tax_template.name, tax_template.parent_id.name), True) - if tax_template.base_code_id and not tax_code_template_mapping.get(tax_template.base_code_id.id): - log.add(_("Tax %s: The tax code for the base %s can not be set.\n") % (tax_template.name, tax_template.base_code_id.name), True) - if tax_template.tax_code_id and not tax_code_template_mapping.get(tax_template.tax_code_id.id): - log.add(_("Tax %s: The tax code for the tax %s can not be set.\n") % (tax_template.name, tax_template.tax_code_id.name), True) - if tax_template.ref_base_code_id and not tax_code_template_mapping.get(tax_template.ref_base_code_id.id): - log.add(_("Tax %s: The tax code for the base refund %s can not be set.\n") % (tax_template.name, tax_template.ref_base_code_id.name), True) - if tax_template.ref_tax_code_id and not tax_code_template_mapping.get(tax_template.ref_tax_code_id.id): - log.add(_("Tax %s: The tax code for the tax refund %s can not be set.\n") % (tax_template.name, tax_template.ref_tax_code_id.name), True) + if (tax_template.parent_id and not + tax_template_mapping.get(tax_template.parent_id.id)): + log.add( + _("Tax %s: The parent tax %s can not be set.\n") % ( + tax_template.name, tax_template.parent_id.name), + True + ) + if (tax_template.base_code_id and not + tax_code_template_mapping.get( + tax_template.base_code_id.id + )): + log.add( + _("Tax %s: The tax code for the base %s " + "can not be set.\n") % ( + tax_template.name, tax_template.base_code_id.name), + True + ) + if (tax_template.tax_code_id and not + tax_code_template_mapping.get( + tax_template.tax_code_id.id)): + log.add( + _("Tax %s: The tax code for the tax %s " + "can not be set.\n") % ( + tax_template.name, tax_template.tax_code_id.name + ), + True + ) + if (tax_template.ref_base_code_id and + not tax_code_template_mapping.get( + tax_template.ref_base_code_id.id)): + log.add( + _("Tax %s: The tax code for the base refund %s " + "can not be set.\n") % ( + tax_template.name, + tax_template.ref_base_code_id.name + ), + True + ) + if (tax_template.ref_tax_code_id and not + tax_code_template_mapping.get( + tax_template.ref_tax_code_id.id)): + log.add( + _("Tax %s: The tax code for the tax refund %s" + " can not be set.\n") % ( + tax_template.name, + tax_template.ref_tax_code_id.name + ), + True + ) return { 'new': new_taxes, 'updated': updated_taxes, @@ -934,12 +1068,13 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, context 'pending': taxes_pending_for_accounts } - """ - Updates the parent_id of accounts that seem to be children of the - given account (accounts that start with the same code and are brothers - of the first account). - """ - def _update_children_accounts_parent(self, cr, uid, wizard, log, parent_account_id, context=None): + def _update_children_accounts_parent(self, cr, uid, wizard, + log, parent_account_id, context=None): + """ + Updates the parent_id of accounts that seem to be children of the + given account (accounts that start with the same code and are brothers + of the first account). + """ account_account = self.pool.get('account.account') parent_account = account_account.browse( cr, uid, parent_account_id, context=context) @@ -957,20 +1092,30 @@ def _update_children_accounts_parent(self, cr, uid, wizard, log, parent_account_ if children_ids: try: - account_account.write(cr, uid, children_ids, {'parent_id': parent_account.id}, context=context) + account_account.write(cr, uid, children_ids, + {'parent_id': parent_account.id}, + context=context) except orm.except_orm, ex: - log.add(_("Exception setting the parent of account %s children: %s - %s.\n") % (parent_account.code, ex.name, ex.value), True) + log.add( + _("Exception setting the parent of " + "account %s children: %s - %s.\n") % ( + parent_account.code, ex.name, ex.value + ), + True + ) return True - """ - Search for, and load, account templates to create/update. - """ - def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=None): + def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, + context=None): + """ + Search for, and load, account templates to create/update. + """ accounts = self.pool.get('account.account') root_account_id = wizard.chart_template_id.account_root_id.id - # Disable the parent_store computing on account_account during the batch - # processing, we will force _parent_store_compute afterwards. + # Disable the parent_store computing on account_account + # during the batch processing, + # we will force _parent_store_compute afterwards. self.pool._init = True new_accounts = 0 updated_accounts = 0 @@ -978,44 +1123,54 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=N for wiz_account in wizard.account_ids: account_template = wiz_account.account_id # Ensure the parent account template is on the map. - self._map_account_template(cr, uid, wizard, account_template_mapping, account_template.parent_id, context) + self._map_account_template(cr, uid, wizard, + account_template_mapping, + account_template.parent_id, + context) # Ensure the related tax templates are on the map. - # for tax_template in account_template.tax_ids: self._map_tax_template(cr, uid, wizard, tax_template_mapping, tax_template, context) # Get the tax ids - tax_ids = [tax_template_mapping[tax_template.id] for tax_template in account_template.tax_ids if tax_template_mapping[tax_template.id]] + tax_ids = [tax_template_mapping[tax_template.id] + for tax_template in account_template.tax_ids + if tax_template_mapping[tax_template.id]] # Calculate the account code (we need to add zeros to non-view # account codes) - # code = account_template.code or '' if account_template.type != 'view': if len(code) > 0 and len(code) <= wizard.code_digits: code = '%s%s' % ( code, '0' * (wizard.code_digits - len(code))) # Values - # + p_id = account_template.parent_id.id vals = { - 'name': (root_account_id == account_template.id) and wizard.company_id.name or account_template.name, - #'sign': account_template.sign, - 'currency_id': account_template.currency_id and account_template.currency_id.id or False, + 'name': ((root_account_id == account_template.id) and + wizard.company_id.name or + account_template.name), + 'currency_id': (account_template.currency_id and + account_template.currency_id.id or + False), 'code': code, 'type': account_template.type, - 'user_type': account_template.user_type and account_template.user_type.id or False, + 'user_type': (account_template.user_type and + account_template.user_type.id or + False), 'reconcile': account_template.reconcile, 'shortcut': account_template.shortcut, 'note': account_template.note, - 'parent_id': account_template.parent_id and account_template_mapping.get(account_template.parent_id.id) or False, + 'parent_id': ( + account_template.parent_id + and account_template_mapping.get(p_id) or + False + ), 'tax_ids': [(6, 0, tax_ids)], 'company_id': wizard.company_id.id, } account_id = None modified = False if wiz_account.type == 'new': - # # Create the account - # try: account_id = accounts.create(cr, uid, vals) log.add(_("Created account %s.\n") % code) @@ -1025,9 +1180,7 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=N log.add(_("Exception creating account %s: %s - %s.\n") % (code, ex.name, ex.value), True) elif wizard.update_account and wiz_account.update_account_id: - # # Update the account - # account_id = wiz_account.update_account_id.id try: accounts.write(cr, uid, [account_id], vals) @@ -1038,24 +1191,29 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, context=N log.add(_("Exception writing account %s: %s - %s.\n") % (code, ex.name, ex.value), True) else: - account_id = wiz_account.update_account_id and wiz_account.update_account_id.id + account_id = (wiz_account.update_account_id and + wiz_account.update_account_id.id) # Store the account on the map account_template_mapping[account_template.id] = account_id if modified: - # # Detect errors - # - if account_template.parent_id and not account_template_mapping.get(account_template.parent_id.id): - log.add(_("Account %s: The parent account %s can not be set.\n") % (code, account_template.parent_id.code), True) + if (account_template.parent_id and not + account_template_mapping.get( + account_template.parent_id.id)): + log.add( + _("Account %s: The parent account %s " + "can not be set.\n") % ( + code, account_template.parent_id.code + ), + True + ) # Set this account as the parent of the accounts that seem to # be its children (brothers starting with the same code). - # if wizard.update_children_accounts_parent: self._update_children_accounts_parent( cr, uid, wizard, log, account_id, context=context) # Reenable the parent_store computing on account_account # and force the recomputation. - # self.pool._init = False self.pool.get('account.account')._parent_store_compute(cr) return { @@ -1075,9 +1233,7 @@ def _update_taxes_pending_for_accounts(self, cr, uid, wizard, log, taxes = self.pool['account.tax'] accounts_template = self.pool['account.account.template'] for key, value in taxes_pending_for_accounts.items(): - # # Ensure the related account templates are on the map. - # if value['account_collected_id']: acc_templ = accounts_template.browse( cr, uid, value['account_collected_id'], context=context) @@ -1089,27 +1245,43 @@ def _update_taxes_pending_for_accounts(self, cr, uid, wizard, log, self._map_account_template(cr, uid, wizard, acc_templ_mapping, acc_templ, context=context) if value['account_collected_id'] or value['account_paid_id']: - if acc_templ_mapping.get(value['account_collected_id']) and acc_templ_mapping.get(value['account_paid_id']): + if (acc_templ_mapping.get(value['account_collected_id']) and + acc_templ_mapping.get(value['account_paid_id'])): vals = { - 'account_collected_id': acc_templ_mapping[value['account_collected_id']], - 'account_paid_id': acc_templ_mapping[value['account_paid_id']], + 'account_collected_id': acc_templ_mapping[ + value['account_collected_id'] + ], + 'account_paid_id': acc_templ_mapping[ + value['account_paid_id'] + ], } taxes.write(cr, uid, [key], vals) else: tax = taxes.browse(cr, uid, key) - if not acc_templ_mapping.get(value['account_collected_id']): - log.add(_("Tax %s: The collected account can not be set.\n") % (tax.name), True) + val = value['account_collected_id'] + if not acc_templ_mapping.get(val): + log.add( + _("Tax %s: The collected account " + "can not be set.\n") % ( + tax.name + ), + True + ) if not acc_templ_mapping.get(value['account_paid_id']): log.add(_("Tax %s: The paid account can not be set.\n") % (tax.name), True) - def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, acc_templ_mapping, context=None): + def _update_fiscal_positions(self, cr, uid, wizard, log, + tax_template_mapping, + acc_templ_mapping, context=None): """ Search for, and load, fiscal position templates to create/update. """ fiscalpositions = self.pool.get('account.fiscal.position') fiscalpositions_taxes = self.pool.get('account.fiscal.position.tax') - fiscalpositions_account = self.pool.get('account.fiscal.position.account') + fiscalpositions_account = self.pool.get( + 'account.fiscal.position.account' + ) new_fps = 0 updated_fps = 0 @@ -1119,9 +1291,7 @@ def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, a fp_id = None modified = False if wiz_fp.type == 'new': - # # Create a new fiscal position - # vals_fp = { 'company_id': wizard.company_id.id, 'name': fp_template.name, @@ -1129,11 +1299,10 @@ def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, a fp_id = fiscalpositions.create(cr, uid, vals_fp) new_fps += 1 modified = True - elif wizard.update_fiscal_position and wiz_fp.update_fiscal_position_id: - # + elif (wizard.update_fiscal_position and + wiz_fp.update_fiscal_position_id): # Update the given fiscal position (remove the tax and account # mappings, that will be regenerated later) - # fp_id = wiz_fp.update_fiscal_position_id.id updated_fps += 1 modified = True @@ -1146,42 +1315,51 @@ def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, a cr, uid, [('position_id', '=', fp_id)]) fiscalpositions_account.unlink(cr, uid, fp_account_ids) else: - fp_id = wiz_fp.update_fiscal_position_id and wiz_fp.update_fiscal_position_id.id + fp_id = (wiz_fp.update_fiscal_position_id and + wiz_fp.update_fiscal_position_id.id) if modified: - # # (Re)create the tax mappings - # for fp_tax in fp_template.tax_ids: - # # Ensure the related tax templates are on the map. - # - self._map_tax_template(cr, uid, wizard, tax_template_mapping, fp_tax.tax_src_id, context) + self._map_tax_template(cr, uid, wizard, + tax_template_mapping, + fp_tax.tax_src_id, context) if fp_tax.tax_dest_id: - self._map_tax_template(cr, uid, wizard, tax_template_mapping, fp_tax.tax_dest_id, context) - - # + self._map_tax_template(cr, uid, wizard, + tax_template_mapping, + fp_tax.tax_dest_id, context) # Create the fp tax mapping - # vals_tax = { - 'tax_src_id': tax_template_mapping.get(fp_tax.tax_src_id.id), - 'tax_dest_id': fp_tax.tax_dest_id and tax_template_mapping.get(fp_tax.tax_dest_id.id), + 'tax_src_id': tax_template_mapping.get( + fp_tax.tax_src_id.id + ), + 'tax_dest_id': (fp_tax.tax_dest_id and + tax_template_mapping.get( + fp_tax.tax_dest_id.id)), 'position_id': fp_id, } fiscalpositions_taxes.create(cr, uid, vals_tax) - - # # Check for errors - # if not tax_template_mapping.get(fp_tax.tax_src_id.id): - log.add(_("Fiscal position %s: The source tax %s can not be set.\n") % (fp_template.name, fp_tax.tax_src_id.code), True) - if fp_tax.tax_dest_id and not tax_template_mapping.get(fp_tax.tax_dest_id.id): - log.add(_("Fiscal position %s: The destination tax %s can not be set.\n") % (fp_template.name, fp_tax.tax_dest_id.name), True) - # + log.add( + _("Fiscal position %s: The source tax %s " + "can not be set.\n") % ( + fp_template.name, fp_tax.tax_src_id.code + ), + True + ) + if fp_tax.tax_dest_id and not tax_template_mapping.get( + fp_tax.tax_dest_id.id): + log.add( + _("Fiscal position %s: The destination" + "tax %s can not be set.\n") % ( + fp_template.name, fp_tax.tax_dest_id.name + ), + True + ) # (Re)create the account mappings - # for fp_account in fp_template.account_ids: - # # Ensure the related account templates are on the map. self._map_account_template(cr, uid, wizard, acc_templ_mapping, @@ -1193,29 +1371,49 @@ def _update_fiscal_positions(self, cr, uid, wizard, log, tax_template_mapping, a fp_account.account_dest_id, context=context) # Create the fp account mapping - # vals_account = { - 'account_src_id': acc_templ_mapping.get(fp_account.account_src_id.id), - 'account_dest_id': fp_account.account_dest_id and acc_templ_mapping.get(fp_account.account_dest_id.id), + 'account_src_id': acc_templ_mapping.get( + fp_account.account_src_id.id + ), + 'account_dest_id': ( + fp_account.account_dest_id and + acc_templ_mapping.get( + fp_account.account_dest_id.id + ) + ), 'position_id': fp_id, } fiscalpositions_account.create(cr, uid, vals_account) - - # # Check for errors if not acc_templ_mapping.get(fp_account.account_src_id.id): - log.add(_("Fiscal position %s: The source account %s can not be set.\n") % (fp_template.name, fp_account.account_src_id.code), True) - if fp_account.account_dest_id and not acc_templ_mapping.get(fp_account.account_dest_id.id): - log.add(_("Fiscal position %s: The destination account %s can not be set.\n") % (fp_template.name, fp_account.account_dest_id.code), True) + log.add( + _("Fiscal position %s: The source account %s " + "can not be set.\n") % ( + fp_template.name, + fp_account.account_src_id.code + ), + True + ) + if (fp_account.account_dest_id and not + acc_templ_mapping.get( + fp_account.account_dest_id.id)): + log.add( + _("Fiscal position %s: The destination account %s " + "can not be set.\n") % ( + fp_template.name, + fp_account.account_dest_id.code + ), + True + ) log.add(_("Created or updated fiscal position %s.\n") % fp_template.name) return {'new': new_fps, 'updated': updated_fps} - """ - Action that creates/updates the selected elements. - """ def action_update_records(self, cr, uid, ids, context=None): + """ + Action that creates/updates the selected elements. + """ if context is None: context = {} wizard = self.browse(cr, uid, ids[0], context=context) @@ -1252,12 +1450,10 @@ def action_update_records(self, cr, uid, ids, context=None): accounts_res['mapping'], context=context) # Check if errors where detected and wether we should stop. - # if log.has_errors() and not wizard.continue_on_errors: raise orm.except_orm(_('Error'), _( "One or more errors detected!\n\n%s") % log.get_errors_str()) # Store the data and go to the next step. - # self.write(cr, uid, [wizard.id], { 'state': 'done', 'new_tax_codes': tax_codes_res.get('new', 0), @@ -1272,8 +1468,6 @@ def action_update_records(self, cr, uid, ids, context=None): }, context=context) return _reopen(self, wizard.id, 'wizard.update.chart.accounts') -wizard_update_charts_accounts() - class wizard_update_charts_accounts_tax_code(orm.TransientModel): """ @@ -1283,19 +1477,32 @@ class wizard_update_charts_accounts_tax_code(orm.TransientModel): """ _name = 'wizard.update.charts.accounts.tax.code' _columns = { - 'tax_code_id': fields.many2one('account.tax.code.template', 'Tax code template', required=True, ondelete='set null'), - 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'tax_code_id': fields.many2one( + 'account.tax.code.template', + 'Tax code template', + required=True, + ondelete='set null' + ), + 'update_chart_wizard_id': fields.many2one( + 'wizard.update.charts.accounts', + 'Update chart wizard', + required=True, + ondelete='cascade' + ), 'type': fields.selection([ ('new', 'New template'), ('updated', 'Updated template'), ], 'Type'), - 'update_tax_code_id': fields.many2one('account.tax.code', 'Tax code to update', required=False, ondelete='set null'), + 'update_tax_code_id': fields.many2one( + 'account.tax.code', + 'Tax code to update', + required=False, + ondelete='set null' + ), 'notes': fields.text('Notes'), } _defaults = { - } - -wizard_update_charts_accounts_tax_code() + } class wizard_update_charts_accounts_tax(orm.TransientModel): @@ -1306,20 +1513,33 @@ class wizard_update_charts_accounts_tax(orm.TransientModel): """ _name = 'wizard.update.charts.accounts.tax' _columns = { - 'tax_id': fields.many2one('account.tax.template', 'Tax template', required=True, ondelete='set null'), - 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'tax_id': fields.many2one( + 'account.tax.template', + 'Tax template', + required=True, + ondelete='set null' + ), + 'update_chart_wizard_id': fields.many2one( + 'wizard.update.charts.accounts', + 'Update chart wizard', + required=True, + ondelete='cascade' + ), 'type': fields.selection([ ('new', 'New template'), ('updated', 'Updated template'), ], 'Type'), - 'update_tax_id': fields.many2one('account.tax', 'Tax to update', required=False, ondelete='set null'), + 'update_tax_id': fields.many2one( + 'account.tax', + 'Tax to update', + required=False, + ondelete='set null' + ), 'notes': fields.text('Notes'), } _defaults = { - } - -wizard_update_charts_accounts_tax() + } class wizard_update_charts_accounts_account(orm.TransientModel): @@ -1332,22 +1552,34 @@ class wizard_update_charts_accounts_account(orm.TransientModel): # The chart of accounts can have a lot of accounts, so we need an higher # limit for the objects in memory to let the wizard create all the items # at once. - _max_count = 4096 _columns = { - 'account_id': fields.many2one('account.account.template', 'Account template', required=True, ondelete='set null'), - 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'account_id': fields.many2one( + 'account.account.template', + 'Account template', + required=True, + ondelete='set null' + ), + 'update_chart_wizard_id': fields.many2one( + 'wizard.update.charts.accounts', + 'Update chart wizard', + required=True, + ondelete='cascade' + ), 'type': fields.selection([ ('new', 'New template'), ('updated', 'Updated template'), ], 'Type'), - 'update_account_id': fields.many2one('account.account', 'Account to update', required=False, ondelete='set null'), + 'update_account_id': fields.many2one( + 'account.account', + 'Account to update', + required=False, + ondelete='set null' + ), 'notes': fields.text('Notes'), } _defaults = { - } - -wizard_update_charts_accounts_account() + } class wizard_update_charts_accounts_fiscal_position(orm.TransientModel): @@ -1358,19 +1590,31 @@ class wizard_update_charts_accounts_fiscal_position(orm.TransientModel): """ _name = 'wizard.update.charts.accounts.fiscal.position' _columns = { - 'fiscal_position_id': fields.many2one('account.fiscal.position.template', 'Fiscal position template', required=True, ondelete='set null'), - 'update_chart_wizard_id': fields.many2one('wizard.update.charts.accounts', 'Update chart wizard', required=True, ondelete='cascade'), + 'fiscal_position_id': fields.many2one( + 'account.fiscal.position.template', + 'Fiscal position template', + required=True, + ondelete='set null' + ), + 'update_chart_wizard_id': fields.many2one( + 'wizard.update.charts.accounts', + 'Update chart wizard', + required=True, + ondelete='cascade' + ), 'type': fields.selection([ ('new', 'New template'), ('updated', 'Updated template'), ], 'Type'), - 'update_fiscal_position_id': fields.many2one('account.fiscal.position', 'Fiscal position to update', required=False, ondelete='set null'), + 'update_fiscal_position_id': fields.many2one( + 'account.fiscal.position', + 'Fiscal position to update', + required=False, + ondelete='set null' + ), 'notes': fields.text('Notes'), } _defaults = { - } - - -wizard_update_charts_accounts_fiscal_position() + } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/account_chart_update/wizard/wizard_chart_update_view.xml b/account_chart_update/wizard/wizard_chart_update_view.xml deleted file mode 100644 index b0b93d39796..00000000000 --- a/account_chart_update/wizard/wizard_chart_update_view.xml +++ /dev/null @@ -1,151 +0,0 @@ - - - - - - - - Update Chart of Accounts from a Chart Template - - wizard.update.charts.accounts - -
-
- -
- -

-

This wizard will update your accounts, taxes and fiscal positions according to the selected chart template

-

-
- - - - - - - - - - - - - - - - - - - - -
-

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)

-

Note: Not all the fields are tested for changes, just the main ones

-
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
-
-
-
-
-
-
-
-
-
- - - Update Chart of Accounts from a Chart Template - - ir.actions.act_window - wizard.update.charts.accounts - form - form - new - - - - -
-
From 1f48ac7fd640bcd1bb3ae46041af9bb84a0fe9f1 Mon Sep 17 00:00:00 2001 From: Adrien Peiffer Date: Thu, 27 Nov 2014 10:18:59 +0100 Subject: [PATCH 08/86] [MIG] account_chart_update: Migration to 8.0 * Move out of unported * Set account_chart_update installable * value_reference of ir.property is a char * Use get_by_record method of ir.property * number digits is returned before assignment in case of property exist but account not * product_obj isn't used --- account_chart_update/__openerp__.py | 2 +- .../wizard/wizard_chart_update.py | 19 +-- .../wizard/wizard_chart_update_view.xml | 150 ++++++++++++++++++ 3 files changed, 159 insertions(+), 12 deletions(-) create mode 100644 account_chart_update/wizard/wizard_chart_update_view.xml diff --git a/account_chart_update/__openerp__.py b/account_chart_update/__openerp__.py index 1ebdbfc8610..e1f10c21bd8 100644 --- a/account_chart_update/__openerp__.py +++ b/account_chart_update/__openerp__.py @@ -72,5 +72,5 @@ 'wizard/wizard_chart_update_view.xml', ], "active": False, - "installable": True + 'installable': True } diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index 1cd817503ac..891faf0db30 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -19,10 +19,6 @@ # along with this program. If not, see . # ############################################################################## -""" -Account Chart Update Wizard -""" - from openerp.osv import fields, orm from openerp.tools.translate import _ import logging @@ -255,7 +251,6 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): if context is None: context = {} property_obj = self.pool.get('ir.property') - account_obj = self.pool.get('account.account') if not company_id: user = self.pool.get('res.users').browse(cr, uid, uid, context) company_id = user.company_id.id @@ -265,6 +260,7 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): ('res_id', '=', False), ('value_reference', '!=', False) ]) + number_digits = 6 if not property_ids: # Try to get a generic (no-company) property property_ids = property_obj.search(cr, uid, [ @@ -272,15 +268,13 @@ def _get_code_digits(self, cr, uid, context=None, company_id=None): ('res_id', '=', False), ('value_reference', '!=', False) ]) - number_digits = 6 if property_ids: prop = property_obj.browse( cr, uid, property_ids[0], context=context) - account_id = prop.value_reference.id - if account_id: - code = account_obj.read( - cr, uid, account_id, ['code'], context)['code'] - number_digits = len(code) + account = property_obj.get_by_record(cr, uid, prop, + context=context) + if account: + number_digits = len(account.code) return number_digits _defaults = { @@ -464,6 +458,7 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, 'notes': _('Name or code not found.'), }, context) elif wizard.update_tax_code: + # Check the tax code for changes. modified = False notes = "" tax_code = tax_code_obj.browse( @@ -479,6 +474,7 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, modified = True # TODO: We could check other account fields for changes... if modified: + # Tax code to update. updated_tax_codes += 1 wiz_tax_code_obj.create(cr, uid, { 'tax_code_id': tax_code_template.id, @@ -533,6 +529,7 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): else: delay_wiz_tax.append(vals_wiz) elif wizard.update_tax: + # Check the tax for changes. modified = False notes = "" tax = tax_obj.browse(cr, uid, tax_id, context=context) diff --git a/account_chart_update/wizard/wizard_chart_update_view.xml b/account_chart_update/wizard/wizard_chart_update_view.xml new file mode 100644 index 00000000000..91c7927d8bb --- /dev/null +++ b/account_chart_update/wizard/wizard_chart_update_view.xml @@ -0,0 +1,150 @@ + + + + + + + + Update Chart of Accounts from a Chart Template + + wizard.update.charts.accounts + +
+
+ +
+ +

+

This wizard will update your accounts, taxes and fiscal positions according to the selected chart template

+

+
+ + + + + + + + + + + + + + + + + + + + +
+

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)

+

Note: Not all the fields are tested for changes, just the main ones

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+
+
+
+
+
+
+ + + Update chart of accounts + ir.actions.act_window + wizard.update.charts.accounts + form + form + new + + + + +
+
From ef73f5ad50f6ccf64a936f6d0de27c1a2fae06fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Bidoul?= Date: Wed, 24 Dec 2014 00:23:39 +0100 Subject: [PATCH 09/86] [FIX+IMP] account_chart_update: Several things * search on code first to match tax codes The tax code code should be more discriminant that the tax code name. * compare more fields in tax codes * deletion of tax codes removed from templates For tax codes, it make sense to propose deletion, since tax codes are normally defined by the tax authority and the user does not customize them. * update accounts on taxes even if an update of the account was not requested Useful when the chart of taxes changes but the chart of account need not be updated. * depth-first search of tax codes This helps creating parents before children. * compare more fields in taxes * add active field on tax code Deactivate tax codes which are not in the template. * deactivate taxes that are not in the template * multi-company criteria for taxes * avoid inserting duplicates in presence of inactive taxes or tax codes --- account_chart_update/__init__.py | 2 + account_chart_update/__openerp__.py | 2 +- account_chart_update/model/__init__.py | 1 + .../model/account_tax_code.py | 27 +++ .../wizard/wizard_chart_update.py | 208 +++++++++++++++--- .../wizard/wizard_chart_update_view.xml | 4 + 6 files changed, 214 insertions(+), 30 deletions(-) create mode 100644 account_chart_update/model/__init__.py create mode 100644 account_chart_update/model/account_tax_code.py diff --git a/account_chart_update/__init__.py b/account_chart_update/__init__.py index d04374b714a..4319b4213ec 100644 --- a/account_chart_update/__init__.py +++ b/account_chart_update/__init__.py @@ -23,4 +23,6 @@ """ Account Chart Update Wizard """ + +from . import model from . import wizard diff --git a/account_chart_update/__openerp__.py b/account_chart_update/__openerp__.py index e1f10c21bd8..80afbf9fe40 100644 --- a/account_chart_update/__openerp__.py +++ b/account_chart_update/__openerp__.py @@ -27,7 +27,7 @@ { 'name': "Detect changes and update the Account Chart from a template", 'version': "1.2", - 'author': "Zikzakmedia SL", + 'author': "Zikzakmedia SL,Odoo Community Association (OCA)", 'website': "www.zikzakmedia.com", 'depends': ["account"], 'category': "Generic Modules/Accounting", diff --git a/account_chart_update/model/__init__.py b/account_chart_update/model/__init__.py new file mode 100644 index 00000000000..a7362088adf --- /dev/null +++ b/account_chart_update/model/__init__.py @@ -0,0 +1 @@ +from . import account_tax_code diff --git a/account_chart_update/model/account_tax_code.py b/account_chart_update/model/account_tax_code.py new file mode 100644 index 00000000000..ae68fd812fd --- /dev/null +++ b/account_chart_update/model/account_tax_code.py @@ -0,0 +1,27 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (c) 2014 ACSONE SA/NV (http://acsone.eu) +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp import models, fields + + +class AccountTaxCode(models.Model): + _inherit = 'account.tax.code' + + active = fields.Boolean('Active', default=True) diff --git a/account_chart_update/wizard/wizard_chart_update.py b/account_chart_update/wizard/wizard_chart_update.py index 891faf0db30..149060448e8 100644 --- a/account_chart_update/wizard/wizard_chart_update.py +++ b/account_chart_update/wizard/wizard_chart_update.py @@ -194,6 +194,14 @@ def _get_lang_selection_options(self, cr, uid, context=None): 'Updated fiscal positions', readonly=True ), + 'deleted_tax_codes': fields.integer( + 'Deactivated tax codes', + readonly=True + ), + 'deleted_taxes': fields.integer( + 'Deactivated taxes', + readonly=True + ), 'log': fields.text('Messages and Errors', readonly=True) } @@ -324,6 +332,8 @@ def _map_tax_template(self, cr, uid, wizard, tax_templ_mapping, """ Adds a tax template -> tax id to the mapping. """ + if context is None: + context = {} if not tax_templ: return False if tax_templ_mapping.get(tax_templ.id): @@ -337,7 +347,11 @@ def _map_tax_template(self, cr, uid, wizard, tax_templ_mapping, criteria = (['|', '|'] + criteria + [('description', '=', tax_templ.description), ('name', '=', tax_templ.description)]) - tax_ids = tax_obj.search(cr, uid, criteria, context=context) + criteria += [('company_id', '=', wizard.company_id.id)] + # search inactive taxes too, to avoid re-creating + # taxes that have been deactivated before + search_context = dict(context, active_test=False) + tax_ids = tax_obj.search(cr, uid, criteria, context=search_context) tax_templ_mapping[tax_templ.id] = tax_ids and tax_ids[0] or False return tax_templ_mapping[tax_templ.id] @@ -353,24 +367,25 @@ def _map_tax_code_template(self, cr, uid, wizard, return False if tax_code_templ_mapping.get(tax_code_template.id): return tax_code_templ_mapping[tax_code_template.id] - # In other case + # prepare a search context in order to + # search inactive tax codes too, to avoid re-creating + # tax codes that have been deactivated before + search_context = dict(context, active_test=False) tax_code_obj = self.pool['account.tax.code'] root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id - tax_code_name = ((tax_code_template.id == root_tax_code_id) and - wizard.company_id.name or tax_code_template.name) - tax_code_ids = tax_code_obj.search(cr, uid, [ - ('name', '=', tax_code_name), - ('company_id', '=', wizard.company_id.id) - ], context=context) - if not tax_code_ids: - # if we could not match no tax code template name, - # try to match on tax code template code, if any - tax_code_code = tax_code_template.code - if tax_code_code: - tax_code_ids = tax_code_obj.search(cr, uid, [ - ('code', '=', tax_code_code), - ('company_id', '=', wizard.company_id.id) - ], context=context) + tax_code_code = tax_code_template.code + if tax_code_code: + tax_code_ids = tax_code_obj.search(cr, uid, [ + ('code', '=', tax_code_code), + ('company_id', '=', wizard.company_id.id) + ], context=search_context) + if not tax_code_code or not tax_code_ids: + tax_code_name = ((tax_code_template.id == root_tax_code_id) and + wizard.company_id.name or tax_code_template.name) + tax_code_ids = tax_code_obj.search(cr, uid, [ + ('name', '=', tax_code_name), + ('company_id', '=', wizard.company_id.id) + ], context=search_context) tax_code_templ_mapping[tax_code_template.id] = (tax_code_ids and tax_code_ids[0] or False) @@ -416,6 +431,21 @@ def _map_fp_template(self, cr, uid, wizard, fp_templ_mapping, fp_templ_mapping[fp_template.id] = fp_ids and fp_ids[0] or False return fp_templ_mapping[fp_template.id] + def _get_depth_first_tax_code_template_ids(self, cr, uid, root_tax_code_id, + context=None): + tax_code_templ_obj = self.pool['account.tax.code.template'] + + def get_children(tct): + for child in tct.child_ids: + res.append(child.id) + get_children(child) + + tct = tax_code_templ_obj.browse(cr, uid, root_tax_code_id, + context=context) + res = [tct.id] + get_children(tct) + return res + def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, context=None): """ @@ -436,9 +466,9 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, wiz_tax_code_obj.unlink(cr, uid, wiz_tax_code_obj.search(cr, uid, [])) # Search for new / updated tax codes root_tax_code_id = wizard.chart_template_id.tax_code_root_id.id - children_tax_code_template = tax_code_templ_obj.search(cr, uid, [( - 'parent_id', 'child_of', [root_tax_code_id])], order='id', - context=context) + children_tax_code_template = \ + self._get_depth_first_tax_code_template_ids( + cr, uid, root_tax_code_id, context=context) for tax_code_template in tax_code_templ_obj.browse( cr, uid, children_tax_code_template, context=context): @@ -463,6 +493,9 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, notes = "" tax_code = tax_code_obj.browse( cr, uid, tax_code_id, context=context) + if tax_code.name != tax_code_template.name: + notes += _("The name field is different.\n") + modified = True if tax_code.code != tax_code_template.code: notes += _("The code field is different.\n") modified = True @@ -472,7 +505,18 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, if tax_code.sign != tax_code_template.sign: notes += _("The sign field is different.\n") modified = True - # TODO: We could check other account fields for changes... + if tax_code.notprintable != tax_code_template.notprintable: + notes += _("The notprintable field is different.\n") + modified = True + if tax_code.sequence != tax_code_template.sequence: + notes += _("The sequence field is different.\n") + modified = True + if tax_code.parent_id.id != self._map_tax_code_template( + cr, uid, wizard, + tax_code_template_mapping, + tax_code_template.parent_id, context=context): + notes += _("The parent field is different.\n") + modified = True if modified: # Tax code to update. updated_tax_codes += 1 @@ -483,6 +527,24 @@ def _find_tax_codes(self, cr, uid, wizard, chart_template_ids, 'update_tax_code_id': tax_code_id, 'notes': notes, }, context) + # search for tax codes not in the template + # and propose them for deletion + tax_code_ids = tax_code_obj.\ + search(cr, uid, [('company_id', '=', wizard.company_id.id)], + context=context) + tax_code_ids = set(tax_code_ids) + template_tax_code_ids = set(tax_code_template_mapping.values()) + tax_code_ids_to_delete = tax_code_ids - template_tax_code_ids + for tax_code_id in tax_code_ids_to_delete: + updated_tax_codes += 1 + wiz_tax_code_obj.create(cr, uid, { + 'tax_code_id': False, + 'update_chart_wizard_id': wizard.id, + 'type': 'deleted', + 'update_tax_code_id': tax_code_id, + 'notes': "To deactivate: not in the template", + }, context) + return { 'new': new_tax_codes, 'updated': updated_tax_codes, @@ -499,6 +561,8 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): new_taxes = 0 updated_taxes = 0 tax_templ_mapping = {} + tax_code_template_mapping = {} + acc_templ_mapping = {} tax_obj = self.pool['account.tax'] tax_templ_obj = self.pool['account.tax.template'] wiz_taxes_obj = self.pool['wizard.update.charts.accounts.tax'] @@ -569,6 +633,46 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): if tax.type_tax_use != tax_templ.type_tax_use: notes += _("The type tax use field is different.\n") modified = True + # compare tax code fields + if tax.base_code_id.id != self._map_tax_code_template( + cr, uid, wizard, + tax_code_template_mapping, + tax_templ.base_code_id, context=context): + notes += _("The base_code_id field is different.\n") + modified = True + if tax.tax_code_id.id != self._map_tax_code_template( + cr, uid, wizard, + tax_code_template_mapping, + tax_templ.tax_code_id, context=context): + notes += _("The tax_code_id field is different.\n") + modified = True + if tax.ref_base_code_id.id != self._map_tax_code_template( + cr, uid, wizard, + tax_code_template_mapping, + tax_templ.ref_base_code_id, context=context): + notes += _("The ref_base_code_id field is different.\n") + modified = True + if tax.ref_tax_code_id.id != self._map_tax_code_template( + cr, uid, wizard, + tax_code_template_mapping, + tax_templ.ref_tax_code_id, context=context): + notes += _("The ref_tax_code_id field is different.\n") + modified = True + # compare tax account fields + if tax.account_paid_id.id != self._map_account_template( + cr, uid, wizard, + acc_templ_mapping, + tax_templ.account_paid_id, + context=context): + notes += _("The account_paid field is different.\n") + modified = True + if tax.account_collected_id.id != self._map_account_template( + cr, uid, wizard, + acc_templ_mapping, + tax_templ.account_collected_id, + context=context): + notes += _("The account_collected field is different.\n") + modified = True # TODO: We could check other tax fields for changes... if modified: # Tax code to update. @@ -582,6 +686,23 @@ def _find_taxes(self, cr, uid, wizard, chart_template_ids, context=None): }, context) for delay_vals_wiz in delay_wiz_tax: wiz_taxes_obj.create(cr, uid, delay_vals_wiz, context) + # search for taxes not in the template + # and propose them for deletion + tax_ids = tax_obj.\ + search(cr, uid, [('company_id', '=', wizard.company_id.id)], + context=context) + tax_ids = set(tax_ids) + template_tax_ids = set(tax_templ_mapping.values()) + tax_ids_to_delete = tax_ids - template_tax_ids + for tax_id in tax_ids_to_delete: + updated_taxes += 1 + wiz_taxes_obj.create(cr, uid, { + 'tax_id': False, + 'update_chart_wizard_id': wizard.id, + 'type': 'deleted', + 'update_tax_id': tax_id, + 'notes': "To deactivate: not in the template", + }, context) return {'new': new_taxes, 'updated': updated_taxes, @@ -848,7 +969,10 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): new_tax_codes = 0 updated_tax_codes = 0 tax_code_template_mapping = {} + # process new/updated for wiz_tax_code in wizard.tax_code_ids: + if wiz_tax_code.type == 'deleted': + continue tax_code_template = wiz_tax_code.tax_code_id tax_code_name = ((root_tax_code_id == tax_code_template.id) and wizard.company_id.name or tax_code_template.name) @@ -867,6 +991,8 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): tax_code_template_mapping.get(p_id)), 'company_id': wizard.company_id.id, 'sign': tax_code_template.sign, + 'notprintable': tax_code_template.notprintable, + 'sequence': tax_code_template.sequence, } tax_code_id = None modified = False @@ -900,9 +1026,19 @@ def _update_tax_codes(self, cr, uid, wizard, log, context=None): tax_code_name, tax_code_template.parent_id.name), True ) + # process deleted + tax_code_ids_to_delete = [wtc.update_tax_code_id.id + for wtc in wizard.tax_code_ids + if wtc.type == 'deleted'] + taxcodes.write(cr, uid, tax_code_ids_to_delete, + {'active': False}, + context=context) + log.add(_("Deactivated %d tax codes\n" % len(tax_code_ids_to_delete))) + deleted_tax_codes = len(tax_code_ids_to_delete) return { 'new': new_tax_codes, 'updated': updated_tax_codes, + 'deleted': deleted_tax_codes, 'mapping': tax_code_template_mapping } @@ -917,6 +1053,8 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, tax_template_mapping = {} taxes_pending_for_accounts = {} for wiz_tax in wizard.tax_ids: + if wiz_tax.type == 'deleted': + continue tax_template = wiz_tax.tax_id # Ensure the parent tax template is on the map. self._map_tax_template(cr, uid, wizard, tax_template_mapping, @@ -1058,9 +1196,19 @@ def _update_taxes(self, cr, uid, wizard, log, tax_code_template_mapping, ), True ) + # process deleted + tax_ids_to_delete = [wtc.update_tax_id.id + for wtc in wizard.tax_ids + if wtc.type == 'deleted'] + taxes.write(cr, uid, tax_ids_to_delete, + {'active': False}, + context=context) + log.add(_("Deactivated %d taxes\n" % len(tax_ids_to_delete))) + deleted_taxes = len(tax_ids_to_delete) return { 'new': new_taxes, 'updated': updated_taxes, + 'deleted': deleted_taxes, 'mapping': tax_template_mapping, 'pending': taxes_pending_for_accounts } @@ -1157,9 +1305,9 @@ def _update_accounts(self, cr, uid, wizard, log, tax_template_mapping, 'shortcut': account_template.shortcut, 'note': account_template.note, 'parent_id': ( - account_template.parent_id - and account_template_mapping.get(p_id) or - False + account_template_mapping.get(p_id) + if account_template.parent_id + else False ), 'tax_ids': [(6, 0, tax_ids)], 'company_id': wizard.company_id.id, @@ -1436,7 +1584,7 @@ def action_update_records(self, cr, uid, ids, context=None): accounts_res = self._update_accounts(cr, uid, wizard, log, taxes_res['mapping'], context=context) - if wizard.update_tax and wizard.update_account: + if wizard.update_tax: self._update_taxes_pending_for_accounts(cr, uid, wizard, log, taxes_res['pending'], accounts_res['mapping'], @@ -1461,6 +1609,8 @@ def action_update_records(self, cr, uid, ids, context=None): 'updated_taxes': taxes_res.get('updated', 0), 'updated_accounts': accounts_res.get('updated', 0), 'updated_fps': fps_res.get('updated', 0), + 'deleted_tax_codes': tax_codes_res.get('deleted', 0), + 'deleted_taxes': taxes_res.get('deleted', 0), 'log': log(), }, context=context) return _reopen(self, wizard.id, 'wizard.update.chart.accounts') @@ -1477,7 +1627,6 @@ class wizard_update_charts_accounts_tax_code(orm.TransientModel): 'tax_code_id': fields.many2one( 'account.tax.code.template', 'Tax code template', - required=True, ondelete='set null' ), 'update_chart_wizard_id': fields.many2one( @@ -1487,8 +1636,9 @@ class wizard_update_charts_accounts_tax_code(orm.TransientModel): ondelete='cascade' ), 'type': fields.selection([ - ('new', 'New template'), - ('updated', 'Updated template'), + ('new', 'New tax code'), + ('updated', 'Updated tax code'), + ('deleted', 'Tax code to deactivate'), ], 'Type'), 'update_tax_code_id': fields.many2one( 'account.tax.code', @@ -1513,7 +1663,6 @@ class wizard_update_charts_accounts_tax(orm.TransientModel): 'tax_id': fields.many2one( 'account.tax.template', 'Tax template', - required=True, ondelete='set null' ), 'update_chart_wizard_id': fields.many2one( @@ -1525,6 +1674,7 @@ class wizard_update_charts_accounts_tax(orm.TransientModel): 'type': fields.selection([ ('new', 'New template'), ('updated', 'Updated template'), + ('deleted', 'Tax to deactivate'), ], 'Type'), 'update_tax_id': fields.many2one( 'account.tax', diff --git a/account_chart_update/wizard/wizard_chart_update_view.xml b/account_chart_update/wizard/wizard_chart_update_view.xml index 91c7927d8bb..f4f1586e619 100644 --- a/account_chart_update/wizard/wizard_chart_update_view.xml +++ b/account_chart_update/wizard/wizard_chart_update_view.xml @@ -113,6 +113,10 @@ + + + +