summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--addons/account/views/report_invoice.xml2
-rw-r--r--addons/stock/static/tests/route_tour.js56
-rw-r--r--addons/stock/tests/__init__.py3
-rw-r--r--addons/stock/tests/test_ui.py10
-rw-r--r--addons/stock/views/stock_template.xml1
-rw-r--r--addons/web/static/src/js/report/report.editor.js24
-rw-r--r--addons/web/static/src/js/report/report.js40
-rw-r--r--addons/web/views/report_templates.xml26
-rw-r--r--odoo/addons/base/models/ir_actions_report.py26
9 files changed, 142 insertions, 46 deletions
diff --git a/addons/account/views/report_invoice.xml b/addons/account/views/report_invoice.xml
index b43f48eab9e..18fac77f256 100644
--- a/addons/account/views/report_invoice.xml
+++ b/addons/account/views/report_invoice.xml
@@ -8,7 +8,7 @@
<address t-field="o.partner_id" t-options='{"widget": "contact", "fields": ["address", "name"], "no_marker": True}' />
<div t-if="o.partner_id.vat" class="mt16"><t t-esc="o.company_id.country_id.vat_label or 'Tax ID'"/>: <span t-field="o.partner_id.vat"/></div>
</t>
- <div class="page">
+ <div class="page" t-att-data-model="o._name" t-att-data-id="o.id">
<h2>
<span t-if="o.type == 'out_invoice' and o.state in ('open', 'in_payment', 'paid')">Invoice</span>
<span t-if="o.type == 'out_invoice' and o.state == 'draft'">Draft Invoice</span>
diff --git a/addons/stock/static/tests/route_tour.js b/addons/stock/static/tests/route_tour.js
new file mode 100644
index 00000000000..e75695a5f69
--- /dev/null
+++ b/addons/stock/static/tests/route_tour.js
@@ -0,0 +1,56 @@
+odoo.define('stock.tour', function (require) {
+'use strict';
+
+var tour = require('web_tour.tour');
+
+tour.register('stock', {
+ test: true,
+ url: '/web?debug=assets#action=stock.action_stock_config_settings',
+ },
+ [
+ {
+ content: "wait web client",
+ trigger: ".o_base_settings",
+ run: function() {}
+ },
+ {
+ content: "active 'Multi-Step Routes'",
+ trigger: '.o_field_boolean[name="group_stock_adv_location"]',
+ run: function() {
+ if (!this.$anchor.find('input').prop('checked')) {
+ this.$anchor.find('label').click();
+ $('.o_statusbar_buttons button[name="execute"]').click();
+ }
+ }
+ },
+ {
+ content: "list of product variants",
+ trigger: '.o_sub_menu .oe_secondary_submenu [data-menu-xmlid="stock.menu_product_variant_config_stock"]',
+ extra_trigger: '.o_sub_menu .oe_secondary_submenu:has(a[data-menu-xmlid="stock.menu_routes_config"])',
+ timeout: 5000,
+ },
+ {
+ content: "select a product variant",
+ trigger: '.oe_kanban_global_click:first',
+ },
+ {
+ content: "click on routes",
+ trigger: 'button.oe_stat_button i.fa-cogs',
+ },
+ {
+ content: "print the report",
+ trigger: 'button[name="print_report"]',
+ },
+ {
+ content: "print inside the report and check the breadcrum",
+ trigger: '.o_content iframe .o_report_stock_rule_rule_name',
+ extra_trigger: 'ol.breadcrumb li:eq(2).active',
+ },
+ {
+ content: "print the report",
+ trigger: 'ol.breadcrumb li:eq(3).active',
+ },
+ ]
+);
+
+});
diff --git a/addons/stock/tests/__init__.py b/addons/stock/tests/__init__.py
index 25ae6888c7c..50780301d3d 100644
--- a/addons/stock/tests/__init__.py
+++ b/addons/stock/tests/__init__.py
@@ -14,3 +14,6 @@ from . import test_packing
from . import test_packing_neg
from . import test_proc_rule
from . import test_wise_operator
+
+# TODO enable this test: error on runbot to create asset and open the iframe
+# from . import test_ui
diff --git a/addons/stock/tests/test_ui.py b/addons/stock/tests/test_ui.py
new file mode 100644
index 00000000000..ef434ea678a
--- /dev/null
+++ b/addons/stock/tests/test_ui.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import odoo.tests
+
+@odoo.tests.tagged('post_install', '-at_install')
+class TestUi(odoo.tests.HttpCase):
+
+ def test_01_admin_stock_route(self):
+ self.phantom_js("/web", "odoo.__DEBUG__.services['web_tour.tour'].run('stock')", "odoo.__DEBUG__.services['web_tour.tour'].tours.stock.ready", login='admin')
diff --git a/addons/stock/views/stock_template.xml b/addons/stock/views/stock_template.xml
index fa3ae244ee2..3ca9f6783b2 100644
--- a/addons/stock/views/stock_template.xml
+++ b/addons/stock/views/stock_template.xml
@@ -3,6 +3,7 @@
<template id="stock_assets_backend" name="mrp_workorder assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
+ <script type="text/javascript" src="/stock/static/tests/route_tour.js"></script>
<script type="text/javascript" src="/stock/static/src/js/stock_traceability_report_backend.js"></script>
<script type="text/javascript" src="/stock/static/src/js/stock_traceability_report_widgets.js"></script>
<link rel="stylesheet" type="text/scss" href="/stock/static/src/scss/stock_traceability_report.scss"/>
diff --git a/addons/web/static/src/js/report/report.editor.js b/addons/web/static/src/js/report/report.editor.js
index 15da9885e31..4955417a759 100644
--- a/addons/web/static/src/js/report/report.editor.js
+++ b/addons/web/static/src/js/report/report.editor.js
@@ -14,7 +14,6 @@ var trusted_origin = utils.build_origin(trusted_protocol, trusted_host);
// Patch the editor's behavior when it is launched inside an iframe.
if (window.self !== window.top) {
- $(document.body).addClass('o_in_iframe'); // in order to apply css rules
// And now we chain some deferred to `save` and `cancel` in order to inform
// the report's client action that the actions are done.
@@ -60,29 +59,6 @@ if (window.self !== window.top) {
}
}
}, false);
-
- // Allow to send commands to the webclient when the editor is disabled.
- if (window.location.search.indexOf('enable_editor') === -1) {
- // `do_action` command
- $('[res-id][res-model][view-type]')
- .wrap('<a/>')
- .attr('href', '#')
- .on('click', function (ev) {
- ev.preventDefault();
- var action = {
- 'type': 'ir.actions.act_window',
- 'view_type': $(this).attr('view-type'),
- 'view_mode': $(this).attr('view-mode') || $(this).attr('view-type'),
- 'res_id': Number($(this).attr('res-id')),
- 'res_model': $(this).attr('res-model'),
- 'views': [[$(this).attr('view-id') || false, $(this).attr('view-type')]],
- };
- window.parent.postMessage({
- 'message': 'report:do_action',
- 'action': action,
- }, trusted_origin);
- });
- }
}
options.registry.many2one.include({
diff --git a/addons/web/static/src/js/report/report.js b/addons/web/static/src/js/report/report.js
new file mode 100644
index 00000000000..50d78a9d151
--- /dev/null
+++ b/addons/web/static/src/js/report/report.js
@@ -0,0 +1,40 @@
+odoo.define('report', function (require) {
+'use strict';
+
+require('web.dom_ready');
+var utils = require('report.utils');
+
+if (window.self === window.top) {
+ return;
+}
+
+$(document.body).addClass('o_in_iframe'); // in order to apply css rules
+
+var web_base_url = $('html').attr('web-base-url');
+var trusted_host = utils.get_host_from_url(web_base_url);
+var trusted_protocol = utils.get_protocol_from_url(web_base_url);
+var trusted_origin = utils.build_origin(trusted_protocol, trusted_host);
+
+// Allow to send commands to the webclient when the editor is disabled.
+if (window.location.search.indexOf('enable_editor') === -1) {
+ // `do_action` command
+ $('[res-id][res-model][view-type]')
+ .wrap('<a/>')
+ .attr('href', '#')
+ .on('click', function (ev) {
+ ev.preventDefault();
+ var action = {
+ 'type': 'ir.actions.act_window',
+ 'view_type': $(this).attr('view-type'),
+ 'view_mode': $(this).attr('view-mode') || $(this).attr('view-type'),
+ 'res_id': Number($(this).attr('res-id')),
+ 'res_model': $(this).attr('res-model'),
+ 'views': [[$(this).attr('view-id') || false, $(this).attr('view-type')]],
+ };
+ window.parent.postMessage({
+ 'message': 'report:do_action',
+ 'action': action,
+ }, trusted_origin);
+ });
+}
+});
diff --git a/addons/web/views/report_templates.xml b/addons/web/views/report_templates.xml
index 6f83ae6254c..bc84d62a065 100644
--- a/addons/web/views/report_templates.xml
+++ b/addons/web/views/report_templates.xml
@@ -25,6 +25,12 @@
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/layout_background.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/layout_boxed.scss"/>
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/layout_clean.scss"/>
+
+ <script type="text/javascript" src="web/static/src/js/services/session.js"/>
+ <script type="text/javascript" src="/web/static/src/js/report/utils.js"/>
+ <script type="text/javascript" src="/web_editor/static/src/js/content/body_manager.js"/>
+ <script type="text/javascript" src="/web_editor/static/src/js/root_widget.js"/>
+ <script type="text/javascript" src='/web/static/src/js/report/report.js' />
</template>
<template id="report_assets_pdf">
@@ -37,7 +43,6 @@
<link rel="stylesheet" type="text/scss" href="/web/static/src/scss/report.editor.scss"/>
<script type="text/javascript" src="/web/static/src/js/services/session.js"/>
- <script type="text/javascript" src="/web/static/src/js/report/utils.js"/>
<script type="text/javascript" src='/web/static/src/js/report/report.editor.js' />
</template>
@@ -65,14 +70,13 @@
<t t-call-assets="web_editor.assets_editor" t-js="false"/>
<t t-call-assets="web.report_assets_editor" t-js="false"/>
</t>
+ <t t-call-assets="web.assets_common" t-css="false"/>
+ <t t-call-assets="web.report_assets_common" t-css="false"/>
<t t-if="editable">
- <t t-call-assets="web.assets_common" t-css="false"/>
<t t-call-assets="web_editor.summernote" t-css="false"/>
<t t-call-assets="web_editor.assets_editor" t-css="false"/>
<t t-call-assets="web.report_assets_editor" t-css="false"/>
- <script type="text/javascript" src="/web_editor/static/src/js/content/body_manager.js"/>
- <script type="text/javascript" src="/web_editor/static/src/js/root_widget.js"/>
<script type="text/javascript" src="/web_editor/static/src/js/iframe.js"></script>
<script t-if="enable_editor and inline_mode" type="text/javascript" src="/web_editor/static/src/js/inline.js"></script>
</t>
@@ -178,7 +182,7 @@
<div class="clearfix mb8"/>
</div>
- <div class="article o_report_layout_background" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
+ <div class="article o_report_layout_background">
<t t-call="web.address_layout"/>
<t t-raw="0"/>
</div>
@@ -218,7 +222,7 @@
</div>
</div>
- <div class="article o_report_layout_boxed" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
+ <div class="article o_report_layout_boxed">
<t t-call="web.address_layout"/>
<t t-raw="0"/>
</div>
@@ -257,7 +261,7 @@
</div>
</div>
- <div class="article o_report_layout_clean" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
+ <div class="article o_report_layout_clean">
<t t-call="web.address_layout"/>
<t t-raw="0"/>
</div>
@@ -305,7 +309,7 @@
</div>
</div>
- <div class="article o_report_layout_standard" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
+ <div class="article o_report_layout_standard">
<t t-call="web.address_layout"/>
<t t-raw="0"/>
</div>
@@ -386,16 +390,14 @@
</div>
</div>
</div>
- <div class="article" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
+ <div class="article">
<t t-raw="0"/>
</div>
</template>
<template id="basic_layout">
- <t t-if="not o" t-set="o" t-value="doc"/>
-
<t t-call="web.html_container">
- <div class="article" t-att-data-oe-model="o and o._name" t-att-data-oe-id="o and o.id">
+ <div class="article">
<t t-raw="0"/>
</div>
</t>
diff --git a/odoo/addons/base/models/ir_actions_report.py b/odoo/addons/base/models/ir_actions_report.py
index 5e81443d2bb..eedcb4e8e2d 100644
--- a/odoo/addons/base/models/ir_actions_report.py
+++ b/odoo/addons/base/models/ir_actions_report.py
@@ -300,27 +300,31 @@ class IrActionsReport(models.Model):
bodies = []
res_ids = []
+ body_parent = root.xpath('//main')
# Retrieve headers
for node in root.xpath(match_klass.format('header')):
+ body_parent = node.getparent()
+ node.getparent().remove(node)
header_node.append(node)
# Retrieve footers
for node in root.xpath(match_klass.format('footer')):
+ body_parent = node.getparent()
+ node.getparent().remove(node)
footer_node.append(node)
# Retrieve bodies
- for node in root.xpath(match_klass.format('article')):
- if node.get('data-oe-model') == self.model:
- body = layout.render(dict(subst=False, body=lxml.html.tostring(node), base_url=base_url))
- bodies.append(body)
- res_ids.append(int(node.get('data-oe-id', False)))
+ for node in root.xpath(match_klass.format('page')):
+ body = layout.render(dict(subst=False, body=lxml.html.tostring(node), base_url=base_url))
+ bodies.append(body)
+ if node.get('data-model') == self.model:
+ res_ids.append(int(node.get('data-id', 0)))
else:
- _logger.warning("The report's template '%s' does not contains the attributes 'data-oe-model' and 'data-oe-id' on the container (with class 'article')", self.name)
- raise UserError(_("The report's template is wrong, please contact your administrator"))
+ res_ids.append(None)
if not bodies:
- _logger.warning("The report's template '%s' does not contains the container with the class 'article'", self.name)
- raise UserError(_("The report's template is wrong, please contact your administrator"))
+ body = bytearray().join([lxml.html.tostring(c) for c in body_parent.getchildren()])
+ bodies.append(body)
# Get paperformat arguments set in the root html tag. They are prioritized over
# paperformat-record arguments.
@@ -660,6 +664,10 @@ class IrActionsReport(models.Model):
bodies, html_ids, header, footer, specific_paperformat_args = self.with_context(context)._prepare_html(html)
+ if self.attachment and set(res_ids) != set(html_ids):
+ raise UserError(_("The report's template '%s' is wrong, please contact your administrator. \n\n"
+ "Can not separate file to save as attachment because the report's template does not contains the attributes 'data-model' and 'data-id' on the div with 'page' classname.") % self.name)
+
pdf_content = self._run_wkhtmltopdf(
bodies,
header=header,