[MERGE]: Merge with lp:openobject-server

bzr revid: rpa@tinyerp.com-20100903061133-2aamj5doyxpx2ppj
This commit is contained in:
rpa (Open ERP)
2010-09-03 11:41:33 +05:30
28 changed files with 1708 additions and 1521 deletions
+6 -2
View File
@@ -82,7 +82,7 @@
context="{'user_id': self, 'user_preference': 1}" groups="base.group_multi_company"/>
<field name="view" readonly="0"/>
<label string="" colspan="2"/>
<field name="menu_tips" colspan="2"/>
<field name="menu_tips" colspan="2" readonly="0"/>
<newline/>
<separator colspan="4" string="Preferences"/>
</page>
@@ -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-26 06:44+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-27 03:37+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."
+78 -67
View File
@@ -8,93 +8,93 @@ msgstr ""
"Project-Id-Version: openobject-addons\n"
"Report-Msgid-Bugs-To: FULL NAME <EMAIL@ADDRESS>\n"
"POT-Creation-Date: 2009-12-18 08:39+0000\n"
"PO-Revision-Date: 2009-11-24 18:49+0000\n"
"Last-Translator: Iman Sulaiman <isulaiman@hotmail.com>\n"
"PO-Revision-Date: 2010-08-28 06:59+0000\n"
"Last-Translator: Iman Sulaiman <iman_sl02@yahoo.com>\n"
"Language-Team: Indonesian <id@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-07-13 03:46+0000\n"
"X-Launchpad-Export-Date: 2010-08-29 03:43+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
#: model:res.country,name:base.sh
msgid "Saint Helena"
msgstr ""
msgstr "Santa Helena"
#. module: base
#: wizard_view:res.partner.sms_send,init:0
msgid "SMS - Gateway: clickatell"
msgstr ""
msgstr "SMS - Gateway: clickatell"
#. module: base
#: view:res.lang:0
msgid "%j - Day of the year as a decimal number [001,366]."
msgstr ""
msgstr "%j - Hari dalam setahun sebagai angka desimal [001,366]."
#. module: base
#: field:ir.values,meta_unpickle:0
msgid "Metadata"
msgstr ""
msgstr "Metadata"
#. module: base
#: field:ir.ui.view,arch:0
#: field:ir.ui.view.custom,arch:0
msgid "View Architecture"
msgstr ""
msgstr "Arsitektur View"
#. module: base
#: code:addons/base/ir/ir_model.py:0
#, python-format
msgid "You can not create this kind of document! (%s)"
msgstr ""
msgstr "Anda tidak dapat membuat dokumen seperti ini! (%s)"
#. module: base
#: wizard_field:module.lang.import,init,code:0
msgid "Code (eg:en__US)"
msgstr ""
msgstr "Kode (misal:en__US)"
#. module: base
#: view:workflow:0
#: field:workflow.activity,wkf_id:0
#: field:workflow.instance,wkf_id:0
msgid "Workflow"
msgstr ""
msgstr "Alur kerja"
#. module: base
#: view:wizard.module.lang.export:0
msgid "To browse official translations, you can visit this link: "
msgstr ""
msgstr "Untuk mencari penterjemahan resmi, anda bisa kunjungi tautan ini: "
#. module: base
#: selection:module.lang.install,init,lang:0
msgid "Hungarian / Magyar"
msgstr ""
msgstr "Bahasa Hungaria"
#. module: base
#: field:ir.actions.server,wkf_model_id:0
msgid "Workflow On"
msgstr ""
msgstr "Alur kerja Pada"
#. module: base
#: view:ir.module.module:0
msgid "Created Views"
msgstr ""
msgstr "View Tercipta"
#. module: base
#: view:workflow.activity:0
msgid "Outgoing transitions"
msgstr ""
msgstr "Transisi Keluar"
#. module: base
#: selection:ir.report.custom,frequency:0
msgid "Yearly"
msgstr ""
msgstr "Tahunan"
#. module: base
#: field:ir.actions.act_window,target:0
msgid "Target Window"
msgstr ""
msgstr "Jendela Sasaran"
#. module: base
#: model:ir.actions.todo,note:base.config_wizard_simple_view
@@ -107,6 +107,12 @@ msgid ""
"understand. You will be able to switch to the extended view later.\n"
" "
msgstr ""
"Pilih antara \"Antaramuka Sederhana\" atau yang diperluas.\n"
"Jika anda sedang mencoba atau menggunakan OpenERP untuk pertama kalinya, "
"kami sarankan untuk menggunakan antarmuka sederhana, yang memiliki sedikit "
"opsi dan field namun mudah untuk dipahami dan anda masih dapat merubahnya ke "
"antarmuka yang diperluas nantinya.\n"
" "
#. module: base
#: field:ir.rule,operand:0
@@ -116,93 +122,93 @@ msgstr ""
#. module: base
#: model:res.country,name:base.kr
msgid "South Korea"
msgstr ""
msgstr "Korea Selatan"
#. module: base
#: model:ir.actions.act_window,name:base.action_workflow_transition_form
#: model:ir.ui.menu,name:base.menu_workflow_transition
#: view:workflow.activity:0
msgid "Transitions"
msgstr ""
msgstr "Transisi"
#. module: base
#: model:ir.model,name:base.model_ir_ui_view_custom
msgid "ir.ui.view.custom"
msgstr ""
msgstr "ir.ui.view.custom"
#. module: base
#: model:res.country,name:base.sz
msgid "Swaziland"
msgstr ""
msgstr "Swaziland"
#. module: base
#: model:ir.model,name:base.model_ir_actions_report_custom
#: selection:ir.ui.menu,action:0
msgid "ir.actions.report.custom"
msgstr ""
msgstr "ir.actions.report.custom"
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "STOCK_CANCEL"
msgstr ""
msgstr "STOCK_CANCEL"
#. module: base
#: field:ir.report.custom,sortby:0
msgid "Sorted By"
msgstr ""
msgstr "Diurut Berdasarkan"
#. module: base
#: field:ir.sequence,number_increment:0
msgid "Increment Number"
msgstr ""
msgstr "Kenaikan Angka"
#. module: base
#: model:ir.actions.act_window,name:base.action_res_company_tree
#: model:ir.ui.menu,name:base.menu_action_res_company_tree
msgid "Company's Structure"
msgstr ""
msgstr "Struktur Perusahaan"
#. module: base
#: model:ir.model,name:base.model_ir_report_custom_fields
msgid "ir.report.custom.fields"
msgstr ""
msgstr "ir.report.custom.fields"
#. module: base
#: view:res.partner:0
msgid "Search Partner"
msgstr ""
msgstr "Pencarian Partner"
#. module: base
#: code:addons/base/module/wizard/wizard_export_lang.py:0
#, python-format
msgid "new"
msgstr ""
msgstr "baru"
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "STOCK_GOTO_TOP"
msgstr ""
msgstr "STOCK_GOTO_TOP"
#. module: base
#: field:ir.actions.report.custom,multi:0
#: field:ir.actions.report.xml,multi:0
msgid "On multiple doc."
msgstr ""
msgstr "Pada multi dok."
#. module: base
#: field:ir.module.category,module_nr:0
msgid "Number of Modules"
msgstr ""
msgstr "Jumlah Modul"
#. module: base
#: field:res.partner.bank.type.field,size:0
msgid "Max. Size"
msgstr ""
msgstr "Ukuran Maksimal"
#. module: base
#: field:res.partner.address,name:0
msgid "Contact Name"
msgstr ""
msgstr "Nama Kontak"
#. module: base
#: code:addons/base/module/wizard/wizard_export_lang.py:0
@@ -211,142 +217,145 @@ msgid ""
"Save this document to a %s file and edit it with a specific software or a "
"text editor. The file encoding is UTF-8."
msgstr ""
"Simpan dokumen ini ke dalam file %s dan editlah menggunakan program text "
"editor. Gunakan encoding UTF-8."
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "STOCK_DELETE"
msgstr ""
msgstr "STOCK_DELETE"
#. module: base
#: code:addons/base/ir/ir_model.py:0
#, python-format
msgid "Password mismatch !"
msgstr ""
msgstr "Password tidak sama!"
#. module: base
#: code:addons/base/module/module.py:0
#, python-format
msgid "This url '%s' must provide an html file with links to zip modules"
msgstr ""
"Url '%s' ini harus memiliki sebuah file html dengan tautan ke module zip"
#. module: base
#: selection:res.request,state:0
msgid "active"
msgstr ""
msgstr "aktif"
#. module: base
#: field:ir.actions.wizard,wiz_name:0
msgid "Wizard Name"
msgstr ""
msgstr "Nama Wizard"
#. module: base
#: view:res.lang:0
msgid "%y - Year without century as a decimal number [00,99]."
msgstr ""
msgstr "%y - Tahun tanpa abad sebagai angka desimal [00,99]."
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "STOCK_GOTO_FIRST"
msgstr ""
msgstr "STOCK_GOTO_FIRST"
#. module: base
#: help:ir.rule.group,rules:0
msgid "The rule is satisfied if at least one test is True"
msgstr ""
msgstr "Aturan ini memuaskan jika setidaknya satu test Benar"
#. module: base
#: selection:ir.report.custom.fields,operation:0
msgid "Get Max"
msgstr ""
msgstr "Dapatkan Mak"
#. module: base
#: help:ir.actions.act_window,limit:0
msgid "Default limit for the list view"
msgstr ""
msgstr "Batas baku untuk daftar view"
#. module: base
#: field:ir.model.data,date_update:0
msgid "Update Date"
msgstr ""
msgstr "Tanggal Pembaharuan"
#. module: base
#: field:ir.actions.act_window,src_model:0
msgid "Source Object"
msgstr ""
msgstr "Sumber Obyek"
#. module: base
#: model:ir.actions.act_window,name:base.act_ir_actions_todo_form
#: view:ir.actions.todo:0
#: model:ir.ui.menu,name:base.menu_ir_actions_todo_form
msgid "Config Wizard Steps"
msgstr ""
msgstr "Langkah Konfigurasi Wizard"
#. module: base
#: model:ir.model,name:base.model_ir_ui_view_sc
msgid "ir.ui.view_sc"
msgstr ""
msgstr "ir.ui.view_sc"
#. module: base
#: field:ir.model.access,group_id:0
#: field:ir.rule,rule_group:0
msgid "Group"
msgstr ""
msgstr "Grup"
#. module: base
#: field:ir.exports.line,name:0
#: field:ir.translation,name:0
#: field:res.partner.bank.type.field,name:0
msgid "Field Name"
msgstr ""
msgstr "Nama Kolom"
#. module: base
#: model:ir.actions.act_window,name:base.open_module_tree_uninstall
#: model:ir.ui.menu,name:base.menu_module_tree_uninstall
msgid "Uninstalled modules"
msgstr ""
msgstr "Modul belum terinstal"
#. module: base
#: selection:ir.actions.report.xml,report_type:0
msgid "txt"
msgstr ""
msgstr "txt"
#. module: base
#: wizard_view:server.action.create,init:0
#: wizard_field:server.action.create,init,type:0
msgid "Select Action Type"
msgstr ""
msgstr "Pilih Jenis Aksi"
#. module: base
#: selection:ir.actions.todo,type:0
msgid "Configure"
msgstr ""
msgstr "Konfigur"
#. module: base
#: model:res.country,name:base.tv
msgid "Tuvalu"
msgstr ""
msgstr "Tuvalu"
#. module: base
#: selection:ir.model,state:0
#: selection:ir.model.grid,state:0
msgid "Custom Object"
msgstr ""
msgstr "Obyek Kesukaan"
#. module: base
#: field:res.lang,date_format:0
msgid "Date Format"
msgstr ""
msgstr "Format Tanggal"
#. module: base
#: field:res.bank,email:0
#: field:res.partner.address,email:0
msgid "E-Mail"
msgstr ""
msgstr "E-Mail"
#. module: base
#: model:res.country,name:base.an
msgid "Netherlands Antilles"
msgstr ""
msgstr "Netherlands Antilles"
#. module: base
#: code:addons/base/res/res_user.py:0
@@ -355,21 +364,23 @@ msgid ""
"You can not remove the admin user as it is used internally for resources "
"created by OpenERP (updates, module installation, ...)"
msgstr ""
"Anda tidak dapat menghapus pengguna admin sebab digunakan secara internal "
"sebagai sumber yang dibuat oleh OpenERP (pembaharuan, instalasi modul, ...)"
#. module: base
#: model:res.country,name:base.gf
msgid "French Guyana"
msgstr ""
msgstr "Guyana Perancis"
#. module: base
#: field:ir.ui.view.custom,ref_id:0
msgid "Original View"
msgstr ""
msgstr "View Asli"
#. module: base
#: selection:module.lang.install,init,lang:0
msgid "Bosnian / bosanski jezik"
msgstr ""
msgstr "Bosnia"
#. module: base
#: help:ir.actions.report.xml,attachment_use:0
@@ -381,27 +392,27 @@ msgstr ""
#. module: base
#: help:res.lang,iso_code:0
msgid "This ISO code is the name of po files to use for translations"
msgstr ""
msgstr "Kode ISO ini adalah nama file po untuk digunakan pada penerjemahan"
#. module: base
#: selection:ir.ui.menu,icon:0
msgid "STOCK_MEDIA_REWIND"
msgstr ""
msgstr "STOCK_MEDIA_REWIND"
#. module: base
#: field:ir.actions.todo,note:0
msgid "Text"
msgstr ""
msgstr "Teks"
#. module: base
#: field:res.country,name:0
msgid "Country Name"
msgstr ""
msgstr "Nama Negara"
#. module: base
#: model:res.country,name:base.coreturn
msgid "Colombia"
msgstr ""
msgstr "Kolombia"
#. module: base
#: view:ir.module.module:0
+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-26 06:37+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-27 03:37+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-26 06:47+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-27 03:37+0000\n"
"X-Launchpad-Export-Date: 2010-09-03 03:44+0000\n"
"X-Generator: Launchpad (build Unknown)\n"
#. module: base
+1242 -1161
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-26 06:38+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-27 03:37+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-26 06:50+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-27 03:37+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-26 06:41+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-27 03:37+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-26 06:49+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-27 03:38+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
+17 -29
View File
@@ -179,14 +179,13 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Sequences">
<field name="name"/>
<field name="code"/>
<field name="name"/>
<field name="prefix"/>
<field name="padding"/>
<field name="company_id" groups="base.group_multi_company"/>
<field name="number_next"/>
<field name="number_increment"/>
<field name="active"/>
</tree>
</field>
</record>
@@ -197,10 +196,10 @@
<field name="type">search</field>
<field name="arch" type="xml">
<search string="Sequences">
<field name="name" select="1"/>
<field name="code" select="1"/>
<field name="name"/>
<field name="code"/>
<separator orientation="vertical"/>
<field name="company_id" select="1"/>
<field name="company_id" select="1" groups="base.group_multi_company"/>
</search>
</field>
</record>
@@ -709,7 +708,6 @@
<menuitem id="menu_res_company_global"
parent="base.menu_administration"
name="Companies"
groups="base.group_multi_company"
sequence="5"/>
<record id="action_res_company_tree" model="ir.actions.act_window">
@@ -884,13 +882,12 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Views">
<field name="priority"/>
<field name="priority" string="Sequence"/>
<field name="name"/>
<field name="type"/>
<field name="model"/>
<field name="xml_id"/>
<field name="inherit_id"/>
<field name="field_parent"/>
</tree>
</field>
</record>
@@ -1201,11 +1198,6 @@
<field name="model"/>
<field name="state"/>
<field name="osv_memory"/>
<button colspan="2"
icon="gtk-justify-fill"
name="%(act_menu_create)d"
string="Create a Menu" type="action"
target="new" />
</tree>
</field>
</record>
@@ -1324,9 +1316,8 @@
<tree string="Module Data">
<field name="module"/>
<field name="name"/>
<field name="model" select="1" />
<field name="model"/>
<field name="res_id"/>
<field name="noupdate"/>
</tree>
</field>
</record>
@@ -1543,13 +1534,12 @@
<field name="type">tree</field>
<field name="arch" type="xml">
<tree string="Scheduled Actions">
<field name="priority"/>
<field name="priority" string="Sequence"/>
<field name="name"/>
<field name="nextcall"/>
<field name="interval_number"/>
<field name="interval_type"/>
<field name="numbercall"/>
<field name="active"/>
<field name="user_id" invisible="1"/>
</tree>
</field>
@@ -1915,9 +1905,12 @@
<field name="arch" type="xml">
<tree editable="bottom" string="Config Wizard Steps">
<field name="sequence"/>
<field name="action_id" select="1"/>
<field name="state"/>
<button name="action_id" states="open,skip" string="Launch" type="action" icon="gtk-execute" help="Launch Configuration Wizard"/>
<field name="action_id"/>
<field name="state" readonly="1"/>
<button name="action_launch" states="open" string="Launch" type="object" icon="gtk-execute" help="Launch Configuration Wizard"/>
<button name="action_open" states="cancel,skip,done"
string="Set as Todo" type="object"
icon="gtk-convert"/>
</tree>
</field>
</record>
@@ -1929,21 +1922,16 @@
<field name="arch" type="xml">
<form editable="bottom" string="Config Wizard Steps">
<group colspan="4" col="6">
<field name="sequence"/>
<field name="action_id" select="1"/>
<field name="action_id"/>
<field name="restart"/>
<field name="sequence"/>
</group>
<separator string="Groups" colspan="4"/>
<field name="groups_id" nolabel="1" colspan="4"/>
<separator string="State" colspan="4"/>
<group colspan="4" col="4">
<field name="state" colspan="2" readonly="1"/>
<!--TO CHECK: This is working in tree view but not here in form view -->
<button name="action_id" states="open,skip"
string="Launch" type="action"
icon="gtk-execute"
help="Launch Configuration Wizard" />
<button name="action_open" states="cancel,done"
<button name="action_launch" states="open" string="Launch" type="object" icon="gtk-execute" help="Launch Configuration Wizard"/>
<button name="action_open" states="cancel,skip,done"
string="Set as Todo" type="object"
icon="gtk-convert"/>
</group>
+10
View File
@@ -757,6 +757,16 @@ class ir_actions_todo(osv.osv):
}
_order="sequence,id"
def action_launch(self, cr, uid, ids, context=None):
""" Launch Action of Wizard"""
if context is None:
context = {}
wizard_id = ids and ids[0] or False
wizard = self.browse(cr, uid, wizard_id, context=context)
res = self.pool.get('ir.actions.act_window').read(cr, uid, wizard.action_id.id, ['name', 'view_type', 'view_mode', 'res_model', 'context', 'views', 'type'], context=context)
res.update({'target':'new', 'nodestroy': True})
return res
def action_open(self, cr, uid, ids, context=None):
""" Sets configuration wizard in TODO state"""
return self.write(cr, uid, ids, {'state': 'open'}, context=context)
-5
View File
@@ -44,11 +44,6 @@ class ir_filters(osv.osv):
'context': fields.text('Context Value', required=True),
'model_id': fields.selection(_list_all_models, 'Model', required=True),
}
def get_filters(self, cr, uid, model):
act_ids = self.search(cr,uid,[('model_id','=',model),('user_id','=',uid)])
my_acts = self.read(cr, uid, act_ids, ['name', 'domain','context'])
return my_acts
ir_filters()
+2 -1
View File
@@ -80,6 +80,7 @@ class ir_ui_menu(osv.osv):
menu_id = self.pool.get('ir.ui.menu').create(cr, uid, menu_data)
sc_data= {'name':values['name'], 'sequence': 1,'res_id': menu_id }
sc_menu_id = self.pool.get('ir.ui.view_sc').create(cr, uid, sc_data, context)
user_groups = set(self.pool.get('res.users').read(cr, 1, uid, ['groups_id'])['groups_id'])
key = (cr.dbname, shortcut_menu_id, tuple(user_groups))
self._cache[key] = True
@@ -182,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)'
+9 -8
View File
@@ -222,14 +222,15 @@ class ir_values(osv.osv):
res2 = res[:]
for r in res:
if type(r[2])==type({}) and 'type' in r[2]:
groups = r[2].get('groups_id')
if groups:
cr.execute('SELECT COUNT(1) FROM res_groups_users_rel WHERE gid IN %s AND uid=%s',(tuple(groups), uid))
cnt = cr.fetchone()[0]
if cnt:
res2.remove(r)
if r[1] == 'Menuitem' and not res2:
raise osv.except_osv('Error !','You do not have the permission to perform this operation !!!')
if r[2]['type'] in ('ir.actions.report.xml','ir.actions.act_window','ir.actions.wizard'):
groups = r[2].get('groups_id')
if groups:
cr.execute('SELECT COUNT(1) FROM res_groups_users_rel WHERE gid IN %s AND uid=%s',(tuple(groups), uid))
cnt = cr.fetchone()[0]
if not cnt:
res2.remove(r)
if r[1] == 'Menuitem' and not res2:
raise osv.except_osv('Error !','You do not have the permission to perform this operation !!!')
return res2
ir_values()
+10
View File
@@ -118,6 +118,16 @@
<xsl:value-of select="."/>
</font></para>
</xsl:when>
<xsl:when test="@tree='undefined'">
<para>
<xsl:attribute name="leftIndent">
<xsl:value-of select="@space"/>
</xsl:attribute>
<font fontName="Helvetica-Bold" fontSize="9" color="gray">
<xsl:value-of select="."/>
</font>
</para>
</xsl:when>
<xsl:otherwise>
<para>
+19 -9
View File
@@ -72,7 +72,7 @@ class res_config_configurable(osv.osv_memory):
config_logo = _get_image
)
def _next_action(self, cr, uid):
def _next_action(self, cr, uid, context=None):
todos = self.pool.get('ir.actions.todo')
self.logger.notifyChannel('actions', netsvc.LOG_INFO,
'getting next %s' % todos)
@@ -92,7 +92,7 @@ class res_config_configurable(osv.osv_memory):
return self._next_action(cr, uid)
return None
def _set_previous_todo(self, cr, uid, state):
def _set_previous_todo(self, cr, uid, state, context=None):
""" lookup the previous (which is still the next at this point)
ir.actions.todo, set it to whatever state was provided.
@@ -101,10 +101,12 @@ class res_config_configurable(osv.osv_memory):
`ValueError`: if no state is provided
anything ir_actions_todo.write can throw
"""
if context is None:
context = {}
# this is ultra brittle, but apart from storing the todo id
# into the res.config view, I'm not sure how to get the
# "previous" todo
previous_todo = self._next_action(cr, uid)
previous_todo = self._next_action(cr, uid, context=context)
if not previous_todo:
raise LookupError(_("Couldn't find previous ir.actions.todo"))
if not state:
@@ -112,7 +114,7 @@ class res_config_configurable(osv.osv_memory):
"nothingness"))
previous_todo.write({'state':state})
def _next(self, cr, uid):
def _next(self, cr, uid, context=None):
self.logger.notifyChannel('actions', netsvc.LOG_INFO,
'getting next operation')
next = self._next_action(cr, uid)
@@ -139,7 +141,6 @@ class res_config_configurable(osv.osv_memory):
.read(cr, uid, current_user_menu.id)
def start(self, cr, uid, ids, context=None):
print 'Start'
ids2 = self.pool.get('ir.actions.todo').search(cr, uid, [], context=context)
for todo in self.pool.get('ir.actions.todo').browse(cr, uid, ids2, context=context):
if (todo.restart=='always') or (todo.restart=='onskip' and (todo.state in ('skip','cancel'))):
@@ -150,7 +151,7 @@ class res_config_configurable(osv.osv_memory):
""" Returns the next todo action to execute (using the default
sort order)
"""
return self._next(cr, uid)
return self._next(cr, uid, context=context)
def execute(self, cr, uid, ids, context=None):
""" Method called when the user clicks on the ``Next`` button.
@@ -185,7 +186,10 @@ class res_config_configurable(osv.osv_memory):
an action dictionary -- executes the action provided by calling
``next``.
"""
self._set_previous_todo(cr, uid, state='done')
try:
self._set_previous_todo(cr, uid, state='done', context=context)
except Exception, e:
raise osv.except_osv(_('Error'), e.message)
next = self.execute(cr, uid, ids, context=None)
if next: return next
return self.next(cr, uid, ids, context=context)
@@ -198,7 +202,10 @@ class res_config_configurable(osv.osv_memory):
an action dictionary -- executes the action provided by calling
``next``.
"""
self._set_previous_todo(cr, uid, state='skip')
try:
self._set_previous_todo(cr, uid, state='skip', context=context)
except Exception, e:
raise osv.except_osv(_('Error'), e.message)
next = self.cancel(cr, uid, ids, context=None)
if next: return next
return self.next(cr, uid, ids, context=context)
@@ -214,7 +221,10 @@ class res_config_configurable(osv.osv_memory):
an action dictionary -- executes the action provided by calling
``next``.
"""
self._set_previous_todo(cr, uid, state='cancel')
try:
self._set_previous_todo(cr, uid, state='cancel', context=context)
except Exception, e:
raise osv.except_osv(_('Error'), e.message)
next = self.cancel(cr, uid, ids, context=None)
if next: return next
return self.next(cr, uid, ids, context=context)
+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">
+12 -1
View File
@@ -209,13 +209,17 @@ class users(osv.osv):
return dict(zip(ids, ['extended' if user in extended_users else 'simple' for user in ids]))
def _email_get(self, cr, uid, ids, name, arg, context=None):
return dict([(user.id, user.address_id.email) for user in self.browse(cr, uid, ids, context=context)])
# perform this as superuser because the current user is allowed to read users, and that includes
# the email, even without any direct read access on the res_partner_address object.
return dict([(user.id, user.address_id.email) for user in self.browse(cr, 1, ids)]) # no context to avoid potential security issues as superuser
def _email_set(self, cr, uid, ids, name, value, arg, context=None):
if not isinstance(ids,list):
ids = [ids]
address_obj = self.pool.get('res.partner.address')
for user in self.browse(cr, uid, ids, context=context):
# perform this as superuser because the current user is allowed to write to the user, and that includes
# the email even without any direct write access on the res_partner_address object.
if user.address_id:
address_obj.write(cr, 1, user.address_id.id, {'email': value or None}) # no context to avoid potential security issues as superuser
else:
@@ -264,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" />
+163 -154
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 !'))
@@ -1830,7 +1927,33 @@ class orm_template(object):
def _check_removed_columns(self, cr, log=False):
raise NotImplementedError()
def _add_missing_default_values(self, cr, uid, values, context=None):
missing_defaults = []
avoid_tables = [] # avoid overriding inherited values when parent is set
for tables, parent_field in self._inherits.items():
if parent_field in values:
avoid_tables.append(tables)
for field in self._columns.keys():
if not field in values:
missing_defaults.append(field)
for field in self._inherit_fields.keys():
if (field not in values) and (self._inherit_fields[field][0] not in avoid_tables):
missing_defaults.append(field)
if len(missing_defaults):
# override defaults with the provided values, never allow the other way around
defaults = self.default_get(cr, uid, missing_defaults, context)
for dv in defaults:
# FIXME: also handle inherited m2m
if dv in self._columns and self._columns[dv]._type == 'many2many' \
and defaults[dv] and isinstance(defaults[dv][0], (int, long)):
defaults[dv] = [(6, 0, defaults[dv])]
defaults.update(values)
values = defaults
return values
class orm_memory(orm_template):
_protected = ['read', 'write', 'create', 'default_get', 'perm_read', 'unlink', 'fields_get', 'fields_view_get', 'search', 'name_get', 'distinct_field_get', 'name_search', 'copy', 'import_data', 'search_count', 'exists']
_inherit_fields = {}
_max_count = 200
@@ -1922,10 +2045,7 @@ class orm_memory(orm_template):
self.next_id += 1
id_new = self.next_id
# override defaults with the provided values, never allow the other way around
defaults = self.default_get(cr, user, [], context)
defaults.update(vals)
vals = defaults
vals = self._add_missing_default_values(cr, user, vals, context)
vals2 = {}
upd_todo = []
@@ -1975,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 = {}
@@ -3385,30 +3504,7 @@ class orm(orm_template):
context = {}
self.pool.get('ir.model.access').check(cr, user, self._name, 'create', context=context)
default = []
avoid_table = []
for (t, c) in self._inherits.items():
if c in vals:
avoid_table.append(t)
for f in self._columns.keys(): # + self._inherit_fields.keys():
if not f in vals:
default.append(f)
for f in self._inherit_fields.keys():
if (not f in vals) and (self._inherit_fields[f][0] not in avoid_table):
default.append(f)
if len(default):
default_values = self.default_get(cr, user, default, context)
for dv in default_values:
if dv in self._columns and self._columns[dv]._type == 'many2many':
if default_values[dv] and isinstance(default_values[dv][0], (int, long)):
default_values[dv] = [(6, 0, default_values[dv])]
# override defaults with the provided values, never allow the other way around
default_values.update(vals)
vals = default_values
vals = self._add_missing_default_values(cr, user, vals, context)
tocreate = {}
for v in self._inherits:
@@ -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
+19 -7
View File
@@ -83,20 +83,21 @@ class report_printscreen_list(report_int):
for rec in records:
rec['__group'] = True
rec['__no_leaf'] = self.groupby_no_leaf
rec['__grouped_by'] = groupby[0] if (isinstance(groupby, list) and groupby) else groupby
for f in fields_order:
if f not in rec:
rec.update({f:False})
elif isinstance(rec[f], tuple):
rec[f] = rec[f][1]
rows.append(rec)
groupby = (rec.get('__context', {})).get('group_by',[])
domain = rec.get('__domain', [])
if groupby:
get_groupby_data(groupby, domain)
inner_groupby = (rec.get('__context', {})).get('group_by',[])
inner_domain = rec.get('__domain', [])
if inner_groupby:
get_groupby_data(inner_groupby, inner_domain)
else:
if self.groupby_no_leaf:
continue
child_ids = model.search(cr, uid, domain)
child_ids = model.search(cr, uid, inner_domain)
res = model.read(cr, uid, child_ids, result['fields'].keys(), context)
rows.extend(res)
dom = [('id','in',ids)]
@@ -175,7 +176,7 @@ class report_printscreen_list(report_int):
count += 1
if fields[f]['type']=='many2one' and line[f]:
if not line.get('__group'):
line[f]= line[f][1]
line[f] = line[f][1]
if fields[f]['type']=='selection' and line[f]:
for key, value in fields[f]['selection']:
if key == line[f]:
@@ -212,10 +213,18 @@ class report_printscreen_list(report_int):
d1 = datetime.strptime(line[f], '%Y-%m-%d %H:%M:%S')
new_d1 = d1.strftime(format)
line[f] = new_d1
if line.get('__group'):
col = etree.SubElement(node_line, 'col', para='group', tree='no')
else:
col = etree.SubElement(node_line, 'col', para='yes', tree='no')
# Prevent empty labels in groups
if f == line.get('__grouped_by') and line.get('__group') and not line[f] and not float_flag and not temp[count]:
col.text = line[f] = 'Undefined'
col.set('tree', 'undefined')
if line[f] != None:
col.text = tools.ustr(line[f] or '')
if float_flag:
@@ -225,7 +234,10 @@ class report_printscreen_list(report_int):
if not line.get('__group') and f != 'id' and temp[count] == 1:
tsum[count] = float(tsum[count]) + float(line[f]);
else:
col.text = '/'
col.text = '/'
node_line = etree.SubElement(lines, 'row')
for f in range(0, len(fields_order)):
col = etree.SubElement(node_line, 'col', para='group', tree='no')
+11 -8
View File
@@ -364,15 +364,18 @@ class _rml_canvas(object):
image_data = self.images[node.get('name')]
s = cStringIO.StringIO(image_data)
else:
import base64
if self.localcontext:
res = utils._regex.findall(node.text)
for key in res:
newtext = eval(key, {}, self.localcontext)
node.text = newtext
image_data = base64.decodestring(node.text)
if not image_data: return False
s = cStringIO.StringIO(image_data)
res = utils._regex.findall(node.text)
for key in res:
newtext = eval(key, {}, self.localcontext)
node.text = newtext
image_data = None
if node.text:
image_data = base64.decodestring(node.text)
if image_data:
s = cStringIO.StringIO(image_data)
else:
return False
else:
if node.get('file') in self.images:
s = cStringIO.StringIO(self.images[node.get('file')])
+19 -11
View File
@@ -523,29 +523,35 @@ form: module.record_id""" % (xml_id,)
m_l = map(escape, escape_re.split(rec.get("name",'').encode('utf8')))
values = {'parent_id': False}
if not rec.get('parent'):
if rec.get('parent', False) is False and len(m_l) > 1:
# No parent attribute specified and the menu name has several menu components,
# try to determine the ID of the parent according to menu path
pid = False
res = None
values['name'] = m_l[-1]
m_l = m_l[:-1] # last part is our name, not a parent
for idx, menu_elem in enumerate(m_l):
if pid:
cr.execute('select id from ir_ui_menu where parent_id=%s and name=%s', (pid, menu_elem))
else:
cr.execute('select id from ir_ui_menu where parent_id is null and name=%s', (menu_elem,))
res = cr.fetchone()
if idx==len(m_l)-1:
values = {'parent_id': pid,'name':menu_elem}
elif res:
if res:
pid = res[0]
xml_id = idx==len(m_l)-1 and rec.get('id','').encode('utf8')
try:
self.pool.get('ir.model.data')._update_dummy(cr, self.uid, 'ir.ui.menu', self.module, xml_id, idx==len(m_l)-1)
except:
self.logger.notifyChannel('init', netsvc.LOG_ERROR, "module: %s xml_id: %s" % (self.module, xml_id))
else:
# the menuitem does't exist but we are in branch (not a leaf)
self.logger.notifyChannel("init", netsvc.LOG_WARNING, 'Warning no ID for submenu %s of menu %s !' % (menu_elem, str(m_l)))
pid = self.pool.get('ir.ui.menu').create(cr, self.uid, {'parent_id' : pid, 'name' : menu_elem})
values['parent_id'] = pid
else:
menu_parent_id = self.id_get(cr, 'ir.ui.menu', rec.get('parent',''))
# The parent attribute was specified, if non-empty determine its ID, otherwise
# explicitly make a top-level menu
if rec.get('parent'):
menu_parent_id = self.id_get(cr, 'ir.ui.menu', rec.get('parent',''))
else:
# we get here with <menuitem parent="">, explicit clear of parent, or
# if no parent attribute at all but menu name is not a menu path
menu_parent_id = False
values = {'parent_id': menu_parent_id}
if rec.get('name'):
values['name'] = rec.get('name')
@@ -793,7 +799,9 @@ form: module.record_id""" % (xml_id,)
def id_get(self, cr, model, id_str):
if id_str in self.idref:
return self.idref[id_str]
return self.model_id_get(cr, model, id_str)[1]
res = self.model_id_get(cr, model, id_str)
if res and len(res)>1: res = res[1]
return res
def model_id_get(self, cr, model, id_str):
model_data_obj = self.pool.get('ir.model.data')
+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)