[Merge]
bzr revid: vir@tinyerp.com-20100901043056-e8pwz72pezbhqy40 bzr revid: vir@tinyerp.com-20100903043718-c6nv0ayvqpom7uuh
This commit is contained in:
@@ -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"/>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)'
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 ):
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user