commit
151d176331
|
@ -1,7 +1,7 @@
|
||||||
# Do NOT update manually; changes here will be overwritten by Copier
|
# Do NOT update manually; changes here will be overwritten by Copier
|
||||||
_commit: v1.6.1
|
_commit: v1.6.1
|
||||||
_src_path: git+https://github.com/OCA/oca-addons-repo-template
|
_src_path: git+https://github.com/OCA/oca-addons-repo-template
|
||||||
ci: Travis
|
ci: GitHub
|
||||||
dependency_installation_mode: PIP
|
dependency_installation_mode: PIP
|
||||||
generate_requirements_txt: true
|
generate_requirements_txt: true
|
||||||
include_wkhtmltopdf: true
|
include_wkhtmltopdf: true
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
name: tests
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- "13.0*"
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- "13.0"
|
||||||
|
- "13.0-ocabot-*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unreleased-deps:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Detect unreleased dependencies
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
for reqfile in requirements.txt test-requirements.txt ; do
|
||||||
|
if [ -f ${reqfile} ] ; then
|
||||||
|
result=0
|
||||||
|
# reject non-comment lines that contain a / (i.e. URLs, relative paths)
|
||||||
|
grep "^[^#].*/" ${reqfile} || result=$?
|
||||||
|
if [ $result -eq 0 ] ; then
|
||||||
|
echo "Unreleased dependencies found in ${reqfile}."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: ${{ matrix.container }}
|
||||||
|
name: ${{ matrix.name }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- container: ghcr.io/oca/oca-ci/py3.6-odoo13.0:latest
|
||||||
|
makepot: "true"
|
||||||
|
name: test with Odoo
|
||||||
|
- container: ghcr.io/oca/oca-ci/py3.6-ocb13.0:latest
|
||||||
|
name: test with OCB
|
||||||
|
services:
|
||||||
|
postgres:
|
||||||
|
image: postgres:9.6
|
||||||
|
env:
|
||||||
|
POSTGRES_USER: odoo
|
||||||
|
POSTGRES_PASSWORD: odoo
|
||||||
|
POSTGRES_DB: odoo
|
||||||
|
ports:
|
||||||
|
- 5432:5432
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
persist-credentials: false
|
||||||
|
- name: Install addons and dependencies
|
||||||
|
run: oca_install_addons
|
||||||
|
- name: Check licenses
|
||||||
|
run: manifestoo -d . check-licenses
|
||||||
|
- name: Check development status
|
||||||
|
run: manifestoo -d . check-dev-status --default-dev-status=Beta
|
||||||
|
- name: Initialize test db
|
||||||
|
run: oca_init_test_database
|
||||||
|
- name: Run tests
|
||||||
|
run: oca_run_tests
|
||||||
|
- uses: codecov/codecov-action@v1
|
||||||
|
- name: Update .pot files
|
||||||
|
run: oca_export_and_push_pot https://x-access-token:${{ secrets.GIT_PUSH_TOKEN }}@github.com/${{ github.repository }}
|
||||||
|
if: ${{ matrix.makepot == 'true' && github.event_name == 'push' && github.repository_owner == 'OCA' }}
|
45
.travis.yml
45
.travis.yml
|
@ -1,45 +0,0 @@
|
||||||
language: python
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- $HOME/.cache/pip
|
|
||||||
- $HOME/.cache/pre-commit
|
|
||||||
|
|
||||||
python:
|
|
||||||
- "3.6"
|
|
||||||
|
|
||||||
addons:
|
|
||||||
postgresql: "9.6"
|
|
||||||
apt:
|
|
||||||
packages:
|
|
||||||
- expect-dev # provides unbuffer utility
|
|
||||||
- "swig"
|
|
||||||
- "libreoffice"
|
|
||||||
|
|
||||||
stages:
|
|
||||||
- test
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
include:
|
|
||||||
- stage: test
|
|
||||||
env:
|
|
||||||
- TESTS=1 ODOO_REPO="odoo/odoo" MAKEPOT="1"
|
|
||||||
- stage: test
|
|
||||||
env:
|
|
||||||
- TESTS=1 ODOO_REPO="OCA/OCB"
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
- VERSION="13.0" TESTS="0" LINT_CHECK="0" MAKEPOT="0"
|
|
||||||
- WKHTMLTOPDF_VERSION="0.12.5"
|
|
||||||
- MQT_DEP=PIP
|
|
||||||
|
|
||||||
install:
|
|
||||||
- git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git
|
|
||||||
${HOME}/maintainer-quality-tools
|
|
||||||
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
|
|
||||||
- travis_install_nightly
|
|
||||||
|
|
||||||
script:
|
|
||||||
- travis_run_tests
|
|
||||||
|
|
||||||
after_success:
|
|
||||||
- travis_after_tests_success
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
[](https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=13.0)
|
[](https://runboat.odoo-community.org/builds?repo=OCA/reporting-engine&target_branch=13.0)
|
||||||
[](https://travis-ci.com/OCA/reporting-engine)
|
[](https://github.com/OCA/reporting-engine/actions/workflows/pre-commit.yml?query=branch%3A13.0)
|
||||||
|
[](https://github.com/OCA/reporting-engine/actions/workflows/test.yml?query=branch%3A13.0)
|
||||||
[](https://codecov.io/gh/OCA/reporting-engine)
|
[](https://codecov.io/gh/OCA/reporting-engine)
|
||||||
[](https://translation.odoo-community.org/engage/reporting-engine-13-0/?utm_source=widget)
|
[](https://translation.odoo-community.org/engage/reporting-engine-13-0/?utm_source=widget)
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,10 @@
|
||||||
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/reporting-engine",
|
"website": "https://github.com/OCA/reporting-engine",
|
||||||
"depends": ["web"],
|
"depends": ["web"],
|
||||||
"external_dependencies": {"python": ["py3o.template", "py3o.formats", "PyPDF2"]},
|
"external_dependencies": {
|
||||||
|
"python": ["py3o.template", "py3o.formats", "PyPDF2"],
|
||||||
|
"deb": ["libreoffice"],
|
||||||
|
},
|
||||||
"data": [
|
"data": [
|
||||||
"security/ir.model.access.csv",
|
"security/ir.model.access.csv",
|
||||||
"views/menu.xml",
|
"views/menu.xml",
|
||||||
|
|
|
@ -9,7 +9,10 @@
|
||||||
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
||||||
"website": "https://github.com/OCA/reporting-engine",
|
"website": "https://github.com/OCA/reporting-engine",
|
||||||
"depends": ["report_py3o"],
|
"depends": ["report_py3o"],
|
||||||
"external_dependencies": {"python": ["py3o.template", "py3o.formats"]},
|
"external_dependencies": {
|
||||||
|
"python": ["py3o.template", "py3o.formats"],
|
||||||
|
"deb": ["libreoffice"],
|
||||||
|
},
|
||||||
"demo": ["demo/report_py3o.xml", "demo/py3o_pdf_options.xml"],
|
"demo": ["demo/report_py3o.xml", "demo/py3o_pdf_options.xml"],
|
||||||
"data": [
|
"data": [
|
||||||
"views/ir_actions_report.xml",
|
"views/ir_actions_report.xml",
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"installable": True,
|
"installable": True,
|
||||||
"depends": ["web_editor"],
|
"depends": ["web_editor"],
|
||||||
"external_dependencies": {"python": ["endesive", "cryptography"]},
|
"external_dependencies": {
|
||||||
|
"python": ["endesive", "cryptography"],
|
||||||
|
"deb": ["default-jre-headless"],
|
||||||
|
},
|
||||||
"data": [
|
"data": [
|
||||||
"data/defaults.xml",
|
"data/defaults.xml",
|
||||||
"security/ir.model.access.csv",
|
"security/ir.model.access.csv",
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
<odoo noupdate="1">
|
<odoo noupdate="1">
|
||||||
<record model="ir.config_parameter" id="report_qweb_signer_java_param">
|
<record model="ir.config_parameter" id="report_qweb_signer_java_param">
|
||||||
<field name="key">report_qweb_signer.java_parameters</field>
|
<field name="key">report_qweb_signer.java_parameters</field>
|
||||||
<field name="value">-Xms4M -Xmx4M -XX:CompressedClassSpaceSize=256m</field>
|
<field name="value">-Xms16M -Xmx16M -XX:CompressedClassSpaceSize=256m</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.config_parameter" id="report_qweb_signer_java_position_param">
|
||||||
|
<field name="key">report_qweb_signer.java_position_parameters</field>
|
||||||
|
<field name="value">-llx 400 -lly 820 -urx 600 -ury 100 -fs 8</field>
|
||||||
</record>
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
@ -33,14 +33,16 @@ License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
</t>
|
</t>
|
||||||
</t>
|
</t>
|
||||||
</template>
|
</template>
|
||||||
<report
|
<record id="partner_demo_report" model="ir.actions.report">
|
||||||
id="partner_demo_report"
|
<field name="name">Test PDF certificate</field>
|
||||||
model="res.partner"
|
<field name="model">res.partner</field>
|
||||||
string="Test PDF certificate"
|
<field name="report_type">qweb-pdf</field>
|
||||||
report_type="qweb-pdf"
|
<field name="report_name">report_qweb_signer.report_partner_demo</field>
|
||||||
name="report_qweb_signer.report_partner_demo"
|
<field
|
||||||
file="report_qweb_signer.report_partner_demo"
|
name="attachment"
|
||||||
attachment_use="True"
|
>'test_' + (object.name or '').replace(' ', '_').lower() + '.pdf'</field>
|
||||||
attachment="'test_' + (object.name or '').replace(' ', '_').lower() + '.pdf'"
|
<field name="attachment_use">True</field>
|
||||||
/>
|
<field name="binding_model_id" ref="base.model_res_partner" />
|
||||||
|
<field name="binding_type">report</field>
|
||||||
|
</record>
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|
|
@ -39,11 +39,13 @@ class IrActionsReport(models.Model):
|
||||||
"""Obtain the proper certificate for the report and the conditions."""
|
"""Obtain the proper certificate for the report and the conditions."""
|
||||||
if self.report_type != "qweb-pdf":
|
if self.report_type != "qweb-pdf":
|
||||||
return False
|
return False
|
||||||
|
company_id = self.env.company.id
|
||||||
|
if res_ids:
|
||||||
|
obj = self.env[self.model].browse(res_ids[0])
|
||||||
|
if "company_id" in obj:
|
||||||
|
company_id = obj.company_id.id or company_id
|
||||||
certificates = self.env["report.certificate"].search(
|
certificates = self.env["report.certificate"].search(
|
||||||
[
|
[("company_id", "=", company_id), ("model_id", "=", self.model)]
|
||||||
("company_id", "=", self.env.user.company_id.id),
|
|
||||||
("model_id", "=", self.model),
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
if not certificates:
|
if not certificates:
|
||||||
return False
|
return False
|
||||||
|
@ -122,8 +124,13 @@ class IrActionsReport(models.Model):
|
||||||
irc_param = self.env["ir.config_parameter"].sudo()
|
irc_param = self.env["ir.config_parameter"].sudo()
|
||||||
java_bin = "java -jar"
|
java_bin = "java -jar"
|
||||||
java_param = irc_param.get_param("report_qweb_signer.java_parameters")
|
java_param = irc_param.get_param("report_qweb_signer.java_parameters")
|
||||||
jar = "{}/../static/jar/jPdfSign.jar".format(me)
|
java_position_param = irc_param.get_param(
|
||||||
return "{} {} {} {}".format(java_bin, java_param, jar, opts)
|
"report_qweb_signer.java_position_parameters"
|
||||||
|
)
|
||||||
|
jar = "{}/../static/jar/JSignPdf.jar".format(me)
|
||||||
|
return "{} {} {} {} {}".format(
|
||||||
|
java_bin, java_param, jar, opts, java_position_param
|
||||||
|
)
|
||||||
|
|
||||||
def _get_endesive_params(self, certificate):
|
def _get_endesive_params(self, certificate):
|
||||||
date = datetime.datetime.utcnow() - datetime.timedelta(hours=12)
|
date = datetime.datetime.utcnow() - datetime.timedelta(hours=12)
|
||||||
|
@ -160,7 +167,7 @@ class IrActionsReport(models.Model):
|
||||||
return pdfsigned
|
return pdfsigned
|
||||||
|
|
||||||
def pdf_sign(self, pdf, certificate):
|
def pdf_sign(self, pdf, certificate):
|
||||||
pdfsigned = pdf + ".signed.pdf"
|
pdfsigned = pdf[:-4] + "_signed.pdf"
|
||||||
p12 = _normalize_filepath(certificate.path)
|
p12 = _normalize_filepath(certificate.path)
|
||||||
passwd = _normalize_filepath(certificate.password_file)
|
passwd = _normalize_filepath(certificate.password_file)
|
||||||
method_used = certificate.signing_method
|
method_used = certificate.signing_method
|
||||||
|
@ -169,7 +176,10 @@ class IrActionsReport(models.Model):
|
||||||
_("Signing report (PDF): " "Certificate or password file not found")
|
_("Signing report (PDF): " "Certificate or password file not found")
|
||||||
)
|
)
|
||||||
if method_used == "java":
|
if method_used == "java":
|
||||||
signer_opts = '"{}" "{}" "{}" "{}"'.format(p12, pdf, pdfsigned, passwd)
|
passwd_f = open(passwd, "tr")
|
||||||
|
passwd = passwd_f.read().strip()
|
||||||
|
passwd_f.close()
|
||||||
|
signer_opts = ' "{}" -ksf "{}" -ksp "{}" -d "/tmp"'.format(pdf, p12, passwd)
|
||||||
signer = self._signer_bin(signer_opts)
|
signer = self._signer_bin(signer_opts)
|
||||||
process = subprocess.Popen(
|
process = subprocess.Popen(
|
||||||
signer, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
|
signer, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True
|
||||||
|
@ -220,7 +230,7 @@ class IrActionsReport(models.Model):
|
||||||
for fname in (pdf, signed):
|
for fname in (pdf, signed):
|
||||||
try:
|
try:
|
||||||
os.unlink(fname)
|
os.unlink(fname)
|
||||||
except (OSError, IOError):
|
except OSError:
|
||||||
_logger.error("Error when trying to remove file %s", fname)
|
_logger.error("Error when trying to remove file %s", fname)
|
||||||
if certificate.attachment:
|
if certificate.attachment:
|
||||||
self._attach_signed_write(res_ids, certificate, content)
|
self._attach_signed_write(res_ids, certificate, content)
|
||||||
|
|
|
@ -31,6 +31,7 @@ class ReportCertificate(models.Model):
|
||||||
required=True,
|
required=True,
|
||||||
comodel_name="ir.model",
|
comodel_name="ir.model",
|
||||||
help="Model where apply this certificate",
|
help="Model where apply this certificate",
|
||||||
|
ondelete="cascade",
|
||||||
)
|
)
|
||||||
domain = fields.Char(
|
domain = fields.Char(
|
||||||
string="Domain", help="Domain for filtering if sign or not the document",
|
string="Domain", help="Domain for filtering if sign or not the document",
|
||||||
|
|
|
@ -5,3 +5,5 @@
|
||||||
* Pedro M. Baeza
|
* Pedro M. Baeza
|
||||||
* Jairo Llopis
|
* Jairo Llopis
|
||||||
* David Vidal
|
* David Vidal
|
||||||
|
* Santi Argüeso <santi@comunitea.com>
|
||||||
|
* Omar Castiñeira <omar@comunitea.com>
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
External utilities
|
External utilities
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
* iText v1.4.8: © 2000-2006, Paulo Soares, Bruno Lowagie and others - License `MPL <http://www.mozilla.org/MPL>`__ or `LGPL2 <http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html>`__ - http://sourceforge.net/projects/itext
|
* JSignPdf: © Josef Cacek - License `MPL <http://www.mozilla.org/MPL>`__ or `LGPL2 <http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html>`__ - http://jsignpdf.sourceforge.net/
|
||||||
* jPdfSign: © 2006 Jan Peter Stotz - License `MPL <http://www.mozilla.org/MPL>`__ or `LGPL2 <http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html>`__ (inherited from iText) - http://private.sit.fraunhofer.de/~stotz/software/jpdfsign
|
|
||||||
* Modified jPdfSign: © 2015 Antonio Espinosa - License `MPL <http://www.mozilla.org/MPL>`__ or `LGPL2 <http://www.gnu.org/licenses/old-licenses/lgpl-2.0.html>`__ (inherited from iText) - static/src/java/JPdfSign.java
|
|
||||||
|
|
||||||
Icon
|
Icon
|
||||||
++++
|
++++
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
To install this module, you need to install Java JDK Headlees, e.g.:
|
To install this module, you need to install Java JDK Headlees, e.g.:
|
||||||
|
|
||||||
apt-get install openjdk-8-jre-headless
|
apt-get install default-jre-headless
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
* When signing multiple documents (if 'Allow only one document' is disable)
|
* When signing multiple documents (if 'Allow only one document' is disable)
|
||||||
then 'Save as attachment' is not applied and signed result is not
|
then 'Save as attachment' is not applied and signed result is not
|
||||||
saved as attachment.
|
saved as attachment.
|
||||||
* To have a visible signature through an image embedded in the resulting PDF.
|
|
||||||
* Add tests.
|
* Add tests.
|
||||||
|
|
|
@ -8,3 +8,8 @@ when signing date is important, for example, when signing customer invoices.
|
||||||
|
|
||||||
You can try the signing with the demo report that is included for customers
|
You can try the signing with the demo report that is included for customers
|
||||||
called "Test PDF certificate".
|
called "Test PDF certificate".
|
||||||
|
|
||||||
|
You can set extra parameters of JSignPdf library in the system parameter
|
||||||
|
named 'report_qweb_signer.java_position_parameters', for example '-V' to
|
||||||
|
visible signature into pdf. You can also set extra parameters for Java in the
|
||||||
|
system parameter named 'report_qweb_signer.java_parameters'.
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -2,3 +2,4 @@ py3o.template
|
||||||
py3o.formats
|
py3o.formats
|
||||||
genshi>=0.7
|
genshi>=0.7
|
||||||
cryptography
|
cryptography
|
||||||
|
endesive
|
||||||
|
|
Loading…
Reference in New Issue