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