[MERGE] trunk

bzr revid: al@openerp.com-20140227161819-p9chmskfifo0rygs
This commit is contained in:
Antony Lesuisse 2014-02-27 17:18:19 +01:00
commit 38d1ca1ff2
220 changed files with 7447 additions and 3528 deletions

1
debian/control vendored
View File

@ -16,6 +16,7 @@ Depends:
python,
postgresql-client,
python-dateutil,
python-decorator,
python-docutils,
python-feedparser,
python-gdata,

View File

@ -172,40 +172,80 @@ is as follows:
</data>
</openerp>
Record Tag
//////////
``<record>``
////////////
**Description**
Defines a new record in a specified OpenERP model.
The addition of new data is made with the record tag. This one takes a
mandatory attribute : model. Model is the object name where the insertion has
to be done. The tag record can also take an optional attribute: id. If this
attribute is given, a variable of this name can be used later on, in the same
file, to make reference to the newly created resource ID.
``@model`` (required)
A record tag may contain field tags. They indicate the record's fields value.
If a field is not specified the default value will be used.
Name of the model in which this record will be created/inserted.
The Record Field tag
////////////////////
``@id`` (optional)
The attributes for the field tag are the following:
:term:`external ID` for the record, also allows referring to this record in
the rest of this file or in other files (through ``field/@ref`` or the
:py:func:`ref() <openerp.tools.convert._ref>` function)
name : mandatory
the field name
A record tag generally contains multiple ``field`` tags specifying the values
set on the record's fields when creating it. Fields left out will be set to
their default value unless required.
eval : optional
python expression that indicating the value to add
ref
reference to an id defined in this file
``<field>``
///////////
model
model to be looked up in the search
In its most basic use, the ``field`` tag will set its body (as a string) as
the value of the corresponding ``record``'s ``@name`` field.
search
a query
Extra attributes can either preprocess the body or replace its use entirely:
``@name`` (mandatory)
Name of the field in the containing ``record``'s model
``@type`` (optional)
One of ``char``, ``int``, ``float``, ``list``, ``tuple``, ``xml`` or
``html``, ``file`` or ``base64``. Converts the ``field``'s body to the
specified type (or validates the body's content)
* ``xml`` will join multiple XML nodes under a single ``<data>`` root
* in ``xml`` and ``html``, external ids can be referenced using
``%(id_name)s``
* ``list`` and ``tuple``'s element are specified using ``<value>``
sub-nodes with the same attributes as ``field``.
* ``file`` expects a module-local path and will save the path prefixed with
the current module's name, separated by a ``,`` (comma). For use with
:py:func:`~openerp.modules.module.get_module_resource`.
* ``base64`` expects binary data, encodes it to base64 and sets it. Mostly
useful with ``@file``
``@file``
Can be used with types ``char`` and ``base64``, sources the field's content
from the specified file instead of the field's text body.
``@model``
Model used for ``@search``'s search, or registry object put in context for
``@eval``. Required if ``@search`` but optional if ``@eval``.
``@eval`` (optional)
A Python expression evaluated to obtain the value to set on the record
``@ref`` (optional)
Links to an other record through its :term:`external id`. The module prefix
may be ommitted to link to a record defined in the same module.
``@search`` (optional)
Search domain (evaluated Python expression) into ``@model`` to get the
records to set on the field.
Sets all the matches found for m2m fields, the first id for other field
types.
**Example**

98
doc/06_ir_qweb.rst Normal file
View File

@ -0,0 +1,98 @@
.. _qweb:
====
QWeb
====
``t-field``
===========
The server version of qweb includes a directive dedicated specifically to
formatting and rendering field values from
:class:`~openerp.osv.orm.browse_record` objects.
The directive is implemented through
:meth:`~base.ir.ir_qweb.QWeb.render_tag_field` on the ``ir.qweb`` openerp
object, and generally delegates to converters for rendering. These converters
are obtained through :meth:`~base.ir.ir_qweb.QWeb.get_converter_for`.
By default, the key for obtaining a converter is the type of the field's
column, but this can be overridden by providing a ``widget`` as field option.
Field options are specified through ``t-field-options``, which must be a JSON
object (map). Custom widgets may define their own (possibly mandatory) options.
Global options
--------------
A global option ``html-escape`` is provided. It defaults to ``True``, and for
many (not all) fields it determines whether the field's output will be
html-escaped before being output.
Date and datetime converters
----------------------------
The default rendering for ``date`` and ``datetime`` fields. They render the
field's value according to the current user's ``lang.date_format`` and
``lang.time_format``. The ``datetime`` converter will also localize the value
to the user's timezone (as defined by the ``tz`` context key, or the timezone
in the user's profile if there is no ``tz`` key in the context).
A custom format can be provided to use a non-default rendering. The custom
format uses the ``format`` options key, and uses the
`ldml date format patterns`_ [#ldml]_.
For instance if one wanted a date field to be rendered as
"(month) (day of month)" rather than whatever the default is, one could use:
.. code-block:: xml
<span t-field="object.datefield" t-field-options='{"format": "MMMM d"}'/>
Monetary converter (widget: ``monetary``)
-----------------------------------------
Used to format and render monetary value, requires a ``display_currency``
options value which is a path from the rendering context to a ``res.currency``
object. This object is used to set the right currency symbol, and set it at the
right position relative to the formatted value.
The field itself should be a float field.
Relative Datetime (widget: ``relative``)
----------------------------------------
Used on a ``datetime`` field, formats it relatively to the current time
(``datetime.now()``), e.g. if the field's value is 3 hours before now and the
user's lang is english, it will render to *3 hours ago*.
.. note:: this field uses babel's ``format_timedelta`` more or less directly
and will only display the biggest unit and round up at 85% e.g.
1 hour 15 minutes will be rendered as *1 hour*, and 55 minutes will
also be rendered as *1 hour*.
.. warning:: this converter *requires* babel 1.0 or more recent.
Duration (widget: ``duration``)
-------------------------------
Renders a duration defined as a ``float`` to a human-readable localized string,
e.g. ``1.5`` as hours in an english locale will be rendered to
*1 hour 30 minutes*.
Requires a ``unit`` option which may be one of ``second``, ``minute``,
``hour``, ``day``, ``week``, ``month`` or ``year``. This specifies the unit in
which the value should be interpreted before formatting.
The duration must be a positive number, and no rounding is applied.
.. [#ldml] in part because `babel`_ is used for rendering, as ``strftime``
would require altering the process's locale on the fly in order to
get correctly localized date and time output. Babel uses the CLDR
as its core and thus uses LDML date format patterns.
.. _babel: http://babel.pocoo.org
.. _ldml date format patterns:
http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns

View File

@ -11,3 +11,4 @@ Miscellanous
06_misc_user_img_specs.rst
06_misc_import.rst
06_misc_auto_join.rst
06_ir_qweb.rst

View File

@ -252,5 +252,4 @@ texinfo_documents = [
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
'python': ('http://docs.python.org/', None),
'openerpweb': ('http://doc.openerp.com/trunk/developers/web', None),
}

View File

@ -12,26 +12,20 @@ Server actions
.. currentmodule:: openerp.addons.base.ir.ir_actions
.. autoclass:: actions_server
:noindex:
.. autoclass:: ir_actions_server
:members: run, _get_states
Adding a new sever action
-------------------------
The ``state`` field holds the various available types of server action. In order
to add a new server action, the first thing to do is to override the ``_get_states``
to add a new server action, the first thing to do is to override the :meth:`~.ir_actions_server._get_states`
method that returns the list of values available for the selection field.
.. automethod:: actions_server._get_states
:noindex:
The method called when executing the server action is the ``run`` method. This
The method called when executing the server action is the :meth:`~.ir_actions_server.run` method. This
method calls ``run_action_<STATE>``. When adding a new server action type, you
have to define the related method that will be called upon execution.
.. automethod:: actions_server.run
:noindex:
Changelog
---------

3
oe
View File

@ -1,5 +1,8 @@
#! /usr/bin/env python2
if __name__ == '__main__':
import sys
if sys.argv[1] == 'run-tests':
sys.exit(0)
import openerpcommand.main
openerpcommand.main.run()

View File

@ -19,17 +19,27 @@
#
##############################################################################
""" OpenERP core library..
"""
import sys
""" OpenERP core library."""
#----------------------------------------------------------
# Running mode flags (gevent, prefork)
#----------------------------------------------------------
# Is the server running with gevent.
import sys
evented = False
if sys.modules.get("gevent") is not None:
evented = True
# Is the server running in pefork mode (e.g. behind Gunicorn).
# If this is True, the processes have to communicate some events,
# e.g. database update or cache invalidation. Each process has also
# its own copy of the data structure and we don't need to care about
# locks between threads.
multi_process = False
#----------------------------------------------------------
# libc UTC hack
#----------------------------------------------------------
# Make sure the OpenERP server runs in UTC. This is especially necessary
# under Windows as under Linux it seems the real import of time is
# sufficiently deferred so that setting the TZ environment variable
@ -40,9 +50,22 @@ import time # ... *then* import time.
del os
del time
#----------------------------------------------------------
# Shortcuts
#----------------------------------------------------------
# The hard-coded super-user id (a.k.a. administrator, or root user).
SUPERUSER_ID = 1
def registry(database_name):
"""
Return the model registry for the given database. If the registry does not
exist yet, it is created on the fly.
"""
return modules.registry.RegistryManager.get(database_name)
#----------------------------------------------------------
# Imports
#----------------------------------------------------------
import addons
import cli
import conf
@ -58,23 +81,6 @@ import service
import sql_db
import tools
import workflow
# backward compatilbility
# TODO: This is for the web addons, can be removed later.
wsgi = service
wsgi.register_wsgi_handler = wsgi.wsgi_server.register_wsgi_handler
# Is the server running in multi-process mode (e.g. behind Gunicorn).
# If this is True, the processes have to communicate some events,
# e.g. database update or cache invalidation. Each process has also
# its own copy of the data structure and we don't need to care about
# locks between threads.
multi_process = False
def registry(database_name):
"""
Return the model registry for the given database. If the registry does not
exist yet, it is created on the fly.
"""
return modules.registry.RegistryManager.get(database_name)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -34,7 +34,4 @@ Importing them from here is deprecated.
"""
# get_module_path is used only by base_module_quality
from openerp.modules import get_module_resource, get_module_path
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -25,6 +25,7 @@ import module
import res
import report
import test
import tests
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -92,8 +92,6 @@ The kernel of OpenERP, needed for all installation.
],
'test': [
'test/base_test.yml',
'test/test_context.xml',
'test/bug_lp541545.xml',
'test/test_osv_expression.yml',
'test/test_ir_rule.yml', # <-- These tests modify/add/delete ir_rules.
],

View File

@ -112,18 +112,6 @@ CREATE TABLE ir_act_client (
)
INHERITS (ir_actions);
CREATE TABLE ir_ui_view (
id serial NOT NULL,
name varchar(64) DEFAULT ''::varchar NOT NULL,
model varchar(64) DEFAULT ''::varchar NOT NULL,
"type" varchar(64) DEFAULT 'form'::varchar NOT NULL,
arch text NOT NULL,
field_parent varchar(64),
priority integer DEFAULT 5 NOT NULL,
primary key(id)
);
CREATE TABLE ir_ui_menu (
id serial NOT NULL,
parent_id int references ir_ui_menu on delete set null,
@ -409,4 +397,4 @@ insert into ir_model_data (name,module,model,noupdate,res_id) VALUES ('main_comp
select setval('res_company_id_seq', 2);
select setval('res_users_id_seq', 2);
select setval('res_partner_id_seq', 2);
select setval('res_currency_id_seq', 2);
select setval('res_currency_id_seq', 2);

View File

@ -91,6 +91,25 @@ Administrator</field>
<field eval="10" name="sequence"/>
</record>
<!--
A group dedicated to the portal users, making groups
restrictions more convenient.
-->
<record id="group_portal" model="res.groups">
<field name="name">Portal</field>
<field name="comment">Portal members have specific access rights (such as record rules and restricted menus).
They usually do not belong to the usual OpenERP groups.</field>
</record>
<!--
A group dedicated to the public user only, making groups
restrictions more convenient.
-->
<record id="group_public" model="res.groups">
<field name="name">Public</field>
<field name="comment">Public users have specific access rights (such as record rules and restricted menus).
They usually do not belong to the usual OpenERP groups.</field>
</record>
<!-- Basic fonts family included in PDF standart, will always be in the font list -->
<record model="res.font" id="base.font_helvetica">
<field name="name">Helvetica</field>
@ -111,5 +130,21 @@ Administrator</field>
<field name="mode">all</field>
</record>
<record id="public_partner" model="res.partner">
<field name="name">Public user</field>
<field name="active" eval="False"/>
</record>
<record id="public_user" model="res.users">
<field name="name">Public user</field>
<field name="login">public</field>
<field name="password"></field>
<!-- Avoid auto-including this demo user in any default group -->
<field name="groups_id" eval="[(6,0,[ref('base.group_public')])]"/>
<field name="image" type="base64" file="base/static/img/public_user-image.png"/>
<field name="partner_id" ref="public_partner"/>
<field name="active" eval="False"/>
</record>
</data>
</openerp>

View File

@ -1,17 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="partner_demo" model="res.partner">
<field name="name">Demo User</field>
<field name="company_id" ref="main_company"/>
<field name="customer" eval="False"/>
<field name="email">demo@example.com</field>
<field name="email">demo@yourcompany.example.com</field>
<field name="street">Avenue des Dessus-de-Lives, 2</field>
<field name="city">Namur (Loyers)</field>
<field name="zip">5101</field>
<field name="country_id" ref="be"/>
</record>
<record id="main_partner" model="res.partner">
<field name="name">YourCompany</field>
<field name="street">1725 Slough Ave.</field>
<field name="city">Scranton</field>
<field name="zip">18540</field>
<field name="phone">+1 555 123 8069</field>
<field name="email">info@yourcompany.example.com</field>
<field name="website">www.example.com</field>
<field name="image" type="base64" file="base/static/img/main_partner-image.png"/>
</record>
<record id="main_company" model="res.company">
<field name="name">YourCompany</field>
</record>
<record id="user_demo" model="res.users">
<field name="partner_id" ref="base.partner_demo"/>
<field name="login">demo</field>
@ -24,7 +41,7 @@ Mr Demo</field>
</record>
<record model="res.partner" id="base.partner_root">
<field name="email">admin@example.com</field>
<field name="email">admin@yourcompany.example.com</field>
<field name="tz">Europe/Brussels</field>
<field name="image" type="base64" file="base/static/img/partner_root-image.jpg"/>
</record>

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:15+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:21+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:15+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -60,12 +60,12 @@ msgstr "Kyk na argitektuur"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
msgstr ""
msgstr "Kwotasie, Bestellins, Aflewerings en Faktuur beheer."
#. module: base
#: selection:ir.sequence,implementation:0
msgid "No gap"
msgstr ""
msgstr "Geep Spasie"
#. module: base
#: selection:base.language.install,lang:0
@ -89,23 +89,24 @@ msgstr ""
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr ""
msgstr "Tasskerm koppelvlak vir Winkels"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
msgid "Indian Payroll"
msgstr ""
msgstr "Indiese Betaalstaat"
#. module: base
#: help:ir.cron,model:0
msgid ""
"Model name on which the method to be called is located, e.g. 'res.partner'."
msgstr ""
"Model naam waarin die metode wat geroep word verskyn, bv. \"res.partner\"."
#. module: base
#: view:ir.module.module:0
msgid "Created Views"
msgstr ""
msgstr "Geskepte Afbeelding"
#. module: base
#: model:ir.module.module,description:base.module_product_manufacturer
@ -122,11 +123,24 @@ msgid ""
" * Product Attributes\n"
" "
msgstr ""
"\n"
"'n Module wat die vervaardegiers en eienskappe van die produk op die vorm "
"byvoeg.\n"
"===================================================================\n"
"\n"
"Jy behoort nu die volgende vir produkte te kan definieer:\n"
"-----------------------------------------------------------------------------"
"--\n"
" * Vervaardiger\n"
" * Vervaardiger Produk Naame\n"
" * Vervaardiger Produk Kode\n"
" * Produk Eienskappe\n"
" "
#. module: base
#: field:ir.actions.client,params:0
msgid "Supplementary arguments"
msgstr ""
msgstr "Aanvullende argumente"
#. module: base
#: model:ir.module.module,description:base.module_google_base_account
@ -135,11 +149,14 @@ msgid ""
"The module adds google user in res user.\n"
"========================================\n"
msgstr ""
"\n"
"Hierdie module voeg google user bu res.user.\n"
"=====================================\n"
#. module: base
#: help:res.partner,employee:0
msgid "Check this box if this contact is an Employee."
msgstr ""
msgstr "Selekteer hierdie block as die kontak 'n Verknemer is."
#. module: base
#: help:ir.model.fields,domain:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:15+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -366,7 +366,7 @@ msgstr "አክቲቭ"
#. module: base
#: field:ir.actions.wizard,wiz_name:0
msgid "Wizard Name"
msgstr "የዊዘርዱ ስም"
msgstr ""
#. module: base
#: model:ir.module.module,description:base.module_knowledge
@ -481,7 +481,7 @@ msgstr ""
msgid ""
"One of the records you are trying to modify has already been deleted "
"(Document type: %s)."
msgstr "ለማሻሻል የሞከሩት ሰነድ ከዚህ በፊት የተሰረዘ ሆኖ ተገኝትዋል (የሰነዱ አይነት፡ %s)።"
msgstr ""
#. module: base
#: help:ir.actions.act_window,views:0

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:15+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:16+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-16 05:17+0000\n"
"X-Generator: Launchpad (build 16901)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:16+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:16+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-06 04:39+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
"X-Generator: Launchpad (build 16926)\n"
"X-Poedit-Language: Czech\n"
#. module: base
@ -38,7 +38,7 @@ msgstr "Svatá Helena"
#. module: base
#: view:ir.actions.report.xml:0
msgid "Other Configuration"
msgstr "Další nastavení"
msgstr "Ostatní nastavení"
#. module: base
#: selection:ir.property,type:0
@ -69,7 +69,7 @@ msgstr "Nabídky, zakázky, řízení dopravy a fakturace"
#. module: base
#: selection:ir.sequence,implementation:0
msgid "No gap"
msgstr "Bez mezer"
msgstr "Bez mezery"
#. module: base
#: selection:base.language.install,lang:0
@ -9335,7 +9335,7 @@ msgstr "Stránka dokumentu"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_ar
msgid "Argentina Localization Chart Account"
msgstr ""
msgstr "Argentinská účtová osnova"
#. module: base
#: field:ir.module.module,description_html:0
@ -10393,6 +10393,10 @@ msgid ""
"=========================\n"
"\n"
msgstr ""
"\n"
"Zobrazení Openerp Web Diagramu.\n"
"=========================\n"
"\n"
#. module: base
#: model:ir.module.module,description:base.module_l10n_ch

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:17+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:18+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
"X-Generator: Launchpad (build 16926)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
"X-Poedit-SourceCharset: utf-8\n"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:24+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:22+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:24+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:25+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:24+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:25+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
"X-Generator: Launchpad (build 16926)\n"
"Language: \n"
#. module: base

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:24+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:26+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:26+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:26+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:24+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:17+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:16+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:23+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -9,8 +9,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:20+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
"X-Generator: Launchpad (build 16926)\n"
"X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
"X-Poedit-Language: Persian\n"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:26+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:17+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,7 +25,7 @@ msgid ""
" "
msgstr ""
"\n"
"Moduuli Šekkien kirjoittamisen ja tulostamiseen.\n"
"Moduuli Shekkien kirjoittamisen ja tulostamiseen.\n"
"===========================================\n"
" "
@ -129,7 +129,7 @@ msgstr ""
"Moduuli joka lisää valmistajat ja ominaisuudet tuotelomakkeelle.\n"
"=========================================================\n"
"\n"
"Voit net määritellä tuotteelle seuraavat tiedot:\n"
"Voit nyt määritellä tuotteelle seuraavat tiedot:\n"
"---------------------------------------------------------\n"
" * Valmistaja\n"
" * Valmistajan tuotenimi\n"
@ -688,7 +688,7 @@ msgstr "Palau"
#. module: base
#: view:res.partner:0
msgid "Sales & Purchases"
msgstr "Myynti ja hankinta"
msgstr "Myynnit & Ostot"
#. module: base
#: view:ir.translation:0
@ -3836,7 +3836,7 @@ msgstr "Raportointi"
#: field:res.partner,title:0
#: field:res.partner.title,name:0
msgid "Title"
msgstr "Yhtiömuoto"
msgstr "Titteli"
#. module: base
#: help:ir.property,res_id:0
@ -10138,7 +10138,7 @@ msgstr ""
#: view:res.groups:0
#: field:res.partner,comment:0
msgid "Notes"
msgstr "Huomautukset"
msgstr "Muistiinpanot"
#. module: base
#: field:ir.config_parameter,value:0
@ -13158,7 +13158,7 @@ msgstr ""
#. module: base
#: field:res.company,company_registry:0
msgid "Company Registry"
msgstr "Yritysrekisteri"
msgstr "Y-tunnus"
#. module: base
#: view:ir.actions.report.xml:0
@ -13471,7 +13471,7 @@ msgstr "Riippuvuudet:"
#. module: base
#: field:res.company,vat:0
msgid "Tax ID"
msgstr "Vero ID"
msgstr "VAT-numero"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_bank_statement_extensions
@ -13821,7 +13821,7 @@ msgstr "Marokko - Kirjanpito"
#: field:res.bank,bic:0
#: field:res.partner.bank,bank_bic:0
msgid "Bank Identifier Code"
msgstr "BIC koodi"
msgstr "BIC-koodi"
#. module: base
#: view:base.language.export:0
@ -15482,7 +15482,7 @@ msgstr "Matkapuhelinnumero"
#: model:ir.model,name:base.model_res_partner_category
#: view:res.partner.category:0
msgid "Partner Categories"
msgstr "Kumppanien ryhmät"
msgstr "Kumppaniryhmät"
#. module: base
#: view:base.module.upgrade:0
@ -15690,7 +15690,7 @@ msgstr ""
#. module: base
#: view:res.partner:0
msgid "Internal Notes"
msgstr "Sisäiset huomautukset"
msgstr "Sisäiset muistiinpanot"
#. module: base
#: model:res.partner.title,name:base.res_partner_title_pvt_ltd

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:17+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -11393,7 +11393,7 @@ msgstr "Islande"
#: model:ir.actions.act_window,name:base.ir_action_window
#: model:ir.ui.menu,name:base.menu_ir_action_window
msgid "Window Actions"
msgstr "Actions de fênetres"
msgstr "Actions de fetres"
#. module: base
#: model:ir.module.module,description:base.module_portal_project_issue

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:25+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:18+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:18+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:26+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:18+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:22+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
"X-Generator: Launchpad (build 16926)\n"
"Language: hr\n"
#. module: base

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:18+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -9,8 +9,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:16+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:19+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -58,7 +58,7 @@ msgstr ""
#: field:ir.ui.view,arch:0
#: field:ir.ui.view.custom,arch:0
msgid "View Architecture"
msgstr "Arsitektur View"
msgstr "Lihat Arsitektur"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
@ -86,13 +86,13 @@ msgid ""
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
"Memungkinkan Anda untuk mengelola proyek dan tugas dengan cara melacaknya, "
"menghasilkan perencanaan dan lain sebagainya ..."
"Membantu anda mengelola proyek dan tugas dengan cara melacak, menghasilkan "
"perencanaan, dan lain sebagainya..."
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr "Antarmuka layar sentuh untuk digunakan di toko"
msgstr "Antarmuka Layar Sentuh untuk Toko"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
@ -104,12 +104,12 @@ msgstr "Payroll untuk India"
msgid ""
"Model name on which the method to be called is located, e.g. 'res.partner'."
msgstr ""
"Sebutkan nama model yang mana metode ini akan dipanggil, misal 'res.partner'."
"Nama model dimana terletak metode yang akan dipanggil, contoh 'res.partner'."
#. module: base
#: view:ir.module.module:0
msgid "Created Views"
msgstr "View yang diciptakan"
msgstr "Tampilan yang Diciptakan"
#. module: base
#: model:ir.module.module,description:base.module_product_manufacturer
@ -127,17 +127,17 @@ msgid ""
" "
msgstr ""
"\n"
"Modul ini berfungsi untuk menambahkan nama produsen beserta atributnya pada "
"Sebuah modul yang berfungsi menambahkan nama produsen dan keterangan pada "
"formulir produk.\n"
"============================================================================="
"==\n"
"=====\n"
"\n"
"Anda dapat mengisi data-data berikut pada produk:\n"
"------------------------------------------------\n"
"* Nama produsen\n"
"* Nama produk produsen\n"
"* Code produk produsen\n"
"* Atribut produk\n"
"Anda sekarang dapat menentukan data berikut untuk sebuah produk:\n"
"-------------------------------------------------------------------\n"
" * Produsen\n"
" * Nama Produk Produsen\n"
" * Kode Produk Produsen\n"
" * Keterangan Produk\n"
" "
#. module: base
@ -153,8 +153,8 @@ msgid ""
"========================================\n"
msgstr ""
"\n"
"Modul ini akan menambahkan google user dalam obyek res.user\n"
"====================================================\n"
"Modul ini menambahkan pengguna google dalam res user.\n"
"======================================================\n"
#. module: base
#: help:res.partner,employee:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:19+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:27+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:19+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:19+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -480,7 +480,7 @@ msgstr ""
#. module: base
#: field:ir.model.relation,name:0
msgid "Relation Name"
msgstr ""
msgstr "リレーション名"
#. module: base
#: view:ir.rule:0
@ -976,7 +976,7 @@ msgstr "ジンバブエ"
#: help:ir.model.constraint,type:0
msgid ""
"Type of the constraint: `f` for a foreign key, `u` for other constraints."
msgstr ""
msgstr "制約のタイプ:`f`は外部キー、`u`は他の制約"
#. module: base
#: view:ir.actions.report.xml:0
@ -1105,7 +1105,7 @@ msgstr "アンドラ公国"
#. module: base
#: field:ir.rule,perm_read:0
msgid "Apply for Read"
msgstr ""
msgstr "読み込みに適用"
#. module: base
#: model:res.country,name:base.mn
@ -1322,7 +1322,7 @@ msgstr "貢献者"
#. module: base
#: field:ir.rule,perm_unlink:0
msgid "Apply for Delete"
msgstr ""
msgstr "削除に適用"
#. module: base
#: selection:ir.property,type:0
@ -1420,7 +1420,7 @@ msgstr "テスト"
#. module: base
#: field:ir.actions.report.xml,attachment:0
msgid "Save as Attachment Prefix"
msgstr ""
msgstr "添付ファイルのプリフィックスとして保存"
#. module: base
#: field:ir.ui.view_sc,res_id:0
@ -1718,7 +1718,7 @@ msgstr "見積り要求や仕入先請求書といった発注関係のプロセ
#. module: base
#: help:res.partner,website:0
msgid "Website of Partner or Company"
msgstr ""
msgstr "取引先または会社のWebサイト"
#. module: base
#: help:base.language.install,overwrite:0
@ -1792,6 +1792,9 @@ msgid ""
"Launch Manually Once: after having been launched manually, it sets "
"automatically to Done."
msgstr ""
"手動:手動で起動します。\n"
"自動:システムを再設定するたびに実行します。\n"
"手動でいったん起動:手動で起動した後は自動に設定されます。"
#. module: base
#: field:res.partner,image_small:0
@ -1936,7 +1939,7 @@ msgstr "読み込みアクセス"
#. module: base
#: help:ir.attachment,res_id:0
msgid "The record id this is attached to"
msgstr ""
msgstr "これに添付するレコードID"
#. module: base
#: model:ir.module.module,description:base.module_share
@ -1969,7 +1972,7 @@ msgstr "企業の処理"
msgid ""
"Check this box if this contact is a supplier. If it's not checked, purchase "
"people will not see it when encoding a purchase order."
msgstr ""
msgstr "連絡先が仕入先の場合はこのボックスをチェックします。チェックしない場合、発注書を作成する際に表示されません。"
#. module: base
#: model:ir.module.module,shortdesc:base.module_hr_evaluation
@ -2255,7 +2258,7 @@ msgstr "バハマ"
#. module: base
#: field:ir.rule,perm_create:0
msgid "Apply for Create"
msgstr ""
msgstr "作成に適用"
#. module: base
#: model:ir.module.category,name:base.module_category_tools
@ -2277,7 +2280,7 @@ msgstr "アイルランド"
msgid ""
"Appears by default on the top right corner of your printed documents (report "
"header)."
msgstr ""
msgstr "印刷された文書(レポートヘッダ)の右上隅にデフォルトで表示されます。"
#. module: base
#: field:base.module.update,update:0
@ -2292,7 +2295,7 @@ msgstr "メソッド"
#. module: base
#: model:ir.module.module,shortdesc:base.module_auth_crypt
msgid "Password Encryption"
msgstr ""
msgstr "パスワード暗号化"
#. module: base
#: view:workflow.activity:0
@ -2509,7 +2512,7 @@ msgstr ""
msgid ""
"View type: Tree type to use for the tree view, set to 'tree' for a "
"hierarchical tree view, or 'form' for a regular list view"
msgstr ""
msgstr "ビュータイプ:ツリー表示に使用する型式、階層ツリー表示のための「ツリー」または通常のリスト表示のための「フォーム」に設定"
#. module: base
#: sql_constraint:ir.ui.view_sc:0
@ -3280,7 +3283,7 @@ msgstr "スウェーデン"
#. module: base
#: field:ir.actions.report.xml,report_file:0
msgid "Report File"
msgstr ""
msgstr "レポートファイル"
#. module: base
#: selection:ir.actions.act_window.view,view_mode:0
@ -3595,7 +3598,7 @@ msgstr ""
#. module: base
#: field:base.language.export,modules:0
msgid "Modules To Export"
msgstr ""
msgstr "エクスポートするモジュール"
#. module: base
#: model:res.country,name:base.mt
@ -3855,7 +3858,7 @@ msgstr "トーゴ"
#: field:ir.actions.act_window,res_model:0
#: field:ir.actions.client,res_model:0
msgid "Destination Model"
msgstr ""
msgstr "宛先モデル"
#. module: base
#: selection:ir.sequence,implementation:0
@ -4202,7 +4205,7 @@ msgstr ""
#. module: base
#: model:ir.actions.server,name:base.action_run_ir_action_todo
msgid "Run Remaining Action Todo"
msgstr ""
msgstr "Todoアクションの残りを実行"
#. module: base
#: field:res.partner,ean13:0
@ -4988,7 +4991,7 @@ msgstr ""
#. module: base
#: help:ir.attachment,res_model:0
msgid "The database object this attachment will be attached to"
msgstr ""
msgstr "この添付ファイルに添付されるデータベースオブジェクト"
#. module: base
#: code:addons/base/ir/ir_fields.py:327
@ -5122,7 +5125,7 @@ msgstr "保存"
#. module: base
#: field:ir.actions.report.xml,report_xml:0
msgid "XML Path"
msgstr ""
msgstr "XMLパス"
#. module: base
#: model:res.country,name:base.bj
@ -5519,7 +5522,7 @@ msgstr "ブーベ島"
#. module: base
#: field:ir.model.constraint,type:0
msgid "Constraint Type"
msgstr ""
msgstr "制約タイプ"
#. module: base
#: field:res.company,child_ids:0
@ -5658,7 +5661,7 @@ msgstr ""
#. module: base
#: model:res.groups,name:base.group_sale_salesman_all_leads
msgid "See all Leads"
msgstr ""
msgstr "全ての見込み客を参照"
#. module: base
#: model:res.country,name:base.ci
@ -5684,7 +5687,7 @@ msgstr "リソース名"
#. module: base
#: model:ir.ui.menu,name:base.menu_ir_filters
msgid "User-defined Filters"
msgstr ""
msgstr "ユーザ定義のフィルタ"
#. module: base
#: field:ir.actions.act_window_close,name:0
@ -6074,6 +6077,8 @@ msgid ""
"deleting it (if you delete a native record rule, it may be re-created when "
"you reload the module."
msgstr ""
"アクティブなフィールドのチェックを外すと、レコードのルールを削除せずに無効化します(レコードのルールを削除すると、モジュールを再ロードするときに再作成され"
"ます)。"
#. module: base
#: selection:base.language.install,lang:0
@ -6237,7 +6242,7 @@ msgstr ""
#: help:res.country.state,name:0
msgid ""
"Administrative divisions of a country. E.g. Fed. State, Departement, Canton"
msgstr ""
msgstr "国の行政区画。たとえば連邦、省、州。"
#. module: base
#: view:res.partner.bank:0
@ -6257,12 +6262,12 @@ msgstr "このルールにより影響を受けたオブジェクト"
#. module: base
#: selection:ir.actions.act_window,target:0
msgid "Inline View"
msgstr ""
msgstr "インラインビュー"
#. module: base
#: field:ir.filters,is_default:0
msgid "Default filter"
msgstr ""
msgstr "デフォルトのフィルタ"
#. module: base
#: report:ir.module.reference:0
@ -6630,7 +6635,7 @@ msgstr "世紀なしの現在年: %(y)s"
#: view:ir.config_parameter:0
#: model:ir.ui.menu,name:base.ir_config_menu
msgid "System Parameters"
msgstr ""
msgstr "システムパラメータ"
#. module: base
#: help:ir.actions.client,tag:0
@ -6805,7 +6810,7 @@ msgstr "ランドスケープレポート用RML内部ヘッダ"
#. module: base
#: model:res.groups,name:base.group_partner_manager
msgid "Contact Creation"
msgstr ""
msgstr "連絡先作成"
#. module: base
#: view:ir.module.module:0
@ -7083,7 +7088,7 @@ msgstr "モジュールファイルのインポートが成功しました。"
#: view:ir.model.constraint:0
#: model:ir.ui.menu,name:base.ir_model_constraint_menu
msgid "Model Constraints"
msgstr ""
msgstr "モデル制約"
#. module: base
#: model:ir.actions.act_window,name:base.action_workflow_transition_form
@ -7198,7 +7203,7 @@ msgstr "のコピー"
#. module: base
#: field:ir.model.data,display_name:0
msgid "Record Name"
msgstr ""
msgstr "レコード名"
#. module: base
#: model:ir.model,name:base.model_ir_actions_client
@ -7214,7 +7219,7 @@ msgstr "イギリス領インド洋地域"
#. module: base
#: model:ir.actions.server,name:base.action_server_module_immediate_install
msgid "Module Immediate Install"
msgstr ""
msgstr "モジュール即時インストール"
#. module: base
#: view:ir.actions.server:0
@ -7565,6 +7570,8 @@ msgid ""
"use the same timezone that is otherwise used to pick and render date and "
"time values: your computer's timezone."
msgstr ""
"取引先のタイムゾーン。印刷するレポート内に適切な日付と時刻を出力するために使用します。このフィールドに値を設定することは重要です。日付と時刻を選択して表示"
"するのでなければ、あなたのコンピュータと同じタイムゾーンを使用すべきです。"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_analytic_default
@ -7633,7 +7640,7 @@ msgstr ""
#. module: base
#: view:ir.rule:0
msgid "Rule Definition (Domain Filter)"
msgstr ""
msgstr "ルール定義(ドメインフィルタ)"
#. module: base
#: selection:ir.actions.act_url,target:0
@ -8009,6 +8016,12 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" クリックしてアドレス帳に連絡先を追加してください。\n"
" </p><p>\n"
" OpenERPは顧客、ディスカッション、商機の履歴、文書など関連するすべての活動の追跡を容易にします。\n"
" </p>\n"
" "
#. module: base
#: model:ir.actions.act_window,name:base.bank_account_update
@ -8340,7 +8353,7 @@ msgstr ""
#. module: base
#: help:ir.model.relation,name:0
msgid "PostgreSQL table name implementing a many2many relation."
msgstr ""
msgstr "多対多の関係を実装するPostgreSQLのテーブル名。"
#. module: base
#: model:ir.module.module,description:base.module_base
@ -8441,7 +8454,7 @@ msgstr "常時検索可能"
#. module: base
#: help:res.country.state,code:0
msgid "The state code in max. three chars."
msgstr ""
msgstr "最大3文字の州コード。"
#. module: base
#: model:res.country,name:base.hk
@ -8604,7 +8617,7 @@ msgstr "ドミニカ"
#. module: base
#: field:ir.translation,name:0
msgid "Translated field"
msgstr ""
msgstr "翻訳フィールド"
#. module: base
#: model:ir.module.module,shortdesc:base.module_stock_location
@ -8682,7 +8695,7 @@ msgstr "アクション結合"
msgid ""
"If the selected language is loaded in the system, all documents related to "
"this contact will be printed in this language. If not, it will be English."
msgstr ""
msgstr "選択された言語がシステムにロードされている場合、この連絡先に関連するすべての文書はこの言語で印刷されます。そうでない場合は英語です。"
#. module: base
#: model:ir.module.module,description:base.module_hr_evaluation
@ -8839,7 +8852,7 @@ msgstr ""
msgid ""
"This field specifies whether the model is transient or not (i.e. if records "
"are automatically deleted from the database or not)"
msgstr ""
msgstr "このフィールドはモデルが一時的かどうか(レコードがデータベースから自動的に削除されるかどうか)を指定します。"
#. module: base
#: code:addons/base/ir/ir_mail_server.py:445
@ -9231,7 +9244,7 @@ msgstr ""
#. module: base
#: model:ir.module.category,name:base.module_category_warehouse_management
msgid "Warehouse"
msgstr ""
msgstr "倉庫"
#. module: base
#: field:ir.exports,resource:0
@ -9568,7 +9581,7 @@ msgstr "%H - 時24時間表示[00,23]."
#. module: base
#: field:ir.model.fields,on_delete:0
msgid "On Delete"
msgstr ""
msgstr "削除時"
#. module: base
#: code:addons/base/ir/ir_model.py:347
@ -9782,7 +9795,7 @@ msgstr "ドイツ"
#. module: base
#: model:ir.module.module,shortdesc:base.module_auth_oauth
msgid "OAuth2 Authentication"
msgstr ""
msgstr "OAuth2認証"
#. module: base
#: view:workflow:0
@ -9825,7 +9838,7 @@ msgstr "通貨コードは会社ごとに固有でなければいけません。
#: code:addons/base/module/wizard/base_export_language.py:39
#, python-format
msgid "New Language (Empty translation template)"
msgstr ""
msgstr "新しい言語 (空の翻訳テンプレート)"
#. module: base
#: help:ir.actions.server,email:0
@ -10025,6 +10038,12 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" クリックしてアドレス帳に連絡先を追加してください。\n"
" </p><p>\n"
" OpenERPは仕入先、ディスカッション、購入の履歴、文書など関連するすべての活動の追跡を容易にします。\n"
" </p>\n"
" "
#. module: base
#: model:res.country,name:base.lr
@ -10296,7 +10315,7 @@ msgstr "ファイルの内容"
#: view:ir.model.relation:0
#: model:ir.ui.menu,name:base.ir_model_relation_menu
msgid "ManyToMany Relations"
msgstr ""
msgstr "多対多の関係"
#. module: base
#: model:res.country,name:base.pa
@ -10400,7 +10419,7 @@ msgstr "OpenERPは自動的に次の番号に要求されているサイズに
#. module: base
#: help:ir.model.constraint,name:0
msgid "PostgreSQL constraint or foreign key name."
msgstr ""
msgstr "PostgreSQLの制約や外部キーの名前。"
#. module: base
#: view:res.company:0
@ -10425,7 +10444,7 @@ msgstr "ギニアビサウ"
#. module: base
#: field:ir.actions.report.xml,header:0
msgid "Add RML Header"
msgstr ""
msgstr "RMLヘッダを追加"
#. module: base
#: help:res.company,rml_footer:0
@ -10547,7 +10566,7 @@ msgstr "イタリア"
#. module: base
#: model:res.groups,name:base.group_sale_salesman
msgid "See Own Leads"
msgstr ""
msgstr "自分の見込み客を参照"
#. module: base
#: view:ir.actions.todo:0
@ -11057,7 +11076,7 @@ msgstr "オフィス用品"
#. module: base
#: field:ir.attachment,res_model:0
msgid "Resource Model"
msgstr ""
msgstr "リソースモデル"
#. module: base
#: code:addons/custom.py:555
@ -11184,7 +11203,7 @@ msgstr ""
#: model:ir.actions.act_window,name:base.action_inventory_form
#: model:ir.ui.menu,name:base.menu_action_inventory_form
msgid "Default Company per Object"
msgstr ""
msgstr "オブジェクトごとのデフォルト会社"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_hello
@ -11229,7 +11248,7 @@ msgstr "州名"
#. module: base
#: help:ir.attachment,type:0
msgid "Binary File or URL"
msgstr ""
msgstr "バイナリファイルまたはURL"
#. module: base
#: code:addons/base/ir/ir_fields.py:313
@ -11374,7 +11393,7 @@ msgstr ""
#. module: base
#: field:workflow.transition,signal:0
msgid "Signal (Button Name)"
msgstr ""
msgstr "シグナル(ボタン名)"
#. module: base
#: view:ir.actions.act_window:0
@ -11404,7 +11423,7 @@ msgstr "グレナダ"
#. module: base
#: help:res.partner,customer:0
msgid "Check this box if this contact is a customer."
msgstr ""
msgstr "連絡先が顧客の場合はこのボックスをチェックします。"
#. module: base
#: view:ir.actions.server:0
@ -11439,7 +11458,7 @@ msgstr ""
#. module: base
#: field:res.users,partner_id:0
msgid "Related Partner"
msgstr ""
msgstr "関連取引先"
#. module: base
#: code:addons/osv.py:172
@ -11719,6 +11738,7 @@ msgid ""
"(if you delete a native ACL, it will be re-created when you reload the "
"module."
msgstr ""
"アクティブなフィールドのチェックを外すと、ACLを削除せずに無効化します(ACLを削除すると、モジュールを再ロードするときに再作成されます)。"
#. module: base
#: model:ir.model,name:base.model_ir_fields_converter
@ -12185,7 +12205,7 @@ msgstr "見積書、販売注文書、請求書の処理に役立ちます。"
#. module: base
#: field:res.users,login_date:0
msgid "Latest connection"
msgstr ""
msgstr "最後の接続"
#. module: base
#: field:res.groups,implied_ids:0
@ -12349,7 +12369,7 @@ msgstr "デフォルト値、またはアクションへの参照"
#. module: base
#: field:ir.actions.report.xml,auto:0
msgid "Custom Python Parser"
msgstr ""
msgstr "特注のPythonパーサ"
#. module: base
#: sql_constraint:res.groups:0
@ -12933,7 +12953,7 @@ msgstr "ニューカレドニア(フランス領)"
#. module: base
#: field:ir.model,osv_memory:0
msgid "Transient Model"
msgstr ""
msgstr "過度的なモデル"
#. module: base
#: model:res.country,name:base.cy
@ -13073,7 +13093,7 @@ msgstr "送信メールサーバ"
#. module: base
#: model:ir.ui.menu,name:base.menu_custom
msgid "Technical"
msgstr ""
msgstr "技術"
#. module: base
#: model:res.country,name:base.cn
@ -13290,7 +13310,7 @@ msgstr "起動するアクション"
#: field:ir.model,modules:0
#: field:ir.model.fields,modules:0
msgid "In Modules"
msgstr ""
msgstr "モジュールリスト"
#. module: base
#: model:ir.module.module,shortdesc:base.module_contacts
@ -13783,7 +13803,7 @@ msgstr ""
msgid ""
"Check this to define the report footer manually. Otherwise it will be "
"filled in automatically."
msgstr ""
msgstr "レポートフッタをマニュアルで定義する場合はチェックしてください。それ以外は自動で入力されます。"
#. module: base
#: view:res.partner:0
@ -13829,7 +13849,7 @@ msgstr "ソース"
#: field:ir.model.constraint,date_init:0
#: field:ir.model.relation,date_init:0
msgid "Initialization Date"
msgstr ""
msgstr "初期化の日付"
#. module: base
#: model:res.country,name:base.vu
@ -13998,7 +14018,7 @@ msgstr "複数ドキュメントのアクション"
#: model:ir.actions.act_window,name:base.action_partner_title_partner
#: model:ir.ui.menu,name:base.menu_partner_title_partner
msgid "Titles"
msgstr ""
msgstr "敬称"
#. module: base
#: model:ir.module.module,description:base.module_anonymization
@ -14298,7 +14318,7 @@ msgstr "ヘルプデスク"
#. module: base
#: field:ir.rule,perm_write:0
msgid "Apply for Write"
msgstr ""
msgstr "読み込みに適用"
#. module: base
#: field:ir.ui.menu,parent_left:0
@ -14456,7 +14476,7 @@ msgstr "ペルシア語 / فارس"
#. module: base
#: view:base.language.export:0
msgid "Export Settings"
msgstr ""
msgstr "エクスポート設定"
#. module: base
#: field:ir.actions.act_window,src_model:0
@ -15333,7 +15353,7 @@ msgstr ""
#. module: base
#: field:ir.model.data,complete_name:0
msgid "Complete ID"
msgstr ""
msgstr "完了ID"
#. module: base
#: model:ir.module.module,description:base.module_stock
@ -15488,7 +15508,7 @@ msgstr "購買依頼"
#. module: base
#: selection:ir.actions.act_window,target:0
msgid "Inline Edit"
msgstr ""
msgstr "インライン編集"
#. module: base
#: selection:ir.cron,interval_type:0
@ -15555,6 +15575,12 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" クリックしてアドレス帳に連絡先を追加してください。\n"
" </p><p>\n"
" OpenERPは顧客、ディスカッション、商機の履歴、文書など関連するすべての活動の追跡を容易にします。\n"
" </p>\n"
" "
#. module: base
#: model:res.partner.category,name:base.res_partner_category_2

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:17+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:19+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:19+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:20+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:20+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -16519,3 +16519,10 @@ msgstr ""
#~ msgstr ""
#~ "Nevar izveidot dokumentu (%s) ! Pārbaudiet, vai lietotājs pieder kādai no "
#~ "šīm grupām: %s."
#~ msgid ""
#~ "\n"
#~ " "
#~ msgstr ""
#~ "\n"
#~ " "

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:20+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:20+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -3094,7 +3094,7 @@ msgstr "Моделийн Тойм"
#. module: base
#: model:ir.module.module,shortdesc:base.module_product_margin
msgid "Margins by Products"
msgstr "Захалбар Бараагаар"
msgstr "Бохир ашиг Бараагаар"
#. module: base
#: model:ir.ui.menu,name:base.menu_invoiced
@ -5214,7 +5214,7 @@ msgstr ""
" * Дагавар\n"
" * Дараагийн Дугаар\n"
" * Нэмэгдэх Тоо\n"
" * Гүйцээлтийн тоо\n"
" * Дугаарлалтын гүйцээлт\n"
" "
#. module: base
@ -7400,7 +7400,7 @@ msgid ""
" "
msgstr ""
"\n"
"Энэ модуль нь борлуулалтын захиалга дээр 'Тодотгол' нэмдэг.\n"
"Энэ модуль нь борлуулалтын захиалга дээр 'Бохир ашиг' нэмдэг.\n"
"=============================================\n"
"\n"
"Нэгж үнэ, Өртөг үнийг харьцуулан бохир ашгийг харуулдаг.\n"
@ -11017,7 +11017,7 @@ msgstr "Өөриймшүүлсэн"
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale_margin
msgid "Margins in Sales Orders"
msgstr "Борлуулалтын захиалгын зөрүү"
msgstr "Борлуулалтын захиалгын бохир ашиг"
#. module: base
#: model:ir.module.module,shortdesc:base.module_purchase
@ -12353,7 +12353,7 @@ msgid ""
"you need.\n"
msgstr ""
"\n"
"Бараанд борлуулалт, худалдан авалт, тохируулалт зэрэг олон сонирхолтой "
"Бараанд борлуулалт, худалдан авалт, бохир ашиг зэрэг олон сонирхолтой "
"үзүүлэлтийг тооцолох тайлангийн менюг нэмдэг.\n"
"============================================================================="
"================================================\n"
@ -13178,7 +13178,7 @@ msgstr "Гүйцэтгэх дараагийн огноо"
#. module: base
#: field:ir.sequence,padding:0
msgid "Number Padding"
msgstr "Тоон дугаарын гүйцээлт"
msgstr "Дугаарын гүйцээлт"
#. module: base
#: help:multi_company.default,field_id:0
@ -14808,6 +14808,15 @@ msgid ""
"automatically new claims based on incoming emails.\n"
" "
msgstr ""
"\n"
"\n"
"Захиалагчийн Гомдлын Менежмент.\n"
"=======================\n"
"Энэ аппликэйшн нь захиалагч/нийлүүлэгчийн гомдлыг хөтлөх боломжийг олгодог.\n"
"\n"
"Энэ модуль нь эмэйл үүдтэй бүрэн уялддаг тул ирж буй имэйлээс\n"
"автоматаар гомдлыг үүсгэх боломжтой.\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_test
@ -18259,9 +18268,6 @@ msgstr "Бүртгүүлэх"
#~ msgid "View Ordering"
#~ msgstr "Дэлгэц эрэмблэлт"
#~ msgid "Number padding"
#~ msgstr "Тоон дугаарын урт"
#~ msgid "Object Identifiers"
#~ msgstr "Обьект бүрдүүлбэр"
@ -24122,3 +24128,6 @@ msgstr "Бүртгүүлэх"
#~ msgid "Retro-Planning on Events"
#~ msgstr "Үйл явдлын хойноос урагшаа төлөвлөлт"
#~ msgid "Number padding"
#~ msgstr "Тоон дугаарын гүйцээлт"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:20+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:29+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:17+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:24+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -1625,7 +1625,7 @@ msgstr ""
#: model:ir.module.category,name:base.module_category_purchase_management
#: model:ir.ui.menu,name:base.menu_purchase_root
msgid "Purchases"
msgstr "Inkoop"
msgstr "Inkopen"
#. module: base
#: model:res.country,name:base.md

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:25+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:36+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:21+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:21+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:30+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:24+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:21+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -26,7 +26,7 @@ msgid ""
msgstr ""
"\n"
"Modul pentru Bifeaza Scriere si Bifeaza Imprimare.\n"
"================================================\n"
"==================================================\n"
" "
#. module: base
@ -129,7 +129,7 @@ msgid ""
msgstr ""
"\n"
"Un modul care adauga producatori si atribute la formularul produsului.\n"
"====================================================================\n"
"======================================================================\n"
"\n"
"Acum puteti defini urmatoarele pentru un produs:\n"
"-----------------------------------------------\n"
@ -153,7 +153,7 @@ msgid ""
msgstr ""
"\n"
"Acest modul adauga utilizatorul google la utilizatorul res.\n"
"========================================\n"
"===========================================================\n"
#. module: base
#: help:res.partner,employee:0
@ -212,7 +212,7 @@ msgid ""
msgstr ""
"\n"
"Generează Facturi din Cheltuieli, Înregistrări ale Fișelor de Pontaj.\n"
"========================================================\n"
"=====================================================================\n"
"\n"
"Modul pentru generarea facturilor pe baza costurilor (resurse umane, "
"cheltuieli, ...).\n"
@ -249,7 +249,7 @@ msgstr "Eroare constrângere"
#. module: base
#: model:ir.model,name:base.model_ir_ui_view_custom
msgid "ir.ui.view.custom"
msgstr "ir.ui.vizualizare.personalizata"
msgstr "ir.ui.view.custom"
#. module: base
#: code:addons/base/ir/ir_model.py:374
@ -405,7 +405,7 @@ msgid ""
msgstr ""
"\n"
"Programul de instalare Ascuns bazat pe cunostinte.\n"
"=====================================\n"
"==================================================\n"
"\n"
"Face Configuratia Aplicatiei Cunostinte disponibila, de unde puteti instala\n"
"documente si Ascuns bazat pe Wiki.\n"
@ -431,7 +431,8 @@ msgstr ""
"\n"
"Va permite sa adaugati metode de livrare la comenzile de vanzare si "
"ridicare.\n"
"==============================================================\n"
"============================================================================="
"\n"
"\n"
"Va puteti defini propriile grile de preturi pentru transport si livrare. "
"Atunci cand creati \n"
@ -617,7 +618,7 @@ msgid ""
msgstr ""
"\n"
"Modul pentru definirea obiectului contabilitatii analitice.\n"
"===============================================\n"
"===========================================================\n"
"\n"
"In OpenERP, conturile analitice sunt legate de conturile generale, dar sunt "
"tratate\n"
@ -650,7 +651,7 @@ msgid ""
msgstr ""
"\n"
"Organizarea si gestionarea Evenimentelor.\n"
"======================================\n"
"=========================================\n"
"\n"
"Modulul eveniment va permite sa organizati eficient evenimente si toate "
"sarcinile asociate lor: planificare, urmarirea inregistrarii,\n"
@ -855,7 +856,7 @@ msgid ""
msgstr ""
"\n"
"Contabilitate si Management Financiar.\n"
"====================================\n"
"======================================\n"
"\n"
"Modulul Finante si contabilitate acopera:\n"
"--------------------------------------------\n"
@ -899,7 +900,7 @@ msgid ""
msgstr ""
"\n"
"Meniul pentru Marketing.\n"
"=======================\n"
"========================\n"
"\n"
"Contine programul de instalare pentru modulele legate de marketing.\n"
" "
@ -915,7 +916,7 @@ msgid ""
msgstr ""
"\n"
"Modulul OpenERP Web LinkedIn.\n"
"============================\n"
"=============================\n"
"Acest modul asigura Integrarea lui LinkedIn in OpenERP.\n"
" "
@ -950,7 +951,7 @@ msgstr "Data urmatoarei executii planificate pentru aceasta sarcina."
#. module: base
#: model:ir.model,name:base.model_ir_ui_view
msgid "ir.ui.view"
msgstr "ir.ui.vizualizare"
msgstr "ir.ui.view"
#. module: base
#: model:res.country,name:base.er
@ -975,7 +976,7 @@ msgstr "România - Contabilitate"
#. module: base
#: model:ir.model,name:base.model_res_config_settings
msgid "res.config.settings"
msgstr "res.configurare.setari"
msgstr "res.config.settings"
#. module: base
#: help:res.partner,image_small:0
@ -996,8 +997,8 @@ msgid ""
"the correct mobile number"
msgstr ""
"Furnizeaza campurile care sunt folosite pentru a cauta numarul de telefon "
"mobil, de exemplu dumneavoastra selectati factura, atunci "
"`obiect.factura_adresa_id.mobil` este campul care va da numarul corect de "
"mobil, de exemplu dumneavoastra selectati factura, atunci "
"`object.invoice_address_id.mobile` este campul care va da numarul corect de "
"telefon mobil"
#. module: base
@ -1072,7 +1073,7 @@ msgid ""
msgstr ""
"\n"
"Gestioneaza concediile si cererile de alocare\n"
"=====================================\n"
"=============================================\n"
"\n"
"Aceasta aplicatie controleaza programul de concedii al companiei "
"dumneavoastra. Le permite angajatilor sa solicite concedii. Astfel, "
@ -1331,7 +1332,7 @@ msgid ""
msgstr ""
"\n"
"Managementul general OpenERP al Relatiilor cu Clientii\n"
" ====================================================\n"
"======================================================\n"
" \n"
"Aceasta aplicatie permite unui grup de oameni sa gestioneze in mod "
"inteligent si eficient piste, oportunitati, intalniri si apeluri "
@ -1356,7 +1357,7 @@ msgstr ""
" \n"
"\n"
"Tabloul de bord pentru MRC va include:\n"
" -------------------------------\n"
"--------------------------------------\n"
" * Veniturile Planificate dupa Etapa si Utilizator (grafic)\n"
" * Oportunitati dupa Etapa (grafic)\n"
@ -1932,7 +1933,7 @@ msgstr "Sfantul Martin (partea franceza)"
#. module: base
#: model:ir.model,name:base.model_ir_exports
msgid "ir.exports"
msgstr "ir.exporturi"
msgstr "ir.exports"
#. module: base
#: model:ir.module.module,description:base.module_l10n_lu
@ -2011,7 +2012,7 @@ msgid ""
msgstr ""
"\n"
"Modulul de baza pentru gestionarea pranzului.\n"
"================================\n"
"=============================================\n"
"\n"
"Multe companii comanda sandwich-uri, pizza si alte mancaruri de la "
"furnizorii obisnuiti, pentru angajatii lor pentru a le oferi mai multe "
@ -2056,7 +2057,7 @@ msgstr "Bancă"
#. module: base
#: model:ir.model,name:base.model_ir_exports_line
msgid "ir.exports.line"
msgstr "ir.linie.exporturi"
msgstr "ir.exports.line"
#. module: base
#: model:ir.module.category,description:base.module_category_purchase_management
@ -2125,8 +2126,8 @@ msgid ""
"Access all the fields related to the current object using expressions, i.e. "
"object.partner_id.name "
msgstr ""
"Acceseaza toate fisierele asociate obiectului actual folosind expresii, de "
"exemplu obiect.partener_id.nume "
"Accesează toate câmpurile asociate obiectului actual folosind expresii, de "
"exemplu object.partner_id.name "
#. module: base
#: model:ir.module.module,shortdesc:base.module_portal_project_issue
@ -2169,7 +2170,7 @@ msgstr "Gestiunea depozitului"
#. module: base
#: model:ir.model,name:base.model_res_request_link
msgid "res.request.link"
msgstr "res.link.cerere"
msgstr "res.request.link"
#. module: base
#: field:ir.actions.wizard,name:0
@ -2250,7 +2251,7 @@ msgid ""
msgstr ""
"\n"
"Drepturi de acces contabile\n"
"========================\n"
"===========================\n"
"Ii ofera utilizatorului Administrator acces la toate caracteristicile "
"contabile, precum elemente ale jurnalului si planul de conturi.\n"
"\n"
@ -2260,7 +2261,7 @@ msgstr ""
#. module: base
#: view:ir.sequence:0
msgid "Day: %(day)s"
msgstr "Ziua: %(zi)s"
msgstr "Ziua: %(day)s"
#. module: base
#: model:ir.module.category,description:base.module_category_point_of_sale
@ -2299,7 +2300,7 @@ msgstr "Traducere în desfășurare"
#. module: base
#: model:ir.model,name:base.model_ir_rule
msgid "ir.rule"
msgstr "ir.regula"
msgstr "ir.rule"
#. module: base
#: selection:ir.cron,interval_type:0
@ -2444,7 +2445,8 @@ msgstr ""
"\n"
"Sincronizarea inregistrarilor sarcinilor proiectului cu inregistrarile fisei "
"de pontaj.\n"
"====================================================================\n"
"============================================================================="
"==========\n"
"\n"
"Acest modul va permite sa transferati inregistrarile sub sarcini definite "
"pentru Managementul\n"
@ -2456,7 +2458,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_model_access
msgid "ir.model.access"
msgstr "ir.model.acces"
msgstr "ir.model.access"
#. module: base
#: model:ir.module.module,description:base.module_l10n_multilang
@ -2778,7 +2780,7 @@ msgid ""
msgstr ""
"\n"
"Inregistreaza si valideaza fisele de pontaj si prezenta cu usurinta\n"
"=====================================================\n"
"===================================================================\n"
"\n"
"Aceasta aplicatie ofera un ecran nou care va permite sa gestionati atat "
"prezenta (La intrare/La iesire) cat si inregistrare muncii (fisa de pontaj) "
@ -2874,7 +2876,7 @@ msgid ""
msgstr ""
"\n"
"Permite anonimilor sa Acceseze Portalul.\n"
"=================================\n"
"========================================\n"
" "
#. module: base
@ -2987,7 +2989,7 @@ msgstr "Va fi șters"
#. module: base
#: model:ir.model,name:base.model_ir_sequence
msgid "ir.sequence"
msgstr "ir.secventa"
msgstr "ir.sequence"
#. module: base
#: help:ir.actions.server,expression:0
@ -2996,9 +2998,9 @@ msgid ""
"order in Object, and you can have loop on the sales order line. Expression = "
"`object.order_line`."
msgstr ""
"Introduceti campul/expresia care va genera lista. De exemplu, selectati "
"comanda de vanzare in Obiect, si puteti parcurge in bucla pozitiile din "
"comanda de vanzare. Expresie = `obiect.linie_comanda`."
"Introduceți câmpul / expresia care sa genereze lista. De exemplu, selectând "
"comanda de vânzare în Obiecte puteți parcurge în buclă pozițiile din "
"comandă. Expresie = `object.order_line`."
#. module: base
#: field:ir.mail_server,smtp_debug:0
@ -3021,7 +3023,7 @@ msgid ""
msgstr ""
"\n"
"Managementul Serviciului de asistenta tehnica.\n"
"===================================\n"
"==============================================\n"
"\n"
"La fel ca si inregistrarea si prelucrarea reclamatiilor, Serviciul de "
"Asistenta tehnica este un instrument\n"
@ -3095,7 +3097,8 @@ msgstr ""
"\n"
"Acesta este modulul de baza pentru gestionarea produselor si a listelor de "
"preturi in OpenERP.\n"
"========================================================================\n"
"============================================================================="
"=================\n"
"\n"
"Produsele accepta variante, diferite metode de stabilire a pretului, "
"informatii referitoare la furnizori,\n"
@ -3103,7 +3106,7 @@ msgstr ""
"proprietati.\n"
"\n"
"Listele de preturi accepta:\n"
"--------------------\n"
"---------------------------\n"
" * Niveluri multiple de reducere (dupa produs, categorie, cantitati)\n"
" * Calculeaza pretul pe baza unor criterii diferite:\n"
" * Alte liste de preturi\n"
@ -3134,11 +3137,10 @@ msgid ""
msgstr ""
"\n"
"Configureaza valorile implicite pentru conturile dumneavoastra analitice.\n"
"==============================================\n"
"=========================================================================\n"
"\n"
"Permite selectarea automata a conturilor analitice pe baza criteriilor:\n"
"-----------------------------------------------------------------------------"
"------\n"
"-----------------------------------------------------------------------\n"
" * Produs \n"
" * Partener\n"
" * Utilizator\n"
@ -3216,7 +3218,8 @@ msgstr ""
"\n"
"Modulul de baza pentru gestionarea distribuirii analitice si a comenzilor de "
"vanzare.\n"
"==========================================================================\n"
"============================================================================="
"========\n"
"\n"
"Folosind acest modul veti putea lega conturile analitice de comenzile de "
"vanzare.\n"
@ -3292,7 +3295,7 @@ msgid ""
msgstr ""
"\n"
"Acesta este un sistem complet de gestionare a documentelor.\n"
"==============================================\n"
"===========================================================\n"
" * Autentificare Utilizator\n"
" * Indexare Documente:- fisierele .pptx si .docx nu sunt acceptate in "
"platforma Windows.\n"
@ -3351,8 +3354,8 @@ msgid ""
" "
msgstr ""
"\n"
"Gestiunea cotarilor si a comenzilor de vanzare\n"
" ==================================\n"
"Gestionare cotațiilor și a comenzilor de vânzare\n"
"================================================\n"
"\n"
"Aceasta aplicatie va permite sa va gestionati obiectivele de vanzari intr-un "
"mod efectiv si eficient, tinand evidenta tuturor comenzilor de vanzare si "
@ -3363,7 +3366,7 @@ msgstr ""
"* **Cotare** -> **Comanda de vanzare** -> **Factura**\n"
"\n"
"Preferinte (numai daca este instalat si modulul Gestionarea Depozitului)\n"
"-----------------------------------------------------\n"
"------------------------------------------------------------------------\n"
"\n"
"Daca ati instalat si Gestionarea Depozitului, puteti efectua urmatoarele:\n"
"\n"
@ -3382,7 +3385,7 @@ msgstr ""
"\n"
"\n"
"Tabloul de bord pentru Managerul de Vanzari va include\n"
"------------------------------------------------\n"
"------------------------------------------------------\n"
"* Cotatiile mele\n"
"* Cifra de afaceri lunara (Grafic)\n"
" "
@ -3414,7 +3417,7 @@ msgid ""
msgstr ""
"\n"
"Modul pentru atasarea unui document google oricarui model.\n"
"================================================\n"
"==========================================================\n"
#. module: base
#: code:addons/base/ir/ir_fields.py:333
@ -3591,7 +3594,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_actions_act_window_close
msgid "ir.actions.act_window_close"
msgstr "ir.actiuni.inchide_fereastra_act"
msgstr "ir.actions.act_window_close"
#. module: base
#: field:ir.server.object.lines,col1:0
@ -4878,7 +4881,7 @@ msgstr "Jersey"
#. module: base
#: model:ir.model,name:base.model_ir_translation
msgid "ir.translation"
msgstr "ir.traducere"
msgstr "ir.translation"
#. module: base
#: view:res.lang:0
@ -4954,7 +4957,7 @@ msgstr "Reg"
#. module: base
#: model:ir.model,name:base.model_ir_property
msgid "ir.property"
msgstr "ir.proprietate"
msgstr "ir.property"
#. module: base
#: selection:ir.actions.act_window,view_type:0
@ -6083,9 +6086,9 @@ msgid ""
"the same values as those available in the condition field, e.g. `Dear [[ "
"object.partner_id.name ]]`"
msgstr ""
"Continuturile e-mail-urilor, pot sa contina expresii incluse in paranteze "
"duble bazate pe aceleasi valori ca si cele disponibile in campul conditie, "
"de exemplu: `Stimate [[ obiect.id_nume.partener ]]`"
"Conținuturile e-mail-urilor, pot sa includă expresii incluse în paranteze "
"duble bazate pe aceleași valori ca și cele disponibile în câmpul condiție, "
"de exemplu: `Stimate [[ object.partner_id.name ]]`"
#. module: base
#: model:ir.actions.act_window,name:base.action_workflow_form
@ -6329,7 +6332,7 @@ msgstr "Nume de utilizator optional pentru autentificarea SMTP"
#. module: base
#: model:ir.model,name:base.model_ir_actions_actions
msgid "ir.actions.actions"
msgstr "ir.actiuni.actiuni"
msgstr "ir.actions.actions"
#. module: base
#: selection:ir.model.fields,select_level:0
@ -6364,19 +6367,19 @@ msgid ""
" \n"
"%(country_code)s: the code of the country"
msgstr ""
"Aici puteti mentiona formatul obisnuit care va fi folosit pentru adresele "
"care apartin acestei tari.\n"
"Aici puteți menționa formatul obișnuit care va fi folosit pentru adresele "
"acestei țări.\n"
"\n"
"Puteti folosi tiparul in sir stil python cu toate campurile adreselor (de "
"exemplu, folositi '%(strada)s' pentru a afisa campul 'strada') plus\n"
"Puteți folosi tiparul in sir stil python cu toate câmpurile adreselor (de "
"exemplu, folosiți '%(street)s' pentru a afișa câmpul 'strada') plus\n"
" \n"
"%(nume_stat)s: numele statului\n"
"%(state_name)s: numele statului (județului)\n"
" \n"
"%(cod_stat)s: codul statului\n"
"%(state_code)s: codul statului (județului)\n"
" \n"
"%(nume_tara)s: numele tarii\n"
"%(country_name)s: numele țării\n"
" \n"
"%(cod_tara)s: codul tarii"
"%(country_code)s: codul țării"
#. module: base
#: model:res.country,name:base.mu
@ -7194,7 +7197,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_actions_act_window_view
msgid "ir.actions.act_window.view"
msgstr "ir.actiuni.act_fereastra.vizualizare"
msgstr "ir.actions.act_window.view"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web
@ -7278,7 +7281,7 @@ msgstr "Insulele Svalbard si Jan Mayen"
#: model:ir.model,name:base.model_ir_actions_wizard
#: selection:ir.ui.menu,action:0
msgid "ir.actions.wizard"
msgstr "ir.asistent.actiuni"
msgstr "ir.actions.wizard"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_kanban
@ -7567,7 +7570,7 @@ msgstr "Start Flux"
#. module: base
#: model:ir.model,name:base.model_res_partner_title
msgid "res.partner.title"
msgstr "res.partener.titlu"
msgstr "res.partner.title"
#. module: base
#: view:res.partner.bank:0
@ -8097,7 +8100,7 @@ msgstr "Meniuri Create"
#: view:ir.module.module:0
#, python-format
msgid "Uninstall"
msgstr "Dezinstaleaza"
msgstr "Dezinstalați"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_budget
@ -8208,7 +8211,7 @@ msgstr "Curaçao"
#. module: base
#: view:ir.sequence:0
msgid "Current Year without Century: %(y)s"
msgstr "Anul curent fara Secol: %(y)s"
msgstr "Anul curent fără secol: %(y)s"
#. module: base
#: model:ir.actions.act_window,name:base.ir_config_list_action
@ -8490,7 +8493,7 @@ msgstr ""
#. module: base
#: view:ir.sequence:0
msgid "Week of the Year: %(woy)s"
msgstr "Saptamana din An: %(sda)s"
msgstr "Săptămâna din an: %(woy)s"
#. module: base
#: field:res.users,id:0
@ -8601,7 +8604,7 @@ msgstr "Filtre vizibile doar pentru un utilizator"
#. module: base
#: model:ir.model,name:base.model_ir_attachment
msgid "ir.attachment"
msgstr "ir.atasament"
msgstr "ir.attachment"
#. module: base
#: code:addons/orm.py:4348
@ -9154,7 +9157,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_config_parameter
msgid "ir.config_parameter"
msgstr "ir.configurare_parametru"
msgstr "ir.config_parameter"
#. module: base
#: model:ir.module.module,description:base.module_project_long_term
@ -9243,7 +9246,7 @@ msgstr "Compania pentru care acest utilizator lucreaza in prezent."
#. module: base
#: model:ir.model,name:base.model_wizard_ir_model_menu_create
msgid "wizard.ir.model.menu.create"
msgstr "wizard.ir.creeaza.model.meniu"
msgstr "wizard.ir.model.menu.create"
#. module: base
#: view:workflow.transition:0
@ -9981,9 +9984,9 @@ msgid ""
"the same values as those available in the condition field, e.g. `Hello [[ "
"object.partner_id.name ]]`"
msgstr ""
"Subiectul e-mail-ului poate sa contina expresii intre paranteze duble, "
"bazate pe aceleasi valori ca si cele disponibile in campul conditie, de ex. "
"`Buna ziua [[obiect.partener_id.nume]]`"
"Subiectul e-mail-ului poate să conțină expresii intre paranteze duble, "
"bazate pe aceleași valori ca și cele disponibile în câmpul condiție, de ex. "
"`Buna ziua [[ object.partner_id.name ]]`"
#. module: base
#: help:res.partner,image:0
@ -10209,7 +10212,7 @@ msgstr "Austria - Contabilitate"
#. module: base
#: model:ir.model,name:base.model_ir_ui_menu
msgid "ir.ui.menu"
msgstr "ir.ui.meniu"
msgstr "ir.ui.menu"
#. module: base
#: model:ir.module.module,shortdesc:base.module_project
@ -10219,7 +10222,7 @@ msgstr "Managementul Proiectelor"
#. module: base
#: view:ir.module.module:0
msgid "Cancel Uninstall"
msgstr "Anulati dezinstalarea"
msgstr "Anulați dezinstalarea"
#. module: base
#: view:res.bank:0
@ -10234,7 +10237,7 @@ msgstr "Contabilitate Analitica"
#. module: base
#: model:ir.model,name:base.model_ir_model_constraint
msgid "ir.model.constraint"
msgstr "ir.restrictie.model"
msgstr "ir.model.constraint"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_graph
@ -10260,7 +10263,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_server_object_lines
msgid "ir.server.object.lines"
msgstr "ir.linii.obiect.server"
msgstr "ir.server.object.lines"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_be
@ -10889,7 +10892,7 @@ msgstr "Instalati Actualizare Modul"
#. module: base
#: model:ir.model,name:base.model_ir_actions_configuration_wizard
msgid "ir.actions.configuration.wizard"
msgstr "ir.wizard.configurare.actiuni"
msgstr "ir.actions.configuration.wizard"
#. module: base
#: view:res.lang:0
@ -11835,7 +11838,7 @@ msgstr "Statele Unite - Plan de Conturi"
#: view:res.users:0
#: view:wizard.ir.model.menu.create:0
msgid "Cancel"
msgstr "Anulati"
msgstr "Anulați"
#. module: base
#: code:addons/orm.py:1507
@ -12119,9 +12122,9 @@ msgid ""
"same values as for the condition field.\n"
"Example: object.invoice_address_id.email, or 'me@example.com'"
msgstr ""
"Expresie care intoarce adresa de e-mail la trimite catre. Poate fi bazata pe "
"aceleasi valori ca si pentru campul conditie.\n"
"Exemplu: obiect.id_adresa_factura.e-mail, sau 'me@exemplu.com'"
"Expresie care întoarce adresa de e-mail în câmpul trimite către. Poate fi "
"bazată pe aceleași valori ca și pentru câmpul condiție.\n"
"Exemplu: object.invoice_address_id.email, sau 'me@exemplu.com'"
#. module: base
#: model:ir.module.module,description:base.module_project_issue_sheet
@ -12326,7 +12329,7 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<clasa p=\"creeaza_niciuncontinut_vizualizare_oe\">\n"
"<p class=\"oe_view_nocontent_create\">\n"
" Faceti click pentru a adauga un contact in agenda "
"dumneavoastra.\n"
" </p><p>\n"
@ -12389,7 +12392,7 @@ msgstr "Cod"
#. module: base
#: model:ir.model,name:base.model_res_config_installer
msgid "res.config.installer"
msgstr "res.config.program_de_instalare"
msgstr "res.config.installer"
#. module: base
#: model:res.country,name:base.mc
@ -12452,7 +12455,7 @@ msgstr ""
#. module: base
#: view:ir.sequence:0
msgid "Current Year with Century: %(year)s"
msgstr "Anul curent cu Secol: %(an)s"
msgstr "Anul curent cu secol: %(year)s"
#. module: base
#: field:ir.exports,export_fields:0
@ -12593,7 +12596,7 @@ msgstr "Chineza (TW) / 正體字"
#. module: base
#: model:ir.model,name:base.model_res_request
msgid "res.request"
msgstr "res.cerere"
msgstr "res.request"
#. module: base
#: field:res.partner,image_medium:0
@ -13120,7 +13123,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_mail_server
msgid "ir.mail_server"
msgstr "ir.server_e-mail"
msgstr "ir.mail_server"
#. module: base
#: selection:base.language.install,lang:0
@ -13689,7 +13692,7 @@ msgstr "Fus orar"
#: model:ir.model,name:base.model_ir_actions_report_xml
#: selection:ir.ui.menu,action:0
msgid "ir.actions.report.xml"
msgstr "ir.actiuni.raport.xml"
msgstr "ir.actions.report.xml"
#. module: base
#: model:ir.actions.act_window,name:base.ir_sequence_form
@ -14248,7 +14251,7 @@ msgstr "Data trimiterii"
#. module: base
#: view:ir.sequence:0
msgid "Month: %(month)s"
msgstr "Luna: %(luna)s"
msgstr "Luna: %(month)s"
#. module: base
#: field:ir.actions.act_window.view,sequence:0
@ -14285,7 +14288,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_fields_converter
msgid "ir.fields.converter"
msgstr "ir.convertor.campuri"
msgstr "ir.fields.converter"
#. module: base
#: code:addons/base/res/res_partner.py:439
@ -14308,12 +14311,12 @@ msgstr "Comore"
#. module: base
#: view:ir.module.module:0
msgid "Cancel Install"
msgstr "Anulati Instalarea"
msgstr "Anulați Instalarea"
#. module: base
#: model:ir.model,name:base.model_ir_model_relation
msgid "ir.model.relation"
msgstr "ir.model.relatie"
msgstr "ir.model.relation"
#. module: base
#: model:ir.module.module,shortdesc:base.module_account_check_writing
@ -14534,7 +14537,7 @@ msgstr "Planuri Analitice Multiple"
#. module: base
#: model:ir.model,name:base.model_ir_default
msgid "ir.default"
msgstr "ir.implicit"
msgstr "ir.default"
#. module: base
#: view:ir.sequence:0
@ -14633,9 +14636,9 @@ msgstr ""
"*URL:** legatura dumneavoastra moodle, de exemplu: "
"http://openerp.moodle.com\n"
"\n"
"**AUTENTIFICARE:** ${obiect.nume_de_utilizator_moodle}\n"
"**AUTENTIFICARE:**${object.moodle_username}\n"
" \n"
"**PAROLA:** ${obiect.parola_utilizator_moodle}\n"
"**PAROLA:** ${object.moodle_user_password}\n"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_uk
@ -15423,7 +15426,7 @@ msgid ""
msgstr ""
"\n"
"Retele Sociale orientate spre afaceri\n"
"===================================\n"
"=====================================\n"
"Modulul Retele Sociale furnizeaza un strat de abstractizare unificat de "
"retele sociale, permitand aplicatiilor sa afiseze un istoric\n"
"complet al conversatiilor in documente cu un sistem complet integrat de "
@ -15537,7 +15540,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_values
msgid "ir.values"
msgstr "ir.valori"
msgstr "ir.values"
#. module: base
#: model:ir.model,name:base.model_base_module_update
@ -16201,7 +16204,7 @@ msgstr "Agenda"
#. module: base
#: model:ir.model,name:base.model_ir_sequence_type
msgid "ir.sequence.type"
msgstr "ir.tip.secventa"
msgstr "ir.sequence.type"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_be_hr_payroll_account
@ -16825,7 +16828,7 @@ msgstr "Nu pot exista doi utilizatori cu acelasi nume de autentificare !"
#. module: base
#: model:ir.model,name:base.model_res_request_history
msgid "res.request.history"
msgstr "res.istoric.solicitari"
msgstr "res.request.history"
#. module: base
#: model:ir.model,name:base.model_multi_company_default
@ -17409,7 +17412,7 @@ msgstr "Uzbekistan"
#: model:ir.model,name:base.model_ir_actions_act_window
#: selection:ir.ui.menu,action:0
msgid "ir.actions.act_window"
msgstr "ir.actiuni.act_fereastra"
msgstr "ir.actions.act_window"
#. module: base
#: model:res.country,name:base.vi
@ -17597,7 +17600,7 @@ msgstr "Germania - Contabilitate"
#. module: base
#: view:ir.sequence:0
msgid "Day of the Year: %(doy)s"
msgstr "Ziua din An: %(doy)s"
msgstr "Ziua din an: %(doy)s"
#. module: base
#: field:ir.ui.menu,web_icon:0
@ -17642,7 +17645,7 @@ msgstr "Model sursa"
#. module: base
#: view:ir.sequence:0
msgid "Day of the Week (0:Monday): %(weekday)s"
msgstr "Ziua din Saptamana (0:Luni): %(weekday)s"
msgstr "Ziua din saptămâna (0:Luni): %(weekday)s"
#. module: base
#: code:addons/base/module/wizard/base_module_upgrade.py:84
@ -17936,7 +17939,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_model_data
msgid "ir.model.data"
msgstr "ir.date.model"
msgstr "ir.model.data"
#. module: base
#: selection:base.language.install,lang:0
@ -18442,7 +18445,7 @@ msgstr "Grafic"
#: model:ir.model,name:base.model_ir_actions_server
#: selection:ir.ui.menu,action:0
msgid "ir.actions.server"
msgstr "ir.actiuni.server"
msgstr "ir.actions.server"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_ca
@ -18953,7 +18956,7 @@ msgstr "Note Interne"
#: model:res.partner.title,name:base.res_partner_title_pvt_ltd
#: model:res.partner.title,shortcut:base.res_partner_title_pvt_ltd
msgid "Corp."
msgstr "Corp."
msgstr "SA"
#. module: base
#: model:ir.module.module,shortdesc:base.module_purchase_requisition

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:21+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:22+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,6 +25,10 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"Modul pre vypisovanie a tlač šekov.\n"
"================================================\n"
" "
#. module: base
#: model:res.country,name:base.sh

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:22+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:32+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:15+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:22+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:21+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:31+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:26+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:38+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:22+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,6 +25,9 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"โมดูลสำหรับการเขียน และพิมพ์เช็ค\n"
" "
#. module: base
#: model:res.country,name:base.sh

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:33+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:34+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:25+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:23+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:35+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-01-01 05:25+0000\n"
"X-Generator: Launchpad (build 16877)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:37+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -37,6 +37,7 @@ import ir_config_parameter
import osv_memory_autovacuum
import ir_mail_server
import ir_fields
import ir_qweb
import ir_http
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -24,6 +24,8 @@ import logging
import operator
import os
import time
import datetime
import dateutil
import openerp
from openerp import SUPERUSER_ID
@ -268,7 +270,7 @@ class ir_actions_act_window(osv.osv):
'filter': fields.boolean('Filter'),
'auto_search':fields.boolean('Auto Search'),
'search_view' : fields.function(_search_view, type='text', string='Search View'),
'multi': fields.boolean('Action on Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view"),
'multi': fields.boolean('Restrict to lists', help="If checked and the action is bound to a model, it will only appear in the More menu on list views"),
}
_defaults = {
@ -550,6 +552,7 @@ class ir_actions_server(osv.osv):
# - uid: current user id
# - context: current context
# - time: Python time module
# - workflow: Workflow engine
# If you plan to return an action, assign: action = {...}""",
'use_relational_model': 'base',
'use_create': 'new',
@ -910,11 +913,38 @@ class ir_actions_server(osv.osv):
if action.link_new_record and action.link_field_id:
self.pool[action.model_id.model].write(cr, uid, [context.get('active_id')], {action.link_field_id.name: res_id})
def _get_eval_context(self, cr, uid, action, context=None):
""" Prepare the context used when evaluating python code, like the
condition or code server actions.
:param action: the current server action
:type action: browse record
:returns: dict -- evaluation context given to (safe_)eval """
user = self.pool.get('res.users').browse(cr, uid, uid, context=context)
obj_pool = self.pool[action.model_id.model]
obj = None
if context.get('active_model') == action.model_id.model and context.get('active_id'):
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
return {
'self': obj_pool,
'object': obj,
'obj': obj,
'pool': self.pool,
'time': time,
'datetime': datetime,
'dateutil': dateutil,
'cr': cr,
'uid': uid,
'user': user,
'context': context,
'workflow': workflow
}
def run(self, cr, uid, ids, context=None):
""" Run the server action. For each server action, the condition is
checked. Note that A void (aka False) condition is considered as always
""" Runs the server action. For each server action, the condition is
checked. Note that a void (``False``) condition is considered as always
valid. If it is verified, the run_action_<STATE> method is called. This
allows easy inheritance of the server actions.
allows easy overriding of the server actions.
:param dict context: context should contain following keys
@ -932,33 +962,14 @@ class ir_actions_server(osv.osv):
if context is None:
context = {}
res = False
user = self.pool.get('res.users').browse(cr, uid, uid)
active_ids = context.get('active_ids', [context.get('active_id')])
for action in self.browse(cr, uid, ids, context):
obj_pool = self.pool[action.model_id.model]
obj = None
if context.get('active_model') == action.model_id.model and context.get('active_id'):
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
# evaluation context for python strings to evaluate
eval_context = {
'self': obj_pool,
'object': obj,
'obj': obj,
'pool': self.pool,
'time': time,
'cr': cr,
'uid': uid,
'user': user,
}
eval_context = self._get_eval_context(cr, uid, action, context=context)
condition = action.condition
if condition is False:
# Void (aka False) conditions are considered as True
condition = True
if hasattr(self, 'run_action_%s_multi' % action.state):
# set active_ids in context only needed if one active_id
run_context = dict(context, active_ids=active_ids)
eval_context["context"] = run_context
run_context = eval_context['context']
expr = eval(str(condition), eval_context)
if not expr:
continue
@ -968,6 +979,8 @@ class ir_actions_server(osv.osv):
elif hasattr(self, 'run_action_%s' % action.state):
func = getattr(self, 'run_action_%s' % action.state)
active_id = context.get('active_id')
active_ids = context.get('active_ids', [active_id] if active_id else [])
for active_id in active_ids:
# run context dedicated to a particular active_id
run_context = dict(context, active_ids=[active_id], active_id=active_id)

View File

@ -180,6 +180,7 @@
<field name="auto_refresh"/>
<field name="auto_search"/>
<field name="filter"/>
<field name="multi"/>
</group>
</group>
<group string="Help">
@ -411,6 +412,7 @@
<li>cr: database cursor</li>
<li>uid: current user id</li>
<li>context: current context</li>
<li>workflow: Workflow engine</li>
</ul>
<div>
<p>Example of condition expression using Python</p>

View File

@ -45,6 +45,7 @@ class ir_attachment(osv.osv):
The default implementation is the file:dirname location that stores files
on the local filesystem using name based on their sha1 hash
"""
_order = 'id desc'
def _name_get_resname(self, cr, uid, ids, object, method, context):
data = {}
for attachment in self.browse(cr, uid, ids, context=context):

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import cStringIO
import datetime
import functools
import operator
@ -12,6 +13,7 @@ from openerp.osv import orm
from openerp.tools.translate import _
from openerp.tools.misc import DEFAULT_SERVER_DATE_FORMAT,\
DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools import html_sanitize
REFERENCING_FIELDS = set([None, 'id', '.id'])
def only_ref_fields(record):
@ -128,14 +130,17 @@ class ir_fields_converter(orm.Model):
:param column: column object to generate a value for
:type column: :class:`fields._column`
:param type fromtype: type to convert to something fitting for ``column``
:param fromtype: type to convert to something fitting for ``column``
:type fromtype: type | str
:param context: openerp request context
:return: a function (fromtype -> column.write_type), if a converter is found
:rtype: Callable | None
"""
assert isinstance(fromtype, (type, str))
# FIXME: return None
typename = fromtype.__name__ if isinstance(fromtype, type) else fromtype
converter = getattr(
self, '_%s_to_%s' % (fromtype.__name__, column._type), None)
self, '_%s_to_%s' % (typename, column._type), None)
if not converter: return None
return functools.partial(
@ -184,7 +189,7 @@ class ir_fields_converter(orm.Model):
def _str_id(self, cr, uid, model, column, value, context=None):
return value, []
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_id
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_to_html = _str_id
def _str_to_date(self, cr, uid, model, column, value, context=None):
try:

View File

@ -15,9 +15,7 @@ from openerp.osv import osv, orm
_logger = logging.getLogger(__name__)
# FIXME: replace by proxy on request.uid?
_uid = object()
UID_PLACEHOLDER = object()
class ModelConverter(werkzeug.routing.BaseConverter):
@ -29,7 +27,7 @@ class ModelConverter(werkzeug.routing.BaseConverter):
def to_python(self, value):
m = re.match(self.regex, value)
return request.registry[self.model].browse(
request.cr, _uid, int(m.group(1)), context=request.context)
request.cr, UID_PLACEHOLDER, int(m.group(1)), context=request.context)
def to_url(self, value):
return value.id
@ -43,10 +41,7 @@ class ModelsConverter(werkzeug.routing.BaseConverter):
self.regex = '([0-9,]+)'
def to_python(self, value):
# TODO:
# - raise routing.ValidationError() if no browse record can be createdm
# - support slug
return request.registry[self.model].browse(request.cr, _uid, [int(i) for i in value.split(',')], context=request.context)
return request.registry[self.model].browse(request.cr, UID_PLACEHOLDER, [int(i) for i in value.split(',')], context=request.context)
def to_url(self, value):
return ",".join(i.id for i in value)
@ -66,15 +61,15 @@ class ir_http(osv.AbstractModel):
if not request.uid:
raise http.SessionExpiredException("Session expired")
def _auth_method_admin(self):
if not request.db:
raise http.SessionExpiredException("No valid database for request %s" % request.httprequest)
request.uid = openerp.SUPERUSER_ID
def _auth_method_none(self):
request.disable_db = True
request.uid = None
def _auth_method_public(self):
if not request.session.uid:
dummy, request.uid = self.pool['ir.model.data'].get_object_reference(request.cr, openerp.SUPERUSER_ID, 'base', 'public_user')
else:
request.uid = request.session.uid
def _authenticate(self, auth_method='user'):
if request.session.uid:
try:
@ -88,16 +83,8 @@ class ir_http(osv.AbstractModel):
return auth_method
def _handle_exception(self, exception):
if isinstance(exception, openerp.exceptions.AccessError):
code = 403
else:
code = getattr(exception, 'code', 500)
fn = getattr(self, '_handle_%d' % code, self._handle_unknown_exception)
return fn(exception)
def _handle_unknown_exception(self, exception):
raise exception
# If handle exception return something different than None, it will be used as a response
raise
def _dispatch(self):
# locate the controller method
@ -108,17 +95,17 @@ class ir_http(osv.AbstractModel):
# check authentication level
try:
auth_method = self._authenticate(getattr(func, "auth", None))
auth_method = self._authenticate(func.routing["auth"])
except Exception:
# force a Forbidden exception with the original traceback
return self._handle_exception(
convert_exception_to(
werkzeug.exceptions.Forbidden))
# post process arg to set uid on browse records
for arg in arguments.itervalues():
if isinstance(arg, orm.browse_record) and arg._uid is _uid:
arg._uid = request.uid
processing = self._postprocess_args(arguments)
if processing:
return processing
# set and execute handler
try:
@ -131,6 +118,16 @@ class ir_http(osv.AbstractModel):
return result
def _postprocess_args(self, arguments):
""" post process arg to set uid on browse records """
for arg in arguments.itervalues():
if isinstance(arg, orm.browse_record) and arg._uid is UID_PLACEHOLDER:
arg._uid = request.uid
try:
arg[arg._rec_name]
except KeyError:
return self._handle_exception(werkzeug.exceptions.NotFound())
def routing_map(self):
if not hasattr(self, '_routing_map'):
_logger.info("Generating routing map")
@ -138,7 +135,9 @@ class ir_http(osv.AbstractModel):
m = request.registry.get('ir.module.module')
ids = m.search(cr, openerp.SUPERUSER_ID, [('state', '=', 'installed'), ('name', '!=', 'web')], context=request.context)
installed = set(x['name'] for x in m.read(cr, 1, ids, ['name'], context=request.context))
mods = ['', "web"] + sorted(installed)
if openerp.tools.config['test_enable']:
installed.add(openerp.modules.module.current_test)
mods = [''] + openerp.conf.server_wide_modules + sorted(installed)
self._routing_map = http.routing_map(mods, False, converters=self._get_converters())
return self._routing_map

View File

@ -3,7 +3,7 @@
##############################################################################
#
# OpenERP, Open Source Business Applications
# Copyright (C) 2004-2012 OpenERP S.A. (<http://openerp.com>).
# Copyright (C) 2004-2014 OpenERP S.A. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -29,7 +29,7 @@ import openerp.modules.registry
from openerp import SUPERUSER_ID
from openerp import tools
from openerp.osv import fields,osv
from openerp.osv.orm import Model
from openerp.osv.orm import Model, browse_null
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools import config
from openerp.tools.translate import _
@ -737,7 +737,7 @@ class ir_model_access(osv.osv):
msg_params = (model_name,)
_logger.warning('Access Denied by ACLs for operation: %s, uid: %s, model: %s', mode, uid, model_name)
msg = '%s %s' % (msg_heads[mode], msg_tail)
raise except_orm(_('Access Denied'), msg % msg_params)
raise openerp.exceptions.AccessError(msg % msg_params)
return r or False
__cache_clearing_methods = []
@ -853,24 +853,58 @@ class ir_model_data(osv.osv):
if not cr.fetchone():
cr.execute('CREATE INDEX ir_model_data_module_name_index ON ir_model_data (module, name)')
@tools.ormcache()
# NEW V8 API
@tools.ormcache(skiparg=3)
def xmlid_lookup(self, cr, uid, xmlid):
"""Low level xmlid lookup
Return (id, res_model, res_id) or raise ValueError if not found
"""
module, name = xmlid.split('.', 1)
ids = self.search(cr, uid, [('module','=',module), ('name','=', name)])
if not ids:
raise ValueError('External ID not found in the system: %s' % (xmlid))
# the sql constraints ensure us we have only one result
res = self.read(cr, uid, ids[0], ['model', 'res_id'])
if not res['res_id']:
raise ValueError('External ID not found in the system: %s' % (xmlid))
return ids[0], res['model'], res['res_id']
def xmlid_to_res_model_res_id(self, cr, uid, xmlid, raise_if_not_found=False):
""" Return (res_model, res_id)"""
try:
return self.xmlid_lookup(cr, uid, xmlid)[1:3]
except ValueError:
if raise_if_not_found:
raise
return (False, False)
def xmlid_to_res_id(self, cr, uid, xmlid, raise_if_not_found=False):
""" Returns res_id """
return self.xmlid_to_res_model_res_id(cr, uid, xmlid, raise_if_not_found)[1]
def xmlid_to_object(self, cr, uid, xmlid, raise_if_not_found=False, context=None):
""" Return a browse_record
if not found and raise_if_not_found is True return the browse_null
"""
t = self.xmlid_to_res_model_res_id(cr, uid, xmlid, raise_if_not_found)
res_model, res_id = t
if res_model and res_id:
record = self.pool[res_model].browse(cr, uid, res_id, context=context)
if record.exists():
return record
if raise_if_not_found:
raise ValueError('No record found for unique ID %s. It may have been deleted.' % (xml_id))
return browse_null()
# OLD API
def _get_id(self, cr, uid, module, xml_id):
"""Returns the id of the ir.model.data record corresponding to a given module and xml_id (cached) or raise a ValueError if not found"""
ids = self.search(cr, uid, [('module','=',module), ('name','=', xml_id)])
if not ids:
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
# the sql constraints ensure us we have only one result
return ids[0]
return self.xmlid_lookup(cr, uid, "%s.%s" % (module, xml_id))[0]
@tools.ormcache()
def get_object_reference(self, cr, uid, module, xml_id):
"""Returns (model, res_id) corresponding to a given module and xml_id (cached) or raise ValueError if not found"""
data_id = self._get_id(cr, uid, module, xml_id)
#assuming data_id is not False, as it was checked upstream
res = self.read(cr, uid, data_id, ['model', 'res_id'])
if not res['res_id']:
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
return res['model'], res['res_id']
return self.xmlid_lookup(cr, uid, "%s.%s" % (module, xml_id))[1:3]
def check_object_reference(self, cr, uid, module, xml_id, raise_on_access_error=False):
"""Returns (model, res_id) corresponding to a given module and xml_id (cached), if and only if the user has the necessary access rights
@ -885,12 +919,11 @@ class ir_model_data(osv.osv):
return model, False
def get_object(self, cr, uid, module, xml_id, context=None):
"""Returns a browsable record for the given module name and xml_id or raise ValueError if not found"""
res_model, res_id = self.get_object_reference(cr, uid, module, xml_id)
result = self.pool[res_model].browse(cr, uid, res_id, context=context)
if not result.exists():
raise ValueError('No record found for unique ID %s.%s. It may have been deleted.' % (module, xml_id))
return result
""" Returns a browsable record for the given module name and xml_id.
If not found, raise a ValueError or return a browse_null, depending
on the value of `raise_exception`.
"""
return self.xmlid_to_object(cr, uid, "%s.%s" % (module, xml_id), raise_if_not_found=True, context=context)
def _update_dummy(self,cr, uid, model, module, xml_id=False, store=True):
if not xml_id:
@ -907,8 +940,7 @@ class ir_model_data(osv.osv):
:returns: itself
"""
self._get_id.clear_cache(self)
self.get_object_reference.clear_cache(self)
self.xmlid_lookup.clear_cache(self)
return self
def unlink(self, cr, uid, ids, context=None):
@ -929,15 +961,17 @@ class ir_model_data(osv.osv):
return False
action_id = False
if xml_id:
cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model
cr.execute('''SELECT imd.id, imd.res_id, md.id, imd.model, imd.noupdate
FROM ir_model_data imd LEFT JOIN %s md ON (imd.res_id = md.id)
WHERE imd.module=%%s AND imd.name=%%s''' % model_obj._table,
(module, xml_id))
results = cr.fetchall()
for imd_id2,res_id2,real_id2,real_model in results:
for imd_id2,res_id2,real_id2,real_model,noupdate_imd in results:
# In update mode, do not update a record if it's ir.model.data is flagged as noupdate
if mode == 'update' and noupdate_imd:
return res_id2
if not real_id2:
self._get_id.clear_cache(self, uid, module, xml_id)
self.get_object_reference.clear_cache(self, uid, module, xml_id)
self.clear_caches()
cr.execute('delete from ir_model_data where id=%s', (imd_id2,))
res_id = False
else:

View File

@ -0,0 +1,850 @@
# -*- coding: utf-8 -*-
import collections
import cStringIO
import datetime
import json
import logging
import math
import re
import sys
import xml # FIXME use lxml and etree
import babel
import babel.dates
import werkzeug.utils
from PIL import Image
import openerp.tools
from openerp.tools.safe_eval import safe_eval as eval
from openerp.osv import osv, orm, fields
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
#--------------------------------------------------------------------
# QWeb template engine
#--------------------------------------------------------------------
class QWebException(Exception):
def __init__(self, message, **kw):
Exception.__init__(self, message)
self.qweb = dict(kw)
class QWebTemplateNotFound(QWebException):
pass
def convert_to_qweb_exception(etype=None, **kw):
if etype is None:
etype = QWebException
orig_type, original, tb = sys.exc_info()
try:
raise etype, original, tb
except etype, e:
for k, v in kw.items():
e.qweb[k] = v
# Will use `raise foo from bar` in python 3 and rename cause to __cause__
e.qweb['cause'] = original
return e
class QWebContext(dict):
def __init__(self, cr, uid, data, loader=None, templates=None, context=None):
self.cr = cr
self.uid = uid
self.loader = loader
self.templates = templates or {}
self.context = context
dic = dict(data)
super(QWebContext, self).__init__(dic)
self['defined'] = lambda key: key in self
def safe_eval(self, expr):
locals_dict = collections.defaultdict(lambda: None)
locals_dict.update(self)
locals_dict.pop('cr', None)
locals_dict.pop('loader', None)
return eval(expr, None, locals_dict, nocopy=True, locals_builtins=True)
def copy(self):
return QWebContext(self.cr, self.uid, dict.copy(self),
loader=self.loader,
templates=self.templates,
context=self.context)
def __copy__(self):
return self.copy()
class QWeb(orm.AbstractModel):
"""QWeb Xml templating engine
The templating engine use a very simple syntax based "magic" xml
attributes, to produce textual output (even non-xml).
The core magic attributes are:
flow attributes:
t-if t-foreach t-call
output attributes:
t-att t-raw t-esc t-trim
assignation attribute:
t-set
QWeb can be extended like any OpenERP model and new attributes can be
added.
If you need to customize t-fields rendering, subclass the ir.qweb.field
model (and its sub-models) then override :meth:`~.get_converter_for` to
fetch the right field converters for your qweb model.
Beware that if you need extensions or alterations which could be
incompatible with other subsystems, you should create a local object
inheriting from ``ir.qweb`` and customize that.
"""
_name = 'ir.qweb'
node = xml.dom.Node
_void_elements = frozenset([
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'keygen',
'link', 'menuitem', 'meta', 'param', 'source', 'track', 'wbr'])
_format_regex = re.compile(
'(?:'
# ruby-style pattern
'#\{(.+?)\}'
')|(?:'
# jinja-style pattern
'\{\{(.+?)\}\}'
')')
def __init__(self, pool, cr):
super(QWeb, self).__init__(pool, cr)
self._render_tag = self.prefixed_methods('render_tag_')
self._render_att = self.prefixed_methods('render_att_')
def prefixed_methods(self, prefix):
""" Extracts all methods prefixed by ``prefix``, and returns a mapping
of (t-name, method) where the t-name is the method name with prefix
removed and underscore converted to dashes
:param str prefix:
:return: dict
"""
n_prefix = len(prefix)
return dict(
(name[n_prefix:].replace('_', '-'), getattr(type(self), name))
for name in dir(self)
if name.startswith(prefix)
)
def register_tag(self, tag, func):
self._render_tag[tag] = func
def add_template(self, qwebcontext, name, node):
"""Add a parsed template in the context. Used to preprocess templates."""
qwebcontext.templates[name] = node
def load_document(self, document, qwebcontext):
"""
Loads an XML document and installs any contained template in the engine
"""
if hasattr(document, 'documentElement'):
dom = document
elif document.startswith("<?xml"):
dom = xml.dom.minidom.parseString(document)
else:
dom = xml.dom.minidom.parse(document)
for node in dom.documentElement.childNodes:
if node.nodeType == self.node.ELEMENT_NODE and node.getAttribute('t-name'):
name = str(node.getAttribute("t-name"))
self.add_template(qwebcontext, name, node)
def get_template(self, name, qwebcontext):
origin_template = qwebcontext.get('__caller__') or qwebcontext['__stack__'][0]
if qwebcontext.loader and name not in qwebcontext.templates:
try:
xml_doc = qwebcontext.loader(name)
except ValueError:
raise convert_to_qweb_exception(QWebTemplateNotFound, message="Loader could not find template %r" % name, template=origin_template)
self.load_document(xml_doc, qwebcontext=qwebcontext)
if name in qwebcontext.templates:
return qwebcontext.templates[name]
raise QWebTemplateNotFound("Template %r not found" % name, template=origin_template)
def eval(self, expr, qwebcontext):
try:
return qwebcontext.safe_eval(expr)
except Exception:
template = qwebcontext.get('__template__')
raise convert_to_qweb_exception(message="Could not evaluate expression %r" % expr, expression=expr, template=template)
def eval_object(self, expr, qwebcontext):
return self.eval(expr, qwebcontext)
def eval_str(self, expr, qwebcontext):
if expr == "0":
return qwebcontext.get(0, '')
val = self.eval(expr, qwebcontext)
if isinstance(val, unicode):
return val.encode("utf8")
if val is False or val is None:
return ''
return str(val)
def eval_format(self, expr, qwebcontext):
expr, replacements = self._format_regex.subn(
lambda m: self.eval_str(m.group(1) or m.group(2), qwebcontext),
expr
)
if replacements:
return expr
try:
return str(expr % qwebcontext)
except Exception:
template = qwebcontext.get('__template__')
raise convert_to_qweb_exception(message="Format error for expression %r" % expr, expression=expr, template=template)
def eval_bool(self, expr, qwebcontext):
return int(bool(self.eval(expr, qwebcontext)))
def render(self, cr, uid, id_or_xml_id, qwebcontext=None, loader=None, context=None):
if qwebcontext is None:
qwebcontext = {}
if not isinstance(qwebcontext, QWebContext):
qwebcontext = QWebContext(cr, uid, qwebcontext, loader=loader, context=context)
qwebcontext['__template__'] = id_or_xml_id
stack = qwebcontext.get('__stack__', [])
if stack:
qwebcontext['__caller__'] = stack[-1]
stack.append(id_or_xml_id)
qwebcontext['__stack__'] = stack
qwebcontext['xmlid'] = str(stack[0]) # Temporary fix
return self.render_node(self.get_template(id_or_xml_id, qwebcontext), qwebcontext)
def render_node(self, element, qwebcontext):
result = ""
if element.nodeType == self.node.TEXT_NODE or element.nodeType == self.node.CDATA_SECTION_NODE:
result = element.data.encode("utf8")
elif element.nodeType == self.node.ELEMENT_NODE:
generated_attributes = ""
t_render = None
template_attributes = {}
for (attribute_name, attribute_value) in element.attributes.items():
attribute_name = str(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
can_see = self.user_has_groups(cr, uid, groups=attribute_value)
if not can_see:
return ''
continue
if isinstance(attribute_value, unicode):
attribute_value = attribute_value.encode("utf8")
else:
attribute_value = attribute_value.nodeValue.encode("utf8")
if attribute_name.startswith("t-"):
for attribute in self._render_att:
if attribute_name[2:].startswith(attribute):
att, val = self._render_att[attribute](self, element, attribute_name, attribute_value, qwebcontext)
generated_attributes += val and ' %s="%s"' % (att, werkzeug.utils.escape(val)) or " "
break
else:
if attribute_name[2:] in self._render_tag:
t_render = attribute_name[2:]
template_attributes[attribute_name[2:]] = attribute_value
else:
generated_attributes += ' %s="%s"' % (attribute_name, werkzeug.utils.escape(attribute_value))
if 'debug' in template_attributes:
debugger = template_attributes.get('debug', 'pdb')
__import__(debugger).set_trace() # pdb, ipdb, pudb, ...
if t_render:
result = self._render_tag[t_render](self, element, template_attributes, generated_attributes, qwebcontext)
else:
result = self.render_element(element, template_attributes, generated_attributes, qwebcontext)
if isinstance(result, unicode):
return result.encode('utf-8')
return result
def render_element(self, element, template_attributes, generated_attributes, qwebcontext, inner=None):
# element: element
# template_attributes: t-* attributes
# generated_attributes: generated attributes
# qwebcontext: values
# inner: optional innerXml
if inner:
g_inner = inner
else:
g_inner = []
for current_node in element.childNodes:
try:
g_inner.append(self.render_node(current_node, qwebcontext))
except QWebException:
raise
except Exception:
template = qwebcontext.get('__template__')
raise convert_to_qweb_exception(message="Could not render element %r" % element.nodeName, node=element, template=template)
name = str(element.nodeName)
inner = "".join(g_inner)
trim = template_attributes.get("trim", 0)
if trim == 0:
pass
elif trim == 'left':
inner = inner.lstrip()
elif trim == 'right':
inner = inner.rstrip()
elif trim == 'both':
inner = inner.strip()
if name == "t":
return inner
elif len(inner) or name not in self._void_elements:
return "<%s%s>%s</%s>" % tuple(
qwebcontext if isinstance(qwebcontext, str) else qwebcontext.encode('utf-8')
for qwebcontext in (name, generated_attributes, inner, name)
)
else:
return "<%s%s/>" % (name, generated_attributes)
# Attributes
def render_att_att(self, element, attribute_name, attribute_value, qwebcontext):
if attribute_name.startswith("t-attf-"):
att, val = attribute_name[7:], self.eval_format(attribute_value, qwebcontext)
elif attribute_name.startswith("t-att-"):
att, val = attribute_name[6:], self.eval(attribute_value, qwebcontext)
if isinstance(val, unicode):
val = val.encode("utf8")
else:
att, val = self.eval_object(attribute_value, qwebcontext)
return att, val
# Tags
def render_tag_raw(self, element, template_attributes, generated_attributes, qwebcontext):
inner = self.eval_str(template_attributes["raw"], qwebcontext)
return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner)
def render_tag_esc(self, element, template_attributes, generated_attributes, qwebcontext):
inner = werkzeug.utils.escape(self.eval_str(template_attributes["esc"], qwebcontext))
return self.render_element(element, template_attributes, generated_attributes, qwebcontext, inner)
def render_tag_foreach(self, element, template_attributes, generated_attributes, qwebcontext):
expr = template_attributes["foreach"]
enum = self.eval_object(expr, qwebcontext)
if enum is not None:
var = template_attributes.get('as', expr).replace('.', '_')
copy_qwebcontext = qwebcontext.copy()
size = -1
if isinstance(enum, (list, tuple)):
size = len(enum)
elif hasattr(enum, 'count'):
size = enum.count()
copy_qwebcontext["%s_size" % var] = size
copy_qwebcontext["%s_all" % var] = enum
index = 0
ru = []
for i in enum:
copy_qwebcontext["%s_value" % var] = i
copy_qwebcontext["%s_index" % var] = index
copy_qwebcontext["%s_first" % var] = index == 0
copy_qwebcontext["%s_even" % var] = index % 2
copy_qwebcontext["%s_odd" % var] = (index + 1) % 2
copy_qwebcontext["%s_last" % var] = index + 1 == size
if index % 2:
copy_qwebcontext["%s_parity" % var] = 'odd'
else:
copy_qwebcontext["%s_parity" % var] = 'even'
if 'as' in template_attributes:
copy_qwebcontext[var] = i
elif isinstance(i, dict):
copy_qwebcontext.update(i)
ru.append(self.render_element(element, template_attributes, generated_attributes, copy_qwebcontext))
index += 1
return "".join(ru)
else:
template = qwebcontext.get('__template__')
raise QWebException("foreach enumerator %r is not defined while rendering template %r" % (expr, template), template=template)
def render_tag_if(self, element, template_attributes, generated_attributes, qwebcontext):
if self.eval_bool(template_attributes["if"], qwebcontext):
return self.render_element(element, template_attributes, generated_attributes, qwebcontext)
return ""
def render_tag_call(self, element, template_attributes, generated_attributes, qwebcontext):
d = qwebcontext.copy()
d[0] = self.render_element(element, template_attributes, generated_attributes, d)
cr = d.get('request') and d['request'].cr or None
uid = d.get('request') and d['request'].uid or None
return self.render(cr, uid, self.eval_format(template_attributes["call"], d), d)
def render_tag_set(self, element, template_attributes, generated_attributes, qwebcontext):
if "value" in template_attributes:
qwebcontext[template_attributes["set"]] = self.eval_object(template_attributes["value"], qwebcontext)
elif "valuef" in template_attributes:
qwebcontext[template_attributes["set"]] = self.eval_format(template_attributes["valuef"], qwebcontext)
else:
qwebcontext[template_attributes["set"]] = self.render_element(element, template_attributes, generated_attributes, qwebcontext)
return ""
def render_tag_field(self, element, template_attributes, generated_attributes, qwebcontext):
""" eg: <span t-record="browse_record(res.partner, 1)" t-field="phone">+1 555 555 8069</span>"""
node_name = element.nodeName
assert node_name not in ("table", "tbody", "thead", "tfoot", "tr", "td",
"li", "ul", "ol", "dl", "dt", "dd"),\
"RTE widgets do not work correctly on %r elements" % node_name
assert node_name != 't',\
"t-field can not be used on a t element, provide an actual HTML node"
record, field_name = template_attributes["field"].rsplit('.', 1)
record = self.eval_object(record, qwebcontext)
column = record._model._all_columns[field_name].column
options = json.loads(template_attributes.get('field-options') or '{}')
field_type = get_field_type(column, options)
converter = self.get_converter_for(field_type)
return converter.to_html(qwebcontext.cr, qwebcontext.uid, field_name, record, options,
element, template_attributes, generated_attributes, qwebcontext, context=qwebcontext.context)
def get_converter_for(self, field_type):
return self.pool.get('ir.qweb.field.' + field_type,
self.pool['ir.qweb.field'])
#--------------------------------------------------------------------
# QWeb Fields converters
#--------------------------------------------------------------------
class FieldConverter(osv.AbstractModel):
""" Used to convert a t-field specification into an output HTML field.
:meth:`~.to_html` is the entry point of this conversion from QWeb, it:
* converts the record value to html using :meth:`~.record_to_html`
* generates the metadata attributes (``data-oe-``) to set on the root
result node
* generates the root result node itself through :meth:`~.render_element`
"""
_name = 'ir.qweb.field'
def attributes(self, cr, uid, field_name, record, options,
source_element, g_att, t_att, qweb_context,
context=None):
"""
Generates the metadata attributes (prefixed by ``data-oe-`` for the
root node of the field conversion. Attribute values are escaped by the
parent using ``werkzeug.utils.escape``.
The default attributes are:
* ``model``, the name of the record's model
* ``id`` the id of the record to which the field belongs
* ``field`` the name of the converted field
* ``type`` the logical field type (widget, may not match the column's
``type``, may not be any _column subclass name)
* ``translate``, a boolean flag (``0`` or ``1``) denoting whether the
column is translatable
* ``expression``, the original expression
:returns: iterable of (attribute name, attribute value) pairs.
"""
column = record._model._all_columns[field_name].column
field_type = get_field_type(column, options)
return [
('data-oe-model', record._model._name),
('data-oe-id', record.id),
('data-oe-field', field_name),
('data-oe-type', field_type),
('data-oe-expression', t_att['field']),
]
def value_to_html(self, cr, uid, value, column, options=None, context=None):
""" Converts a single value to its HTML version/output
"""
if not value: return ''
return value
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
""" Converts the specified field of the browse_record ``record`` to
HTML
"""
return self.value_to_html(
cr, uid, record[field_name], column, options=options, context=context)
def to_html(self, cr, uid, field_name, record, options,
source_element, t_att, g_att, qweb_context, context=None):
""" Converts a ``t-field`` to its HTML output. A ``t-field`` may be
extended by a ``t-field-options``, which is a JSON-serialized mapping
of configuration values.
A default configuration key is ``widget`` which can override the
field's own ``_type``.
"""
content = None
try:
content = self.record_to_html(
cr, uid, field_name, record,
record._model._all_columns[field_name].column,
options, context=context)
if options.get('html-escape', True):
content = werkzeug.utils.escape(content)
elif hasattr(content, '__html__'):
content = content.__html__()
except Exception:
_logger.warning("Could not get field %s for model %s",
field_name, record._model._name, exc_info=True)
content = None
g_att += ''.join(
' %s="%s"' % (name, werkzeug.utils.escape(value))
for name, value in self.attributes(
cr, uid, field_name, record, options,
source_element, g_att, t_att, qweb_context)
)
return self.render_element(cr, uid, source_element, t_att, g_att,
qweb_context, content)
def qweb_object(self):
return self.pool['ir.qweb']
def render_element(self, cr, uid, source_element, t_att, g_att,
qweb_context, content):
""" Final rendering hook, by default just calls ir.qweb's ``render_element``
"""
return self.qweb_object().render_element(
source_element, t_att, g_att, qweb_context, content or '')
def user_lang(self, cr, uid, context):
"""
Fetches the res.lang object corresponding to the language code stored
in the user's context. Fallbacks to en_US if no lang is present in the
context *or the language code is not valid*.
:returns: res.lang browse_record
"""
if context is None: context = {}
lang_code = context.get('lang') or 'en_US'
Lang = self.pool['res.lang']
lang_ids = Lang.search(cr, uid, [('code', '=', lang_code)], context=context) \
or Lang.search(cr, uid, [('code', '=', 'en_US')], context=context)
return Lang.browse(cr, uid, lang_ids[0], context=context)
class FloatConverter(osv.AbstractModel):
_name = 'ir.qweb.field.float'
_inherit = 'ir.qweb.field'
def precision(self, cr, uid, column, options=None, context=None):
_, precision = column.digits or (None, None)
return precision
def value_to_html(self, cr, uid, value, column, options=None, context=None):
if context is None:
context = {}
precision = self.precision(cr, uid, column, options=options, context=context)
fmt = '%f' if precision is None else '%.{precision}f'
lang_code = context.get('lang') or 'en_US'
lang = self.pool['res.lang']
formatted = lang.format(cr, uid, [lang_code], fmt.format(precision=precision), value, grouping=True)
# %f does not strip trailing zeroes. %g does but its precision causes
# it to switch to scientific notation starting at a million *and* to
# strip decimals. So use %f and if no precision was specified manually
# strip trailing 0.
if not precision:
formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)
return formatted
class DateConverter(osv.AbstractModel):
_name = 'ir.qweb.field.date'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
if not value: return ''
lang = self.user_lang(cr, uid, context=context)
locale = babel.Locale.parse(lang.code)
if isinstance(value, basestring):
value = datetime.datetime.strptime(
value, openerp.tools.DEFAULT_SERVER_DATE_FORMAT)
if options and 'format' in options:
pattern = options['format']
else:
strftime_pattern = lang.date_format
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
return babel.dates.format_datetime(
value, format=pattern,
locale=locale)
class DateTimeConverter(osv.AbstractModel):
_name = 'ir.qweb.field.datetime'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
if not value: return ''
lang = self.user_lang(cr, uid, context=context)
locale = babel.Locale.parse(lang.code)
if isinstance(value, basestring):
value = datetime.datetime.strptime(
value, openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT)
value = column.context_timestamp(
cr, uid, timestamp=value, context=context)
if options and 'format' in options:
pattern = options['format']
else:
strftime_pattern = (u"%s %s" % (lang.date_format, lang.time_format))
pattern = openerp.tools.posix_to_ldml(strftime_pattern, locale=locale)
return babel.dates.format_datetime(value, format=pattern, locale=locale)
class TextConverter(osv.AbstractModel):
_name = 'ir.qweb.field.text'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
"""
Escapes the value and converts newlines to br. This is bullshit.
"""
if not value: return ''
return nl2br(value, options=options)
class SelectionConverter(osv.AbstractModel):
_name = 'ir.qweb.field.selection'
_inherit = 'ir.qweb.field'
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
value = record[field_name]
if not value: return ''
selection = dict(fields.selection.reify(
cr, uid, record._model, column))
return self.value_to_html(
cr, uid, selection[value], column, options=options)
class ManyToOneConverter(osv.AbstractModel):
_name = 'ir.qweb.field.many2one'
_inherit = 'ir.qweb.field'
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
[read] = record.read([field_name])
if not read[field_name]: return ''
_, value = read[field_name]
return nl2br(value, options=options)
class HTMLConverter(osv.AbstractModel):
_name = 'ir.qweb.field.html'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
return HTMLSafe(value or '')
class ImageConverter(osv.AbstractModel):
""" ``image`` widget rendering, inserts a data:uri-using image tag in the
document. May be overridden by e.g. the website module to generate links
instead.
.. todo:: what happens if different output need different converters? e.g.
reports may need embedded images or FS links whereas website
needs website-aware
"""
_name = 'ir.qweb.field.image'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
try:
image = Image.open(cStringIO.StringIO(value.decode('base64')))
image.verify()
except IOError:
raise ValueError("Non-image binary fields can not be converted to HTML")
except: # image.verify() throws "suitable exceptions", I have no idea what they are
raise ValueError("Invalid image content")
return HTMLSafe('<img src="data:%s;base64,%s">' % (Image.MIME[image.format], value))
class MonetaryConverter(osv.AbstractModel):
""" ``monetary`` converter, has a mandatory option
``display_currency``.
The currency is used for formatting *and rounding* of the float value. It
is assumed that the linked res_currency has a non-empty rounding value and
res.currency's ``round`` method is used to perform rounding.
.. note:: the monetary converter internally adds the qweb context to its
options mapping, so that the context is available to callees.
It's set under the ``_qweb_context`` key.
"""
_name = 'ir.qweb.field.monetary'
_inherit = 'ir.qweb.field'
def to_html(self, cr, uid, field_name, record, options,
source_element, t_att, g_att, qweb_context, context=None):
options['_qweb_context'] = qweb_context
return super(MonetaryConverter, self).to_html(
cr, uid, field_name, record, options,
source_element, t_att, g_att, qweb_context, context=context)
def record_to_html(self, cr, uid, field_name, record, column, options, context=None):
if context is None:
context = {}
Currency = self.pool['res.currency']
display = self.display_currency(cr, uid, options)
# lang.format mandates a sprintf-style format. These formats are non-
# minimal (they have a default fixed precision instead), and
# lang.format will not set one by default. currency.round will not
# provide one either. So we need to generate a precision value
# (integer > 0) from the currency's rounding (a float generally < 1.0).
#
# The log10 of the rounding should be the number of digits involved if
# negative, if positive clamp to 0 digits and call it a day.
# nb: int() ~ floor(), we want nearest rounding instead
precision = int(round(math.log10(display.rounding)))
fmt = "%.{0}f".format(-precision if precision < 0 else 0)
lang_code = context.get('lang') or 'en_US'
lang = self.pool['res.lang']
formatted_amount = lang.format(cr, uid, [lang_code],
fmt, Currency.round(cr, uid, display, record[field_name]),
grouping=True, monetary=True)
pre = post = u''
if display.position == 'before':
pre = u'{symbol} '
else:
post = u' {symbol}'
return HTMLSafe(u'{pre}<span class="oe_currency_value">{0}</span>{post}'.format(
formatted_amount,
pre=pre, post=post,
).format(
symbol=display.symbol,
))
def display_currency(self, cr, uid, options):
return self.qweb_object().eval_object(
options['display_currency'], options['_qweb_context'])
TIMEDELTA_UNITS = (
('year', 3600 * 24 * 365),
('month', 3600 * 24 * 30),
('week', 3600 * 24 * 7),
('day', 3600 * 24),
('hour', 3600),
('minute', 60),
('second', 1)
)
class DurationConverter(osv.AbstractModel):
""" ``duration`` converter, to display integral or fractional values as
human-readable time spans (e.g. 1.5 as "1 hour 30 minutes").
Can be used on any numerical field.
Has a mandatory option ``unit`` which can be one of ``second``, ``minute``,
``hour``, ``day``, ``week`` or ``year``, used to interpret the numerical
field value before converting it.
Sub-second values will be ignored.
"""
_name = 'ir.qweb.field.duration'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
units = dict(TIMEDELTA_UNITS)
if value < 0:
raise ValueError(_("Durations can't be negative"))
if not options or options.get('unit') not in units:
raise ValueError(_("A unit must be provided to duration widgets"))
locale = babel.Locale.parse(
self.user_lang(cr, uid, context=context).code)
factor = units[options['unit']]
sections = []
r = value * factor
for unit, secs_per_unit in TIMEDELTA_UNITS:
v, r = divmod(r, secs_per_unit)
if not v: continue
section = babel.dates.format_timedelta(
v*secs_per_unit, threshold=1, locale=locale)
if section:
sections.append(section)
return u' '.join(sections)
class RelativeDatetimeConverter(osv.AbstractModel):
_name = 'ir.qweb.field.relative'
_inherit = 'ir.qweb.field'
def value_to_html(self, cr, uid, value, column, options=None, context=None):
parse_format = openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT
locale = babel.Locale.parse(
self.user_lang(cr, uid, context=context).code)
if isinstance(value, basestring):
value = datetime.datetime.strptime(value, parse_format)
# value should be a naive datetime in UTC. So is fields.datetime.now()
reference = datetime.datetime.strptime(column.now(), parse_format)
return babel.dates.format_timedelta(
value - reference, add_direction=True, locale=locale)
class HTMLSafe(object):
""" HTMLSafe string wrapper, Werkzeug's escape() has special handling for
objects with a ``__html__`` methods but AFAIK does not provide any such
object.
Wrapping a string in HTML will prevent its escaping
"""
__slots__ = ['string']
def __init__(self, string):
self.string = string
def __html__(self):
return self.string
def __str__(self):
s = self.string
if isinstance(s, unicode):
return s.encode('utf-8')
return s
def __unicode__(self):
s = self.string
if isinstance(s, str):
return s.decode('utf-8')
return s
def nl2br(string, options=None):
""" Converts newlines to HTML linebreaks in ``string``. Automatically
escapes content unless options['html-escape'] is set to False, and returns
the result wrapped in an HTMLSafe object.
:param str string:
:param dict options:
:rtype: HTMLSafe
"""
if options is None: options = {}
if options.get('html-escape', True):
string = werkzeug.utils.escape(string)
return HTMLSafe(string.replace('\n', '<br>\n'))
def get_field_type(column, options):
""" Gets a t-field's effective type from the field's column and its options
"""
return options.get('widget', column._type)
# vim:et:

View File

@ -268,13 +268,8 @@ class ir_translation(osv.osv):
return translations
def _set_ids(self, cr, uid, name, tt, lang, ids, value, src=None):
# clear the caches
tr = self._get_ids(cr, uid, name, tt, lang, ids)
for res_id in tr:
if tr[res_id]:
self._get_source.clear_cache(self, uid, name, tt, lang, tr[res_id])
self._get_ids.clear_cache(self, uid, name, tt, lang, res_id)
self._get_source.clear_cache(self, uid, name, tt, lang)
self._get_ids.clear_cache(self)
self._get_source.clear_cache(self)
cr.execute('delete from ir_translation '
'where lang=%s '
@ -294,7 +289,7 @@ class ir_translation(osv.osv):
return len(ids)
@tools.ormcache(skiparg=3)
def _get_source(self, cr, uid, name, types, lang, source=None):
def _get_source(self, cr, uid, name, types, lang, source=None, res_id=None):
"""
Returns the translation for the given combination of name, type, language
and source. All values passed to this method should be unicode (not byte strings),
@ -304,6 +299,7 @@ class ir_translation(osv.osv):
:param types: single string defining type of term to translate (see ``type`` field on ir.translation), or sequence of allowed types (strings)
:param lang: language code of the desired translation
:param source: optional source term to translate (should be unicode)
:param res_id: optional resource id to translate (if used, ``source`` should be set)
:rtype: unicode
:return: the request translation, or an empty unicode string if no translation was
found and `source` was not passed
@ -321,6 +317,9 @@ class ir_translation(osv.osv):
AND type in %s
AND src=%s"""
params = (lang or '', types, tools.ustr(source))
if res_id:
query += "AND res_id=%s"
params += (res_id,)
if name:
query += " AND name=%s"
params += (tools.ustr(name),)
@ -342,8 +341,9 @@ class ir_translation(osv.osv):
if context is None:
context = {}
ids = super(ir_translation, self).create(cr, uid, vals, context=context)
self._get_source.clear_cache(self, uid, vals.get('name',0), vals.get('type',0), vals.get('lang',0), vals.get('src',0))
self._get_ids.clear_cache(self, uid, vals.get('name',0), vals.get('type',0), vals.get('lang',0), vals.get('res_id',0))
self._get_source.clear_cache(self)
self._get_ids.clear_cache(self)
self.pool['ir.ui.view'].clear_cache()
return ids
def write(self, cursor, user, ids, vals, context=None):
@ -356,9 +356,9 @@ class ir_translation(osv.osv):
if vals.get('value'):
vals.update({'state':'translated'})
result = super(ir_translation, self).write(cursor, user, ids, vals, context=context)
for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
self._get_source.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['src'])
self._get_ids.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['res_id'])
self._get_source.clear_cache(self)
self._get_ids.clear_cache(self)
self.pool['ir.ui.view'].clear_cache()
return result
def unlink(self, cursor, user, ids, context=None):
@ -366,9 +366,9 @@ class ir_translation(osv.osv):
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
self._get_source.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['src'])
self._get_ids.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['res_id'])
self._get_source.clear_cache(self)
self._get_ids.clear_cache(self)
result = super(ir_translation, self).unlink(cursor, user, ids, context=context)
return result

View File

@ -14,7 +14,7 @@
domain="[('comments', 'like', 'openerp-web')]"/>
<field name="name" operator="="/>
<field name="lang"/>
<field name="source"/>
<field name="src"/>
<field name="value"/>
</search>
</field>

View File

@ -18,20 +18,43 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import collections
import copy
import fnmatch
import logging
from lxml import etree
from operator import itemgetter
import os
import simplejson
import werkzeug
import HTMLParser
import openerp
from openerp import tools
from openerp.osv import fields,osv
from openerp.tools import graph
from openerp.http import request
from openerp.osv import fields, osv, orm
from openerp.tools import graph, SKIPPED_ELEMENT_TYPES
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.view_validation import valid_view
from openerp.tools import misc
from openerp.tools.translate import _
_logger = logging.getLogger(__name__)
MOVABLE_BRANDING = ['data-oe-model', 'data-oe-id', 'data-oe-field', 'data-oe-xpath']
def keep_query(*args, **kw):
if not args and not kw:
args = ('*',)
params = kw.copy()
query_params = frozenset(werkzeug.url_decode(request.httprequest.query_string).keys())
for keep_param in args:
for param in fnmatch.filter(query_params, keep_param):
if param not in params and param in request.params:
params[param] = request.params[param]
return werkzeug.urls.url_encode(params)
class view_custom(osv.osv):
_name = 'ir.ui.view.custom'
_order = 'create_date desc' # search(limit=1) should return the last customization
@ -50,59 +73,45 @@ class view_custom(osv.osv):
class view(osv.osv):
_name = 'ir.ui.view'
def _type_field(self, cr, uid, ids, name, args, context=None):
result = {}
for record in self.browse(cr, uid, ids, context):
# Get the type from the inherited view if any.
if record.inherit_id:
result[record.id] = record.inherit_id.type
else:
result[record.id] = etree.fromstring(record.arch.encode('utf8')).tag
def _get_model_data(self, cr, uid, ids, *args, **kwargs):
ir_model_data = self.pool.get('ir.model.data')
data_ids = ir_model_data.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)])
result = dict(zip(ids, data_ids))
return result
_columns = {
'name': fields.char('View Name', required=True),
'model': fields.char('Object', size=64, required=True, select=True),
'model': fields.char('Object', select=True),
'priority': fields.integer('Sequence', required=True),
'type': fields.function(_type_field, type='selection', selection=[
'type': fields.selection([
('tree','Tree'),
('form','Form'),
('mdx','mdx'),
('graph', 'Graph'),
('calendar', 'Calendar'),
('diagram','Diagram'),
('gantt', 'Gantt'),
('kanban', 'Kanban'),
('search','Search')], string='View Type', required=True, select=True, store=True),
('search','Search'),
('qweb', 'QWeb')], string='View Type'),
'arch': fields.text('View Architecture', required=True),
'inherit_id': fields.many2one('ir.ui.view', 'Inherited View', ondelete='cascade', select=True),
'field_parent': fields.char('Child Field',size=64),
'inherit_children_ids': fields.one2many('ir.ui.view','inherit_id', 'Inherit Views'),
'field_parent': fields.char('Child Field'),
'model_data_id': fields.function(_get_model_data, type='many2one', relation='ir.model.data', string="Model Data", store=True),
'xml_id': fields.function(osv.osv.get_xml_id, type='char', size=128, string="External ID",
help="ID of the view defined in xml file"),
'groups_id': fields.many2many('res.groups', 'ir_ui_view_group_rel', 'view_id', 'group_id',
string='Groups', help="If this field is empty, the view applies to all users. Otherwise, the view applies to the users of those groups only."),
'model_ids': fields.one2many('ir.model.data', 'res_id', domain=[('model','=','ir.ui.view')], auto_join=True),
}
_defaults = {
'arch': '<?xml version="1.0"?>\n<tree string="My view">\n\t<field name="name"/>\n</tree>',
'priority': 16,
'type': 'tree',
}
_order = "priority,name"
# Holds the RNG schema
_relaxng_validator = None
def create(self, cr, uid, values, context=None):
if 'type' in values:
_logger.warning("Setting the `type` field is deprecated in the `ir.ui.view` model.")
if not values.get('name'):
if values.get('inherit_id'):
inferred_type = self.browse(cr, uid, values['inherit_id'], context).type
else:
inferred_type = etree.fromstring(values['arch'].encode('utf8')).tag
values['name'] = "%s %s" % (values['model'], inferred_type)
return super(view, self).create(cr, uid, values, context)
def _relaxng(self):
if not self._relaxng_validator:
frng = tools.file_open(os.path.join('base','rng','view.rng'))
@ -115,59 +124,37 @@ class view(osv.osv):
frng.close()
return self._relaxng_validator
def _check_render_view(self, cr, uid, view, context=None):
"""Verify that the given view's hierarchy is valid for rendering, along with all the changes applied by
its inherited views, by rendering it using ``fields_view_get()``.
@param browse_record view: view to validate
@return: the rendered definition (arch) of the view, always utf-8 bytestring (legacy convention)
if no error occurred, else False.
"""
if view.model not in self.pool:
return False
try:
fvg = self.pool[view.model].fields_view_get(cr, uid, view_id=view.id, view_type=view.type, context=context)
return fvg['arch']
except Exception:
_logger.exception('cannot render view %s', view.xml_id)
return False
def _check_xml(self, cr, uid, ids, context=None):
if context is None:
context = {}
context['check_view_ids'] = ids
context = dict(context, check_view_ids=ids)
# Sanity checks: the view should not break anything upon rendering!
# Any exception raised below will cause a transaction rollback.
for view in self.browse(cr, uid, ids, context):
# Sanity check: the view should not break anything upon rendering!
view_arch_utf8 = self._check_render_view(cr, uid, view, context=context)
# always utf-8 bytestring - legacy convention
if not view_arch_utf8: return False
# RNG-based validation is not possible anymore with 7.0 forms
# TODO 7.0: provide alternative assertion-based validation of view_arch_utf8
view_docs = [etree.fromstring(view_arch_utf8)]
if view_docs[0].tag == 'data':
# A <data> element is a wrapper for multiple root nodes
view_docs = view_docs[0]
validator = self._relaxng()
for view_arch in view_docs:
if (view_arch.get('version') < '7.0') and validator and not validator.validate(view_arch):
for error in validator.error_log:
_logger.error(tools.ustr(error))
return False
if not valid_view(view_arch):
return False
return True
def _check_model(self, cr, uid, ids, context=None):
for view in self.browse(cr, uid, ids, context):
if view.model not in self.pool:
return False
view_def = self.read_combined(cr, uid, view.id, None, context=context)
view_arch_utf8 = view_def['arch']
if view.type != 'qweb':
view_doc = etree.fromstring(view_arch_utf8)
# verify that all fields used are valid, etc.
self.postprocess_and_fields(cr, uid, view.model, view_doc, view.id, context=context)
# RNG-based validation is not possible anymore with 7.0 forms
view_docs = [view_doc]
if view_docs[0].tag == 'data':
# A <data> element is a wrapper for multiple root nodes
view_docs = view_docs[0]
validator = self._relaxng()
for view_arch in view_docs:
if (view_arch.get('version') < '7.0') and validator and not validator.validate(view_arch):
for error in validator.error_log:
_logger.error(tools.ustr(error))
return False
if not valid_view(view_arch):
return False
return True
_constraints = [
(_check_model, 'The model name does not exist.', ['model']),
(_check_xml, 'The model name does not exist or the view architecture cannot be rendered.', ['arch', 'model']),
(_check_xml, 'Invalid view definition', ['arch'])
]
def _auto_init(self, cr, context=None):
@ -176,6 +163,73 @@ class view(osv.osv):
if not cr.fetchone():
cr.execute('CREATE INDEX ir_ui_view_model_type_inherit_id ON ir_ui_view (model, inherit_id)')
def create(self, cr, uid, values, context=None):
if 'type' not in values:
if values.get('inherit_id'):
values['type'] = self.browse(cr, uid, values['inherit_id'], context).type
else:
values['type'] = etree.fromstring(values['arch']).tag
if not values.get('name'):
values['name'] = "%s %s" % (values['model'], values['type'])
self.read_template.clear_cache(self)
return super(view, self).create(cr, uid, values, context)
def write(self, cr, uid, ids, vals, context=None):
if not isinstance(ids, (list, tuple)):
ids = [ids]
if context is None:
context = {}
# drop the corresponding view customizations (used for dashboards for example), otherwise
# not all users would see the updated views
custom_view_ids = self.pool.get('ir.ui.view.custom').search(cr, uid, [('ref_id', 'in', ids)])
if custom_view_ids:
self.pool.get('ir.ui.view.custom').unlink(cr, uid, custom_view_ids)
self.read_template.clear_cache(self)
ret = super(view, self).write(cr, uid, ids, vals, context)
# if arch is modified views become noupdatable
if 'arch' in vals and not context.get('install_mode', False):
# TODO: should be doable in a read and a write
for view_ in self.browse(cr, uid, ids, context=context):
if view_.model_data_id:
self.pool.get('ir.model.data').write(cr, openerp.SUPERUSER_ID, view_.model_data_id.id, {'noupdate': True})
return ret
def copy(self, cr, uid, id, default=None, context=None):
if not default:
default = {}
default.update({
'model_ids': [],
})
return super(view, self).copy(cr, uid, id, default, context=context)
# default view selection
def default_view(self, cr, uid, model, view_type, context=None):
""" Fetches the default view for the provided (model, view_type) pair:
view with no parent (inherit_id=Fase) with the lowest priority.
:param str model:
:param int view_type:
:return: id of the default view of False if none found
:rtype: int
"""
domain = [
['model', '=', model],
['type', '=', view_type],
['inherit_id', '=', False],
]
ids = self.search(cr, uid, domain, limit=1, order='priority', context=context)
if not ids:
return False
return ids[0]
#------------------------------------------------------
# Inheritance mecanism
#------------------------------------------------------
def get_inheriting_views_arch(self, cr, uid, view_id, model, context=None):
"""Retrieves the architecture of views that inherit from the given view, from the sets of
views that should currently be used in the system. During the module upgrade phase it
@ -185,43 +239,611 @@ class view(osv.osv):
after the module initialization phase is completely finished.
:param int view_id: id of the view whose inheriting views should be retrieved
:param str model: model identifier of the view's related model (for double-checking)
:param str model: model identifier of the inheriting views.
:rtype: list of tuples
:return: [(view_arch,view_id), ...]
"""
user_groups = frozenset(self.pool.get('res.users').browse(cr, 1, uid, context).groups_id)
check_view_ids = context and context.get('check_view_ids') or (0,)
conditions = [['inherit_id', '=', view_id], ['model', '=', model]]
if self.pool._init:
# Module init currently in progress, only consider views from modules whose code was already loaded
check_view_ids = context and context.get('check_view_ids') or (0,)
query = """SELECT v.id FROM ir_ui_view v LEFT JOIN ir_model_data md ON (md.model = 'ir.ui.view' AND md.res_id = v.id)
WHERE v.inherit_id=%s AND v.model=%s AND (md.module in %s OR v.id in %s)
ORDER BY priority"""
query_params = (view_id, model, tuple(self.pool._init_modules), tuple(check_view_ids))
else:
# Modules fully loaded, consider all views
query = """SELECT v.id FROM ir_ui_view v
WHERE v.inherit_id=%s AND v.model=%s
ORDER BY priority"""
query_params = (view_id, model)
cr.execute(query, query_params)
view_ids = [v[0] for v in cr.fetchall()]
# filter views based on user groups
# Module init currently in progress, only consider views from
# modules whose code is already loaded
conditions.extend([
'|',
['model_ids.module', 'in', tuple(self.pool._init_modules)],
['id', 'in', check_view_ids],
])
view_ids = self.search(cr, uid, conditions, context=context)
return [(view.arch, view.id)
for view in self.browse(cr, 1, view_ids, context)
if not (view.groups_id and user_groups.isdisjoint(view.groups_id))]
def write(self, cr, uid, ids, vals, context=None):
if not isinstance(ids, (list, tuple)):
ids = [ids]
def raise_view_error(self, cr, uid, message, view_id, context=None):
view = self.browse(cr, uid, view_id, context)
not_avail = _('n/a')
message = ("%(msg)s\n\n" +
_("Error context:\nView `%(view_name)s`") +
"\n[view_id: %(viewid)s, xml_id: %(xmlid)s, "
"model: %(model)s, parent_id: %(parent)s]") % \
{
'view_name': view.name or not_avail,
'viewid': view_id or not_avail,
'xmlid': view.xml_id or not_avail,
'model': view.model or not_avail,
'parent': view.inherit_id.id or not_avail,
'msg': message,
}
_logger.error(message)
raise AttributeError(message)
# drop the corresponding view customizations (used for dashboards for example), otherwise
# not all users would see the updated views
custom_view_ids = self.pool.get('ir.ui.view.custom').search(cr, uid, [('ref_id','in',ids)])
if custom_view_ids:
self.pool.get('ir.ui.view.custom').unlink(cr, uid, custom_view_ids)
def locate_node(self, arch, spec):
""" Locate a node in a source (parent) architecture.
return super(view, self).write(cr, uid, ids, vals, context)
Given a complete source (parent) architecture (i.e. the field
`arch` in a view), and a 'spec' node (a node in an inheriting
view that specifies the location in the source view of what
should be changed), return (if it exists) the node in the
source view matching the specification.
:param arch: a parent architecture to modify
:param spec: a modifying node in an inheriting view
:return: a node in the source matching the spec
"""
if spec.tag == 'xpath':
nodes = arch.xpath(spec.get('expr'))
return nodes[0] if nodes else None
elif spec.tag == 'field':
# Only compare the field name: a field can be only once in a given view
# at a given level (and for multilevel expressions, we should use xpath
# inheritance spec anyway).
for node in arch.iter('field'):
if node.get('name') == spec.get('name'):
return node
return None
for node in arch.iter(spec.tag):
if isinstance(node, SKIPPED_ELEMENT_TYPES):
continue
if all(node.get(attr) == spec.get(attr) for attr in spec.attrib
if attr not in ('position','version')):
# Version spec should match parent's root element's version
if spec.get('version') and spec.get('version') != arch.get('version'):
return None
return node
return None
def inherit_branding(self, specs_tree, view_id, root_id):
for node in specs_tree.iterchildren(tag=etree.Element):
xpath = node.getroottree().getpath(node)
if node.tag == 'data' or node.tag == 'xpath':
self.inherit_branding(node, view_id, root_id)
else:
node.set('data-oe-id', str(view_id))
node.set('data-oe-source-id', str(root_id))
node.set('data-oe-xpath', xpath)
node.set('data-oe-model', 'ir.ui.view')
node.set('data-oe-field', 'arch')
return specs_tree
def apply_inheritance_specs(self, cr, uid, source, specs_tree, inherit_id, context=None):
""" Apply an inheriting view (a descendant of the base view)
Apply to a source architecture all the spec nodes (i.e. nodes
describing where and what changes to apply to some parent
architecture) given by an inheriting view.
:param Element source: a parent architecture to modify
:param Elepect specs_tree: a modifying architecture in an inheriting view
:param inherit_id: the database id of specs_arch
:return: a modified source where the specs are applied
:rtype: Element
"""
# Queue of specification nodes (i.e. nodes describing where and
# changes to apply to some parent architecture).
specs = [specs_tree]
while len(specs):
spec = specs.pop(0)
if isinstance(spec, SKIPPED_ELEMENT_TYPES):
continue
if spec.tag == 'data':
specs += [c for c in spec]
continue
node = self.locate_node(source, spec)
if node is not None:
pos = spec.get('position', 'inside')
if pos == 'replace':
if node.getparent() is None:
source = copy.deepcopy(spec[0])
else:
for child in spec:
node.addprevious(child)
node.getparent().remove(node)
elif pos == 'attributes':
for child in spec.getiterator('attribute'):
attribute = (child.get('name'), child.text and child.text.encode('utf8') or None)
if attribute[1]:
node.set(attribute[0], attribute[1])
elif attribute[0] in node.attrib:
del node.attrib[attribute[0]]
else:
sib = node.getnext()
for child in spec:
if pos == 'inside':
node.append(child)
elif pos == 'after':
if sib is None:
node.addnext(child)
node = child
else:
sib.addprevious(child)
elif pos == 'before':
node.addprevious(child)
else:
self.raise_view_error(cr, uid, _("Invalid position attribute: '%s'") % pos, inherit_id, context=context)
else:
attrs = ''.join([
' %s="%s"' % (attr, spec.get(attr))
for attr in spec.attrib
if attr != 'position'
])
tag = "<%s%s>" % (spec.tag, attrs)
self.raise_view_error(cr, uid, _("Element '%s' cannot be located in parent view") % tag, inherit_id, context=context)
return source
def apply_view_inheritance(self, cr, uid, source, source_id, model, root_id=None, context=None):
""" Apply all the (directly and indirectly) inheriting views.
:param source: a parent architecture to modify (with parent modifications already applied)
:param source_id: the database view_id of the parent view
:param model: the original model for which we create a view (not
necessarily the same as the source's model); only the inheriting
views with that specific model will be applied.
:return: a modified source where all the modifying architecture are applied
"""
if context is None: context = {}
if root_id is None:
root_id = source_id
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, uid, source_id, model, context=context)
for (specs, view_id) in sql_inherit:
specs_tree = etree.fromstring(specs.encode('utf-8'))
if context.get('inherit_branding'):
self.inherit_branding(specs_tree, view_id, root_id)
source = self.apply_inheritance_specs(cr, uid, source, specs_tree, view_id, context=context)
source = self.apply_view_inheritance(cr, uid, source, view_id, model, root_id=root_id, context=context)
return source
def read_combined(self, cr, uid, view_id, fields=None, context=None):
"""
Utility function to get a view combined with its inherited views.
* Gets the top of the view tree if a sub-view is requested
* Applies all inherited archs on the root view
* Returns the view with all requested fields
.. note:: ``arch`` is always added to the fields list even if not
requested (similar to ``id``)
"""
if context is None: context = {}
# if view_id is not a root view, climb back to the top.
base = v = self.browse(cr, uid, view_id, context=context)
while v.inherit_id:
v = v.inherit_id
root_id = v.id
# arch and model fields are always returned
if fields:
fields = list(set(fields) | set(['arch', 'model']))
# read the view arch
[view] = self.read(cr, uid, [root_id], fields=fields, context=context)
arch_tree = etree.fromstring(view['arch'].encode('utf-8'))
if context.get('inherit_branding'):
arch_tree.attrib.update({
'data-oe-model': 'ir.ui.view',
'data-oe-id': str(root_id),
'data-oe-field': 'arch',
})
# and apply inheritance
arch = self.apply_view_inheritance(
cr, uid, arch_tree, root_id, base.model, context=context)
return dict(view, arch=etree.tostring(arch, encoding='utf-8'))
#------------------------------------------------------
# Postprocessing: translation, groups and modifiers
#------------------------------------------------------
# TODO:
# - split postprocess so that it can be used instead of translate_qweb
# - remove group processing from ir_qweb
#------------------------------------------------------
def postprocess(self, cr, user, model, node, view_id, in_tree_view, model_fields, context=None):
"""Return the description of the fields in the node.
In a normal call to this method, node is a complete view architecture
but it is actually possible to give some sub-node (this is used so
that the method can call itself recursively).
Originally, the field descriptions are drawn from the node itself.
But there is now some code calling fields_get() in order to merge some
of those information in the architecture.
"""
if context is None:
context = {}
result = False
fields = {}
children = True
modifiers = {}
Model = self.pool.get(model)
if not Model:
self.raise_view_error(cr, user, _('Model not found: %(model)s') % dict(model=model),
view_id, context)
def encode(s):
if isinstance(s, unicode):
return s.encode('utf8')
return s
def check_group(node):
"""Apply group restrictions, may be set at view level or model level::
* at view level this means the element should be made invisible to
people who are not members
* at model level (exclusively for fields, obviously), this means
the field should be completely removed from the view, as it is
completely unavailable for non-members
:return: True if field should be included in the result of fields_view_get
"""
if node.tag == 'field' and node.get('name') in Model._all_columns:
column = Model._all_columns[node.get('name')].column
if column.groups and not self.user_has_groups(
cr, user, groups=column.groups, context=context):
node.getparent().remove(node)
fields.pop(node.get('name'), None)
# no point processing view-level ``groups`` anymore, return
return False
if node.get('groups'):
can_see = self.user_has_groups(
cr, user, groups=node.get('groups'), context=context)
if not can_see:
node.set('invisible', '1')
modifiers['invisible'] = True
if 'attrs' in node.attrib:
del(node.attrib['attrs']) #avoid making field visible later
del(node.attrib['groups'])
return True
if node.tag in ('field', 'node', 'arrow'):
if node.get('object'):
attrs = {}
views = {}
xml = "<form>"
for f in node:
if f.tag == 'field':
xml += etree.tostring(f, encoding="utf-8")
xml += "</form>"
new_xml = etree.fromstring(encode(xml))
ctx = context.copy()
ctx['base_model_name'] = model
xarch, xfields = self.postprocess_and_fields(cr, user, node.get('object'), new_xml, view_id, ctx)
views['form'] = {
'arch': xarch,
'fields': xfields
}
attrs = {'views': views}
fields = xfields
if node.get('name'):
attrs = {}
try:
if node.get('name') in Model._columns:
column = Model._columns[node.get('name')]
else:
column = Model._inherit_fields[node.get('name')][2]
except Exception:
column = False
if column:
children = False
views = {}
for f in node:
if f.tag in ('form', 'tree', 'graph', 'kanban', 'calendar'):
node.remove(f)
ctx = context.copy()
ctx['base_model_name'] = model
xarch, xfields = self.postprocess_and_fields(cr, user, column._obj or None, f, view_id, ctx)
views[str(f.tag)] = {
'arch': xarch,
'fields': xfields
}
attrs = {'views': views}
fields[node.get('name')] = attrs
field = model_fields.get(node.get('name'))
if field:
orm.transfer_field_to_modifiers(field, modifiers)
elif node.tag in ('form', 'tree'):
result = Model.view_header_get(cr, user, False, node.tag, context)
if result:
node.set('string', result)
in_tree_view = node.tag == 'tree'
elif node.tag == 'calendar':
for additional_field in ('date_start', 'date_delay', 'date_stop', 'color', 'all_day', 'attendee'):
if node.get(additional_field):
fields[node.get(additional_field)] = {}
if not check_group(node):
# node must be removed, no need to proceed further with its children
return fields
# The view architeture overrides the python model.
# Get the attrs before they are (possibly) deleted by check_group below
orm.transfer_node_to_modifiers(node, modifiers, context, in_tree_view)
# TODO remove attrs counterpart in modifiers when invisible is true ?
# translate view
if 'lang' in context:
Translations = self.pool['ir.translation']
if node.text and node.text.strip():
trans = Translations._get_source(cr, user, model, 'view', context['lang'], node.text.strip())
if trans:
node.text = node.text.replace(node.text.strip(), trans)
if node.tail and node.tail.strip():
trans = Translations._get_source(cr, user, model, 'view', context['lang'], node.tail.strip())
if trans:
node.tail = node.tail.replace(node.tail.strip(), trans)
if node.get('string') and not result:
trans = Translations._get_source(cr, user, model, 'view', context['lang'], node.get('string'))
if trans == node.get('string') and ('base_model_name' in context):
# If translation is same as source, perhaps we'd have more luck with the alternative model name
# (in case we are in a mixed situation, such as an inherited view where parent_view.model != model
trans = Translations._get_source(cr, user, context['base_model_name'], 'view', context['lang'], node.get('string'))
if trans:
node.set('string', trans)
for attr_name in ('confirm', 'sum', 'avg', 'help', 'placeholder'):
attr_value = node.get(attr_name)
if attr_value:
trans = Translations._get_source(cr, user, model, 'view', context['lang'], attr_value)
if trans:
node.set(attr_name, trans)
for f in node:
if children or (node.tag == 'field' and f.tag in ('filter','separator')):
fields.update(self.postprocess(cr, user, model, f, view_id, in_tree_view, model_fields, context))
orm.transfer_modifiers_to_node(modifiers, node)
return fields
def _disable_workflow_buttons(self, cr, user, model, node):
""" Set the buttons in node to readonly if the user can't activate them. """
if model is None or user == 1:
# admin user can always activate workflow buttons
return node
# TODO handle the case of more than one workflow for a model or multiple
# transitions with different groups and same signal
usersobj = self.pool.get('res.users')
buttons = (n for n in node.getiterator('button') if n.get('type') != 'object')
for button in buttons:
user_groups = usersobj.read(cr, user, [user], ['groups_id'])[0]['groups_id']
cr.execute("""SELECT DISTINCT t.group_id
FROM wkf
INNER JOIN wkf_activity a ON a.wkf_id = wkf.id
INNER JOIN wkf_transition t ON (t.act_to = a.id)
WHERE wkf.osv = %s
AND t.signal = %s
AND t.group_id is NOT NULL
""", (model, button.get('name')))
group_ids = [x[0] for x in cr.fetchall() if x[0]]
can_click = not group_ids or bool(set(user_groups).intersection(group_ids))
button.set('readonly', str(int(not can_click)))
return node
def postprocess_and_fields(self, cr, user, model, node, view_id, context=None):
""" Return an architecture and a description of all the fields.
The field description combines the result of fields_get() and
postprocess().
:param node: the architecture as as an etree
:return: a tuple (arch, fields) where arch is the given node as a
string and fields is the description of all the fields.
"""
fields = {}
Model = self.pool.get(model)
if not Model:
self.raise_view_error(cr, user, _('Model not found: %(model)s') % dict(model=model), view_id, context)
if node.tag == 'diagram':
if node.getchildren()[0].tag == 'node':
node_model = self.pool[node.getchildren()[0].get('object')]
node_fields = node_model.fields_get(cr, user, None, context)
fields.update(node_fields)
if not node.get("create") and not node_model.check_access_rights(cr, user, 'create', raise_exception=False):
node.set("create", 'false')
if node.getchildren()[1].tag == 'arrow':
arrow_fields = self.pool[node.getchildren()[1].get('object')].fields_get(cr, user, None, context)
fields.update(arrow_fields)
else:
fields = Model.fields_get(cr, user, None, context)
fields_def = self.postprocess(cr, user, model, node, view_id, False, fields, context=context)
node = self._disable_workflow_buttons(cr, user, model, node)
if node.tag in ('kanban', 'tree', 'form', 'gantt'):
for action, operation in (('create', 'create'), ('delete', 'unlink'), ('edit', 'write')):
if not node.get(action) and not Model.check_access_rights(cr, user, operation, raise_exception=False):
node.set(action, 'false')
arch = etree.tostring(node, encoding="utf-8").replace('\t', '')
for k in fields.keys():
if k not in fields_def:
del fields[k]
for field in fields_def:
if field == 'id':
# sometime, the view may contain the (invisible) field 'id' needed for a domain (when 2 objects have cross references)
fields['id'] = {'readonly': True, 'type': 'integer', 'string': 'ID'}
elif field in fields:
fields[field].update(fields_def[field])
else:
message = _("Field `%(field_name)s` does not exist") % \
dict(field_name=field)
self.raise_view_error(cr, user, message, view_id, context)
return arch, fields
#------------------------------------------------------
# QWeb template views
#------------------------------------------------------
@tools.ormcache_context(accepted_keys=('lang','inherit_branding', 'editable', 'translatable'))
def read_template(self, cr, uid, xml_id, context=None):
if '.' not in xml_id:
raise ValueError('Invalid template id: %r' % (xml_id,))
view_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, xml_id, raise_if_not_found=True)
arch = self.read_combined(cr, uid, view_id, fields=['arch'], context=context)['arch']
arch_tree = etree.fromstring(arch)
if 'lang' in context:
arch_tree = self.translate_qweb(cr, uid, view_id, arch_tree, context['lang'], context)
self.distribute_branding(arch_tree)
root = etree.Element('templates')
root.append(arch_tree)
arch = etree.tostring(root, encoding='utf-8', xml_declaration=True)
return arch
def clear_cache(self):
self.read_template.clear_cache(self)
def distribute_branding(self, e, branding=None, parent_xpath='',
index_map=misc.ConstantMapping(1)):
if e.get('t-ignore') or e.tag == 'head':
# TODO: find a better name and check if we have a string to boolean helper
return
node_path = e.get('data-oe-xpath')
if node_path is None:
node_path = "%s/%s[%d]" % (parent_xpath, e.tag, index_map[e.tag])
if branding and not (e.get('data-oe-model') or e.get('t-field')):
e.attrib.update(branding)
e.set('data-oe-xpath', node_path)
if not e.get('data-oe-model'): return
# if a branded element contains branded elements distribute own
# branding to children unless it's t-raw, then just remove branding
# on current element
if e.tag == 't' or 't-raw' in e.attrib or \
any(self.is_node_branded(child) for child in e.iterdescendants()):
distributed_branding = dict(
(attribute, e.attrib.pop(attribute))
for attribute in MOVABLE_BRANDING
if e.get(attribute))
if 't-raw' not in e.attrib:
# TODO: collections.Counter if remove p2.6 compat
# running index by tag type, for XPath query generation
indexes = collections.defaultdict(lambda: 0)
for child in e.iterchildren(tag=etree.Element):
if child.get('data-oe-xpath'):
# injected by view inheritance, skip otherwise
# generated xpath is incorrect
continue
indexes[child.tag] += 1
self.distribute_branding(child, distributed_branding,
parent_xpath=node_path,
index_map=indexes)
def is_node_branded(self, node):
""" Finds out whether a node is branded or qweb-active (bears a
@data-oe-model or a @t-* *which is not t-field* as t-field does not
section out views)
:param node: an etree-compatible element to test
:type node: etree._Element
:rtype: boolean
"""
return any(
(attr == 'data-oe-model' or (attr != 't-field' and attr.startswith('t-')))
for attr in node.attrib
)
def translate_qweb(self, cr, uid, id_, arch, lang, context=None):
# TODO: this should be moved in a place before inheritance is applied
# but process() is only called on fields_view_get()
Translations = self.pool['ir.translation']
h = HTMLParser.HTMLParser()
def get_trans(text):
if not text or not text.strip():
return None
text = h.unescape(text.strip())
if len(text) < 2 or (text.startswith('<!') and text.endswith('>')):
return None
return Translations._get_source(cr, uid, 'website', 'view', lang, text, id_)
if arch.tag not in ['script']:
text = get_trans(arch.text)
if text:
arch.text = arch.text.replace(arch.text.strip(), text)
tail = get_trans(arch.tail)
if tail:
arch.tail = arch.tail.replace(arch.tail.strip(), tail)
for attr_name in ('title', 'alt', 'placeholder'):
attr = get_trans(arch.get(attr_name))
if attr:
arch.set(attr_name, attr)
for node in arch.iterchildren("*"):
self.translate_qweb(cr, uid, id_, node, lang, context)
return arch
@openerp.tools.ormcache()
def get_view_xmlid(self, cr, uid, id):
imd = self.pool['ir.model.data']
domain = [('model', '=', 'ir.ui.view'), ('res_id', '=', id)]
xmlid = imd.search_read(cr, uid, domain, ['module', 'name'])[0]
return '%s.%s' % (xmlid['module'], xmlid['name'])
def render(self, cr, uid, id_or_xml_id, values=None, engine='ir.qweb', context=None):
if isinstance(id_or_xml_id, list):
id_or_xml_id = id_or_xml_id[0]
tname = id_or_xml_id
if isinstance(tname, (int, long)):
tname = self.get_view_xmlid(cr, uid, tname)
if not context:
context = {}
if values is None:
values = dict()
qcontext = dict(
keep_query=keep_query,
request=request,
json=simplejson,
quote_plus=werkzeug.url_quote_plus,
)
qcontext.update(values)
def loader(name):
return self.read_template(cr, uid, name, context=context)
return self.pool[engine].render(cr, uid, tname, qcontext, loader=loader, context=context)
#------------------------------------------------------
# Misc
#------------------------------------------------------
def graph_get(self, cr, uid, id, model, node_obj, conn_obj, src_node, des_node, label, scale, context=None):
nodes=[]
@ -305,5 +927,4 @@ class view(osv.osv):
ids = map(itemgetter(0), cr.fetchall())
return self._check_xml(cr, uid, ids)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
# vim:et:

View File

@ -17,6 +17,7 @@
<group>
<field name="field_parent"/>
<field name="inherit_id"/>
<field name="model_data_id"/>
<field name="xml_id"/>
</group>
</group>
@ -49,17 +50,19 @@
<field name="model">ir.ui.view</field>
<field name="arch" type="xml">
<search string="Views">
<field name="name" filter_domain="['|', ('name','ilike',self), ('model','ilike',self)]" string="View"/>
<field name="name" filter_domain="['|', '|', ('name','ilike',self), ('model','ilike',self), ('model_data_id','ilike',self)]" string="View"/>
<filter string="Form" domain="[('type', '=','form')]"/>
<filter string="Tree" domain="[('type', '=', 'tree')]"/>
<filter string="Kanban" domain="[('type', '=', 'kanban')]"/>
<filter string="Search" domain="[('type', '=', 'search')]"/>
<filter string="QWeb" domain="[('type', '=', 'qweb')]"/>
<field name="model"/>
<field name="inherit_id"/>
<field name="type"/>
<group expand="0" string="Group By...">
<filter string="Object" icon="terp-stock_align_left_24" domain="[]" context="{'group_by':'model'}"/>
<filter string="Type" icon="terp-stock_symbol-selection" domain="[]" context="{'group_by':'type'}"/>
<filter string="Object" domain="[]" context="{'group_by':'model'}"/>
<filter string="Type" domain="[]" context="{'group_by':'type'}"/>
<filter string="Inherit" domain="[]" context="{'group_by':'inherit_id'}"/>
</group>
</search>
</field>

View File

@ -394,17 +394,16 @@ class ir_values(osv.osv):
for action in cr.dictfetchall():
if not action['value']:
continue # skip if undefined
action_model,id = action['value'].split(',')
fields = [
field
for field in self.pool[action_model]._all_columns
if field not in EXCLUDED_FIELDS]
action_model_name, action_id = action['value'].split(',')
action_model = self.pool.get(action_model_name)
if not action_model:
continue # unknow model? skip it
fields = [field for field in action_model._all_columns if field not in EXCLUDED_FIELDS]
# FIXME: needs cleanup
try:
action_def = self.pool[action_model].read(cr, uid, int(id), fields, context)
action_def = action_model.read(cr, uid, int(action_id), fields, context)
if action_def:
if action_model in ('ir.actions.report.xml','ir.actions.act_window',
'ir.actions.wizard'):
if action_model_name in ('ir.actions.report.xml', 'ir.actions.act_window'):
groups = action_def.get('groups_id')
if groups:
cr.execute('SELECT 1 FROM res_groups_users_rel WHERE gid IN %s AND uid=%s',

View File

@ -41,8 +41,9 @@ except ImportError:
from StringIO import StringIO # NOQA
import openerp
from openerp import modules, tools, addons
from openerp import modules, tools
from openerp.modules.db import create_categories
from openerp.modules import get_module_resource
from openerp.tools.parse_version import parse_version
from openerp.tools.translate import _
from openerp.osv import fields, osv, orm
@ -154,7 +155,7 @@ class module(osv.osv):
def _get_desc(self, cr, uid, ids, field_name=None, arg=None, context=None):
res = dict.fromkeys(ids, '')
for module in self.browse(cr, uid, ids, context=context):
path = addons.get_module_resource(module.name, 'static/description/index.html')
path = get_module_resource(module.name, 'static/description/index.html')
if path:
with tools.file_open(path, 'rb') as desc_file:
doc = desc_file.read()
@ -233,7 +234,7 @@ class module(osv.osv):
def _get_icon_image(self, cr, uid, ids, field_name=None, arg=None, context=None):
res = dict.fromkeys(ids, '')
for module in self.browse(cr, uid, ids, context=context):
path = addons.get_module_resource(module.name, 'static', 'description', 'icon.png')
path = get_module_resource(module.name, 'static', 'description', 'icon.png')
if path:
image_file = tools.file_open(path, 'rb')
try:

View File

@ -7,6 +7,7 @@
<field name="visible" eval="0" />
</record>
<record model="ir.module.category" id="module_category_localization">
<field name="name">Localization</field>
<field name="visible" eval="0" />
@ -113,6 +114,11 @@
<field name="sequence">15</field>
</record>
<record model="ir.module.category" id="module_category_website">
<field name="name">Website</field>
<field name="sequence">16</field>
</record>
<record model="ir.module.category" id="module_category_administration">
<field name="name">Administration</field>
<field name="sequence">100</field>

Some files were not shown because too many files have changed in this diff Show More