[MIG] report_py3o, report_py3o_fusion_server: Migration to 13.0
parent
e644a32572
commit
f584d505a0
|
@ -9,4 +9,4 @@ line_length=88
|
||||||
known_odoo=odoo
|
known_odoo=odoo
|
||||||
known_odoo_addons=odoo.addons
|
known_odoo_addons=odoo.addons
|
||||||
sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER
|
sections=FUTURE,STDLIB,THIRDPARTY,ODOO,ODOO_ADDONS,FIRSTPARTY,LOCALFOLDER
|
||||||
known_third_party=PyPDF2,mock,openerp,pkg_resources,requests,werkzeug
|
known_third_party=PyPDF2,mock,pkg_resources,requests,werkzeug
|
||||||
|
|
|
@ -12,6 +12,7 @@ addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
- expect-dev # provides unbuffer utility
|
- expect-dev # provides unbuffer utility
|
||||||
|
- libreoffice
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- linting
|
- linting
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"name": "Py3o Report Engine",
|
"name": "Py3o Report Engine",
|
||||||
"summary": "Reporting engine based on Libreoffice (ODT -> ODT, "
|
"summary": "Reporting engine based on Libreoffice (ODT -> ODT, "
|
||||||
"ODT -> PDF, ODT -> DOC, ODT -> DOCX, ODS -> ODS, etc.)",
|
"ODT -> PDF, ODT -> DOC, ODT -> DOCX, ODS -> ODS, etc.)",
|
||||||
"version": "12.0.2.0.2",
|
"version": "13.0.1.0.0",
|
||||||
"category": "Reporting",
|
"category": "Reporting",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
||||||
|
|
Binary file not shown.
|
@ -1,11 +0,0 @@
|
||||||
# © 2018 Therp BV <http://therp.nl>
|
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
|
||||||
|
|
||||||
|
|
||||||
def migrate(cr, version=None):
|
|
||||||
# when migrating from a pre-split version of the module, pull the fusion
|
|
||||||
# server module too to have no loss of features
|
|
||||||
cr.execute(
|
|
||||||
"update ir_module_module set state='to install' "
|
|
||||||
"where name='report_py3o_fusion_server' and state='uninstalled'"
|
|
||||||
)
|
|
|
@ -27,7 +27,6 @@ class IrActionsReport(models.Model):
|
||||||
|
|
||||||
_inherit = "ir.actions.report"
|
_inherit = "ir.actions.report"
|
||||||
|
|
||||||
@api.multi
|
|
||||||
@api.constrains("py3o_filetype", "report_type")
|
@api.constrains("py3o_filetype", "report_type")
|
||||||
def _check_py3o_filetype(self):
|
def _check_py3o_filetype(self):
|
||||||
for report in self:
|
for report in self:
|
||||||
|
@ -114,7 +113,6 @@ class IrActionsReport(models.Model):
|
||||||
return lo_bin
|
return lo_bin
|
||||||
|
|
||||||
@api.depends("report_type", "py3o_filetype")
|
@api.depends("report_type", "py3o_filetype")
|
||||||
@api.multi
|
|
||||||
def _compute_is_py3o_native_format(self):
|
def _compute_is_py3o_native_format(self):
|
||||||
fmt = Formats()
|
fmt = Formats()
|
||||||
for rec in self:
|
for rec in self:
|
||||||
|
@ -123,14 +121,12 @@ class IrActionsReport(models.Model):
|
||||||
filetype = rec.py3o_filetype
|
filetype = rec.py3o_filetype
|
||||||
rec.is_py3o_native_format = fmt.get_format(filetype).native
|
rec.is_py3o_native_format = fmt.get_format(filetype).native
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _compute_lo_bin_path(self):
|
def _compute_lo_bin_path(self):
|
||||||
lo_bin = self._get_lo_bin()
|
lo_bin = self._get_lo_bin()
|
||||||
for rec in self:
|
for rec in self:
|
||||||
rec.lo_bin_path = lo_bin
|
rec.lo_bin_path = lo_bin
|
||||||
|
|
||||||
@api.depends("lo_bin_path", "is_py3o_native_format", "report_type")
|
@api.depends("lo_bin_path", "is_py3o_native_format", "report_type")
|
||||||
@api.multi
|
|
||||||
def _compute_py3o_report_not_available(self):
|
def _compute_py3o_report_not_available(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if not rec.report_type == "py3o":
|
if not rec.report_type == "py3o":
|
||||||
|
@ -156,7 +152,6 @@ class IrActionsReport(models.Model):
|
||||||
[("report_name", "=", report_name), ("report_type", "=", report_type)]
|
[("report_name", "=", report_name), ("report_type", "=", report_type)]
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def render_py3o(self, res_ids, data):
|
def render_py3o(self, res_ids, data):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
if self.report_type != "py3o":
|
if self.report_type != "py3o":
|
||||||
|
@ -170,7 +165,6 @@ class IrActionsReport(models.Model):
|
||||||
.create_report(res_ids, data)
|
.create_report(res_ids, data)
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def gen_report_download_filename(self, res_ids, data):
|
def gen_report_download_filename(self, res_ids, data):
|
||||||
"""Override this function to change the name of the downloaded report
|
"""Override this function to change the name of the downloaded report
|
||||||
"""
|
"""
|
||||||
|
@ -181,7 +175,6 @@ class IrActionsReport(models.Model):
|
||||||
return safe_eval(report.print_report_name, {"object": obj, "time": time})
|
return safe_eval(report.print_report_name, {"object": obj, "time": time})
|
||||||
return "{}.{}".format(self.name, self.py3o_filetype)
|
return "{}.{}".format(self.name, self.py3o_filetype)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _get_attachments(self, res_ids):
|
def _get_attachments(self, res_ids):
|
||||||
""" Return the report already generated for the given res_ids
|
""" Return the report already generated for the given res_ids
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -77,7 +77,6 @@ class Py3oReport(models.TransientModel):
|
||||||
comodel_name="ir.actions.report", required=True
|
comodel_name="ir.actions.report", required=True
|
||||||
)
|
)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _is_valid_template_path(self, path):
|
def _is_valid_template_path(self, path):
|
||||||
""" Check if the path is a trusted path for py3o templates.
|
""" Check if the path is a trusted path for py3o templates.
|
||||||
"""
|
"""
|
||||||
|
@ -100,7 +99,6 @@ class Py3oReport(models.TransientModel):
|
||||||
)
|
)
|
||||||
return is_valid
|
return is_valid
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _is_valid_template_filename(self, filename):
|
def _is_valid_template_filename(self, filename):
|
||||||
""" Check if the filename can be used as py3o template
|
""" Check if the filename can be used as py3o template
|
||||||
"""
|
"""
|
||||||
|
@ -116,7 +114,6 @@ class Py3oReport(models.TransientModel):
|
||||||
logger.warning("%s is not a valid Py3o template filename", filename)
|
logger.warning("%s is not a valid Py3o template filename", filename)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _get_template_from_path(self, tmpl_name):
|
def _get_template_from_path(self, tmpl_name):
|
||||||
""" Return the template from the path to root of the module if specied
|
""" Return the template from the path to root of the module if specied
|
||||||
or an absolute path on your server
|
or an absolute path on your server
|
||||||
|
@ -137,7 +134,6 @@ class Py3oReport(models.TransientModel):
|
||||||
return tmpl.read()
|
return tmpl.read()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _get_template_fallback(self, model_instance):
|
def _get_template_fallback(self, model_instance):
|
||||||
"""
|
"""
|
||||||
Return the template referenced in the report definition
|
Return the template referenced in the report definition
|
||||||
|
@ -147,7 +143,6 @@ class Py3oReport(models.TransientModel):
|
||||||
report_xml = self.ir_actions_report_id
|
report_xml = self.ir_actions_report_id
|
||||||
return self._get_template_from_path(report_xml.py3o_template_fallback)
|
return self._get_template_from_path(report_xml.py3o_template_fallback)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def get_template(self, model_instance):
|
def get_template(self, model_instance):
|
||||||
"""private helper to fetch the template data either from the database
|
"""private helper to fetch the template data either from the database
|
||||||
or from the default template file provided by the implementer.
|
or from the default template file provided by the implementer.
|
||||||
|
@ -176,7 +171,6 @@ class Py3oReport(models.TransientModel):
|
||||||
|
|
||||||
return tmpl_data
|
return tmpl_data
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _extend_parser_context(self, context, report_xml):
|
def _extend_parser_context(self, context, report_xml):
|
||||||
# add default extenders
|
# add default extenders
|
||||||
for fct in _extender_functions.get(None, []):
|
for fct in _extender_functions.get(None, []):
|
||||||
|
@ -187,7 +181,6 @@ class Py3oReport(models.TransientModel):
|
||||||
for fct in _extender_functions[xml_id]:
|
for fct in _extender_functions[xml_id]:
|
||||||
fct(report_xml, context)
|
fct(report_xml, context)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _get_parser_context(self, model_instance, data):
|
def _get_parser_context(self, model_instance, data):
|
||||||
report_xml = self.ir_actions_report_id
|
report_xml = self.ir_actions_report_id
|
||||||
context = Py3oParserContext(self.env).localcontext
|
context = Py3oParserContext(self.env).localcontext
|
||||||
|
@ -196,7 +189,6 @@ class Py3oReport(models.TransientModel):
|
||||||
self._extend_parser_context(context, report_xml)
|
self._extend_parser_context(context, report_xml)
|
||||||
return context
|
return context
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _postprocess_report(self, model_instance, result_path):
|
def _postprocess_report(self, model_instance, result_path):
|
||||||
if len(model_instance) == 1 and self.ir_actions_report_id.attachment:
|
if len(model_instance) == 1 and self.ir_actions_report_id.attachment:
|
||||||
with open(result_path, "rb") as f:
|
with open(result_path, "rb") as f:
|
||||||
|
@ -207,7 +199,6 @@ class Py3oReport(models.TransientModel):
|
||||||
self.ir_actions_report_id.postprocess_pdf_report(model_instance, buffer)
|
self.ir_actions_report_id.postprocess_pdf_report(model_instance, buffer)
|
||||||
return result_path
|
return result_path
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _create_single_report(self, model_instance, data):
|
def _create_single_report(self, model_instance, data):
|
||||||
""" This function to generate our py3o report
|
""" This function to generate our py3o report
|
||||||
"""
|
"""
|
||||||
|
@ -232,7 +223,6 @@ class Py3oReport(models.TransientModel):
|
||||||
|
|
||||||
return self._postprocess_report(model_instance, result_path)
|
return self._postprocess_report(model_instance, result_path)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _convert_single_report(self, result_path, model_instance, data):
|
def _convert_single_report(self, result_path, model_instance, data):
|
||||||
"""Run a command to convert to our target format"""
|
"""Run a command to convert to our target format"""
|
||||||
if not self.ir_actions_report_id.is_py3o_native_format:
|
if not self.ir_actions_report_id.is_py3o_native_format:
|
||||||
|
@ -252,7 +242,6 @@ class Py3oReport(models.TransientModel):
|
||||||
)
|
)
|
||||||
return result_path
|
return result_path
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _convert_single_report_cmd(self, result_path, model_instance, data):
|
def _convert_single_report_cmd(self, result_path, model_instance, data):
|
||||||
"""Return a command list suitable for use in subprocess.call"""
|
"""Return a command list suitable for use in subprocess.call"""
|
||||||
lo_bin = self.ir_actions_report_id.lo_bin_path
|
lo_bin = self.ir_actions_report_id.lo_bin_path
|
||||||
|
@ -271,7 +260,6 @@ class Py3oReport(models.TransientModel):
|
||||||
result_path,
|
result_path,
|
||||||
]
|
]
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _get_or_create_single_report(
|
def _get_or_create_single_report(
|
||||||
self, model_instance, data, existing_reports_attachment
|
self, model_instance, data, existing_reports_attachment
|
||||||
):
|
):
|
||||||
|
@ -285,7 +273,6 @@ class Py3oReport(models.TransientModel):
|
||||||
return report_file
|
return report_file
|
||||||
return self._create_single_report(model_instance, data)
|
return self._create_single_report(model_instance, data)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _zip_results(self, reports_path):
|
def _zip_results(self, reports_path):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
zfname_prefix = self.ir_actions_report_id.name
|
zfname_prefix = self.ir_actions_report_id.name
|
||||||
|
@ -317,7 +304,6 @@ class Py3oReport(models.TransientModel):
|
||||||
writer.write(merged_file)
|
writer.write(merged_file)
|
||||||
return merged_file_path
|
return merged_file_path
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _merge_results(self, reports_path):
|
def _merge_results(self, reports_path):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
filetype = self.ir_actions_report_id.py3o_filetype
|
filetype = self.ir_actions_report_id.py3o_filetype
|
||||||
|
@ -339,7 +325,6 @@ class Py3oReport(models.TransientModel):
|
||||||
except (OSError, IOError):
|
except (OSError, IOError):
|
||||||
logger.error("Error when trying to remove file %s" % temporary_file)
|
logger.error("Error when trying to remove file %s" % temporary_file)
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def create_report(self, res_ids, data):
|
def create_report(self, res_ids, data):
|
||||||
""" Override this function to handle our py3o report
|
""" Override this function to handle our py3o report
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* Copyright 2017-2018 ACSONE SA/NV
|
/* Copyright 2017-2018 ACSONE SA/NV
|
||||||
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
|
* License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). */
|
||||||
odoo.define('report_py3o.report', function (require) {
|
odoo.define('report_py3o.report', function (require) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
var ActionManager = require('web.ActionManager');
|
var ActionManager = require('web.ActionManager');
|
||||||
|
|
||||||
|
@ -9,9 +10,9 @@ ActionManager.include({
|
||||||
// Py3o reports
|
// Py3o reports
|
||||||
if ('report_type' in action && action.report_type === 'py3o' ) {
|
if ('report_type' in action && action.report_type === 'py3o' ) {
|
||||||
return this._triggerDownload(action, options, 'py3o');
|
return this._triggerDownload(action, options, 'py3o');
|
||||||
} else {
|
|
||||||
return this._super.apply(this, arguments);
|
|
||||||
}
|
}
|
||||||
|
return this._super.apply(this, arguments);
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_makeReportUrls: function (action) {
|
_makeReportUrls: function (action) {
|
||||||
|
@ -21,10 +22,10 @@ ActionManager.include({
|
||||||
// were report's using a wizard to customize the output traditionally put
|
// were report's using a wizard to customize the output traditionally put
|
||||||
// their options.
|
// their options.
|
||||||
if (_.isUndefined(action.data) || _.isNull(action.data) ||
|
if (_.isUndefined(action.data) || _.isNull(action.data) ||
|
||||||
(_.isObject(action.data) && _.isEmpty(action.data))) {
|
_.isObject(action.data) && _.isEmpty(action.data)) {
|
||||||
if (action.context.active_ids) {
|
if (action.context.active_ids) {
|
||||||
var activeIDsPath = '/' + action.context.active_ids.join(',');
|
var activeIDsPath = '/' + action.context.active_ids.join(',');
|
||||||
reportUrls.py3o += activeIDsPath;;
|
reportUrls.py3o += activeIDsPath;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
var serializedOptionsPath = '?options=' + encodeURIComponent(JSON.stringify(action.data));
|
var serializedOptionsPath = '?options=' + encodeURIComponent(JSON.stringify(action.data));
|
||||||
|
@ -32,7 +33,7 @@ ActionManager.include({
|
||||||
reportUrls.py3o += serializedOptionsPath;
|
reportUrls.py3o += serializedOptionsPath;
|
||||||
}
|
}
|
||||||
return reportUrls;
|
return reportUrls;
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<openerp>
|
<odoo>
|
||||||
<data>
|
|
||||||
<template id="assets_backend" name="report assets" inherit_id="web.assets_backend">
|
<template id="assets_backend" name="report assets" inherit_id="web.assets_backend">
|
||||||
<xpath expr="." position="inside">
|
<xpath expr="." position="inside">
|
||||||
<script type="text/javascript" src="/report_py3o/static/src/js/py3oactionmanager.js"></script>
|
<script type="text/javascript" src="/report_py3o/static/src/js/py3oactionmanager.js"></script>
|
||||||
</xpath>
|
</xpath>
|
||||||
</template>
|
</template>
|
||||||
</data>
|
</odoo>
|
||||||
</openerp>
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
{
|
{
|
||||||
"name": "Py3o Report Engine - Fusion server support",
|
"name": "Py3o Report Engine - Fusion server support",
|
||||||
"summary": "Let the fusion server handle format conversion.",
|
"summary": "Let the fusion server handle format conversion.",
|
||||||
"version": "12.0.1.0.0",
|
"version": "13.0.1.0.0",
|
||||||
"category": "Reporting",
|
"category": "Reporting",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
"author": "XCG Consulting," "ACSONE SA/NV," "Odoo Community Association (OCA)",
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from openerp import _, api, fields, models
|
from odoo import _, api, fields, models
|
||||||
|
|
||||||
from odoo.exceptions import ValidationError
|
from odoo.exceptions import ValidationError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -13,7 +12,6 @@ logger = logging.getLogger(__name__)
|
||||||
class IrActionsReport(models.Model):
|
class IrActionsReport(models.Model):
|
||||||
_inherit = "ir.actions.report"
|
_inherit = "ir.actions.report"
|
||||||
|
|
||||||
@api.multi
|
|
||||||
@api.constrains("py3o_is_local_fusion", "py3o_server_id")
|
@api.constrains("py3o_is_local_fusion", "py3o_server_id")
|
||||||
def _check_py3o_server_id(self):
|
def _check_py3o_server_id(self):
|
||||||
for report in self:
|
for report in self:
|
||||||
|
@ -46,7 +44,6 @@ class IrActionsReport(models.Model):
|
||||||
@api.depends(
|
@api.depends(
|
||||||
"lo_bin_path", "is_py3o_native_format", "report_type", "py3o_server_id"
|
"lo_bin_path", "is_py3o_native_format", "report_type", "py3o_server_id"
|
||||||
)
|
)
|
||||||
@api.multi
|
|
||||||
def _compute_py3o_report_not_available(self):
|
def _compute_py3o_report_not_available(self):
|
||||||
for rec in self:
|
for rec in self:
|
||||||
if not rec.report_type == "py3o":
|
if not rec.report_type == "py3o":
|
||||||
|
|
|
@ -11,8 +11,9 @@ from datetime import datetime
|
||||||
from io import BytesIO
|
from io import BytesIO
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from openerp import _, api, models
|
|
||||||
from openerp.exceptions import UserError
|
from odoo import _, models
|
||||||
|
from odoo.exceptions import UserError
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -26,7 +27,6 @@ except ImportError:
|
||||||
class Py3oReport(models.TransientModel):
|
class Py3oReport(models.TransientModel):
|
||||||
_inherit = "py3o.report"
|
_inherit = "py3o.report"
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _create_single_report(self, model_instance, data):
|
def _create_single_report(self, model_instance, data):
|
||||||
""" This function to generate our py3o report
|
""" This function to generate our py3o report
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
py3o.template
|
||||||
|
py3o.formats
|
||||||
|
genshi>=0.7
|
Loading…
Reference in New Issue