Vir (Open ERP)
2010-09-03 10:07:18 +05:30
18 changed files with 1057 additions and 958 deletions
+5 -1
View File
@@ -116,7 +116,11 @@
<page string="User">
<field name="address_id" select="1"/>
<field name="user_email" widget="email"/>
<field name="company_id" required="1" context="{'user_id': self, 'user_preference': 1}" groups="base.group_multi_company"/>
<field name="company_id" required="1"
context="{'user_id': self, 'user_preference': 1}"
on_change="on_change_company_id(company_id)"
groups="base.group_multi_company"
/>
<field name="action_id" required="True"/>
<field domain="[('usage','=','menu')]" name="menu_id" required="True"/>
<field name="context_lang"/>
+4 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-04-25 04:24+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"PO-Revision-Date: 2010-09-02 07:50+0000\n"
"Last-Translator: Quentin THEURET <quentin@theuret.net>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-07-13 03:45+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:44+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@@ -7998,7 +7998,7 @@ msgstr "Sierra Leone"
#: view:res.company:0
#: view:res.partner:0
msgid "General Information"
msgstr "Information générale"
msgstr "Informations générales"
#. module: base
#: selection:ir.ui.menu,icon:0
+5 -5
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:47+0000\n"
"Last-Translator: Goran Kliska <gkliska@gmail.com>\n"
"PO-Revision-Date: 2010-09-02 06:44+0000\n"
"Last-Translator: nafterburner <nafterburner@gmail.com>\n"
"Language-Team: openerp-translators\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:55+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:44+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
"Language: hr\n"
@@ -7979,12 +7979,12 @@ msgstr ""
#. module: base
#: model:res.country,name:base.lk
msgid "Sri Lanka"
msgstr ""
msgstr "Sri Lanka"
#. module: base
#: selection:module.lang.install,init,lang:0
msgid "Russian / русский язык"
msgstr ""
msgstr "Ruski / русский язык"
#, python-format
#~ msgid "Recursivity Detected."
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:41+0000\n"
"PO-Revision-Date: 2010-09-02 06:41+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:54+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:44+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+2 -2
View File
@@ -8,13 +8,13 @@ msgstr ""
"Project-Id-Version: openobject-server\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:49+0000\n"
"PO-Revision-Date: 2010-09-02 06:33+0000\n"
"Last-Translator: Harry (Open ERP) <hmo@tinyerp.com>\n"
"Language-Team: Japanese <ja@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:54+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:44+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+818 -772
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: pt_BR\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:42+0000\n"
"PO-Revision-Date: 2010-09-02 06:28+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: <pt@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:55+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:45+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+4 -4
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-10 04:28+0000\n"
"Last-Translator: Nikolay Chesnokov <chesnokov_n@msn.com>\n"
"PO-Revision-Date: 2010-09-02 06:48+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-11 03:47+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:44+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@@ -2820,7 +2820,7 @@ msgstr "Перу"
#. module: base
#: selection:ir.model.fields,on_delete:0
msgid "Set NULL"
msgstr "Устоновить в BULL"
msgstr "Установить в NULL"
#. module: base
#: field:res.partner.event,som:0
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:52+0000\n"
"PO-Revision-Date: 2010-09-02 06:31+0000\n"
"Last-Translator: Anders Wallenquist <anders.wallenquist@vertel.se>\n"
"Language-Team: <>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:55+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:45+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+2 -2
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.0\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:44+0000\n"
"PO-Revision-Date: 2010-09-02 06:38+0000\n"
"Last-Translator: Fabien (Open ERP) <fp@tinyerp.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:55+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:45+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+9 -9
View File
@@ -7,13 +7,13 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2010-08-30 07:51+0000\n"
"Last-Translator: Eleanor Chen <chenyueg@gmail.com>\n"
"PO-Revision-Date: 2010-09-01 06:36+0000\n"
"Last-Translator: OpenERP Administrators <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2010-08-31 03:55+0000\n"
"X-Launchpad-Export-Date: 2010-09-02 03:51+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
@@ -199,7 +199,7 @@ msgstr "模块数"
#. module: base
#: field:res.partner.bank.type.field,size:0
msgid "Max. Size"
msgstr ""
msgstr "字段长度"
#. module: base
#: field:res.partner.address,name:0
@@ -229,7 +229,7 @@ msgstr "密码不符合!"
#: code:addons/base/module/module.py:0
#, python-format
msgid "This url '%s' must provide an html file with links to zip modules"
msgstr ""
msgstr "这个 URL '%s' 必须提供一个链接到 zip 模块文件的 HTML 页面"
#. module: base
#: selection:res.request,state:0
@@ -1232,7 +1232,7 @@ msgstr "提示:这个操作会花费一些时间"
msgid ""
"If set, sequence will only be used in case this python expression matches, "
"and will precede other sequences."
msgstr ""
msgstr "当设置后, 系统会优先使用这个python表达式来做为序号."
#. module: base
#: selection:ir.actions.act_window,view_type:0
@@ -2606,7 +2606,7 @@ msgstr "作者"
#. module: base
#: model:res.country,name:base.mk
msgid "FYROM"
msgstr ""
msgstr "马其顿共和国"
#. module: base
#: selection:ir.ui.menu,icon:0
@@ -5381,7 +5381,7 @@ msgstr "强制域"
#. module: base
#: help:ir.sequence,weight:0
msgid "If two sequences match, the highest weight will be used."
msgstr ""
msgstr "如果有两种设置, 则采用优先级最高的一个."
#. module: base
#: model:ir.actions.act_window,name:base.action_attachment
@@ -6064,7 +6064,7 @@ msgstr "上级"
#. module: base
#: view:multi_company.default:0
msgid "Returning"
msgstr ""
msgstr "所属公司"
#. module: base
#: field:ir.actions.act_window,res_model:0
+1 -1
View File
@@ -183,7 +183,7 @@ class ir_ui_menu(osv.osv):
rex=re.compile('\([0-9]+\)')
concat=rex.findall(datas['name'])
if concat:
next_num=eval(concat[0])+1
next_num=int(concat[0])+1
datas['name']=rex.sub(('(%d)'%next_num),datas['name'])
else:
datas['name']=datas['name']+'(1)'
+17 -4
View File
@@ -57,6 +57,18 @@
</form>
</field>
</record>
<record model="ir.ui.view" id="res_request_calendar_view">
<field name="name">Request - Calendar</field>
<field name="model">res.request</field>
<field name="type">calendar</field>
<field name="priority" eval="2"/>
<field name="arch" type="xml">
<calendar string="Requests" date_start="trigger_date" color="act_to">
<field name="name"/>
<field name="act_from"/>
</calendar>
</field>
</record>
<record id="res_request_search_view" model="ir.ui.view">
<field name="name">res.request.search</field>
<field name="model">res.request</field>
@@ -65,7 +77,7 @@
<search string="Requests">
<group colspan="4" col="10">
<field name="act_from"/>
<field name="act_to"/>
<field name="act_to" select="1"/>
<field name="name"/>
<field name="state"/>
</group>
@@ -81,10 +93,11 @@
<field name="type">ir.actions.act_window</field>
<field name="res_model">res.request</field>
<field name="view_id" eval="False"/>
<field name="view_mode">tree,form,calendar</field>
<field name="search_view_id" ref="res_request_search_view"/>
<field name="context">{"search_default_act_to":uid}</field>
</record>
<menuitem id="next_id_12" name="Requests" parent="base.next_id_4"/>
<menuitem action="res_request-act" id="menu_res_request_act" parent="next_id_12" sequence="1"/>
<menuitem action="res_request-act" id="menu_res_request_act" parent="base.next_id_4" sequence="1"/>
<record id="res_request_link-view" model="ir.ui.view">
<field name="name">res.request.link.form</field>
@@ -129,7 +142,7 @@
<field name="view_id" eval="False"/>
<field name="search_view_id" ref="res_request_link_search_view"/>
</record>
<menuitem action="res_request_link-act" id="menu_res_request_link_act" parent="base.next_id_12" sequence="4"/>
<menuitem action="res_request_link-act" id="menu_res_request_link_act" parent="base.next_id_4" sequence="4"/>
<record id="res_request_history_tree-view" model="ir.ui.view">
+7
View File
@@ -268,6 +268,13 @@ class users(osv.osv):
}
def on_change_company_id(self, cr, uid, ids, company_id):
return {
'value': {
'warning' : _("Please keep in mind that data currently displayed may not be relevant after switching to another company. If you have unsaved changes, please make sure to save and close the forms before switching to a different company (you can click on Cancel now)"),
}
}
def read(self,cr, uid, ids, fields=None, context=None, load='_classic_read'):
def override_password(o):
if 'password' in o and ( 'id' not in o or o['id'] != uid ):
+14 -18
View File
@@ -38,13 +38,20 @@
</rng:optional>
</rng:define>
<rng:define name="access_rights">
<rng:optional>
<rng:attribute name="groups"/>
</rng:optional>
</rng:define>
<rng:define name="container">
<rng:optional><rng:attribute name="col"/></rng:optional>
<rng:zeroOrMore>
<rng:choice>
<rng:ref name="notebook"/>
<rng:ref name="field"/>
<rng:ref name="shortcut"/>
<rng:ref name="group"/>
<rng:ref name="button"/>
<rng:ref name="hpaned" />
@@ -129,7 +136,6 @@
<rng:zeroOrMore>
<rng:choice>
<rng:ref name="field"/>
<rng:ref name="shortcut"/>
<rng:ref name="separator"/>
<rng:ref name="tree"/>
<rng:ref name="group"/>
@@ -299,8 +305,8 @@
<rng:define name="page">
<rng:element name="page">
<rng:ref name="overload"/>
<rng:ref name="access_rights"/>
<rng:optional><rng:attribute name="string"/></rng:optional>
<rng:optional><rng:attribute name="groups"/></rng:optional>
<rng:optional><rng:attribute name="attrs"/></rng:optional>
<rng:zeroOrMore>
<rng:choice>
@@ -308,7 +314,6 @@
<rng:element name="properties"><rng:empty/></rng:element>
<rng:ref name="label" />
<rng:ref name="field"/>
<rng:ref name="shortcut"/>
<rng:ref name="group"/>
<rng:ref name="separator"/>
<rng:ref name="button"/>
@@ -338,6 +343,7 @@
<rng:define name="separator">
<rng:element name="separator">
<rng:ref name="overload"/>
<rng:ref name="access_rights"/>
<rng:optional><rng:attribute name="colspan"/></rng:optional>
<rng:optional><rng:attribute name="rowspan"/></rng:optional>
<rng:optional><rng:attribute name="string"/></rng:optional>
@@ -349,7 +355,6 @@
<rng:ref name="separator"/>
<rng:ref name="button"/>
<rng:ref name="field"/>
<rng:ref name="shortcut"/>
<rng:ref name="label" />
<rng:ref name="group" />
<rng:ref name="filter"/>
@@ -401,6 +406,7 @@
<rng:element name="field">
<rng:attribute name="name" />
<rng:ref name="overload"/>
<rng:ref name="access_rights"/>
<rng:optional><rng:attribute name="editable"/></rng:optional>
<rng:optional><rng:attribute name="attrs"/></rng:optional>
<rng:optional><rng:attribute name="string"/></rng:optional>
@@ -433,7 +439,6 @@
<rng:optional><rng:attribute name="view_mode"/></rng:optional>
<rng:optional><rng:attribute name="widget"/></rng:optional>
<rng:optional><rng:attribute name="context"/></rng:optional>
<rng:optional><rng:attribute name="groups"/></rng:optional>
<rng:optional><rng:attribute name="states"/></rng:optional>
<rng:optional><rng:attribute name="digits"/></rng:optional>
<rng:optional><rng:attribute name="icon"/></rng:optional>
@@ -474,12 +479,12 @@
<rng:define name="group">
<rng:element name="group">
<rng:ref name="overload"/>
<rng:ref name="access_rights"/>
<rng:optional><rng:attribute name="attrs"/></rng:optional>
<rng:optional><rng:attribute name="colspan"/></rng:optional>
<rng:optional><rng:attribute name="rowspan"/></rng:optional>
<rng:optional><rng:attribute name="expand"/></rng:optional>
<rng:optional><rng:attribute name="states"/></rng:optional>
<rng:optional><rng:attribute name="groups"/></rng:optional>
<rng:optional><rng:attribute name="string"/></rng:optional>
<rng:optional><rng:attribute name="fill"/></rng:optional>
<rng:optional><rng:attribute name="height"/></rng:optional>
@@ -527,6 +532,7 @@
<rng:define name="button">
<rng:element name="button">
<rng:ref name="overload"/>
<rng:ref name="access_rights"/>
<rng:optional><rng:attribute name="attrs"/></rng:optional>
<rng:optional><rng:attribute name="invisible"/></rng:optional>
<rng:optional><rng:attribute name="name" /></rng:optional>
@@ -537,7 +543,6 @@
<rng:optional><rng:attribute name="special" /></rng:optional>
<rng:optional><rng:attribute name="align" /></rng:optional>
<rng:optional><rng:attribute name="colspan"/></rng:optional>
<rng:optional><rng:attribute name="groups"/></rng:optional>
<rng:optional><rng:attribute name="target"/></rng:optional>
<rng:optional><rng:attribute name="readonly"/></rng:optional>
<rng:optional><rng:attribute name="context"/></rng:optional>
@@ -571,6 +576,7 @@
<rng:define name="filter">
<rng:element name="filter">
<rng:ref name="overload"/>
<rng:ref name="access_rights"/>
<rng:optional><rng:attribute name="attrs"/></rng:optional>
<rng:optional><rng:attribute name="name" /></rng:optional>
<rng:optional><rng:attribute name="separator" /></rng:optional>
@@ -579,7 +585,6 @@
<rng:optional><rng:attribute name="type" /></rng:optional>
<rng:optional><rng:attribute name="align" /></rng:optional>
<rng:optional><rng:attribute name="colspan"/></rng:optional>
<rng:optional><rng:attribute name="groups"/></rng:optional>
<rng:optional><rng:attribute name="readonly"/></rng:optional>
<rng:optional><rng:attribute name="context"/></rng:optional>
<rng:optional><rng:attribute name="help"/></rng:optional>
@@ -608,15 +613,6 @@
</rng:element>
</rng:define>
<rng:define name="shortcut">
<rng:element name="shortcut">
<rng:optional><rng:attribute name="attrs"/></rng:optional>
<rng:optional><rng:attribute name="name" /></rng:optional>
<rng:optional><rng:attribute name="key"/></rng:optional>
<rng:optional><rng:attribute name="goto" /></rng:optional>
</rng:element>
</rng:define>
<rng:start>
<rng:choice>
<rng:ref name="diagram" />
+135 -126
View File
@@ -1313,29 +1313,25 @@ class orm_template(object):
}
attrs = {'views': views}
if node.get('widget') and node.get('widget') == 'selection':
if not check_group(node):
name = node.get('name')
default = self.default_get(cr, user, [name], context=context).get(name)
if default:
attrs['selection'] = relation.name_get(cr, 1, [default], context=context)
else:
attrs['selection'] = []
# We can not use the 'string' domain has it is defined according to the record !
else:
# If domain and context are strings, we keep them for client-side, otherwise
# we evaluate them server-side to consider them when generating the list of
# possible values
# TODO: find a way to remove this hack, by allow dynamic domains
dom = []
if column._domain and not isinstance(column._domain, basestring):
dom = column._domain
dom += eval(node.get('domain','[]'), {'uid':user, 'time':time})
search_context = dict(context)
if column._context and not isinstance(column._context, basestring):
search_context.update(column._context)
attrs['selection'] = relation._name_search(cr, 1, '', dom, context=search_context, limit=None, name_get_uid=1)
if (node.get('required') and not int(node.get('required'))) or not column.required:
attrs['selection'].append((False,''))
# Prepare the cached selection list for the client. This needs to be
# done even when the field is invisible to the current user, because
# other events could need to change its value to any of the selectable ones
# (such as on_change events, refreshes, etc.)
# If domain and context are strings, we keep them for client-side, otherwise
# we evaluate them server-side to consider them when generating the list of
# possible values
# TODO: find a way to remove this hack, by allow dynamic domains
dom = []
if column._domain and not isinstance(column._domain, basestring):
dom = column._domain
dom += eval(node.get('domain','[]'), {'uid':user, 'time':time})
search_context = dict(context)
if column._context and not isinstance(column._context, basestring):
search_context.update(column._context)
attrs['selection'] = relation._name_search(cr, user, '', dom, context=search_context, limit=None, name_get_uid=1)
if (node.get('required') and not int(node.get('required'))) or not column.required:
attrs['selection'].append((False,''))
fields[node.get('name')] = attrs
elif node.tag in ('form', 'tree'):
@@ -1496,7 +1492,7 @@ class orm_template(object):
view = self.fields_view_get(cr, uid, False, 'form', context)
root = etree.fromstring(encode(view['arch']))
res = etree.XML("<search string='%s'></search>" % root.get("string", ""))
res = etree.XML("""<search string="%s"></search>""" % root.get("string", ""))
node = etree.Element("group")
res.append(node)
@@ -1771,15 +1767,116 @@ class orm_template(object):
return len(res)
return res
def search(self, cr, user, args, offset=0, limit=None, order=None,
context=None, count=False):
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False):
"""
Search for records based on a search domain.
:param cr: database cursor
:param user: current user id
:param args: list of tuples specifying the search domain [('field_name', 'operator', value), ...]. Pass an empty list to match all records.
:param offset: optional number of results to skip in the returned values (default: 0)
:param limit: optional max number of records to return (default: **None**)
:param order: optional columns to sort by (default: self._order=id )
:param context: optional context arguments, like lang, time zone
:type context: dictionary
:param count: optional (default: **False**), if **True**, returns only the number of records matching the criteria, not their ids
:return: id or list of ids of records matching the criteria
:rtype: integer or list of integers
:raise AccessError: * if user tries to bypass access rules for read on the requested object.
**Expressing a search domain (args)**
Each tuple in the search domain needs to have 3 elements, in the form: **('field_name', 'operator', value)**, where:
* **field_name** must be a valid name of field of the object model, possibly following many-to-one relationships using dot-notation, e.g 'street' or 'partner_id.country' are valid values.
* **operator** must be a string with a valid comparison operator from this list: ``=, !=, >, >=, <, <=, like, ilike, in, not in, child_of, parent_left, parent_right``
The semantics of most of these operators are obvious.
The ``child_of`` operator will look for records who are children or grand-children of a given record,
according to the semantics of this model (i.e following the relationship field named by
``self._parent_name``, by default ``parent_id``.
* **value** must be a valid value to compare with the values of **field_name**, depending on its type.
Domain criteria can be combined using 3 logical operators than can be added between tuples: '**&**' (logical AND, default), '**|**' (logical OR), '**!**' (logical NOT).
These are **prefix** operators and the arity of the '**&**' and '**|**' operator is 2, while the arity of the '**!**' is just 1.
Be very careful about this when you combine them the first time.
Here is an example of searching for Partners named *ABC* from Belgium and Germany whose language is not english ::
[('name','=','ABC'),'!',('language.code','=','en_US'),'|',('country_id.code','=','be'),('country_id.code','=','de'))
The '&' is omitted as it is the default, and of course we could have used '!=' for the language, but what this domain really represents is::
(name is 'ABC' AND (language is NOT english) AND (country is Belgium OR Germany))
"""
return self._search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
"""
Private implementation of search() method, allowing specifying the uid to use for the access right check.
This is useful for example when filling in the selection list for a drop-down and avoiding access rights errors,
by specifying ``access_rights_uid=1`` to bypass access rights check, but not ir.rules!
:param access_rights_uid: optional user ID to use when checking access rights
(not for ir.rules, this is only for ir.model.access)
"""
raise NotImplementedError(_('The search method is not implemented on this object !'))
def name_get(self, cr, user, ids, context=None):
raise NotImplementedError(_('The name_get method is not implemented on this object !'))
"""
:param cr: database cursor
:param user: current user id
:type user: integer
:param ids: list of ids
:param context: context arguments, like lang, time zone
:type context: dictionary
:return: tuples with the text representation of requested objects for to-many relationships
"""
if not context:
context = {}
if not ids:
return []
if isinstance(ids, (int, long)):
ids = [ids]
return [(r['id'], tools.ustr(r[self._rec_name])) for r in self.read(cr, user, ids,
[self._rec_name], context, load='_classic_write')]
def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100):
raise NotImplementedError(_('The name_search method is not implemented on this object !'))
"""
Search for records and their display names according to a search domain.
:param cr: database cursor
:param user: current user id
:param name: object name to search
:param args: list of tuples specifying search criteria [('field_name', 'operator', 'value'), ...]
:param operator: operator for search criterion
:param context: context arguments, like lang, time zone
:type context: dictionary
:param limit: optional max number of records to return
:return: list of object names matching the search criteria, used to provide completion for to-many relationships
This method is equivalent of :py:meth:`~osv.osv.osv.search` on **name** + :py:meth:`~osv.osv.osv.name_get` on the result.
See :py:meth:`~osv.osv.osv.search` for an explanation of the possible values for the search domain specified in **args**.
"""
return self._name_search(cr, user, name, args, operator, context, limit)
# private implementation of name_search, allows passing a dedicated user for the name_get part to
# solve some access rights issues
def _name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None):
if args is None:
args = []
if context is None:
context = {}
args = args[:]
if name:
args += [(self._rec_name, operator, name)]
access_rights_uid = name_get_uid or user
ids = self._search(cr, user, args, limit=limit, context=context, access_rights_uid=access_rights_uid)
res = self.name_get(cr, access_rights_uid, ids, context)
return res
def copy(self, cr, uid, id, default=None, context=None):
raise NotImplementedError(_('The copy method is not implemented on this object !'))
@@ -1998,8 +2095,7 @@ class orm_memory(orm_template):
res = e.exp
return res or []
def search(self, cr, user, args, offset=0, limit=None, order=None,
context=None, count=False):
def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
if not context:
context = {}
@@ -3761,52 +3857,19 @@ class orm(orm_template):
return True
return False
def search(self, cr, user, args, offset=0, limit=None, order=None,
context=None, count=False):
def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
"""
Search for record/s based on a search domain.
:param cr: database cursor
:param user: current user id
:param args: list of tuples specifying the search domain [('field_name', 'operator', value), ...]. Pass an empty list to match all records.
:param offset: optional number of results to skip in the returned values (default: 0)
:param limit: optional max number of records to return (default: **None**)
:param order: optional columns to sort by (default: self._order=id )
:param context: optional context arguments, like lang, time zone
:type context: dictionary
:param count: optional (default: **False**), if **True**, returns only the number of records matching the criteria, not their ids
:return: id or list of ids of records matching the criteria
:rtype: integer or list of integers
:raise AccessError: * if user tries to bypass access rules for read on the requested object.
**Expressing a search domain (args)**
Each tuple in the search domain needs to have 3 elements, in the form: **('field_name', 'operator', value)**, where:
* **field_name** must be a valid name of field of the object model, possibly following many-to-one relationships using dot-notation, e.g 'street' or 'partner_id.country' are valid values.
* **operator** must be a string with a valid comparison operator from this list: ``=, !=, >, >=, <, <=, like, ilike, in, not in, child_of, parent_left, parent_right``
The semantics of most of these operators are obvious.
The ``child_of`` operator will look for records who are children or grand-children of a given record,
according to the semantics of this model (i.e following the relationship field named by
``self._parent_name``, by default ``parent_id``.
* **value** must be a valid value to compare with the values of **field_name**, depending on its type.
Domain criteria can be combined using 3 logical operators than can be added between tuples: '**&**' (logical AND, default), '**|**' (logical OR), '**!**' (logical NOT).
These are **prefix** operators and the arity of the '**&**' and '**|**' operator is 2, while the arity of the '**!**' is just 1.
Be very careful about this when you combine them the first time.
Here is an example of searching for Partners named *ABC* from Belgium and Germany whose language is not english ::
[('name','=','ABC'),'!',('language.code','=','en_US'),'|',('country_id.code','=','be'),('country_id.code','=','de'))
The '&' is omitted as it is the default, and of course we could have used '!=' for the language, but what this domain really represents is::
(name is 'ABC' AND (language is NOT english) AND (country is Belgium OR Germany))
Private implementation of search() method, allowing specifying the uid to use for the access right check.
This is useful for example when filling in the selection list for a drop-down and avoiding access rights errors,
by specifying ``access_rights_uid=1`` to bypass access rights check, but not ir.rules!
This is ok at the security level because this method is private and not callable through XML-RPC.
:param access_rights_uid: optional user ID to use when checking access rights
(not for ir.rules, this is only for ir.model.access)
"""
if context is None:
context = {}
self.pool.get('ir.model.access').check(cr, user, self._name, 'read', context=context)
self.pool.get('ir.model.access').check(cr, access_rights_uid or user, self._name, 'read', context=context)
# compute the where, order by, limit and offset clauses
(where_clause, where_clause_params, tables) = self._where_calc(cr, user, args, context=context)
@@ -3867,60 +3930,6 @@ class orm(orm_template):
else:
return self._columns[field].search(cr, self, args, field, value, offset, limit, uid)
def name_get(self, cr, user, ids, context=None):
"""
:param cr: database cursor
:param user: current user id
:type user: integer
:param ids: list of ids
:param context: context arguments, like lang, time zone
:type context: dictionary
:return: tuples with the text representation of requested objects for to-many relationships
"""
if not context:
context = {}
if not ids:
return []
if isinstance(ids, (int, long)):
ids = [ids]
return [(r['id'], tools.ustr(r[self._rec_name])) for r in self.read(cr, user, ids,
[self._rec_name], context, load='_classic_write')]
# private implementation of name_search, allows passing a dedicated user for the name_get part to
# solve some access rights issues
def _name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100, name_get_uid=None):
if args is None:
args = []
if context is None:
context = {}
args = args[:]
if name:
args += [(self._rec_name, operator, name)]
ids = self.search(cr, user, args, limit=limit, context=context)
res = self.name_get(cr, name_get_uid or user, ids, context)
return res
def name_search(self, cr, user, name='', args=None, operator='ilike', context=None, limit=100):
"""
:param cr: database cursor
:param user: current user id
:param name: object name to search
:param args: list of tuples specifying search criteria [('field_name', 'operator', 'value'), ...]
:param operator: operator for search criterion
:param context: context arguments, like lang, time zone
:type context: dictionary
:param limit: optional max number of records to return
:return: list of object names matching the search criteria, used to provide completion for to-many relationships
This method is equivalent of :py:meth:`~osv.osv.osv.search` on **name** + :py:meth:`~osv.osv.osv.name_get` on the result.
See :py:meth:`~osv.osv.osv.search` for an explanation of the possible values for the search domain specified in **args**.
"""
return self._name_search(cr, user, name, args, operator, context, limit)
def copy_data(self, cr, uid, id, default=None, context=None):
"""
Copy given record's data with all its fields values
+3
View File
@@ -375,6 +375,9 @@ def trans_export(lang, modules, buffer, format, dbname=None):
if newlang:
lang = 'en_US'
trans = trans_generate(lang, modules, dbname)
if newlang and format!='csv':
for trx in trans:
trx[-1] = ''
modules = set([t[0] for t in trans[1:]])
_process(format, modules, trans, buffer, lang, newlang)
del trans
+25 -4
View File
@@ -250,6 +250,25 @@ class YamlInterpreter(object):
if not success:
msg = 'Assertion "%s" FAILED\ntest: %s\n'
args = (assertion.string, test)
for aop in ('==', '!=', '<>', 'in', 'not in', '>=', '<=', '>', '<'):
if aop in test:
left, right = test.split(aop,1)
lmsg = ''
rmsg = ''
try:
lmsg = unsafe_eval(left, self.eval_context, RecordDictWrapper(record))
except Exception, e:
lmsg = '<exc>'
try:
rmsg = unsafe_eval(right, self.eval_context, RecordDictWrapper(record))
except Exception, e:
rmsg = '<exc>'
msg += 'values: ! %s %s %s'
args += ( lmsg, aop, rmsg )
break
self._log_assert_failure(assertion.severity, msg, *args)
return
else: # all tests were successful for this assertion tag (no break)
@@ -293,8 +312,10 @@ class YamlInterpreter(object):
record_dict = self._create_record(model, fields)
self.logger.debug("RECORD_DICT %s" % record_dict)
#context = self.get_context(record, self.eval_context)
context = record.context #TOFIX: record.context like {'withoutemployee':True} should pass from self.eval_context. example: test_project.yml in project module
id = self.pool.get('ir.model.data')._update(self.cr, self.uid, record.model, \
self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode)
self.module, record_dict, record.id, noupdate=self.isnoupdate(record), mode=self.mode, context=context)
self.id_map[record.id] = int(id)
if config.get('import_partial'):
self.cr.commit()
@@ -360,14 +381,14 @@ class YamlInterpreter(object):
value = expression
# raise YamlImportException('Unsupported column "%s" or value %s:%s' % (field_name, type(expression), expression))
return value
def process_context(self, node):
self.context = node.__dict__
if node.uid:
self.uid = self.get_id(node.uid)
if node.noupdate:
self.noupdate = node.noupdate
def process_python(self, node):
def log(msg, *args):
self.logger.log(logging.TEST, msg, *args)
@@ -384,7 +405,7 @@ class YamlInterpreter(object):
return
except Exception, e:
self.logger.debug('Exception during evaluation of !python block in yaml_file %s.', self.filename, exc_info=True)
raise YamlImportAbortion(e)
raise
else:
self.assert_report.record(True, python.severity)