Skip to content

Commit 77d96e6

Browse files
committed
[FIX] account: properly unlink tags when unlinking a tax report line, or impacting the tags trough tag_name or tax report modifications
closes odoo#71632 X-original-commit: 697952e Signed-off-by: Laurent Smet <[email protected]> Signed-off-by: oco-odoo <[email protected]>
1 parent 1f34284 commit 77d96e6

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

addons/account/models/account_tax_report.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ def write(self, vals):
3131
new_tags = tags_cache[cache_key]
3232

3333
if new_tags:
34-
tags_to_unlink = line.tag_ids.filtered(lambda x: record == x.mapped('tax_report_line_ids.report_id'))
35-
# == instead of in, as we only want tags_to_unlink to contain the tags that are not linked to any other report than the one we're considering
34+
line._remove_tags_used_only_by_self()
3635
line.write({'tag_ids': [(6, 0, new_tags.ids)]})
37-
self.env['account.tax.report.line']._delete_tags_from_taxes(tags_to_unlink.ids)
3836

3937
elif line.mapped('tag_ids.tax_report_line_ids.report_id').filtered(lambda x: x not in self):
38+
line._remove_tags_used_only_by_self()
4039
line.write({'tag_ids': [(5, 0, 0)] + line._get_tags_create_vals(line.tag_name, vals['country_id'])})
4140
tags_cache[cache_key] = line.tag_ids
4241

@@ -225,7 +224,7 @@ def write(self, vals):
225224
# All the lines sharing their tags must always be synchronized,
226225
tags_to_remove += records_to_link.mapped('tag_ids')
227226
records_to_link = tags_to_remove.mapped('tax_report_line_ids')
228-
self._delete_tags_from_taxes(tags_to_remove.ids)
227+
tags_to_remove.mapped('tax_report_line_ids')._remove_tags_used_only_by_self()
229228
records_to_link.write({'tag_name': tag_name_postponed, 'tag_ids': [(2, tag.id) for tag in tags_to_remove] + [(6, 0, existing_tags.ids)]})
230229

231230
else:
@@ -242,17 +241,27 @@ def write(self, vals):
242241
return rslt
243242

244243
def unlink(self):
245-
self._delete_tags_from_taxes(self.mapped('tag_ids.id'))
244+
self._remove_tags_used_only_by_self()
246245
children = self.mapped('children_line_ids')
247246
if children:
248247
children.unlink()
249248
return super(AccountTaxReportLine, self).unlink()
250249

250+
def _remove_tags_used_only_by_self(self):
251+
""" Deletes and removes from taxes and move lines all the
252+
tags from the provided tax report lines that are not linked
253+
to any other tax report lines.
254+
"""
255+
all_tags = self.mapped('tag_ids')
256+
tags_to_unlink = all_tags.filtered(lambda x: not (x.tax_report_line_ids - self))
257+
self.write({'tag_ids': [(2, tag.id, 0) for tag in tags_to_unlink]})
258+
self._delete_tags_from_taxes(tags_to_unlink.ids)
259+
251260
@api.model
252261
def _delete_tags_from_taxes(self, tag_ids_to_delete):
253262
""" Based on a list of tag ids, removes them first from the
254263
repartition lines they are linked to, then deletes them
255-
from the account move lines.
264+
from the account move lines, and finally unlink them.
256265
"""
257266
if not tag_ids_to_delete:
258267
# Nothing to do, then!
@@ -269,6 +278,8 @@ def _delete_tags_from_taxes(self, tag_ids_to_delete):
269278
self.env['account.move.line'].invalidate_cache(fnames=['tax_tag_ids'])
270279
self.env['account.tax.repartition.line'].invalidate_cache(fnames=['tag_ids'])
271280

281+
self.env['account.account.tag'].browse(tag_ids_to_delete).unlink()
282+
272283
@api.constrains('formula', 'tag_name')
273284
def _validate_formula(self):
274285
for record in self:

addons/account/tests/test_tax_report.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ def setUpClass(cls, chart_template_ref=None):
6464
'sequence': 7,
6565
})
6666

67+
cls.tax_report_line_1_6 = cls.env['account.tax.report.line'].create({
68+
'name': "[100] Line 100",
69+
'tag_name': '100',
70+
'report_id': cls.tax_report_1.id,
71+
'sequence': 8,
72+
})
73+
6774
cls.tax_report_2 = cls.env['account.tax.report'].create({
6875
'name': "Tax report 2",
6976
'country_id': cls.test_country_1.id,
@@ -89,6 +96,13 @@ def setUpClass(cls, chart_template_ref=None):
8996
'sequence': 3,
9097
})
9198

99+
cls.tax_report_line_2_6 = cls.env['account.tax.report.line'].create({
100+
'name': "[100] Line 100",
101+
'tag_name': '100',
102+
'report_id': cls.tax_report_2.id,
103+
'sequence': 4,
104+
})
105+
92106
def _get_tax_tags(self, tag_name=None):
93107
domain = [('country_id', '=', self.test_country_1.id), ('applicability', '=', 'taxes')]
94108
if tag_name:
@@ -255,3 +269,17 @@ def test_tax_report_change_country(self):
255269
self.assertEqual(line.tag_ids.ids, original_report_2_tags[line.id], "The tax report lines not sharing their tags with any other report should keep the same tags when the country of their report is changed")
256270
elif line.tag_ids or original_report_2_tags[line.id]:
257271
self.assertNotEqual(line.tag_ids.ids, original_report_2_tags[line.id], "The tax report lines sharing their tags with other report should receive new tags when the country of their report is changed")
272+
273+
def test_unlink_report_line_tags(self):
274+
""" Under certain circumstances, unlinking a tax report line should also unlink
275+
the tags that are linked to it. We test those cases here.
276+
"""
277+
def check_tags_unlink(tag_name, report_lines, unlinked, error_message):
278+
report_lines.unlink()
279+
surviving_tags = self._get_tax_tags(tag_name)
280+
required_len = 0 if unlinked else 2 # 2 for + and - tag
281+
self.assertEqual(len(surviving_tags), required_len, error_message)
282+
283+
check_tags_unlink('42', self.tax_report_line_2_42, True, "Unlinking one line not sharing its tags should also unlink them")
284+
check_tags_unlink('01', self.tax_report_line_1_1, False, "Unlinking one line sharing its tags with others should keep the tags")
285+
check_tags_unlink('100', self.tax_report_line_1_6 + self.tax_report_line_2_6, True, "Unlinkink all the lines sharing the same tags should also unlink them")

0 commit comments

Comments
 (0)