on_convert_report

on_convert_report(report)

domain: server

language: python

class: Reports class

Description

The framework converts reports internally, using LibreOffice. It is possible to use portable LibreOffice installation.

Use the on_convert_report event if you want to use some other service or change some parameters of report conversion. For example external JSreport service.

The report parameter is the report that triggered the event.

Example

import os
from subprocess import Popen, STDOUT, PIPE

def on_convert_report(report):
    try:
        if os.name == "nt":
            import _winreg
            regpath = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\App Paths\\soffice.exe"
            root = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, regpath)
            s_office = _winreg.QueryValue(root, "")
        else:
            s_office = "soffice"
        convertion = Popen([s_office, '--headless', '--convert-to', report.ext,
            report.report_filename, '--outdir', os.path.join(report.task.work_dir, 'static', 'reports') ],
            stderr=STDOUT,stdout=PIPE)
        out, err = convertion.communicate()
        converted = True
    except Exception as e:
        print(e)

Portable LibreOffice on Windows

Add the event to report and use below with the LO installation path, ie.:

import os
from subprocess import Popen, STDOUT, PIPE

def on_convert_report(report):
    print("running on_convert !!!!!!!!!!!")
    try:
        if os.name == "nt":
            s_office = r"C:\LibreOfficePortable\App\libreoffice\program\soffice.exe"
        convertion = Popen([s_office, '--headless', '--convert-to', report.ext.lstrip('.'),
            report.report_filename, '--outdir', os.path.join(report.task.work_dir, 'static', 'reports') ],
            stderr=STDOUT,stdout=PIPE)
        out, err = convertion.communicate()

        # Check if the converted file exists
        ods_file = report.report_filename
        pdf_file = ods_file.replace('.ods', report.ext)

        if os.path.exists(pdf_file):
            print(f"Conversion successful: {pdf_file}")

            # CRITICAL: Update the report's filename and URL
            report.report_filename = pdf_file
            report.report_url = report.report_url.replace('.ods', report.ext)
            # OR rebuild the URL properly:
            # report.report_url = f"/static/reports/{os.path.basename(pdf_file)}"

            print(f"Updated report_url to: {report.report_url}")
            return True
        else:
            print("Conversion failed: output file not found")
            return False

    except Exception as e:
        print(f"Conversion error: {e}")
        return False

External Report service

This example will run JSreport report name invoice-main from local server jsreport_url. The report parameter might be used to specify jsreport_url.

import os
import json
import requests

def on_convert_report(report):
    # Using the confirmed working template name
    report_data = {
        "template": { "name": "invoice-main" },
        "data": {
            "number": "123",
            "seller": {
                "name": "Next Step Webs, Inc.",
                "road": "12345 Sunny Road",
                "country": "Sunnyville, TX 12345"
            },
            "buyer": {
                "name": "Acme Corp.",
                "road": "16 Johnson Road",
                "country": "Paris, France 8060"
            },
            "items": [
                {
                    "name": "Website design",
                    "price": 300
                }
            ]
        }
    }

    jsreport_url = "http://127.0.0.1:5488/api/report"

    try:
        response = requests.post(
            jsreport_url,
            headers={"Content-Type": "application/json"},
            json=report_data,
            timeout=30
        )
        response.raise_for_status()

        # Save the PDF response
        with open(report.report_filename, 'wb') as f:
            f.write(response.content)

        print(f"Report successfully generated via jsreport: {report.report_filename}")
        return True

    except requests.exceptions.HTTPError as e:
        print(f"HTTP Error: {e}")
        if hasattr(response, 'text'):
            print(f"Response body: {response.text}")
        return False
    except Exception as e:
        print(f"Unexpected error: {e}")
        return False

The above procedure is not based on JSreport authentication. If authentication is enabled, we need to pass the Authorization header for every request:

import base64
def on_convert_report(report):
    username = "your_username"
    password = "your_password"

    credentials = f"{username}:{password}"
    encoded_credentials = base64.b64encode(credentials.encode('utf-8')).decode('utf-8')

    report_data = {
    ...
    }
    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Basic {encoded_credentials}"
    }
    ...