Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion report_py3o/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"website": "https://github.com/OCA/reporting-engine",
"depends": ["web"],
"external_dependencies": {
"python": ["py3o.template", "py3o.formats"],
"python": ["py3o.template", "py3o.formats", "pypdf"],
"deb": ["libreoffice"],
},
"assets": {
Expand Down
2 changes: 1 addition & 1 deletion report_py3o/models/py3o_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ def _create_single_report(self, model_instance, data):
"""This function to generate our py3o report"""
self.ensure_one()
result_fd, result_path = tempfile.mkstemp(
suffix=".ods", prefix="p3o.report.tmp."
suffix=".odt", prefix="py3o.report.tmp."
)
tmpl_data = self.get_template(model_instance)

Expand Down
21 changes: 11 additions & 10 deletions report_py3o/tests/test_report_py3o.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@
from unittest import mock

import pkg_resources
from PyPDF2 import PdfFileWriter
from PyPDF2.pdf import PageObject
from pypdf import PageObject, PdfWriter

from odoo import tools
from odoo.exceptions import ValidationError
Expand Down Expand Up @@ -44,12 +43,14 @@ def temporary_copy(path):


class TestReportPy3o(TransactionCase):
def setUp(self):
super(TestReportPy3o, self).setUp()
self.env.user.image_1920 = PNG
self.report = self.env.ref("report_py3o.res_users_report_py3o")
self.py3o_report = self.env["py3o.report"].create(
{"ir_actions_report_id": self.report.id}
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.env = cls.env(context=dict(cls.env.context, tracking_disable=True))
cls.env.user.image_1920 = PNG
cls.report = cls.env.ref("report_py3o.res_users_report_py3o")
cls.py3o_report = cls.env["py3o.report"].create(
{"ir_actions_report_id": cls.report.id}
)

def test_required_py3_filetype(self):
Expand Down Expand Up @@ -101,8 +102,8 @@ def test_reports_merge_pdf(self):
reports_path = []
for _i in range(0, 3):
result = tempfile.mktemp(".txt")
writer = PdfFileWriter()
writer.addPage(PageObject.createBlankPage(width=100, height=100))
writer = PdfWriter()
writer.add_page(PageObject.create_blank_page(width=100, height=100))
with open(result, "wb") as fp:
writer.write(fp)
reports_path.append(result)
Expand Down
83 changes: 39 additions & 44 deletions report_py3o_fusion_server/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Py3o Report Engine - Fusion server support

|badge1| |badge2| |badge3| |badge4| |badge5|

This module was written to let a py3o fusion server handle format conversion instead of local libreoffice. If you install this module above the *report_py3o* module, you will have to deploy additionnal software components and run 3 daemons (libreoffice, py3o.fusion and py3o.renderserver). This additionnal complexiy comes with several advantages:
This module was written to connect to a local LibreOffice daemon that handle format conversion instead of spawning a new LibreOffice for each conversion. It has several advantages:

* much better performances: Libreoffice runs permanently in the background, no need to spawn a new Libreoffice instance upon every document conversion.
* much better performances: LibreOffice runs permanently in the background, no need to spawn a new LibreOffice instance for every document conversion.
* ability to configure PDF export options in Odoo. This brings many new possibilities such as the ability to generate:

* PDF forms
Expand All @@ -46,83 +46,78 @@ This module was written to let a py3o fusion server handle format conversion ins
Installation
============

Install several additional components and Python libs:

* `Py3o Fusion server <https://bitbucket.org/faide/py3o.fusion>`_,
* `Py3o render server <https://bitbucket.org/faide/py3o.renderserver>`_,
* a Java Runtime Environment (JRE), which can be OpenJDK,
* Libreoffice started in the background in headless mode,
* the Java driver for Libreoffice (Juno).

It is also possible to use the Python driver for Libreoffice (PyUNO), but it is recommended to use the Java driver because it is more stable.

The installation procedure below uses the Java driver. It has been successfully tested on Ubuntu 18.04 LTS ; if you use another OS, you may have to change a few details.

Installation of Libreoffice, JRE and required Java libs on Debian/Ubuntu:
Installation of Libreoffice:

.. code::

sudo apt-get install default-jre ure libgoogle-gson-java libreoffice-java-common libreoffice-writer
sudo apt install libreoffice-writer python3-uno

You may have to install additionnal fonts. For example, to have the special unicode symbols for phone/fax/email in the PDF reports generated by Py3o, you should install the following package:

.. code::

sudo apt-get install fonts-symbola
sudo apt install fonts-symbola

Installation of py3o.fusion:
If you want to produce valid PDF/A documents with this module, activating the corresponding option in the PDF Export Options may not be enough, you also have to make sure that all the fonts used in the document template are installed on the Odoo server, so that they can be embedded in the PDF/A document. For example, if your document template uses the Arial font, you should install that font on your Odoo server:

.. code::

pip3 install py3o.fusion
pip3 install service-identity
sudo apt install msttcorefonts

Installation of py3o.renderserver:
The python libs **py3o.formats** and **py3o.template** are required (they should already be installed for the module *report_py3o*). In the virtualenv of your Odoo server, run:

.. code::

pip3 install py3o.renderserver
% pip install --upgrade py3o.formats py3o.template

At the end, with the dependencies, you should have the following py3o python libs:
Odoo will connect to the LibreOffice via the **uno** python lib which is linked to LibreOffice. So you cannot install the uno lib in Odoo's virtualenv like you do for all the other python libs required by Odoo. Use the following procedure to make the uno lib installed by the package of your Linux distribution available in Odoo's virtualenv. In the virtualenv of your Odoo server, run:

.. code::

% pip3 freeze | grep py3o
py3o.formats==0.3
py3o.fusion==0.8.9
py3o.renderclient==0.3
py3o.renderers.juno==0.8.1
py3o.renderserver==0.5.2
py3o.template==0.10.0
py3o.types==0.1.1
% pip install oooenv
% oooenv cmd-link -a

Start the Py3o Fusion server:
Libreoffice must be run as a daemon. For that, create a file **/etc/systemd/system/libreoffice.service** with the following content:

.. code::

start-py3o-fusion --debug -s localhost -i localhost
[Unit]
Description=Libreoffice headless for Py3o
After=network.target

Start the Py3o render server:
[Service]
Type=simple
User=odoo
Group=odoo
ExecStart=nice -n 10 /usr/lib/libreoffice/program/soffice.bin --nologo --norestore --invisible --headless --nolockcheck --nodefault --accept="socket,host=localhost,port=8997;urp;"
stdout_logfile=/var/log/odoo/libreoffice.log
KillMode=mixed
Restart=always
# number of seconds to attempt restart after failure
RestartSec=5

.. code::

start-py3o-renderserver --java=/usr/lib/jvm/default-java/lib/server/libjvm.so --ure=/usr/share --office=/usr/lib/libreoffice --driver=juno --sofficeport=8997 -i localhost
[Install]
WantedBy=multi-user.target

On the output of the Py3o render server, the first line looks like:
The file content above is an example. You must adapt:

.. code::
- the system user and group that will be used to run libreoffice as a daemon (*odoo* in the exemple)
- the path of the LibreOffice binary (*/usr/lib/libreoffice/program/soffice.bin* in the example)
- the log file (*/var/log/odoo/libreoffice.log* in the example)
- the TCP port on which LibreOffice listens (*8997* in the example)

DEBUG:root:Starting JVM: /usr/lib/jvm/default-java/lib/server/libjvm.so with options: -Djava.class.path=/usr/local/lib/python2.7/dist-packages/py3o/renderers/juno/py3oconverter.jar:/usr/share/java/juh.jar:/usr/share/java/jurt.jar:/usr/share/java/ridl.jar:/usr/share/java/unoloader.jar:/usr/share/java/java_uno.jar:/usr/lib/libreoffice/program/classes/unoil.jar -Xmx150M
Then enable this service and start it:

After **-Djava.class.path**, there is a list of Java libs with *.jar* extension ; check that each JAR file is really present on your filesystem. If one of the jar files is present in another directory, create a symlink that points to the real location of the file. If all the jar files are present on another directory, adapt the *--ure=* argument on the command line of Py3o render server.
.. code::

To check that the Py3o Fusion server is running fine, visit the URL http://<IP_address>:8765/form. On this web page, under the section *Target format*, make sure that you have a line *This server currently supports these formats: ods, odt, docx, doc, html, docbook, pdf, xls.*.
sudo systemctl enable libreoffice
sudo systemctl start libreoffice

If you want to produce valid PDF/A documents with this module, activating the corresponding option in the PDF Export Options may not be enough, you also have to make sure that all the fonts used in the document template are installed on the Odoo server, so that they can be embedded in the PDF/A document. For example, if your document template uses the Arial font, you should install that font on your Odoo server:
Check that LibreOffice runs in the background:

.. code::

sudo apt-get install msttcorefonts
ps aux | grep soffice.bin

Configuration
=============
Expand Down
25 changes: 23 additions & 2 deletions report_py3o_fusion_server/demo/report_py3o.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,27 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="report_py3o.res_users_report_py3o" model="ir.actions.report">
<field name="py3o_is_local_fusion" eval="1" />
<record id="demo_py3o_server" model="py3o.server">
<field name="host">localhost</field>
</record>
<record id="demo_py3o_pdf_options" model="py3o.pdf.options">
<field name="name">Watermark for demo</field>
<field name="watermark" eval="True" />
<field name="watermark_text">DEMO</field>
</record>
<record id="res_users_report_py3o_pdf" model="ir.actions.report">
<field name="name">Py3o Demo Report PDF</field>
<field name="model">res.users</field>
<field name="report_name">py3o_user_info_pdf</field>
<field name="report_type">py3o</field>
<field name="py3o_filetype">pdf</field>
<field name="module">report_py3o</field>
<field name="py3o_template_fallback">demo/res_user.odt</field>
<field name="py3o_server_id" ref="demo_py3o_server" />
<field name="pdf_options_id" ref="demo_py3o_pdf_options" />
<field
name="print_report_name"
>object.name.replace(' ', '_') + '-demo.pdf'</field>
<field name="binding_model_id" ref="base.model_res_users" />
</record>

</odoo>
23 changes: 1 addition & 22 deletions report_py3o_fusion_server/models/ir_actions_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,35 +4,14 @@
import logging

from odoo import _, api, fields, models
from odoo.exceptions import ValidationError

logger = logging.getLogger(__name__)


class IrActionsReport(models.Model):
_inherit = "ir.actions.report"

@api.constrains("py3o_is_local_fusion", "py3o_server_id")
def _check_py3o_server_id(self):
for report in self:
if report.report_type != "py3o":
continue
if not report.py3o_is_local_fusion and not report.py3o_server_id:
raise ValidationError(
_(
"You can not use remote fusion without Fusion server. "
"Please specify a Fusion Server"
)
)

py3o_is_local_fusion = fields.Boolean(
"Local Fusion",
help="Native formats will be processed without a server. "
"You must use this mode if you call methods on your model into "
"the template.",
default=True,
)
py3o_server_id = fields.Many2one("py3o.server", "Fusion Server")
py3o_server_id = fields.Many2one("py3o.server", "LibreOffice for Py3o")
pdf_options_id = fields.Many2one(
"py3o.pdf.options",
string="PDF Options",
Expand Down
Loading