From a780d2a4d652acf822c575f8c223935eed077770 Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Wed, 31 Dec 2025 11:08:04 +0100 Subject: [PATCH 1/5] [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 ebc277b996c315ea9f9bff57c9da30be8c675ec4 Mon Sep 17 00:00:00 2001 From: mymage Date: Thu, 15 Jan 2026 12:25:11 +0000 Subject: [PATCH 2/5] Added translation using Weblate (Italian) --- hr_payroll_document_pymupdf/i18n/it.po | 29 ++++++++++++++++++++++++++ 1 file changed, 29 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..5bd7b911b --- /dev/null +++ b/hr_payroll_document_pymupdf/i18n/it.po @@ -0,0 +1,29 @@ +# 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" +"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 "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 "Retribuzioni inviate" From 5c0dbb0ec6f8b76f3127c51956e1535428a061a9 Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Thu, 27 Aug 2026 12:45:34 +0200 Subject: [PATCH 3/5] [IMP] hr_payroll_document_pymupdf: pre-commit execution --- hr_payroll_document_pymupdf/README.rst | 23 +++++++-------- hr_payroll_document_pymupdf/pyproject.toml | 3 ++ .../readme/DESCRIPTION.md | 2 ++ .../readme/DESCRIPTION.rst | 1 - .../static/description/index.html | 29 ++++++++----------- requirements.txt | 1 + 6 files changed, 28 insertions(+), 31 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 diff --git a/hr_payroll_document_pymupdf/README.rst b/hr_payroll_document_pymupdf/README.rst index b656cddb4..c92d0c6ba 100644 --- a/hr_payroll_document_pymupdf/README.rst +++ b/hr_payroll_document_pymupdf/README.rst @@ -1,7 +1,3 @@ -.. 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 =============================== @@ -17,22 +13,23 @@ HR - Payroll Document - PyMuPDF .. |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 +.. |badge2| image:: https://img.shields.io/badge/licence-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 + :target: https://github.com/OCA/payroll/tree/18.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-18-0/payroll-18-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=18.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 +42,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 +50,12 @@ Credits ======= Authors -~~~~~~~ +------- * PyTech Maintainers -~~~~~~~~~~~ +----------- This module is maintained by the OCA. @@ -78,6 +75,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..b65270f58 100644 --- a/hr_payroll_document_pymupdf/static/description/index.html +++ b/hr_payroll_document_pymupdf/static/description/index.html @@ -3,7 +3,7 @@ -README.rst +HR - Payroll Document - PyMuPDF -
+
+

HR - Payroll Document - PyMuPDF

- - -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.

+

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

    @@ -388,23 +384,23 @@

    HR - Payroll Document - PyMuPDF

-

Bug Tracker

+

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.

-

Credits

+

Credits

-

Authors

+

Authors

  • PyTech
-

Maintainers

+

Maintainers

This module is maintained by the OCA.

Odoo Community Association @@ -414,11 +410,10 @@

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 index 1ab56ace6..455268548 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ # generated from manifests external_dependencies +PyMuPDF pypdf From 028c8b1c5e4c099e7ec74e5cf22d5c6827b73e20 Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Thu, 27 Aug 2026 12:45:41 +0200 Subject: [PATCH 4/5] [MIG] hr_payroll_document_pymupdf: Migration to 18.0 --- hr_payroll_document_pymupdf/README.rst | 7 +++++++ hr_payroll_document_pymupdf/__manifest__.py | 2 +- hr_payroll_document_pymupdf/readme/CONTRIBUTORS.md | 2 ++ .../static/description/index.html | 14 ++++++++++++-- .../tests/test_payroll_management.py | 14 ++++++++++---- 5 files changed, 32 insertions(+), 7 deletions(-) create mode 100644 hr_payroll_document_pymupdf/readme/CONTRIBUTORS.md diff --git a/hr_payroll_document_pymupdf/README.rst b/hr_payroll_document_pymupdf/README.rst index c92d0c6ba..88ec1098c 100644 --- a/hr_payroll_document_pymupdf/README.rst +++ b/hr_payroll_document_pymupdf/README.rst @@ -54,6 +54,13 @@ Authors * PyTech +Contributors +------------ + +- `PyTech `__: + + - Simone Rubino + Maintainers ----------- diff --git a/hr_payroll_document_pymupdf/__manifest__.py b/hr_payroll_document_pymupdf/__manifest__.py index 2091b1d33..61e014eba 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": "18.0.1.0.0", "depends": [ "hr_payroll_document", ], diff --git a/hr_payroll_document_pymupdf/readme/CONTRIBUTORS.md b/hr_payroll_document_pymupdf/readme/CONTRIBUTORS.md new file mode 100644 index 000000000..6e720b67d --- /dev/null +++ b/hr_payroll_document_pymupdf/readme/CONTRIBUTORS.md @@ -0,0 +1,2 @@ +- [PyTech](https://www.pytech.it): + - Simone Rubino \<\> diff --git a/hr_payroll_document_pymupdf/static/description/index.html b/hr_payroll_document_pymupdf/static/description/index.html index b65270f58..c35884666 100644 --- a/hr_payroll_document_pymupdf/static/description/index.html +++ b/hr_payroll_document_pymupdf/static/description/index.html @@ -378,7 +378,8 @@

HR - Payroll Document - PyMuPDF

  • Bug Tracker
  • Credits
  • @@ -399,8 +400,17 @@

    Authors

  • PyTech
  • +
    +

    Contributors

    + +
    -

    Maintainers

    +

    Maintainers

    This module is maintained by the OCA.

    Odoo Community Association diff --git a/hr_payroll_document_pymupdf/tests/test_payroll_management.py b/hr_payroll_document_pymupdf/tests/test_payroll_management.py index dacfb4d68..82190e717 100644 --- a/hr_payroll_document_pymupdf/tests/test_payroll_management.py +++ b/hr_payroll_document_pymupdf/tests/test_payroll_management.py @@ -1,4 +1,7 @@ -from odoo import _ +# Copyright 2026 Simone Rubino - PyTech +# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). + +from odoo import tools from odoo.addons.hr_payroll_document.tests.common import TestHrPayrollDocument @@ -11,8 +14,11 @@ 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): + with ( + self._mock_valid_identification(self.employee_emp, identification_code), + tools.mute_logger("pypdf.generic._image_inline"), + ): 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 7a8730b8506924d078a3b0b4f1661f76fb130d06 Mon Sep 17 00:00:00 2001 From: Simone Rubino Date: Thu, 27 Aug 2026 12:59:52 +0200 Subject: [PATCH 5/5] [DON'T MERGE] test-requirements.txt --- test-requirements.txt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 test-requirements.txt diff --git a/test-requirements.txt b/test-requirements.txt new file mode 100644 index 000000000..4ab2fc8ff --- /dev/null +++ b/test-requirements.txt @@ -0,0 +1,2 @@ +# https://github.com/OCA/payroll/pull/288 +odoo-addon-hr_payroll_document @ git+https://github.com/OCA/payroll.git@refs/pull/288/head#subdirectory=hr_payroll_document