diff --git a/addons/mail/update.py b/addons/mail/update.py
index 92ea8440fde..d898a39f2cf 100644
--- a/addons/mail/update.py
+++ b/addons/mail/update.py
@@ -54,7 +54,9 @@ class publisher_warranty_contract(AbstractModel):
"web_base_url": web_base_url,
"apps": [app['name'] for app in apps],
}
- msg.update(self.pool.get("res.company").read(cr, uid, [1], ["name", "email", "phone"])[0])
+ if user.partner_id.company_id:
+ company_id = user.partner_id.company_id.id
+ msg.update(self.pool.get("res.company").read(cr, uid, [company_id], ["name", "email", "phone"])[0])
return msg
def _get_sys_logs(self, cr, uid):
diff --git a/addons/stock/stock_view.xml b/addons/stock/stock_view.xml
index 24e27d22827..cb52125382e 100644
--- a/addons/stock/stock_view.xml
+++ b/addons/stock/stock_view.xml
@@ -1228,7 +1228,6 @@
-
diff --git a/addons/web/static/lib/py.js/lib/py.js b/addons/web/static/lib/py.js/lib/py.js
index 35bb0b5223e..a59dabb06e5 100644
--- a/addons/web/static/lib/py.js/lib/py.js
+++ b/addons/web/static/lib/py.js/lib/py.js
@@ -317,10 +317,10 @@ var py = {};
} else if (token in symbols) {
var symbol;
// transform 'not in' and 'is not' in a single token
- if (token === 'in' && tokens[tokens.length-1].id === 'not') {
+ if (token === 'in' && tokens.length > 1 && tokens[tokens.length-1].id === 'not') {
symbol = symbols['not in'];
tokens.pop();
- } else if (token === 'not' && tokens.length > 0 && tokens[tokens.length-1].id === 'is') {
+ } else if (token === 'not' && tokens.length > 1 && tokens[tokens.length-1].id === 'is') {
symbol = symbols['is not'];
tokens.pop();
} else {
diff --git a/addons/web/static/lib/qweb/qweb-test-utf8tags.xml b/addons/web/static/lib/qweb/qweb-test-utf8tags.xml
new file mode 100644
index 00000000000..dd51635bab2
--- /dev/null
+++ b/addons/web/static/lib/qweb/qweb-test-utf8tags.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+ ]]>
+
diff --git a/addons/web/static/test/evals.js b/addons/web/static/test/evals.js
index a85f973e874..ff97086b019 100644
--- a/addons/web/static/test/evals.js
+++ b/addons/web/static/test/evals.js
@@ -1,3 +1,16 @@
+openerp.testing.section('eval.basics', {
+ dependencies: ['web.core'],
+ setup: function (instance) {
+ instance.session.uid = 42;
+ }
+}, function (test) {
+ test('not prefix', function (instance) {
+ ok(py.eval('not False'));
+ ok(py.eval('not foo', {foo: false}));
+ ok(py.eval('not a in b', {a: 3, b: [1, 2, 4, 8]}));
+ });
+});
+
openerp.testing.section('eval.types', {
dependencies: ['web.core'],
setup: function (instance) {
diff --git a/addons/website/models/ir_ui_view.py b/addons/website/models/ir_ui_view.py
index fb3f4f6cad9..3d4ed4621ce 100644
--- a/addons/website/models/ir_ui_view.py
+++ b/addons/website/models/ir_ui_view.py
@@ -195,10 +195,11 @@ class view(osv.osv):
qcontext.update(values)
# in edit mode ir.ui.view will tag nodes
- if qcontext.get('editable'):
- context = dict(context, inherit_branding=True)
- elif request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher'):
- context = dict(context, inherit_branding_auto=True)
+ if not qcontext.get('rendering_bundle'):
+ if qcontext.get('editable'):
+ context = dict(context, inherit_branding=True)
+ elif request.registry['res.users'].has_group(cr, uid, 'base.group_website_publisher'):
+ context = dict(context, inherit_branding_auto=True)
view_obj = request.website.get_template(id_or_xml_id)
if 'main_object' not in qcontext:
diff --git a/addons/website_quote/data/website_quotation_data.xml b/addons/website_quote/data/website_quotation_data.xml
index d46997c0d68..835cfd3027d 100644
--- a/addons/website_quote/data/website_quotation_data.xml
+++ b/addons/website_quote/data/website_quotation_data.xml
@@ -19,83 +19,6 @@
-
-
-
- Hello ${object.partner_id.name},
-
- Here is your ${object.state in ('draft', 'sent') and 'quotation' or 'order confirmation'} from ${object.company_id.name}:
-
-
- REFERENCES
- Order number: ${object.name}
- Order total: ${object.amount_total} ${object.pricelist_id.currency_id.name}
- Order date: ${object.date_order}
- % if object.origin:
- Order reference: ${object.origin}
- % endif
- % if object.client_order_ref:
- Your reference: ${object.client_order_ref}
- % endif
- % if object.user_id:
- Your contact: ${object.user_id.name}
- % endif
-
-
- You can view your quotation online:
-
- View ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'}
-
- % if object.paypal_url:
-
- It is also possible to directly pay with Paypal:
-
-
-
- % endif
-
-
- If you have any question, do not hesitate to contact us.
- Thank you for choosing ${object.company_id.name or 'us'}!
-
-
-
-
- ${object.company_id.name}
-
-
-
- % if object.company_id.street:
- ${object.company_id.street}
- % endif
- % if object.company_id.street2:
- ${object.company_id.street2}
- % endif
- % if object.company_id.city or object.company_id.zip:
- ${object.company_id.zip} ${object.company_id.city}
- % endif
- % if object.company_id.country_id:
- ${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
- % endif
-
- % if object.company_id.phone:
-
- Phone: ${object.company_id.phone}
-
- % endif
- % if object.company_id.website:
-
- %endif
-
-
-
- ]]>
-
-
Default Template
30
@@ -200,15 +123,11 @@
Your contact: ${object.user_id.name}
% endif
-
- % set signup_url = object.get_signup_url()
- % if signup_url and object.amount_total:
- You can access this document and pay online via our Customer Portal:
+ You can view your quotation online:
- View ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'}
- % endif
+ View ${object.state in ('draft', 'sent') and 'Quotation' or 'Order'}
% if object.paypal_url and object.amount_total:
diff --git a/doc/howtos/backend.rst b/doc/howtos/backend.rst
index 0b576dcbb78..5a9057194e6 100644
--- a/doc/howtos/backend.rst
+++ b/doc/howtos/backend.rst
@@ -1622,6 +1622,30 @@ http://localhost:8069/report/html/account.report_invoice/1 (if ``account`` is
installed) and the PDF version through
http://localhost:8069/report/pdf/account.report_invoice/1.
+.. _reference/backend/reporting/printed-reports/pdf-without-styles:
+
+.. danger::
+
+ If it appears that your PDF report is missing the styles (i.e. the text
+ appears but the style/layout is different from the html version), probably
+ your wkhtmltopdf_ process cannot reach your web server to download them.
+
+ If you check your server logs and see that the CSS styles are not being
+ downloaded when generating a PDF report, most surely this is the problem.
+
+ The wkhtmltopdf_ process will use the ``web.base.url`` system parameter as
+ the *root path* to all linked files, but this parameter is automatically
+ updated each time the Administrator is logged in. If your server resides
+ behind some kind of proxy, that could not be reachable. You can fix this by
+ adding one of these system parameters:
+
+ - ``report.url``, pointing to an URL reachable from your server
+ (probably ``http://localhost:8069`` or something similar). It will be
+ used for this particular purpose only.
+
+ - ``web.base.url.freeze``, when set to ``True``, will stop the
+ automatic updates to ``web.base.url``.
+
.. exercise:: Create a report for the Session model
For each session, it should display session's name, its start and end,
diff --git a/doc/reference/reports.rst b/doc/reference/reports.rst
index ca3befe6596..1ee0f629013 100644
--- a/doc/reference/reports.rst
+++ b/doc/reference/reports.rst
@@ -216,19 +216,20 @@ Useful Remarks
* Twitter Bootstrap and FontAwesome classes can be used in your report
template
* Local CSS can be put directly in the template
-
* Global CSS can be inserted in the main report layout by inheriting its
template and inserting your CSS::
-
-
-
+
+* If it appears that your PDF report is missing the styles, please check
+ :ref:`these instructions `.
.. _reference/reports/paper_formats:
diff --git a/openerp/addons/base/ir/ir_qweb.py b/openerp/addons/base/ir/ir_qweb.py
index d961673a055..c9bfe1b8684 100644
--- a/openerp/addons/base/ir/ir_qweb.py
+++ b/openerp/addons/base/ir/ir_qweb.py
@@ -136,8 +136,9 @@ class QWeb(orm.AbstractModel):
_name = 'ir.qweb'
_void_elements = frozenset([
- 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
- 'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
+ u'area', u'base', u'br', u'col', u'embed', u'hr', u'img', u'input',
+ u'keygen', u'link', u'menuitem', u'meta', u'param', u'source',
+ u'track', u'wbr'])
_format_regex = re.compile(
'(?:'
# ruby-style pattern
@@ -270,7 +271,7 @@ class QWeb(orm.AbstractModel):
_logger.warning("@t-debug in template '%s' is only available in --dev mode" % qwebcontext['__template__'])
for (attribute_name, attribute_value) in element.attrib.iteritems():
- attribute_name = str(attribute_name)
+ attribute_name = unicode(attribute_name)
if attribute_name == "groups":
cr = qwebcontext.get('request') and qwebcontext['request'].cr or None
uid = qwebcontext.get('request') and qwebcontext['request'].uid or None
@@ -314,7 +315,7 @@ class QWeb(orm.AbstractModel):
# generated_attributes: generated attributes
# qwebcontext: values
# inner: optional innerXml
- name = str(element.tag)
+ name = unicode(element.tag)
if inner:
g_inner = inner.encode('utf-8') if isinstance(inner, unicode) else inner
else:
@@ -346,7 +347,7 @@ class QWeb(orm.AbstractModel):
for qwebcontext in (name, generated_attributes, inner, name)
)
else:
- return "<%s%s/>" % (name, generated_attributes)
+ return "<%s%s/>" % (name.encode("utf-8"), generated_attributes)
def render_attribute(self, element, name, value, qwebcontext):
return _build_attribute(name, value)
@@ -1109,6 +1110,7 @@ class AssetsBundle(object):
context = self.context.copy()
context['inherit_branding'] = False
+ context['inherit_branding_auto'] = False
context['rendering_bundle'] = True
self.html = self.registry['ir.ui.view'].render(self.cr, self.uid, xmlid, context=context)
self.parse()
diff --git a/openerp/models.py b/openerp/models.py
index c21bd76f3dc..9d7d4568e50 100644
--- a/openerp/models.py
+++ b/openerp/models.py
@@ -5316,6 +5316,11 @@ class BaseModel(object):
""" Returns a new version of this recordset attached to the provided
environment
+ .. warning::
+ The new environment will not benefit from the current
+ environment's data cache, so later data access may incur extra
+ delays while re-fetching from the database.
+
:type env: :class:`~openerp.api.Environment`
"""
return self._browse(env, self._ids)
@@ -5325,6 +5330,25 @@ class BaseModel(object):
Returns a new version of this recordset attached to the provided
user.
+
+ By default this returns a `SUPERUSER` recordset, where access control
+ and record rules are bypassed.
+
+ .. note::
+ Using `sudo` could cause data access to cross the boundaries of
+ record rules, possibly mixing records that are meant to be
+ isolated (e.g. records from different companies in multi-company
+ environments).
+
+ It may lead to un-intuitive results in methods which select one
+ record among many - for example getting the default company, or
+ selecting a Bill of Materials.
+
+ .. note::
+ Because the record rules and access control will have to be
+ re-evaluated, the new recordset will not benefit from the current
+ environment's data cache, so later data access may incur extra
+ delays while re-fetching from the database.
"""
return self.with_env(self.env(user=user))