[FIX] account,l10n_lu: Adds a migration for the l10n_lu that will get the latest taxes

All taxes change in Luxembourg, we added a script that will create or update taxes so the clients don't have to
manually update everything or ask the support to do it for them. We don't modify custom taxes.

closes odoo/odoo#108699

Task: 3098941
Related: #104833
X-original-commit: c44a33d67065e20c4ded2a229d0663191c91a0a0
Signed-off-by: William André (wan) <wan@odoo.com>
Signed-off-by: Claire Bretton <clbr@odoo.com>
This commit is contained in:
Claire Bretton (clbr)
2022-12-27 11:17:44 +01:00
parent 8e20e965f0
commit 068f3edff9
4 changed files with 144 additions and 1 deletions
+15
View File
@@ -10233,6 +10233,15 @@ msgstr ""
msgid "Please create new accounts from the Chart of Accounts menu."
msgstr ""
#. module: account
#: code:addons/account/models/chart_template.py:0
#, python-format
msgid ""
"Please check these taxes. They might be outdated. We did not update them. "
"Indeed, they do not exactly match the taxes of the original version of the localization module."
"<br/>You might want to archive or adapt them.<br/><ul>"
msgstr ""
#. module: account
#: code:addons/account/models/account_payment.py:0
#, python-format
@@ -15434,6 +15443,12 @@ msgstr ""
msgid "You should update this document to reflect your T&amp;C."
msgstr ""
#. module: account
#: code:addons/account/models/chart_template.py:0
#, python-format
msgid "Your taxes have been updated !"
msgstr ""
#. module: account
#: model_terms:ir.ui.view,arch_db:account.view_account_position_form
msgid "Zip Range"
+122
View File
@@ -7,6 +7,7 @@ from odoo.exceptions import UserError, ValidationError
from odoo.http import request
from odoo.addons.account.models.account_tax import TYPE_TAX_USE
from odoo.addons.account.models.account_account import ACCOUNT_CODE_REGEX
from odoo.tools import html_escape
import logging
import re
@@ -32,6 +33,127 @@ def preserve_existing_tags_on_taxes(cr, registry, module):
if xml_records:
cr.execute("update ir_model_data set noupdate = 't' where id in %s", [tuple(xml_records.ids)])
def update_taxes_from_templates(cr, chart_template_xmlid):
def _create_tax_from_template(company, template, old_tax=None):
"""
Create a new tax from template with template xmlid, if there was already an old tax with that xmlid we
remove the xmlid from it but don't modify anything else.
"""
def _remove_xml_id(xml_id):
module, name = xml_id.split(".", 1)
env['ir.model.data'].search([('module', '=', module), ('name', '=', name)]).unlink()
template_vals = template._get_tax_vals_complete(company)
chart_template = env["account.chart.template"].with_context(default_company_id=company.id)
if old_tax:
xml_id = old_tax.get_external_id().get(old_tax.id)
if xml_id:
_remove_xml_id(xml_id)
chart_template.create_record_with_xmlid(company, template, "account.tax", template_vals)
def _update_tax_from_template(template, tax):
# -> update the tax : we only updates tax tags
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
for tax_line, template_line in zip(tax_rep_lines, template_rep_lines):
tags_to_add = template_line._get_tags_to_add()
tags_to_unlink = tax_line.tag_ids
if tags_to_add != tags_to_unlink:
tax_line.write({"tag_ids": [(6, 0, tags_to_add.ids)]})
_cleanup_tags(tags_to_unlink)
def _get_template_to_tax_xmlid_mapping(company):
"""
This function uses ir_model_data to return a mapping between the tax templates and the taxes, using their xmlid
:returns: {
account.tax.template.id: account.tax.id
}
"""
env['ir.model.data'].flush_model()
env.cr.execute(
"""
SELECT template.res_id AS template_res_id,
tax.res_id AS tax_res_id
FROM ir_model_data tax
JOIN ir_model_data template
ON template.name = substr(tax.name, strpos(tax.name, '_') + 1)
WHERE tax.model = 'account.tax'
AND tax.name LIKE %s
-- tax.name is of the form: {company_id}_{account.tax.template.name}
""",
[r"%s\_%%" % company.id],
)
tuples = env.cr.fetchall()
return dict(tuples)
def _is_tax_and_template_same(template, tax):
"""
This function compares account.tax and account.tax.template repartition lines.
A tax is considered the same as the template if they have the same:
- amount_type
- amount
- repartition lines percentages in the same order
"""
tax_rep_lines = tax.invoice_repartition_line_ids + tax.refund_repartition_line_ids
template_rep_lines = template.invoice_repartition_line_ids + template.refund_repartition_line_ids
return (
tax.amount_type == template.amount_type
and tax.amount == template.amount
and len(tax_rep_lines) == len(template_rep_lines)
and all(
rep_line_tax.factor_percent == rep_line_template.factor_percent
for rep_line_tax, rep_line_template in zip(tax_rep_lines, template_rep_lines)
)
)
def _cleanup_tags(tags):
"""
Checks if the tags are still used in taxes or move lines. If not we delete it.
"""
for tag in tags:
tax_using_tag = env['account.tax.repartition.line'].sudo().search([('tag_ids', 'in', tag.id)], limit=1)
aml_using_tag = env['account.move.line'].sudo().search([('tax_tag_ids', 'in', tag.id)], limit=1)
report_expr_using_tag = tag._get_related_tax_report_expressions()
if not (aml_using_tag or tax_using_tag or report_expr_using_tag):
tag.unlink()
def _notify_accountant_managers(taxes_to_check):
accountant_manager_group = env.ref("account.group_account_manager")
partner_managers_ids = accountant_manager_group.users.mapped('partner_id')
odoobot = env.ref('base.partner_root')
message_body = _(
"Please check these taxes. They might be outdated. We did not update them. "
"Indeed, they do not exactly match the taxes of the original version of the localization module.<br/>"
"You might want to archive or adapt them.<br/><ul>"
)
for account_tax in taxes_to_check:
message_body += f"<li>{html_escape(account_tax.name)}</li>"
message_body += "</ul>"
env['mail.thread'].message_notify(
subject=_('Your taxes have been updated !'),
author_id=odoobot.id,
body=message_body,
partner_ids=[partner.id for partner in partner_managers_ids],
)
env = api.Environment(cr, SUPERUSER_ID, {})
chart_template_id = env['ir.model.data']._xmlid_to_res_id(chart_template_xmlid)
companies = env['res.company'].search([('chart_template_id', '=', chart_template_id)])
outdated_taxes = []
for company in companies:
template_to_tax = _get_template_to_tax_xmlid_mapping(company)
templates = env['account.tax.template'].with_context(active_test=False).search([("chart_template_id", "=", chart_template_id)])
for template in templates:
tax = env["account.tax"].browse(template_to_tax.get(template.id))
if not tax or not _is_tax_and_template_same(template, tax):
_create_tax_from_template(company, template, old_tax=tax)
if tax:
outdated_taxes.append(tax)
else:
_update_tax_from_template(template, tax)
if outdated_taxes:
_notify_accountant_managers(outdated_taxes)
# ---------------------------------------------------------------
# Account Templates: Account, Tax, Tax Code and chart. + Wizard
# ---------------------------------------------------------------
+1 -1
View File
@@ -7,7 +7,7 @@
{
'name': 'Luxembourg - Accounting',
'version': '2.0',
'version': '2.1',
'category': 'Accounting/Localizations/Account Charts',
'description': """
This is the base module to manage the accounting chart for Luxembourg.
@@ -0,0 +1,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.account.models.chart_template import update_taxes_from_templates
def migrate(cr, version):
update_taxes_from_templates(cr, 'l10n_lu.lu_2011_chart_1')