From 58d1146709e2419144028aa57986d7e405a240eb Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Wed, 31 Dec 2025 11:08:04 +0100 Subject: [PATCH 1/6] [ADD] hr_payroll_document_pymupdf --- hr_payroll_document_pymupdf/README.rst | 83 ++++ hr_payroll_document_pymupdf/__init__.py | 3 + hr_payroll_document_pymupdf/__manifest__.py | 20 + .../i18n/hr_payroll_document_pymupdf.pot | 26 ++ .../readme/DESCRIPTION.rst | 1 + .../static/description/icon.png | Bin 0 -> 10254 bytes .../static/description/index.html | 424 ++++++++++++++++++ hr_payroll_document_pymupdf/tests/__init__.py | 3 + .../tests/test_broken_image.pdf | Bin 0 -> 18752 bytes .../tests/test_payroll_management.py | 18 + .../wizards/__init__.py | 3 + .../wizards/payroll_management_wizard.py | 35 ++ 12 files changed, 616 insertions(+) create mode 100644 hr_payroll_document_pymupdf/README.rst create mode 100644 hr_payroll_document_pymupdf/__init__.py create mode 100644 hr_payroll_document_pymupdf/__manifest__.py create mode 100644 hr_payroll_document_pymupdf/i18n/hr_payroll_document_pymupdf.pot create mode 100644 hr_payroll_document_pymupdf/readme/DESCRIPTION.rst create mode 100644 hr_payroll_document_pymupdf/static/description/icon.png create mode 100644 hr_payroll_document_pymupdf/static/description/index.html create mode 100644 hr_payroll_document_pymupdf/tests/__init__.py create mode 100644 hr_payroll_document_pymupdf/tests/test_broken_image.pdf create mode 100644 hr_payroll_document_pymupdf/tests/test_payroll_management.py create mode 100644 hr_payroll_document_pymupdf/wizards/__init__.py create mode 100644 hr_payroll_document_pymupdf/wizards/payroll_management_wizard.py diff --git a/hr_payroll_document_pymupdf/README.rst b/hr_payroll_document_pymupdf/README.rst new file mode 100644 index 000000000..b656cddb4 --- /dev/null +++ b/hr_payroll_document_pymupdf/README.rst @@ -0,0 +1,83 @@ +.. image:: https://odoo-community.org/readme-banner-image + :target: https://odoo-community.org/get-involved?utm_source=readme + :alt: Odoo Community Association + +=============================== +HR - Payroll Document - PyMuPDF +=============================== + +.. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! source digest: sha256:9b97fc250e9f7c34ba848cdc7ac246d98c29cdd4d8f16c1d6ed18fcf14fbc4f8 + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/license-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpayroll-lightgray.png?logo=github + :target: https://github.com/OCA/payroll/tree/16.0/hr_payroll_document_pymupdf + :alt: OCA/payroll +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/payroll-16-0/payroll-16-0-hr_payroll_document_pymupdf + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png + :target: https://runboat.odoo-community.org/builds?repo=OCA/payroll&target_branch=16.0 + :alt: Try me on Runboat + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt reading the PDF payslip. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* PyTech + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-SirPyTech| image:: https://github.com/SirPyTech.png?size=40px + :target: https://github.com/SirPyTech + :alt: SirPyTech + +Current `maintainer `__: + +|maintainer-SirPyTech| + +This module is part of the `OCA/payroll `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_payroll_document_pymupdf/__init__.py b/hr_payroll_document_pymupdf/__init__.py new file mode 100644 index 000000000..74d71de4b --- /dev/null +++ b/hr_payroll_document_pymupdf/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import wizards diff --git a/hr_payroll_document_pymupdf/__manifest__.py b/hr_payroll_document_pymupdf/__manifest__.py new file mode 100644 index 000000000..2091b1d33 --- /dev/null +++ b/hr_payroll_document_pymupdf/__manifest__.py @@ -0,0 +1,20 @@ +{ + "name": "HR - Payroll Document - PyMuPDF", + "summary": "Try harder to read a PDF payslip with PyMuPDF.", + "author": "PyTech, Odoo Community Association (OCA)", + "website": "https://github.com/OCA/payroll", + "license": "AGPL-3", + "category": "Payrolls", + "version": "16.0.1.0.1", + "depends": [ + "hr_payroll_document", + ], + "maintainers": [ + "SirPyTech", + ], + "external_dependencies": { + "python": [ + "PyMuPDF", + ], + }, +} diff --git a/hr_payroll_document_pymupdf/i18n/hr_payroll_document_pymupdf.pot b/hr_payroll_document_pymupdf/i18n/hr_payroll_document_pymupdf.pot new file mode 100644 index 000000000..75a717f16 --- /dev/null +++ b/hr_payroll_document_pymupdf/i18n/hr_payroll_document_pymupdf.pot @@ -0,0 +1,26 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_payroll_document_pymupdf +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: \n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: hr_payroll_document_pymupdf +#: model:ir.model,name:hr_payroll_document_pymupdf.model_payroll_management_wizard +msgid "Payroll Management" +msgstr "" + +#. module: hr_payroll_document_pymupdf +#. odoo-python +#: code:addons/hr_payroll_document_pymupdf/tests/test_payroll_management.py:0 +#, python-format +msgid "Payrolls sent" +msgstr "" diff --git a/hr_payroll_document_pymupdf/readme/DESCRIPTION.rst b/hr_payroll_document_pymupdf/readme/DESCRIPTION.rst new file mode 100644 index 000000000..5c58f5be0 --- /dev/null +++ b/hr_payroll_document_pymupdf/readme/DESCRIPTION.rst @@ -0,0 +1 @@ +Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt reading the PDF payslip. diff --git a/hr_payroll_document_pymupdf/static/description/icon.png b/hr_payroll_document_pymupdf/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..1dcc49c24f364e9adf0afbc6fc0bac6dbecdeb11 GIT binary patch literal 10254 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 + + + + +README.rst + + + +
+ + + +Odoo Community Association + +
+

HR - Payroll Document - PyMuPDF

+ +

Beta License: AGPL-3 OCA/payroll Translate me on Weblate Try me on Runboat

+

Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt reading the PDF payslip.

+

Table of contents

+ +
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us to smash it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • PyTech
  • +
+
+
+

Maintainers

+

This module is maintained by the OCA.

+ +Odoo Community Association + +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainer:

+

SirPyTech

+

This module is part of the OCA/payroll project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+
+ + diff --git a/hr_payroll_document_pymupdf/tests/__init__.py b/hr_payroll_document_pymupdf/tests/__init__.py new file mode 100644 index 000000000..cbc8cf7e3 --- /dev/null +++ b/hr_payroll_document_pymupdf/tests/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import test_payroll_management diff --git a/hr_payroll_document_pymupdf/tests/test_broken_image.pdf b/hr_payroll_document_pymupdf/tests/test_broken_image.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2d08e2145fc9f3def2948baa1a42f3f0dd389356 GIT binary patch literal 18752 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 literal 0 HcmV?d00001 diff --git a/hr_payroll_document_pymupdf/tests/test_payroll_management.py b/hr_payroll_document_pymupdf/tests/test_payroll_management.py new file mode 100644 index 000000000..dacfb4d68 --- /dev/null +++ b/hr_payroll_document_pymupdf/tests/test_payroll_management.py @@ -0,0 +1,18 @@ +from odoo import _ + +from odoo.addons.hr_payroll_document.tests.common import TestHrPayrollDocument + + +class TestPayrollManagement(TestHrPayrollDocument): + def test_pdf_broken_image(self): + """If the PDF cannot be processed with PyPDF, try with another reader.""" + self.fill_company_id() + identification_code = "xXXXXXXXXXXXXXXX" + with self._mock_valid_identification(self.employee_emp, identification_code): + self.employee_emp.identification_id = identification_code + self.wizard = self._create_wizard( + "Subject", ["hr_payroll_document_pymupdf", "tests", "test_broken_image.pdf"] + ) + with self._mock_valid_identification(self.employee_emp, identification_code): + result_action = self.wizard.send_payrolls() + self.assertEqual(result_action["params"]["title"], _("Payrolls sent")) diff --git a/hr_payroll_document_pymupdf/wizards/__init__.py b/hr_payroll_document_pymupdf/wizards/__init__.py new file mode 100644 index 000000000..723401a24 --- /dev/null +++ b/hr_payroll_document_pymupdf/wizards/__init__.py @@ -0,0 +1,3 @@ +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from . import payroll_management_wizard diff --git a/hr_payroll_document_pymupdf/wizards/payroll_management_wizard.py b/hr_payroll_document_pymupdf/wizards/payroll_management_wizard.py new file mode 100644 index 000000000..07572e891 --- /dev/null +++ b/hr_payroll_document_pymupdf/wizards/payroll_management_wizard.py @@ -0,0 +1,35 @@ +# Copyright 2025 Simone Rubino - PyTech +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +import io + +import pymupdf +import pypdf +from reportlab.pdfgen import canvas + +from odoo import models + + +class PayrollManagamentWizard(models.TransientModel): + _inherit = "payroll.management.wizard" + + def _get_fallback_reader(self, pdf_reader): + reader = super()._get_fallback_reader(pdf_reader) + if not reader: + # Read the file with another reader + doc = pymupdf.Document(stream=pdf_reader.stream) + + # Create a new PDF with only the extracted content + pdf_content = io.BytesIO() + pdf_canvas = canvas.Canvas(pdf_content) + for page_number in range(pdf_reader.get_num_pages()): + page_content = doc[page_number].get_text().split() + # Create a new page with the read content + pdf_canvas.drawString(0, 0, " ".join(page_content)) + pdf_canvas.showPage() + pdf_canvas.save() + + # Return a PyPDF reader for the new PDF, + # that now is readable + reader = pypdf.PdfReader(pdf_content) + return reader From ccf3bfad42bce31d74fa8566b8989e3a0cfcabae Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 15 Jan 2026 12:25:11 +0000 Subject: [PATCH 2/6] Added translation using Weblate (Italian) --- hr_payroll_document_pymupdf/i18n/it.po | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 hr_payroll_document_pymupdf/i18n/it.po diff --git a/hr_payroll_document_pymupdf/i18n/it.po b/hr_payroll_document_pymupdf/i18n/it.po new file mode 100644 index 000000000..aadfb46c5 --- /dev/null +++ b/hr_payroll_document_pymupdf/i18n/it.po @@ -0,0 +1,27 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_payroll_document_pymupdf +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 16.0\n" +"Report-Msgid-Bugs-To: \n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: it\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" + +#. module: hr_payroll_document_pymupdf +#: model:ir.model,name:hr_payroll_document_pymupdf.model_payroll_management_wizard +msgid "Payroll Management" +msgstr "" + +#. module: hr_payroll_document_pymupdf +#. odoo-python +#: code:addons/hr_payroll_document_pymupdf/tests/test_payroll_management.py:0 +#, python-format +msgid "Payrolls sent" +msgstr "" From 2e84248858dee567297522d05089ce59555165be Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 22 Jan 2026 07:32:40 +0000 Subject: [PATCH 3/6] Translated using Weblate (Italian) Currently translated at 100.0% (2 of 2 strings) Translation: payroll-16.0/payroll-16.0-hr_payroll_document_pymupdf Translate-URL: https://translation.odoo-community.org/projects/payroll-16-0/payroll-16-0-hr_payroll_document_pymupdf/it/ --- hr_payroll_document_pymupdf/i18n/it.po | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/hr_payroll_document_pymupdf/i18n/it.po b/hr_payroll_document_pymupdf/i18n/it.po index aadfb46c5..5bd7b911b 100644 --- a/hr_payroll_document_pymupdf/i18n/it.po +++ b/hr_payroll_document_pymupdf/i18n/it.po @@ -6,22 +6,24 @@ msgid "" msgstr "" "Project-Id-Version: Odoo Server 16.0\n" "Report-Msgid-Bugs-To: \n" -"Last-Translator: Automatically generated\n" +"PO-Revision-Date: 2026-01-22 09:50+0000\n" +"Last-Translator: mymage \n" "Language-Team: none\n" "Language: it\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: \n" "Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 5.15.2\n" #. module: hr_payroll_document_pymupdf #: model:ir.model,name:hr_payroll_document_pymupdf.model_payroll_management_wizard msgid "Payroll Management" -msgstr "" +msgstr "Gestione retribuzione" #. module: hr_payroll_document_pymupdf #. odoo-python #: code:addons/hr_payroll_document_pymupdf/tests/test_payroll_management.py:0 #, python-format msgid "Payrolls sent" -msgstr "" +msgstr "Retribuzioni inviate" From 1909406804cefad78ba0f45b1e4bd999ee0f37bb Mon Sep 17 00:00:00 2001 From: Borruso Date: Fri, 17 Jul 2026 13:14:35 +0200 Subject: [PATCH 4/6] [IMP] hr_payroll_document_pymupdf: pre-commit auto fixes --- hr_payroll_document_pymupdf/README.rst | 17 +++++++++-------- hr_payroll_document_pymupdf/pyproject.toml | 3 +++ .../readme/DESCRIPTION.md | 2 ++ .../readme/DESCRIPTION.rst | 1 - .../static/description/index.html | 9 +++++---- requirements.txt | 2 ++ 6 files changed, 21 insertions(+), 13 deletions(-) create mode 100644 hr_payroll_document_pymupdf/pyproject.toml create mode 100644 hr_payroll_document_pymupdf/readme/DESCRIPTION.md delete mode 100644 hr_payroll_document_pymupdf/readme/DESCRIPTION.rst create mode 100644 requirements.txt diff --git a/hr_payroll_document_pymupdf/README.rst b/hr_payroll_document_pymupdf/README.rst index b656cddb4..cbb2e9274 100644 --- a/hr_payroll_document_pymupdf/README.rst +++ b/hr_payroll_document_pymupdf/README.rst @@ -21,18 +21,19 @@ HR - Payroll Document - PyMuPDF :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html :alt: License: AGPL-3 .. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fpayroll-lightgray.png?logo=github - :target: https://github.com/OCA/payroll/tree/16.0/hr_payroll_document_pymupdf + :target: https://github.com/OCA/payroll/tree/19.0/hr_payroll_document_pymupdf :alt: OCA/payroll .. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png - :target: https://translation.odoo-community.org/projects/payroll-16-0/payroll-16-0-hr_payroll_document_pymupdf + :target: https://translation.odoo-community.org/projects/payroll-19-0/payroll-19-0-hr_payroll_document_pymupdf :alt: Translate me on Weblate .. |badge5| image:: https://img.shields.io/badge/runboat-Try%20me-875A7B.png - :target: https://runboat.odoo-community.org/builds?repo=OCA/payroll&target_branch=16.0 + :target: https://runboat.odoo-community.org/builds?repo=OCA/payroll&target_branch=19.0 :alt: Try me on Runboat |badge1| |badge2| |badge3| |badge4| |badge5| -Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt reading the PDF payslip. +Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt +reading the PDF payslip. **Table of contents** @@ -45,7 +46,7 @@ Bug Tracker Bugs are tracked on `GitHub Issues `_. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -`feedback `_. +`feedback `_. Do not contact contributors directly about support or help with technical issues. @@ -53,12 +54,12 @@ Credits ======= Authors -~~~~~~~ +------- * PyTech Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -78,6 +79,6 @@ Current `maintainer `__: |maintainer-SirPyTech| -This module is part of the `OCA/payroll `_ project on GitHub. +This module is part of the `OCA/payroll `_ project on GitHub. You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/hr_payroll_document_pymupdf/pyproject.toml b/hr_payroll_document_pymupdf/pyproject.toml new file mode 100644 index 000000000..4231d0ccc --- /dev/null +++ b/hr_payroll_document_pymupdf/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["whool"] +build-backend = "whool.buildapi" diff --git a/hr_payroll_document_pymupdf/readme/DESCRIPTION.md b/hr_payroll_document_pymupdf/readme/DESCRIPTION.md new file mode 100644 index 000000000..6b5cfcab6 --- /dev/null +++ b/hr_payroll_document_pymupdf/readme/DESCRIPTION.md @@ -0,0 +1,2 @@ +Use the library PyMuPDF () to +attempt reading the PDF payslip. diff --git a/hr_payroll_document_pymupdf/readme/DESCRIPTION.rst b/hr_payroll_document_pymupdf/readme/DESCRIPTION.rst deleted file mode 100644 index 5c58f5be0..000000000 --- a/hr_payroll_document_pymupdf/readme/DESCRIPTION.rst +++ /dev/null @@ -1 +0,0 @@ -Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt reading the PDF payslip. diff --git a/hr_payroll_document_pymupdf/static/description/index.html b/hr_payroll_document_pymupdf/static/description/index.html index cfbfda1fc..8d71e14ee 100644 --- a/hr_payroll_document_pymupdf/static/description/index.html +++ b/hr_payroll_document_pymupdf/static/description/index.html @@ -374,8 +374,9 @@

HR - Payroll Document - PyMuPDF

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !! source digest: sha256:9b97fc250e9f7c34ba848cdc7ac246d98c29cdd4d8f16c1d6ed18fcf14fbc4f8 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! --> -

Beta License: AGPL-3 OCA/payroll Translate me on Weblate Try me on Runboat

-

Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt reading the PDF payslip.

+

Beta License: AGPL-3 OCA/payroll Translate me on Weblate Try me on Runboat

+

Use the library PyMuPDF (https://github.com/pymupdf/pymupdf) to attempt +reading the PDF payslip.

Table of contents

    @@ -392,7 +393,7 @@

    Bug Tracker

    Bugs are tracked on GitHub Issues. In case of trouble, please check there if your issue has already been reported. If you spotted it first, help us to smash it by providing a detailed and welcomed -feedback.

    +feedback.

    Do not contact contributors directly about support or help with technical issues.

@@ -414,7 +415,7 @@

Maintainers

promote its widespread use.

Current maintainer:

SirPyTech

-

This module is part of the OCA/payroll project on GitHub.

+

This module is part of the OCA/payroll project on GitHub.

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 000000000..0e9fc8cd2 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +# generated from manifests external_dependencies +PyMuPDF From ea9c1c87e9e20d4d90f5b9a754eba2295ac8d123 Mon Sep 17 00:00:00 2001 From: Borruso Date: Fri, 17 Jul 2026 14:40:36 +0200 Subject: [PATCH 5/6] [MIG] hr_payroll_document_pymupdf: Migration to 19.0 --- hr_payroll_document_pymupdf/__manifest__.py | 2 +- .../tests/test_payroll_management.py | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/hr_payroll_document_pymupdf/__manifest__.py b/hr_payroll_document_pymupdf/__manifest__.py index 2091b1d33..6ef63bb43 100644 --- a/hr_payroll_document_pymupdf/__manifest__.py +++ b/hr_payroll_document_pymupdf/__manifest__.py @@ -5,7 +5,7 @@ "website": "https://github.com/OCA/payroll", "license": "AGPL-3", "category": "Payrolls", - "version": "16.0.1.0.1", + "version": "19.0.1.0.0", "depends": [ "hr_payroll_document", ], diff --git a/hr_payroll_document_pymupdf/tests/test_payroll_management.py b/hr_payroll_document_pymupdf/tests/test_payroll_management.py index dacfb4d68..f8aa4f442 100644 --- a/hr_payroll_document_pymupdf/tests/test_payroll_management.py +++ b/hr_payroll_document_pymupdf/tests/test_payroll_management.py @@ -1,5 +1,3 @@ -from odoo import _ - from odoo.addons.hr_payroll_document.tests.common import TestHrPayrollDocument @@ -11,8 +9,8 @@ def test_pdf_broken_image(self): with self._mock_valid_identification(self.employee_emp, identification_code): self.employee_emp.identification_id = identification_code self.wizard = self._create_wizard( - "Subject", ["hr_payroll_document_pymupdf", "tests", "test_broken_image.pdf"] + "Subject", "hr_payroll_document_pymupdf/tests/test_broken_image.pdf" ) with self._mock_valid_identification(self.employee_emp, identification_code): result_action = self.wizard.send_payrolls() - self.assertEqual(result_action["params"]["title"], _("Payrolls sent")) + self.assertEqual(result_action["params"]["title"], self.env._("Payrolls sent")) From d1e75eac44624aa2071fc939d81606b6fe84afc4 Mon Sep 17 00:00:00 2001 From: Borruso Date: Fri, 17 Jul 2026 14:43:01 +0200 Subject: [PATCH 6/6] [DONT MERGE] test-requirements.txt --- test-requirements.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 test-requirements.txt diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..d9450ddba --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1 @@ +odoo-addon-hr_payroll_document @ git+https://github.com/OCA/payroll@refs/pull/279/head#subdirectory=hr_payroll_document