diff --git a/addons/l10n_es/__manifest__.py b/addons/l10n_es/__manifest__.py
index ab8f5558f20..ad15d2ea819 100644
--- a/addons/l10n_es/__manifest__.py
+++ b/addons/l10n_es/__manifest__.py
@@ -14,7 +14,7 @@
{
"name" : "Spain - Accounting (PGCE 2008)",
- "version" : "4.0",
+ "version" : "5.0",
"author" : "Spanish Localization Team",
'category': 'Accounting/Localizations/Account Charts',
"description": """
diff --git a/addons/l10n_es/data/account_tax_data.xml b/addons/l10n_es/data/account_tax_data.xml
index ac8145aab58..a1292019c2d 100644
--- a/addons/l10n_es/data/account_tax_data.xml
+++ b/addons/l10n_es/data/account_tax_data.xml
@@ -244,10 +244,31 @@
+
mod303[61]
taxes
+
+ mod303[120]
+ taxes
+
+
+
+ mod303[122]
+ taxes
+
+
+
+ mod303[123]
+ taxes
+
+
+
+ mod303[124]
+ taxes
+
+
@@ -1118,7 +1139,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_120')],
}),
(0,0, {
@@ -1131,7 +1152,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_120')],
}),
(0,0, {
@@ -1152,7 +1173,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_120')],
}),
(0,0, {
@@ -1165,7 +1186,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_120')],
}),
(0,0, {
@@ -1186,7 +1207,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_122')],
}),
(0,0, {
@@ -1199,7 +1220,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_122')],
}),
(0,0, {
@@ -3607,7 +3628,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_122')],
}),
(0,0, {
@@ -3620,7 +3641,7 @@
(0,0, {
'factor_percent': 100,
'repartition_type': 'base',
- 'tag_ids': [ref('mod_303_61')],
+ 'tag_ids': [ref('mod_303_122')],
}),
(0,0, {
diff --git a/addons/l10n_es/upgrades/15.0.5.0/post-61-tag-split-2021.py b/addons/l10n_es/upgrades/15.0.5.0/post-61-tag-split-2021.py
new file mode 100644
index 00000000000..b785b125b09
--- /dev/null
+++ b/addons/l10n_es/upgrades/15.0.5.0/post-61-tag-split-2021.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+
+from odoo import api, SUPERUSER_ID
+
+
+def migrate(cr, version):
+ # For taxes coming from tax templates, replace grid 61 by the right tag.
+ # For the other ones, we can't guess what to use, and the user will have to change his
+ # config manually, possibly creating a ticket to ask to fix his accounting history.
+
+ def get_taxes_from_templates(templates):
+ cr.execute(f"""
+ SELECT array_agg(tax.id)
+ FROM account_tax tax
+ JOIN ir_model_data data
+ ON data.model = 'account.tax'
+ AND data.res_id = tax.id
+ AND data.module = 'l10n_es'
+ AND data.name ~ '^[0-9]*_({'|'.join(templates)})\\Z'
+ """)
+
+ return cr.fetchone()[0]
+ env = api.Environment(cr, SUPERUSER_ID, {})
+
+ templates_mapping = {
+ 'mod_303_120': ['account_tax_template_s_iva_ns', 'account_tax_template_s_iva_ns_b'],
+ 'mod_303_122': ['account_tax_template_s_iva_e', 'account_tax_template_s_iva0_isp'],
+ }
+
+ # To run in a server action to fix issues on dbs with custom taxes,
+ # replace the content of this dict.
+ taxes_mapping = {
+ tag_name: get_taxes_from_templates(template_names)
+ for tag_name, template_names in templates_mapping.items()
+ }
+
+ old_tag = env.ref('l10n_es.mod_303_61')
+ for tag_name, tax_ids in taxes_mapping.items():
+ # Grid 61 is only for base repartition.
+ # If it was used for taxes repartition, we don't touch it (and it'll require manual check,
+ # as the BOE file probably won't pass government checks).
+
+ new_tag = env.ref(f'l10n_es.{tag_name}')
+
+ # Change tax config
+ cr.execute("""
+ UPDATE account_account_tag_account_tax_repartition_line_rel tax_rep_tag
+ SET account_account_tag_id = %s
+ FROM account_account_tag new_tag, account_tax_repartition_line repln
+ WHERE tax_rep_tag.account_account_tag_id = %s
+ AND repln.id = tax_rep_tag.account_tax_repartition_line_id
+ AND COALESCE(repln.invoice_tax_id, repln.refund_tax_id) IN %s
+ """, [new_tag.id, old_tag.id, tuple(tax_ids)])
+
+ # Change amls in history, starting at Q3 2021 (date of introduction for the new tags)
+
+ # Set tags
+ cr.execute("""
+ UPDATE account_account_tag_account_move_line_rel aml_tag
+ SET account_account_tag_id = %s
+ FROM account_move_line aml, account_move_line_account_tax_rel aml_tax
+ WHERE aml_tag.account_move_line_id = aml.id
+ AND aml_tax.account_move_line_id = aml.id
+ AND aml.date >= '2021-07-01'
+ AND aml_tax.account_tax_id IN %s
+ AND aml_tag.account_account_tag_id = %s
+ """, [new_tag.id, tuple(tax_ids), old_tag.id])
+
+ # Fix tax audit string
+ cr.execute("""
+ UPDATE account_move_line aml
+ SET tax_audit = REPLACE(tax_audit, %s, %s)
+ FROM account_account_tag_account_move_line_rel aml_tag
+ WHERE aml_tag.account_move_line_id = aml.id
+ AND aml_tag.account_account_tag_id = %s
+ """, [old_tag.name, f"{new_tag.name}:", new_tag.id])