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))