diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 68a06bc..6395edf 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -12,13 +12,13 @@ jobs: pre-commit: runs-on: ubuntu-22.04 steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v2 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: "3.11" - name: Get python version run: echo "PY=$(python -VV | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - - uses: actions/cache@v1 + - uses: actions/cache@v4 with: path: ~/.cache/pre-commit key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }} diff --git a/report_aeroo/README.rst b/report_aeroo/README.rst index 5736fff..5e12fe5 100644 --- a/report_aeroo/README.rst +++ b/report_aeroo/README.rst @@ -674,6 +674,34 @@ The difference between this feature and a report attachment from `Advanced Setti 2. You do not need to redefine the name of the attachment in the email template. The attachment name will be the one defined on the report. +Watermark Feature +================= +The module includes a TEST watermark feature for development and testing environments. + +Configuration +------------- +To enable the TEST watermark on PDF reports, set the following configuration parameter: + +.. code-block:: bash + + # Enable TEST watermark + ir.config_parameter: AEROO_REPORTS_TESTS = True + + # Disable TEST watermark (default) + ir.config_parameter: AEROO_REPORTS_TESTS = False + +The watermark parameter can be set via the Odoo interface under Settings > Technical > Parameters > System Parameters. + +.. image:: static/description/watermark_config_parameter.png + +When enabled, all PDF reports generated through Aeroo will display a diagonal "TEST" watermark in red with transparency. + +Example Result +-------------- +When the watermark is enabled, PDF reports will show the TEST watermark overlaid on each page: + +.. image:: static/description/watermark_example.png + Contributors ============ * Alistek diff --git a/report_aeroo/__manifest__.py b/report_aeroo/__manifest__.py index 5780c75..f1a1f7f 100644 --- a/report_aeroo/__manifest__.py +++ b/report_aeroo/__manifest__.py @@ -5,7 +5,7 @@ { "name": "Aeroo Reports", - "version": "16.0.1.0.1", + "version": "16.0.1.0.2", "category": "Generic Modules/Aeroo Reports", "summary": "Enterprise grade reporting solution", "author": "Alistek", @@ -13,7 +13,7 @@ "website": "https://bit.ly/numigi-com", "depends": ["mail", "spreadsheet_dashboard"], "external_dependencies": { - "python": ["aeroolib", "babel", "genshi"], + "python": ["aeroolib", "babel", "genshi", "PyPDF2", "reportlab"], }, "data": [ "security/security.xml", diff --git a/report_aeroo/data/report_aeroo_data.xml b/report_aeroo/data/report_aeroo_data.xml index 085a4e2..6b85264 100755 --- a/report_aeroo/data/report_aeroo_data.xml +++ b/report_aeroo/data/report_aeroo_data.xml @@ -43,5 +43,11 @@ csv ods + + + + AEROO_REPORTS_TESTS + False + diff --git a/report_aeroo/models/ir_actions_report.py b/report_aeroo/models/ir_actions_report.py index 48aaa97..949b80e 100644 --- a/report_aeroo/models/ir_actions_report.py +++ b/report_aeroo/models/ir_actions_report.py @@ -21,11 +21,27 @@ from odoo.tools.safe_eval import safe_eval from odoo.tools import file_open + from ..namespace import AerooNamespace from ..extra_functions import aeroo_function_registry _logger = logging.getLogger(__name__) + +try: + from PyPDF2 import PdfFileWriter, PdfFileReader + from reportlab.pdfgen import canvas + from reportlab.lib.pagesizes import letter + from reportlab.lib.colors import red + + PYPDF_AVAILABLE = True +except ImportError: + PYPDF_AVAILABLE = False + _logger.warning( + "PyPDF2 and/or reportlab not available, watermark feature will not work!" + ) + + try: # We use a jinja2 sandboxed environment to render mako templates. # Note that the rendering does not cover all the mako syntax, in particular @@ -399,6 +415,10 @@ def _render_aeroo_content(self, template, data, output_format): if self.aeroo_in_format != output_format: output = self._convert_aeroo_report(output, output_format) + # Add TEST watermark if parameter is enabled + if output_format == "pdf" and self._should_add_test_watermark(): + output = self._add_test_watermark_to_pdf(output) + return output def _get_aeroo_extra_functions(self): @@ -606,6 +626,66 @@ def _merge_aeroo_pdf(self, input_files): return output + def _should_add_test_watermark(self): + """Check if TEST watermark should be added.""" + param_value = ( + self.env["ir.config_parameter"] + .sudo() + .get_param("AEROO_REPORTS_TESTS", "False") + ) + return param_value.lower() == "true" + + def _add_test_watermark_to_pdf(self, pdf_data): + """Add TEST watermark to PDF.""" + if not PYPDF_AVAILABLE: + _logger.warning("PyPDF2 and reportlab not available, cannot add watermark") + return pdf_data + + try: + # Create watermark + watermark_buffer = BytesIO() + watermark_pdf = canvas.Canvas(watermark_buffer, pagesize=letter) + + # Watermark configuration + watermark_pdf.setFillColor(red, alpha=0.3) # Red with transparency + watermark_pdf.setFont("Helvetica-Bold", 72) # Large size + + # Center text on page + page_width, page_height = letter + text_width = watermark_pdf.stringWidth("TEST", "Helvetica-Bold", 72) + x = (page_width - text_width) / 2 + y = page_height / 2 + + # Rotation for diagonal + watermark_pdf.saveState() + watermark_pdf.translate(x, y) + watermark_pdf.rotate(45) + watermark_pdf.drawString(-text_width / 2, 0, "TEST") + watermark_pdf.restoreState() + + watermark_pdf.save() + watermark_buffer.seek(0) + + original_pdf = PdfFileReader(BytesIO(pdf_data)) + watermark_pdf_reader = PdfFileReader(watermark_buffer) + watermark_page = watermark_pdf_reader.pages[0] + + output_pdf = PdfFileWriter() + + for page in original_pdf.pages: + page.mergePage(watermark_page) + output_pdf.addPage(page) + + output_buffer = BytesIO() + output_pdf.write(output_buffer) + output_buffer.seek(0) + + return output_buffer.read() + + except Exception as e: + _logger.error("Error adding watermark: %s", str(e)) + return pdf_data + class IrActionsReportWithSudo(models.Model): @@ -681,6 +761,10 @@ def _render_aeroo_from_list_of_records( template, report_data, output_format ) + # Add TEST watermark if parameter is enabled + if output_format == "pdf" and self._should_add_test_watermark(): + output = self._add_test_watermark_to_pdf(output) + return output, output_format def _onchange_is_aeroo_list_report_set_multi(self): diff --git a/report_aeroo/static/description/watermark_config_parameter.png b/report_aeroo/static/description/watermark_config_parameter.png new file mode 100644 index 0000000..41f435e Binary files /dev/null and b/report_aeroo/static/description/watermark_config_parameter.png differ diff --git a/report_aeroo/static/description/watermark_example.png b/report_aeroo/static/description/watermark_example.png new file mode 100644 index 0000000..5390447 Binary files /dev/null and b/report_aeroo/static/description/watermark_example.png differ