2013-10-01 18:28:19 +02:00
|
|
|
# -*- coding: utf-8 -*-
|
2016-05-25 14:05:38 +02:00
|
|
|
# © 2010 Jordi Esteve, Zikzakmedia S.L. (http://www.zikzakmedia.com)
|
|
|
|
# © 2010 Pexego Sistemas Informáticos S.L.(http://www.pexego.es)
|
|
|
|
# Borja López Soilán
|
|
|
|
# © 2013 Joaquin Gutierrez (http://www.gutierrezweb.es)
|
|
|
|
# © 2015 Antonio Espinosa <antonioea@tecnativa.com>
|
|
|
|
# © 2016 Jairo Llopis <jairo.llopis@tecnativa.com>
|
|
|
|
# © 2016 Jacques-Etienne Baudoux <je@bcim.be>
|
|
|
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
|
|
|
|
|
|
|
from openerp import models, fields, api, exceptions, _, tools
|
|
|
|
from contextlib import closing
|
|
|
|
from cStringIO import StringIO
|
2013-10-01 18:28:19 +02:00
|
|
|
import logging
|
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
_logger = logging.getLogger(__name__)
|
2013-10-01 18:28:19 +02:00
|
|
|
|
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
class WizardUpdateChartsAccounts(models.TransientModel):
|
2013-10-01 18:28:19 +02:00
|
|
|
_name = 'wizard.update.charts.accounts'
|
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
state = fields.Selection(
|
2016-05-25 14:05:38 +02:00
|
|
|
selection=[('init', 'Configuration'),
|
|
|
|
('ready', 'Select records to update'),
|
2015-03-28 14:56:47 +01:00
|
|
|
('done', 'Wizard completed')],
|
|
|
|
string='Status', readonly=True, default='init')
|
|
|
|
company_id = fields.Many2one(
|
|
|
|
comodel_name='res.company', string='Company', required=True,
|
|
|
|
ondelete='set null', default=lambda self: self.env.user.company_id.id)
|
|
|
|
chart_template_id = fields.Many2one(
|
|
|
|
comodel_name='account.chart.template', string='Chart Template',
|
2016-05-25 14:05:38 +02:00
|
|
|
ondelete='cascade', required=True)
|
|
|
|
chart_template_ids = fields.Many2many(
|
|
|
|
"account.chart.template",
|
|
|
|
string="Chart Templates",
|
|
|
|
compute="_compute_chart_template_ids",
|
|
|
|
help="Includes all chart templates.")
|
2015-03-28 14:56:47 +01:00
|
|
|
code_digits = fields.Integer(
|
|
|
|
string='# 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(
|
2016-05-25 14:05:38 +02:00
|
|
|
lambda self: self._get_lang_selection_options(), 'Language', size=5,
|
|
|
|
required=True,
|
|
|
|
help="For records searched by name (taxes, fiscal "
|
2015-03-28 14:56:47 +01:00
|
|
|
"positions), the template name will be matched against the "
|
|
|
|
"record name on this language.",
|
2016-05-25 14:05:38 +02:00
|
|
|
default=lambda self: self.env.context.get('lang', self.env.user.lang))
|
2015-03-28 14:56:47 +01:00
|
|
|
update_tax = fields.Boolean(
|
|
|
|
string='Update taxes', default=True,
|
|
|
|
help="Existing taxes are updated. Taxes are searched by name.")
|
|
|
|
update_account = fields.Boolean(
|
|
|
|
string='Update accounts', default=True,
|
|
|
|
help="Existing accounts are updated. Accounts are searched by code.")
|
|
|
|
update_fiscal_position = fields.Boolean(
|
|
|
|
string='Update fiscal positions', default=True,
|
|
|
|
help="Existing fiscal positions are updated. Fiscal positions are "
|
|
|
|
"searched by name.")
|
|
|
|
continue_on_errors = fields.Boolean(
|
|
|
|
string="Continue on errors", default=False,
|
|
|
|
help="If set, the wizard will continue to the next step even if "
|
2017-08-14 19:36:35 +02:00
|
|
|
"there are minor errors.")
|
2015-03-28 14:56:47 +01:00
|
|
|
tax_ids = fields.One2many(
|
|
|
|
comodel_name='wizard.update.charts.accounts.tax', ondelete='cascade',
|
|
|
|
inverse_name='update_chart_wizard_id', string='Taxes')
|
|
|
|
account_ids = fields.One2many(
|
|
|
|
comodel_name='wizard.update.charts.accounts.account',
|
|
|
|
inverse_name='update_chart_wizard_id', string='Accounts',
|
|
|
|
ondelete='cascade')
|
|
|
|
fiscal_position_ids = fields.One2many(
|
|
|
|
comodel_name='wizard.update.charts.accounts.fiscal.position',
|
|
|
|
inverse_name='update_chart_wizard_id', string='Fiscal positions',
|
|
|
|
ondelete='cascade')
|
|
|
|
new_taxes = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='New taxes', compute="_compute_new_taxes_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
new_accounts = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='New accounts',
|
|
|
|
compute="_compute_new_accounts_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
new_fps = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='New fiscal positions',
|
|
|
|
compute="_compute_new_fps_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
updated_taxes = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='Updated taxes',
|
|
|
|
compute="_compute_updated_taxes_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
updated_accounts = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='Updated accounts',
|
|
|
|
compute="_compute_updated_accounts_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
updated_fps = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='Updated fiscal positions',
|
|
|
|
compute="_compute_updated_fps_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
deleted_taxes = fields.Integer(
|
2016-05-25 14:05:38 +02:00
|
|
|
string='Deactivated taxes',
|
|
|
|
compute="_compute_deleted_taxes_count")
|
2015-03-28 14:56:47 +01:00
|
|
|
log = fields.Text(string='Messages and Errors', readonly=True)
|
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.model
|
|
|
|
def _get_lang_selection_options(self):
|
|
|
|
"""Gets the available languages for the selection."""
|
|
|
|
langs = self.env['res.lang'].search([])
|
|
|
|
return [(lang.code, lang.name) for lang in langs]
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
|
|
|
@api.depends("chart_template_id")
|
|
|
|
def _compute_chart_template_ids(self):
|
|
|
|
self.chart_template_ids = (
|
|
|
|
self.env['wizard.multi.charts.accounts']
|
|
|
|
._get_chart_parent_ids(self.chart_template_id))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('tax_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_new_taxes_count(self):
|
|
|
|
self.new_taxes = len(self.tax_ids.filtered(lambda x: x.type == 'new'))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('account_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_new_accounts_count(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
self.new_accounts = len(
|
2016-05-25 14:05:38 +02:00
|
|
|
self.account_ids.filtered(lambda x: x.type == 'new'))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('fiscal_position_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_new_fps_count(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
self.new_fps = len(
|
2016-05-25 14:05:38 +02:00
|
|
|
self.fiscal_position_ids.filtered(lambda x: x.type == 'new'))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('tax_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_updated_taxes_count(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
self.updated_taxes = len(
|
2016-05-25 14:05:38 +02:00
|
|
|
self.tax_ids.filtered(lambda x: x.type == 'updated'))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('account_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_updated_accounts_count(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
self.updated_accounts = len(
|
2016-05-25 14:05:38 +02:00
|
|
|
self.account_ids.filtered(lambda x: x.type == 'updated'))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('fiscal_position_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_updated_fps_count(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
self.updated_fps = len(
|
2016-05-25 14:05:38 +02:00
|
|
|
self.fiscal_position_ids.filtered(lambda x: x.type == 'updated'))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.depends('tax_ids')
|
2016-05-25 14:05:38 +02:00
|
|
|
def _compute_deleted_taxes_count(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
self.deleted_taxes = len(
|
2016-05-25 14:05:38 +02:00
|
|
|
self.tax_ids.filtered(lambda x: x.type == 'deleted'))
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.onchange("company_id")
|
|
|
|
def _onchage_company_update_chart_template(self):
|
|
|
|
self.chart_template_id = self.company_id.chart_template_id
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.model
|
|
|
|
def _get_code_digits(self, company=None):
|
|
|
|
"""Returns the default code size for the accounts.
|
2014-06-30 11:12:36 +02:00
|
|
|
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).
|
|
|
|
"""
|
2015-03-28 14:56:47 +01:00
|
|
|
property_obj = self.env['ir.property']
|
|
|
|
if not company:
|
|
|
|
company = self.env.user.company_id
|
|
|
|
properties = property_obj.search(
|
|
|
|
[('name', '=', 'property_account_receivable'),
|
|
|
|
('company_id', '=', company.id),
|
|
|
|
('res_id', '=', False),
|
|
|
|
('value_reference', '!=', False)])
|
2014-11-27 10:18:59 +01:00
|
|
|
number_digits = 6
|
2015-03-28 14:56:47 +01:00
|
|
|
if not properties:
|
2013-10-01 18:28:19 +02:00
|
|
|
# Try to get a generic (no-company) property
|
2015-03-28 14:56:47 +01:00
|
|
|
properties = property_obj.search(
|
|
|
|
[('name', '=', 'property_account_receivable'),
|
|
|
|
('res_id', '=', False),
|
|
|
|
('value_reference', '!=', False)])
|
|
|
|
if properties:
|
|
|
|
account = property_obj.get_by_record(properties[0])
|
2014-11-27 10:18:59 +01:00
|
|
|
if account:
|
|
|
|
number_digits = len(account.code)
|
2013-10-01 18:28:19 +02:00
|
|
|
return number_digits
|
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.onchange('company_id')
|
|
|
|
def onchange_company_id(self):
|
|
|
|
"""Update the code digits when the company changes"""
|
|
|
|
self.code_digits = self._get_code_digits(company=self.company_id)
|
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
|
|
|
def _reopen(self):
|
|
|
|
return {
|
|
|
|
'type': 'ir.actions.act_window',
|
|
|
|
'view_mode': 'form',
|
|
|
|
'view_type': 'form',
|
|
|
|
'res_id': self.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': self._name,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.multi
|
|
|
|
def action_init(self):
|
|
|
|
"""Initial action that sets the initial state."""
|
2016-05-25 14:05:38 +02:00
|
|
|
self.state = 'init'
|
|
|
|
return self._reopen()
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
@api.multi
|
|
|
|
def action_find_records(self):
|
|
|
|
"""Searchs for records to update/create and shows them."""
|
|
|
|
self = self.with_context(lang=self.lang)
|
|
|
|
# Search for, and load, the records to create/update.
|
|
|
|
if self.update_tax:
|
2016-05-25 14:05:38 +02:00
|
|
|
self._find_taxes()
|
2015-03-28 14:56:47 +01:00
|
|
|
if self.update_account:
|
2016-05-25 14:05:38 +02:00
|
|
|
self._find_accounts()
|
2015-03-28 14:56:47 +01:00
|
|
|
if self.update_fiscal_position:
|
2016-05-25 14:05:38 +02:00
|
|
|
self._find_fiscal_positions()
|
2015-03-28 14:56:47 +01:00
|
|
|
# Write the results, and go to the next step.
|
2016-05-25 14:05:38 +02:00
|
|
|
self.state = 'ready'
|
|
|
|
return self._reopen()
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.multi
|
|
|
|
def action_update_records(self):
|
2016-05-25 14:05:38 +02:00
|
|
|
"""Action that creates/updates/deletes the selected elements."""
|
|
|
|
self = self.with_context(lang=self.lang)
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
with closing(StringIO()) as log_output:
|
|
|
|
handler = logging.StreamHandler(log_output)
|
|
|
|
_logger.addHandler(handler)
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
# Create or update the records.
|
|
|
|
if self.update_tax:
|
|
|
|
self._update_taxes()
|
|
|
|
if self.update_account:
|
|
|
|
self._update_accounts()
|
|
|
|
if self.update_fiscal_position:
|
|
|
|
self._update_fiscal_positions()
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
# Store new chart in the company
|
|
|
|
self.company_id.chart_template_id = self.chart_template_id
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
_logger.removeHandler(handler)
|
|
|
|
self.log = log_output.getvalue()
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
# Check if errors where detected and wether we should stop.
|
|
|
|
if self.log and not self.continue_on_errors:
|
|
|
|
raise exceptions.Warning(
|
|
|
|
_("One or more errors detected!\n\n%s") % self.log)
|
|
|
|
|
|
|
|
# Store the data and go to the next step.
|
|
|
|
self.state = 'done'
|
|
|
|
return self._reopen()
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
@tools.ormcache("templates")
|
|
|
|
def find_tax_by_templates(self, templates):
|
|
|
|
"""Find a tax that matches the template."""
|
2015-03-28 14:56:47 +01:00
|
|
|
# search inactive taxes too, to avoid re-creating
|
|
|
|
# taxes that have been deactivated before
|
2016-05-25 14:05:38 +02:00
|
|
|
Tax = self.env['account.tax'].with_context(active_test=False)
|
|
|
|
result = Tax
|
|
|
|
for template in templates:
|
|
|
|
single = Tax
|
|
|
|
criteria = (
|
|
|
|
("name", "=", template.name),
|
|
|
|
("description", "=", template.name),
|
|
|
|
("name", "=", template.description),
|
|
|
|
("description", "=", template.description),
|
|
|
|
)
|
|
|
|
for domain in criteria:
|
|
|
|
if single:
|
|
|
|
break
|
|
|
|
if domain[2]:
|
|
|
|
single = Tax.search(
|
|
|
|
[domain,
|
|
|
|
("company_id", "=", self.company_id.id),
|
|
|
|
("type_tax_use", "=", template.type_tax_use)],
|
|
|
|
limit=1)
|
|
|
|
result |= single
|
|
|
|
return result
|
|
|
|
|
|
|
|
@api.model
|
|
|
|
@tools.ormcache("code")
|
|
|
|
def padded_code(self, code):
|
|
|
|
"""Return a right-zero-padded code with the chosen digits."""
|
|
|
|
return code.ljust(self.code_digits, '0')
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
@tools.ormcache("templates")
|
|
|
|
def find_account_by_templates(self, templates):
|
|
|
|
"""Find an account that matches the template."""
|
|
|
|
return self.env['account.account'].search(
|
|
|
|
[('code', 'in', map(self.padded_code, templates.mapped("code"))),
|
2015-03-28 14:56:47 +01:00
|
|
|
('company_id', '=', self.company_id.id)])
|
|
|
|
|
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
@tools.ormcache("templates")
|
|
|
|
def find_fp_by_templates(self, templates):
|
|
|
|
"""Find a real fiscal position from a template."""
|
|
|
|
return self.env['account.fiscal.position'].search(
|
|
|
|
[('name', 'in', templates.mapped("name")),
|
2015-03-28 14:56:47 +01:00
|
|
|
('company_id', '=', self.company_id.id)])
|
2016-05-25 14:05:38 +02:00
|
|
|
|
|
|
|
@api.multi
|
2017-08-14 19:36:35 +02:00
|
|
|
@tools.ormcache("templates", "current_fp_accounts")
|
|
|
|
def find_fp_account_by_templates(self, templates, current_fp_accounts):
|
2016-05-25 14:05:38 +02:00
|
|
|
result = []
|
|
|
|
for tpl in templates:
|
2017-08-14 19:36:35 +02:00
|
|
|
pos = self.find_fp_by_templates(tpl.position_id)
|
|
|
|
src = self.find_account_by_templates(tpl.account_src_id)
|
|
|
|
dest = self.find_account_by_templates(tpl.account_dest_id)
|
|
|
|
mappings = self.env["account.fiscal.position.account"].search([
|
|
|
|
("position_id", "=", pos.id),
|
|
|
|
("account_src_id", "=", src.id),
|
|
|
|
])
|
|
|
|
existing = mappings.filtered(lambda x: x.account_dest_id == dest)
|
|
|
|
if not existing:
|
2016-05-25 14:05:38 +02:00
|
|
|
# create a new mapping
|
|
|
|
result.append((0, 0, {
|
2017-08-14 19:36:35 +02:00
|
|
|
'position_id': pos.id,
|
|
|
|
'account_src_id': src.id,
|
|
|
|
'account_dest_id': dest.id,
|
|
|
|
}))
|
|
|
|
else:
|
|
|
|
current_fp_accounts -= existing
|
|
|
|
# Mark to be removed the lines not found
|
|
|
|
if current_fp_accounts:
|
|
|
|
result += [(2, x.id) for x in current_fp_accounts]
|
2016-05-25 14:05:38 +02:00
|
|
|
return result
|
|
|
|
|
|
|
|
@api.multi
|
2017-08-14 19:36:35 +02:00
|
|
|
@tools.ormcache("templates", "current_fp_taxes")
|
|
|
|
def find_fp_tax_by_templates(self, templates, current_fp_taxes):
|
2016-05-25 14:05:38 +02:00
|
|
|
result = []
|
|
|
|
for tpl in templates:
|
2017-08-14 19:36:35 +02:00
|
|
|
pos = self.find_fp_by_templates(tpl.position_id)
|
|
|
|
src = self.find_tax_by_templates(tpl.tax_src_id)
|
|
|
|
dest = self.find_tax_by_templates(tpl.tax_dest_id)
|
|
|
|
mappings = self.env["account.fiscal.position.tax"].search([
|
|
|
|
("position_id", "=", pos.id),
|
|
|
|
("tax_src_id", "=", src.id),
|
|
|
|
])
|
|
|
|
existing = mappings.filtered(lambda x: x.tax_dest_id == dest)
|
|
|
|
if not existing:
|
2016-05-25 14:05:38 +02:00
|
|
|
# create a new mapping
|
|
|
|
result.append((0, 0, {
|
2017-08-14 19:36:35 +02:00
|
|
|
'position_id': pos.id,
|
|
|
|
'tax_src_id': src.id,
|
|
|
|
'tax_dest_id': dest.id,
|
|
|
|
}))
|
|
|
|
else:
|
|
|
|
current_fp_taxes -= existing
|
|
|
|
# Mark to be removed the lines not found
|
|
|
|
if current_fp_taxes:
|
|
|
|
result += [(2, x.id) for x in current_fp_taxes]
|
2016-05-25 14:05:38 +02:00
|
|
|
return result
|
|
|
|
|
|
|
|
@api.model
|
|
|
|
@tools.ormcache("template")
|
|
|
|
def fields_to_ignore(self, template):
|
|
|
|
"""Get fields that will not be used when checking differences.
|
|
|
|
|
|
|
|
:param str template:
|
|
|
|
The template record.
|
|
|
|
|
|
|
|
:return set:
|
|
|
|
Fields to ignore in diff.
|
2014-03-21 02:01:05 +01:00
|
|
|
"""
|
2016-05-25 14:05:38 +02:00
|
|
|
specials = {
|
|
|
|
"account.account.template": {
|
|
|
|
"code",
|
|
|
|
},
|
|
|
|
"account.tax.template": {
|
|
|
|
"account_id",
|
|
|
|
"refund_account_id",
|
|
|
|
}
|
|
|
|
}
|
2017-08-14 19:36:35 +02:00
|
|
|
to_include = {
|
|
|
|
"account.fiscal.position.template": [
|
|
|
|
'tax_ids',
|
|
|
|
'account_ids',
|
|
|
|
],
|
|
|
|
}
|
2016-05-25 14:05:38 +02:00
|
|
|
specials = ({"display_name", "__last_update"} |
|
|
|
|
specials.get(template._name, set()))
|
|
|
|
for key, field in template._fields.iteritems():
|
2017-08-14 19:36:35 +02:00
|
|
|
if (template._name in to_include and
|
|
|
|
key in to_include[template._name]):
|
2015-03-28 14:56:47 +01:00
|
|
|
continue
|
2016-05-25 14:05:38 +02:00
|
|
|
if ".template" in field.get_description(self.env).get(
|
|
|
|
"relation", ""):
|
|
|
|
specials.add(key)
|
|
|
|
return set(models.MAGIC_COLUMNS) | specials
|
|
|
|
|
|
|
|
@api.model
|
|
|
|
def diff_fields(self, template, real):
|
|
|
|
"""Get fields that are different in template and real records.
|
|
|
|
|
2017-03-14 11:54:08 +01:00
|
|
|
:param odoo.models.Model template:
|
2016-05-25 14:05:38 +02:00
|
|
|
Template record.
|
2017-03-14 11:54:08 +01:00
|
|
|
:param odoo.models.Model real:
|
2016-05-25 14:05:38 +02:00
|
|
|
Real record.
|
|
|
|
|
|
|
|
:return dict:
|
|
|
|
Fields that are different in both records, and the expected value.
|
2014-03-21 02:01:05 +01:00
|
|
|
"""
|
2016-05-25 14:05:38 +02:00
|
|
|
result = dict()
|
|
|
|
ignore = self.fields_to_ignore(template)
|
|
|
|
for key, field in template._fields.iteritems():
|
|
|
|
if key in ignore:
|
|
|
|
continue
|
|
|
|
relation = expected = t = None
|
|
|
|
# Code must be padded to check equality
|
|
|
|
if key == "code":
|
|
|
|
expected = self.padded_code(template.code)
|
|
|
|
# Translate template records to reals for comparison
|
|
|
|
else:
|
|
|
|
relation = field.get_description(self.env).get("relation", "")
|
|
|
|
if relation:
|
|
|
|
if ".tax.template" in relation:
|
|
|
|
t = "tax"
|
|
|
|
elif ".account.template" in relation:
|
|
|
|
t = "account"
|
|
|
|
if t:
|
|
|
|
find = getattr(
|
|
|
|
self,
|
|
|
|
"find_%s%s_by_templates" % (
|
|
|
|
"fp_" if ".fiscal.position" in relation
|
|
|
|
else "",
|
|
|
|
t))
|
2017-08-14 19:36:35 +02:00
|
|
|
if ".fiscal.position" in relation:
|
|
|
|
# Special case
|
|
|
|
expected = find(template[key], real[key])
|
|
|
|
else:
|
|
|
|
expected = find(template[key])
|
2016-05-25 14:05:38 +02:00
|
|
|
# Register detected differences
|
|
|
|
try:
|
|
|
|
if not relation:
|
|
|
|
if expected is not None and expected != real[key]:
|
|
|
|
result[key] = expected
|
|
|
|
elif template[key] != real[key]:
|
|
|
|
result[key] = template[key]
|
|
|
|
elif expected:
|
|
|
|
result[key] = expected
|
|
|
|
except KeyError:
|
|
|
|
pass
|
|
|
|
return result
|
|
|
|
|
|
|
|
@api.model
|
|
|
|
def diff_notes(self, template, real):
|
|
|
|
"""Get notes for humans on why is this record going to be updated.
|
|
|
|
|
|
|
|
:param openerp.models.Model template:
|
|
|
|
Template record.
|
|
|
|
|
|
|
|
:param openerp.models.Model real:
|
|
|
|
Real record.
|
|
|
|
|
|
|
|
:return str:
|
|
|
|
Notes result.
|
2014-03-21 02:01:05 +01:00
|
|
|
"""
|
2016-05-25 14:05:38 +02:00
|
|
|
result = list()
|
|
|
|
different_fields = sorted(
|
|
|
|
template._fields[f].get_description(self.env)["string"]
|
|
|
|
for f in self.diff_fields(template, real).keys())
|
|
|
|
if different_fields:
|
|
|
|
result.append(
|
|
|
|
_("Differences in these fields: %s.") %
|
|
|
|
", ".join(different_fields))
|
|
|
|
# Special for taxes
|
|
|
|
if template._name == "account.tax.template":
|
|
|
|
if not real.active:
|
|
|
|
result.append(_("Tax is disabled."))
|
|
|
|
return "\n".join(result)
|
|
|
|
|
|
|
|
@api.multi
|
|
|
|
def _find_taxes(self):
|
|
|
|
"""Search for, and load, tax templates to create/update/delete."""
|
|
|
|
found_taxes = self.env["account.tax"]
|
2015-03-28 14:56:47 +01:00
|
|
|
self.tax_ids.unlink()
|
2016-05-25 14:05:38 +02:00
|
|
|
|
|
|
|
# Search for changes between template and real tax
|
|
|
|
for template in self.chart_template_ids.mapped("tax_template_ids"):
|
|
|
|
# Check if the template matches a real tax
|
|
|
|
tax = self.find_tax_by_templates(template)
|
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
if not tax:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Tax to be created
|
|
|
|
self.tax_ids.create({
|
|
|
|
'tax_id': template.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_chart_wizard_id': self.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'type': 'new',
|
2014-03-21 02:01:05 +01:00
|
|
|
'notes': _('Name or description not found.'),
|
2016-05-25 14:05:38 +02:00
|
|
|
})
|
2015-03-28 14:56:47 +01:00
|
|
|
else:
|
2016-05-25 14:05:38 +02:00
|
|
|
found_taxes |= tax
|
|
|
|
|
|
|
|
# Check the tax for changes
|
|
|
|
notes = self.diff_notes(template, tax)
|
2015-03-28 14:56:47 +01:00
|
|
|
if notes:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Tax to be updated
|
|
|
|
self.tax_ids.create({
|
|
|
|
'tax_id': template.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_chart_wizard_id': self.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'type': 'updated',
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_tax_id': tax.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'notes': notes,
|
2015-03-28 14:56:47 +01:00
|
|
|
})
|
2016-05-25 14:05:38 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
# search for taxes not in the template and propose them for
|
|
|
|
# deactivation
|
|
|
|
taxes_to_delete = self.env['account.tax'].search(
|
2016-05-25 14:05:38 +02:00
|
|
|
[('company_id', '=', self.company_id.id),
|
|
|
|
("id", "not in", found_taxes.ids),
|
|
|
|
("active", "=", True)])
|
|
|
|
for tax in taxes_to_delete:
|
|
|
|
self.tax_ids.create({
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_chart_wizard_id': self.id,
|
2014-12-24 00:23:39 +01:00
|
|
|
'type': 'deleted',
|
2016-05-25 14:05:38 +02:00
|
|
|
'update_tax_id': tax.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'notes': _("To deactivate: not in the template"),
|
|
|
|
})
|
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
|
|
|
def _find_accounts(self):
|
|
|
|
"""Load account templates to create/update."""
|
2016-02-21 20:05:33 +01:00
|
|
|
self.account_ids.unlink()
|
2016-05-25 14:05:38 +02:00
|
|
|
|
|
|
|
for template in self.chart_template_ids.mapped("account_ids"):
|
|
|
|
# Search for a real account that matches the template
|
|
|
|
account = self.find_account_by_templates(template)
|
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
if not account:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Account to be created
|
|
|
|
self.account_ids.create({
|
|
|
|
'account_id': template.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_chart_wizard_id': self.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'type': 'new',
|
2016-05-25 14:05:38 +02:00
|
|
|
'notes': _('No account found with this code.'),
|
2015-03-28 14:56:47 +01:00
|
|
|
})
|
|
|
|
else:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Check the account for changes
|
|
|
|
notes = self.diff_notes(template, account)
|
2015-03-28 14:56:47 +01:00
|
|
|
if notes:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Account to be updated
|
|
|
|
self.account_ids.create({
|
|
|
|
'account_id': template.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_chart_wizard_id': self.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'type': 'updated',
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_account_id': account.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'notes': notes,
|
2015-03-28 14:56:47 +01:00
|
|
|
})
|
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
@api.multi
|
|
|
|
def _find_fiscal_positions(self):
|
|
|
|
"""Load fiscal position templates to create/update."""
|
2015-03-28 14:56:47 +01:00
|
|
|
wiz_fp = self.env['wizard.update.charts.accounts.fiscal.position']
|
|
|
|
self.fiscal_position_ids.unlink()
|
2017-03-14 11:54:08 +01:00
|
|
|
|
2013-10-01 18:28:19 +02:00
|
|
|
# Search for new / updated fiscal positions
|
2016-05-25 14:05:38 +02:00
|
|
|
templates = self.env['account.fiscal.position.template'].search(
|
|
|
|
[('chart_template_id', 'in', self.chart_template_ids.ids)])
|
|
|
|
for template in templates:
|
|
|
|
# Search for a real fiscal position that matches the template
|
|
|
|
fp = self.find_fp_by_templates(template)
|
2015-03-28 14:56:47 +01:00
|
|
|
if not fp:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Fiscal position to be created
|
2015-03-28 14:56:47 +01:00
|
|
|
wiz_fp.create({
|
2016-05-25 14:05:38 +02:00
|
|
|
'fiscal_position_id': template.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'update_chart_wizard_id': self.id,
|
2013-10-01 18:28:19 +02:00
|
|
|
'type': 'new',
|
2016-05-25 14:05:38 +02:00
|
|
|
'notes': _('No fiscal position found with this name.')
|
2015-03-28 14:56:47 +01:00
|
|
|
})
|
2016-05-25 14:05:38 +02:00
|
|
|
else:
|
|
|
|
# Check the fiscal position for changes
|
|
|
|
notes = self.diff_notes(template, fp)
|
|
|
|
if notes:
|
|
|
|
# Fiscal position template to be updated
|
|
|
|
wiz_fp.create({
|
|
|
|
'fiscal_position_id': template.id,
|
|
|
|
'update_chart_wizard_id': self.id,
|
|
|
|
'type': 'updated',
|
|
|
|
'update_fiscal_position_id': fp.id,
|
|
|
|
'notes': notes,
|
|
|
|
})
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
def _update_taxes(self):
|
|
|
|
"""Process taxes to create/update/deactivate."""
|
2015-03-28 14:56:47 +01:00
|
|
|
for wiz_tax in self.tax_ids:
|
2016-05-25 14:05:38 +02:00
|
|
|
template, tax = wiz_tax.tax_id, wiz_tax.update_tax_id
|
|
|
|
# Deactivate tax
|
2014-12-24 00:23:39 +01:00
|
|
|
if wiz_tax.type == 'deleted':
|
2016-05-25 14:05:38 +02:00
|
|
|
tax.active = False
|
|
|
|
_logger.debug(_("Deactivated tax %s."), tax)
|
2014-12-24 00:23:39 +01:00
|
|
|
continue
|
2016-05-25 14:05:38 +02:00
|
|
|
|
|
|
|
# Create tax
|
2013-10-01 18:28:19 +02:00
|
|
|
if wiz_tax.type == 'new':
|
2016-05-25 14:05:38 +02:00
|
|
|
tax = template._generate_tax(self.company_id)
|
|
|
|
tax = tax['tax_template_to_tax'][template.id]
|
|
|
|
_logger.debug(_("Created tax %s."), template.name)
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
# Update tax
|
|
|
|
else:
|
|
|
|
for key, value in self.diff_fields(template, tax).iteritems():
|
|
|
|
tax[key] = value
|
|
|
|
_logger.debug(_("Updated tax %s."), template.name)
|
|
|
|
wiz_tax.update_tax_id = tax
|
|
|
|
|
|
|
|
def _create_account_from_template(self, account_template):
|
|
|
|
return self.env["account.account"].create({
|
|
|
|
'name': account_template.name,
|
2015-03-28 14:56:47 +01:00
|
|
|
'currency_id': account_template.currency_id,
|
2016-05-25 14:05:38 +02:00
|
|
|
'code': self.padded_code(account_template.code),
|
|
|
|
'user_type_id': account_template.user_type_id.id,
|
2015-03-28 14:56:47 +01:00
|
|
|
'reconcile': account_template.reconcile,
|
|
|
|
'note': account_template.note,
|
2016-05-25 14:05:38 +02:00
|
|
|
'tax_ids': [
|
|
|
|
(6, 0,
|
|
|
|
self.find_tax_by_templates(account_template.tax_ids).ids),
|
|
|
|
],
|
2015-03-28 14:56:47 +01:00
|
|
|
'company_id': self.company_id.id,
|
2016-05-25 14:05:38 +02:00
|
|
|
})
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
def _update_accounts(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
"""Process accounts to create/update."""
|
|
|
|
for wiz_account in self.account_ids:
|
2016-05-25 14:05:38 +02:00
|
|
|
account, template = (wiz_account.update_account_id,
|
|
|
|
wiz_account.account_id)
|
2013-10-01 18:28:19 +02:00
|
|
|
if wiz_account.type == 'new':
|
|
|
|
# Create the account
|
|
|
|
try:
|
2016-05-25 14:05:38 +02:00
|
|
|
with self.env.cr.savepoint():
|
|
|
|
account = (
|
|
|
|
self._create_account_from_template(
|
|
|
|
template))
|
|
|
|
_logger.debug(
|
|
|
|
_("Created account %s."),
|
|
|
|
account.code)
|
|
|
|
except exceptions.except_orm:
|
|
|
|
_logger.exception(
|
|
|
|
_("Exception creating account %s."),
|
|
|
|
template.code)
|
2015-03-28 14:56:47 +01:00
|
|
|
else:
|
2013-10-01 18:28:19 +02:00
|
|
|
# Update the account
|
|
|
|
try:
|
2016-05-25 14:05:38 +02:00
|
|
|
with self.env.cr.savepoint():
|
|
|
|
for key, value in (self.diff_fields(template, account)
|
|
|
|
.iteritems()):
|
|
|
|
account[key] = value
|
|
|
|
_logger.debug(_("Updated account %s."), account)
|
|
|
|
except exceptions.except_orm:
|
|
|
|
_logger.exception(
|
|
|
|
_("Exception writing account %s."),
|
|
|
|
account)
|
|
|
|
wiz_account.update_account_id = account
|
|
|
|
|
|
|
|
if self.update_tax:
|
|
|
|
self._update_taxes_pending_for_accounts()
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
def _update_taxes_pending_for_accounts(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
"""Updates the taxes (created or updated on previous steps) to set
|
2014-03-21 02:01:05 +01:00
|
|
|
the references to the accounts (the taxes where created/updated first,
|
2015-03-28 14:56:47 +01:00
|
|
|
when the referenced accounts are still not available).
|
2014-03-21 02:01:05 +01:00
|
|
|
"""
|
2016-05-25 14:05:38 +02:00
|
|
|
for wiz_tax in self.tax_ids:
|
|
|
|
if wiz_tax.type == "deleted" or not wiz_tax.update_tax_id:
|
|
|
|
continue
|
|
|
|
|
|
|
|
for field in ("account_id", "refund_account_id"):
|
|
|
|
wiz_tax.update_tax_id[field] = (
|
|
|
|
self.find_account_by_templates(wiz_tax.tax_id[field]))
|
2015-03-28 14:56:47 +01:00
|
|
|
|
2016-05-25 14:05:38 +02:00
|
|
|
def _prepare_fp_vals(self, fp_template):
|
2015-03-28 14:56:47 +01:00
|
|
|
# Tax mappings
|
|
|
|
tax_mapping = []
|
|
|
|
for fp_tax in fp_template.tax_ids:
|
|
|
|
# Create the fp tax mapping
|
|
|
|
tax_mapping.append({
|
2016-05-25 14:05:38 +02:00
|
|
|
'tax_src_id': self.find_tax_by_templates(
|
|
|
|
fp_tax.tax_src_id).id,
|
|
|
|
'tax_dest_id': self.find_tax_by_templates(
|
|
|
|
fp_tax.tax_dest_id).id,
|
2015-03-28 14:56:47 +01:00
|
|
|
})
|
|
|
|
# Account mappings
|
|
|
|
account_mapping = []
|
|
|
|
for fp_account in fp_template.account_ids:
|
|
|
|
# Create the fp account mapping
|
|
|
|
account_mapping.append({
|
|
|
|
'account_src_id': (
|
2016-05-25 14:05:38 +02:00
|
|
|
self.find_account_by_templates(
|
|
|
|
fp_account.account_src_id).id),
|
2015-03-28 14:56:47 +01:00
|
|
|
'account_dest_id': (
|
2016-05-25 14:05:38 +02:00
|
|
|
self.find_account_by_templates(
|
|
|
|
fp_account.account_dest_id).id),
|
2015-03-28 14:56:47 +01:00
|
|
|
})
|
|
|
|
return {
|
|
|
|
'company_id': self.company_id.id,
|
|
|
|
'name': fp_template.name,
|
|
|
|
'tax_ids': [(0, 0, x) for x in tax_mapping],
|
|
|
|
'account_ids': [(0, 0, x) for x in account_mapping],
|
|
|
|
}
|
2013-10-01 18:28:19 +02:00
|
|
|
|
2015-03-28 14:56:47 +01:00
|
|
|
@api.multi
|
2016-05-25 14:05:38 +02:00
|
|
|
def _update_fiscal_positions(self):
|
2015-03-28 14:56:47 +01:00
|
|
|
"""Process fiscal position templates to create/update."""
|
|
|
|
for wiz_fp in self.fiscal_position_ids:
|
2016-05-25 14:05:38 +02:00
|
|
|
fp, template = (wiz_fp.update_fiscal_position_id,
|
|
|
|
wiz_fp.fiscal_position_id)
|
2013-10-01 18:28:19 +02:00
|
|
|
if wiz_fp.type == 'new':
|
|
|
|
# Create a new fiscal position
|
2016-05-25 14:05:38 +02:00
|
|
|
fp = self.env['account.fiscal.position'].create(
|
|
|
|
self._prepare_fp_vals(template))
|
2015-03-28 14:56:47 +01:00
|
|
|
else:
|
2016-05-25 14:05:38 +02:00
|
|
|
# Update the given fiscal position
|
|
|
|
for key, value in self.diff_fields(template, fp).iteritems():
|
2017-08-14 19:36:35 +02:00
|
|
|
fp[key] = value
|
2016-05-25 14:05:38 +02:00
|
|
|
wiz_fp.update_fiscal_position_id = fp
|
|
|
|
_logger.debug(
|
|
|
|
_("Created or updated fiscal position %s."),
|
|
|
|
template.name)
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
class WizardUpdateChartsAccountsTax(models.TransientModel):
|
2013-10-01 18:28:19 +02:00
|
|
|
_name = 'wizard.update.charts.accounts.tax'
|
2015-03-28 14:56:47 +01:00
|
|
|
_description = ("Tax that needs to be updated (new or updated in the "
|
|
|
|
"template).")
|
|
|
|
|
|
|
|
tax_id = fields.Many2one(
|
|
|
|
comodel_name='account.tax.template', string='Tax template',
|
|
|
|
ondelete='set null')
|
|
|
|
update_chart_wizard_id = fields.Many2one(
|
|
|
|
comodel_name='wizard.update.charts.accounts',
|
|
|
|
string='Update chart wizard', required=True, ondelete='cascade')
|
|
|
|
type = fields.Selection(
|
|
|
|
selection=[('new', 'New template'),
|
|
|
|
('updated', 'Updated template'),
|
2016-05-25 14:05:38 +02:00
|
|
|
('deleted', 'Tax to deactivate')],
|
|
|
|
string='Type',
|
|
|
|
readonly=True)
|
|
|
|
type_tax_use = fields.Selection(
|
|
|
|
related="tax_id.type_tax_use",
|
|
|
|
readonly=True)
|
2015-03-28 14:56:47 +01:00
|
|
|
update_tax_id = fields.Many2one(
|
|
|
|
comodel_name='account.tax', string='Tax to update', required=False,
|
|
|
|
ondelete='set null')
|
2016-05-25 14:05:38 +02:00
|
|
|
notes = fields.Text('Notes', readonly=True)
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
class WizardUpdateChartsAccountsAccount(models.TransientModel):
|
2013-10-01 18:28:19 +02:00
|
|
|
_name = 'wizard.update.charts.accounts.account'
|
2015-03-28 14:56:47 +01:00
|
|
|
_description = ("Account that needs to be updated (new or updated in the "
|
|
|
|
"template).")
|
|
|
|
|
|
|
|
account_id = fields.Many2one(
|
|
|
|
comodel_name='account.account.template', string='Account template',
|
|
|
|
required=True, ondelete='set null')
|
|
|
|
update_chart_wizard_id = fields.Many2one(
|
|
|
|
comodel_name='wizard.update.charts.accounts',
|
|
|
|
string='Update chart wizard', required=True, ondelete='cascade'
|
|
|
|
)
|
|
|
|
type = fields.Selection(
|
|
|
|
selection=[('new', 'New template'),
|
2016-05-25 14:05:38 +02:00
|
|
|
('updated', 'Updated template')],
|
|
|
|
string='Type',
|
|
|
|
readonly=True)
|
2015-03-28 14:56:47 +01:00
|
|
|
update_account_id = fields.Many2one(
|
|
|
|
comodel_name='account.account', string='Account to update',
|
|
|
|
required=False, ondelete='set null')
|
2016-05-25 14:05:38 +02:00
|
|
|
notes = fields.Text('Notes', readonly=True)
|
2015-03-28 14:56:47 +01:00
|
|
|
|
|
|
|
|
|
|
|
class WizardUpdateChartsAccountsFiscalPosition(models.TransientModel):
|
2013-10-01 18:28:19 +02:00
|
|
|
_name = 'wizard.update.charts.accounts.fiscal.position'
|
2015-03-28 14:56:47 +01:00
|
|
|
_description = ("Fiscal position that needs to be updated (new or updated "
|
|
|
|
"in the template).")
|
|
|
|
|
|
|
|
fiscal_position_id = fields.Many2one(
|
|
|
|
comodel_name='account.fiscal.position.template',
|
|
|
|
string='Fiscal position template', required=True, ondelete='set null')
|
|
|
|
update_chart_wizard_id = fields.Many2one(
|
|
|
|
comodel_name='wizard.update.charts.accounts',
|
|
|
|
string='Update chart wizard', required=True, ondelete='cascade')
|
|
|
|
type = fields.Selection(
|
|
|
|
selection=[('new', 'New template'),
|
2016-05-25 14:05:38 +02:00
|
|
|
('updated', 'Updated template')],
|
2017-08-14 19:36:35 +02:00
|
|
|
string='Type', readonly=True, required=True,
|
|
|
|
)
|
2015-03-28 14:56:47 +01:00
|
|
|
update_fiscal_position_id = fields.Many2one(
|
|
|
|
comodel_name='account.fiscal.position', required=False,
|
|
|
|
string='Fiscal position to update', ondelete='set null')
|
2016-05-25 14:05:38 +02:00
|
|
|
notes = fields.Text('Notes', readonly=True)
|