[FIX] printing_auto_base: don't print twice

Fix same record printed multiple times
This commit is contained in:
Thierry Ducrest
2023-09-15 13:12:38 +02:00
committed by Jacques-Etienne Baudoux
parent fb24e652fe
commit 28ad399edf
4 changed files with 111 additions and 8 deletions

View File

@@ -94,13 +94,13 @@ class PrintingAuto(models.Model):
domain = safe_eval(self.condition, {"env": self.env})
return record.filtered_domain(domain)
def _get_content(self, record):
def _get_content(self, records):
generate_data_func = getattr(
self, f"_generate_data_from_{self.data_source}", None
)
content = []
if generate_data_func:
records = self._get_record(record)
records = self._get_record(records)
for record in records:
content.append(generate_data_func(record)[0])
return content
@@ -127,16 +127,16 @@ class PrintingAuto(models.Model):
)
return [data]
def do_print(self, record):
def do_print(self, records):
self.ensure_one()
record.ensure_one()
behaviour = self._get_behaviour()
printer = behaviour["printer"]
if self.nbr_of_copies <= 0:
return (printer, 0)
if not self._check_condition(record):
records = self._check_condition(records)
if not records:
return (printer, 0)
if not printer:
@@ -145,7 +145,7 @@ class PrintingAuto(models.Model):
)
count = 0
for content in self._get_content(record):
for content in self._get_content(records):
for _n in range(self.nbr_of_copies):
printer.print_document(report=None, content=content, **behaviour)
count += 1

View File

@@ -38,7 +38,6 @@ class PrintingAutoMixin(models.AbstractModel):
return self.auto_printing_ids
def _do_print_auto(self, printing_auto):
self.ensure_one()
printing_auto.ensure_one()
printer, count = printing_auto.do_print(self)
if count:
@@ -63,6 +62,12 @@ class PrintingAutoMixin(models.AbstractModel):
def handle_print_auto(self):
"""Print some report or attachment directly to the corresponding printer."""
self._on_printing_auto_start()
to_print = {}
for record in self:
for printing_auto in record._get_printing_auto():
record._handle_print_auto(printing_auto)
if printing_auto not in to_print.keys():
to_print[printing_auto] = record
else:
to_print[printing_auto] |= record
for printing_auto, records in to_print.items():
records._handle_print_auto(printing_auto)

View File

@@ -0,0 +1,37 @@
from odoo import fields, models
def setup_test_model(env, model_cls):
"""Pass a test model class and initialize it.
Courtesy of SBidoul from https://github.com/OCA/mis-builder :)
"""
model_cls._build_model(env.registry, env.cr)
env.registry.setup_models(env.cr)
env.registry.init_models(
env.cr, [model_cls._name], dict(env.context, update_custom_fields=True)
)
def teardown_test_model(env, model_cls):
"""Pass a test model class and deinitialize it.
Courtesy of SBidoul from https://github.com/OCA/mis-builder :)
"""
if not getattr(model_cls, "_teardown_no_delete", False):
del env.registry.models[model_cls._name]
env.registry.setup_models(env.cr)
class PrintingAutoTesterChild(models.Model):
_name = "printingauto.tester.child"
name = fields.Char()
class PrintingAutoTester(models.Model):
_name = "printingauto.tester"
_inherit = "printing.auto.mixin"
name = fields.Char()
child_ids = fields.Many2many("printingauto.tester.child")

View File

@@ -7,10 +7,17 @@ from unittest import mock
from odoo.exceptions import UserError, ValidationError
from .common import PrintingPrinter, TestPrintingAutoCommon, print_document
from .model_test import PrintingAutoTester, PrintingAutoTesterChild, setup_test_model
@mock.patch.object(PrintingPrinter, "print_document", print_document)
class TestPrintingAutoBase(TestPrintingAutoCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
setup_test_model(cls.env, PrintingAutoTesterChild)
setup_test_model(cls.env, PrintingAutoTester)
def test_check_data_source(self):
with self.assertRaises(UserError):
self._create_printing_auto_report({"report_id": False})
@@ -90,3 +97,57 @@ class TestPrintingAutoBase(TestPrintingAutoCommon):
printing_auto.condition = "[('name', '=', 'test_printing_auto')]"
expected = (self.printer_1, 0)
self.assertEqual(expected, printing_auto.do_print(self.record))
def test_do_not_print_multiple_time_the_same_record(self):
"""Check the same record is not printed multiple times.
When the 'record_change' field is being used on the printing auto configuration
and 'handle_print_auto' is called from a recrodset.
The same record could be send for printing multiple times.
"""
printing_auto = self._create_printing_auto_report(
vals={"record_change": "child_ids", "printer_id": self.printer_1.id}
)
child1 = self.env["printingauto.tester.child"].create({"name": "Child One"})
child2 = self.env["printingauto.tester.child"].create({"name": "Child Two"})
parent1 = self.env["printingauto.tester"].create(
{
"name": "Customer One",
"child_ids": [(4, child1.id, 0)],
"auto_printing_ids": [(4, printing_auto.id, 0)],
}
)
parent2 = self.env["printingauto.tester"].create(
{
"name": "Customer Two",
"child_ids": [(4, child1.id, 0)],
"auto_printing_ids": [(4, printing_auto.id, 0)],
}
)
parents = parent1 | parent2
generate_data_from = (
"odoo.addons.printing_auto_base.models.printing_auto."
"PrintingAuto._generate_data_from_report"
)
with mock.patch(generate_data_from) as generate_data_from:
# Both parents have the same child only print the child report once
parents.handle_print_auto()
self.assertEqual(generate_data_from.call_count, 1)
generate_data_from.assert_called_with(child1)
generate_data_from.reset_mock()
# Both parents have different childs, print both child reports
parent2.child_ids = [(6, 0, child2.ids)]
parents.handle_print_auto()
self.assertEqual(generate_data_from.call_count, 2)
generate_data_from.assert_has_calls(
[mock.call(child1), mock.call(child2)], any_order=True
)
generate_data_from.reset_mock()
# THe parents have one child in common and one parent has a 2nd child
parent2.child_ids = [(4, child1.id, 0)]
parents.handle_print_auto()
self.assertEqual(generate_data_from.call_count, 2)
generate_data_from.assert_has_calls(
[mock.call(child1), mock.call(child2)], any_order=True
)