[MERGE] upstream

bzr revid: fme@openerp.com-20140225105045-9t4a443nq0lw55qu
This commit is contained in:
Fabien Meghazi 2014-02-25 11:50:45 +01:00
commit 5da9305bf5
92 changed files with 544 additions and 301 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-14 06:36+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:25+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,7 +25,7 @@ msgid ""
" "
msgstr ""
"\n"
"Moduuli Šekkien kirjoittamisen ja tulostamiseen.\n"
"Moduuli Shekkien kirjoittamisen ja tulostamiseen.\n"
"===========================================\n"
" "
@ -129,7 +129,7 @@ msgstr ""
"Moduuli joka lisää valmistajat ja ominaisuudet tuotelomakkeelle.\n"
"=========================================================\n"
"\n"
"Voit net määritellä tuotteelle seuraavat tiedot:\n"
"Voit nyt määritellä tuotteelle seuraavat tiedot:\n"
"---------------------------------------------------------\n"
" * Valmistaja\n"
" * Valmistajan tuotenimi\n"
@ -688,7 +688,7 @@ msgstr "Palau"
#. module: base
#: view:res.partner:0
msgid "Sales & Purchases"
msgstr "Myynti ja hankinta"
msgstr "Myynnit & Ostot"
#. module: base
#: view:ir.translation:0
@ -3836,7 +3836,7 @@ msgstr "Raportointi"
#: field:res.partner,title:0
#: field:res.partner.title,name:0
msgid "Title"
msgstr "Yhtiömuoto"
msgstr "Titteli"
#. module: base
#: help:ir.property,res_id:0
@ -10138,7 +10138,7 @@ msgstr ""
#: view:res.groups:0
#: field:res.partner,comment:0
msgid "Notes"
msgstr "Huomautukset"
msgstr "Muistiinpanot"
#. module: base
#: field:ir.config_parameter,value:0
@ -15482,7 +15482,7 @@ msgstr "Matkapuhelinnumero"
#: model:ir.model,name:base.model_res_partner_category
#: view:res.partner.category:0
msgid "Partner Categories"
msgstr "Kumppanien ryhmät"
msgstr "Kumppaniryhmät"
#. module: base
#: view:base.module.upgrade:0
@ -15690,7 +15690,7 @@ msgstr ""
#. module: base
#: view:res.partner:0
msgid "Internal Notes"
msgstr "Sisäiset huomautukset"
msgstr "Sisäiset muistiinpanot"
#. module: base
#: model:res.partner.title,name:base.res_partner_title_pvt_ltd

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2014-02-14 06:39+0000\n"
"X-Generator: Launchpad (build 16916)\n"
"X-Launchpad-Export-Date: 2014-02-22 06:28+0000\n"
"X-Generator: Launchpad (build 16926)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -2295,7 +2295,7 @@ msgstr "メソッド"
#. module: base
#: model:ir.module.module,shortdesc:base.module_auth_crypt
msgid "Password Encryption"
msgstr ""
msgstr "パスワード暗号化"
#. module: base
#: view:workflow.activity:0
@ -8016,6 +8016,12 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" クリックしてアドレス帳に連絡先を追加してください。\n"
" </p><p>\n"
" OpenERPは顧客、ディスカッション、商機の履歴、文書など関連するすべての活動の追跡を容易にします。\n"
" </p>\n"
" "
#. module: base
#: model:ir.actions.act_window,name:base.bank_account_update
@ -9789,7 +9795,7 @@ msgstr "ドイツ"
#. module: base
#: model:ir.module.module,shortdesc:base.module_auth_oauth
msgid "OAuth2 Authentication"
msgstr ""
msgstr "OAuth2認証"
#. module: base
#: view:workflow:0
@ -10032,6 +10038,12 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" クリックしてアドレス帳に連絡先を追加してください。\n"
" </p><p>\n"
" OpenERPは仕入先、ディスカッション、購入の履歴、文書など関連するすべての活動の追跡を容易にします。\n"
" </p>\n"
" "
#. module: base
#: model:res.country,name:base.lr
@ -15563,6 +15575,12 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
" クリックしてアドレス帳に連絡先を追加してください。\n"
" </p><p>\n"
" OpenERPは顧客、ディスカッション、商機の履歴、文書など関連するすべての活動の追跡を容易にします。\n"
" </p>\n"
" "
#. module: base
#: model:res.partner.category,name:base.res_partner_category_2

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -24,6 +24,8 @@ import logging
import operator
import os
import time
import datetime
import dateutil
import openerp
from openerp import SUPERUSER_ID
@ -268,7 +270,7 @@ class ir_actions_act_window(osv.osv):
'filter': fields.boolean('Filter'),
'auto_search':fields.boolean('Auto Search'),
'search_view' : fields.function(_search_view, type='text', string='Search View'),
'multi': fields.boolean('Action on Multiple Doc.', help="If set to true, the action will not be displayed on the right toolbar of a form view"),
'multi': fields.boolean('Restrict to lists', help="If checked and the action is bound to a model, it will only appear in the More menu on list views"),
}
_defaults = {
@ -550,6 +552,7 @@ class ir_actions_server(osv.osv):
# - uid: current user id
# - context: current context
# - time: Python time module
# - workflow: Workflow engine
# If you plan to return an action, assign: action = {...}""",
'use_relational_model': 'base',
'use_create': 'new',
@ -928,9 +931,13 @@ class ir_actions_server(osv.osv):
'obj': obj,
'pool': self.pool,
'time': time,
'datetime': datetime,
'dateutil': dateutil,
'cr': cr,
'uid': uid,
'user': user,
'context': context,
'workflow': workflow
}
def run(self, cr, uid, ids, context=None):
@ -955,7 +962,6 @@ class ir_actions_server(osv.osv):
if context is None:
context = {}
res = False
active_ids = context.get('active_ids', [context.get('active_id')])
for action in self.browse(cr, uid, ids, context):
eval_context = self._get_eval_context(cr, uid, action, context=context)
condition = action.condition
@ -963,9 +969,7 @@ class ir_actions_server(osv.osv):
# Void (aka False) conditions are considered as True
condition = True
if hasattr(self, 'run_action_%s_multi' % action.state):
# set active_ids in context only needed if one active_id
run_context = dict(context, active_ids=active_ids)
eval_context["context"] = run_context
run_context = eval_context['context']
expr = eval(str(condition), eval_context)
if not expr:
continue
@ -975,6 +979,8 @@ class ir_actions_server(osv.osv):
elif hasattr(self, 'run_action_%s' % action.state):
func = getattr(self, 'run_action_%s' % action.state)
active_id = context.get('active_id')
active_ids = context.get('active_ids', [active_id] if active_id else [])
for active_id in active_ids:
# run context dedicated to a particular active_id
run_context = dict(context, active_ids=[active_id], active_id=active_id)

View File

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

View File

@ -316,14 +316,14 @@ class view(osv.osv):
return node
return None
def inherit_branding(self, specs_tree, view_id, source_id):
def inherit_branding(self, specs_tree, view_id, root_id):
for node in specs_tree.iterchildren(tag=etree.Element):
xpath = node.getroottree().getpath(node)
if node.tag == 'data' or node.tag == 'xpath':
self.inherit_branding(node, view_id, source_id)
self.inherit_branding(node, view_id, root_id)
else:
node.set('data-oe-id', str(view_id))
node.set('data-oe-source-id', str(source_id))
node.set('data-oe-source-id', str(root_id))
node.set('data-oe-xpath', xpath)
node.set('data-oe-model', 'ir.ui.view')
node.set('data-oe-field', 'arch')
@ -397,7 +397,7 @@ class view(osv.osv):
return source
def apply_view_inheritance(self, cr, uid, source, source_id, model, context=None):
def apply_view_inheritance(self, cr, uid, source, source_id, model, root_id=None, context=None):
""" Apply all the (directly and indirectly) inheriting views.
:param source: a parent architecture to modify (with parent modifications already applied)
@ -408,13 +408,15 @@ class view(osv.osv):
:return: a modified source where all the modifying architecture are applied
"""
if context is None: context = {}
if root_id is None:
root_id = source_id
sql_inherit = self.pool.get('ir.ui.view').get_inheriting_views_arch(cr, uid, source_id, model, context=context)
for (specs, view_id) in sql_inherit:
specs_tree = etree.fromstring(specs.encode('utf-8'))
if context.get('inherit_branding'):
self.inherit_branding(specs_tree, view_id, source_id)
self.inherit_branding(specs_tree, view_id, root_id)
source = self.apply_inheritance_specs(cr, uid, source, specs_tree, view_id, context=context)
source = self.apply_view_inheritance(cr, uid, source, view_id, model, context=context)
source = self.apply_view_inheritance(cr, uid, source, view_id, model, root_id=root_id, context=context)
return source
def read_combined(self, cr, uid, view_id, fields=None, context=None):
@ -755,6 +757,10 @@ class view(osv.osv):
# running index by tag type, for XPath query generation
indexes = collections.defaultdict(lambda: 0)
for child in e.iterchildren(tag=etree.Element):
if child.get('data-oe-xpath'):
# injected by view inheritance, skip otherwise
# generated xpath is incorrect
continue
indexes[child.tag] += 1
self.distribute_branding(child, distributed_branding,
parent_xpath=node_path,

View File

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

View File

@ -124,7 +124,8 @@ class res_company(osv.osv):
'rml_footer': fields.text('Report Footer', help="Footer text displayed at the bottom of all reports."),
'rml_footer_readonly': fields.related('rml_footer', type='text', string='Report Footer', readonly=True),
'custom_footer': fields.boolean('Custom Footer', help="Check this to define the report footer manually. Otherwise it will be filled in automatically."),
'font': fields.many2one('res.font', string="Font",help="Set the font into the report header, it will be used as default font in the RML reports of the user company"),
'font': fields.many2one('res.font', string="Font", domain=[('mode', 'in', ('Normal', 'Regular', 'all', 'Book'))],
help="Set the font into the report header, it will be used as default font in the RML reports of the user company"),
'logo': fields.related('partner_id', 'image', string="Logo", type="binary"),
'logo_web': fields.function(_get_logo_web, string="Logo Web", type="binary", store={
'res.company': (lambda s, c, u, i, x: i, ['partner_id'], 10),

View File

@ -93,7 +93,7 @@
<label for="font" />
<div>
<div>
<field name="font" class="oe_inline" colspan="2" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)" domain="[('mode', 'in', ('normal', 'regular', 'all', 'book'))]" />
<field name="font" class="oe_inline" colspan="2" on_change="onchange_font_name(font, rml_header, rml_header2, rml_header3)" />
<button string="(reload fonts)" name="act_discover_fonts" type="object" class="oe_link" colspan="1"/>
</div>
</div>

View File

@ -209,6 +209,7 @@ class res_partner(osv.osv, format_address):
context = dict(context or {})
context.pop('show_address', None)
context.pop('show_address_only', None)
context.pop('show_email', None)
return dict(self.name_get(cr, uid, ids, context=context))
# indirections to avoid passing a copy of the overridable method when declaring the function field

View File

@ -906,6 +906,8 @@ class change_password_wizard(osv.TransientModel):
for user in wizard.user_ids:
user_ids.append(user.id)
self.pool.get('change.password.user').change_password_button(cr, uid, user_ids, context=context)
# don't keep temporary password copies in the database longer than necessary
self.pool.get('change.password.user').unlink(cr, uid, user_ids)
return {
'type': 'ir.actions.act_window_close',
}

View File

@ -231,7 +231,7 @@
<field name="model">res.users</field>
<field name="arch" type="xml">
<search string="Users">
<field name="name" filter_domain="['|', '|', ('name','ilike',self), ('login','ilike',self), ('email,'ilike',self)]" string="User"/>
<field name="name" filter_domain="['|', '|', ('name','ilike',self), ('login','ilike',self), ('email','ilike',self)]" string="User"/>
<field name="company_ids" string="Company" groups="base.group_multi_company"/>
</search>
</field>

View File

@ -289,6 +289,7 @@ class test_base(common.TransactionCase):
{'name': 'Alice', 'login': 'alice', 'color': 1, 'function': 'Friend'},
{'name': 'Bob', 'login': 'bob', 'color': 2, 'function': 'Friend'},
{'name': 'Eve', 'login': 'eve', 'color': 3, 'function': 'Eavesdropper'},
{'name': 'Nab', 'login': 'nab', 'color': 2, 'function': '5$ Wrench'},
]:
self.res_users.create(cr, uid, user_data)
@ -298,6 +299,14 @@ class test_base(common.TransactionCase):
self.assertIn('color', group_data, "Aggregated data for the column 'color' is not present in read_group return values")
self.assertEqual(group_data['color'], 3, "Incorrect sum for aggregated data for the column 'color'")
groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve'))], fields=['name', 'color'], groupby='name', orderby='name DESC, color asc')
self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
self.assertEqual([user['name'] for user in groups_data], ['Eve', 'Bob', 'Alice'], 'Incorrect ordering of the list')
groups_data = self.res_users.read_group(cr, uid, domain=[('login', 'in', ('alice', 'bob', 'eve', 'nab'))], fields=['function', 'color'], groupby='function', orderby='color ASC')
self.assertEqual(len(groups_data), 3, "Incorrect number of results when grouping on a field")
self.assertEqual(groups_data, sorted(groups_data, key=lambda x: x['color']), 'Incorrect ordering of the list')
class test_partner_recursion(common.TransactionCase):
def setUp(self):

View File

@ -120,4 +120,62 @@ class TestRelatedField(common.TransactionCase):
# restore res.partner fields
self.partner._columns = old_columns
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
class TestPropertyField(common.TransactionCase):
def setUp(self):
super(TestPropertyField, self).setUp()
self.user = self.registry('res.users')
self.partner = self.registry('res.partner')
self.company = self.registry('res.company')
self.country = self.registry('res.country')
self.property = self.registry('ir.property')
self.imd = self.registry('ir.model.data')
def test_1_property_multicompany(self):
cr, uid = self.cr, self.uid
parent_company_id = self.imd.get_object_reference(cr, uid, 'base', 'main_company')[1]
country_be = self.imd.get_object_reference(cr, uid, 'base', 'be')[1]
country_fr = self.imd.get_object_reference(cr, uid, 'base', 'fr')[1]
group_partner_manager = self.imd.get_object_reference(cr, uid, 'base', 'group_partner_manager')[1]
group_multi_company = self.imd.get_object_reference(cr, uid, 'base', 'group_multi_company')[1]
sub_company = self.company.create(cr, uid, {'name': 'MegaCorp', 'parent_id': parent_company_id})
alice = self.user.create(cr, uid, {'name': 'Alice',
'login':'alice',
'email':'alice@youcompany.com',
'company_id':parent_company_id,
'company_ids':[(6, 0, [parent_company_id, sub_company])],
'country_id':country_be,
'groups_id': [(6, 0, [group_partner_manager, group_multi_company])]
})
bob = self.user.create(cr, uid, {'name': 'Bob',
'login':'bob',
'email':'bob@megacorp.com',
'company_id':sub_company,
'company_ids':[(6, 0, [parent_company_id, sub_company])],
'country_id':country_fr,
'groups_id': [(6, 0, [group_partner_manager, group_multi_company])]
})
self.partner._columns = dict(self.partner._columns)
self.partner._columns.update({
'property_country': fields.property(type='many2one', relation="res.country", string="Country by company"),
})
self.partner._all_columns.update({
'property_country': fields.column_info('property_country', self.partner._columns['property_country'], None, None, None),
})
self.partner._field_create(cr)
partner_id = self.partner.create(cr, alice, {
'name': 'An International Partner',
'email': 'partner@example.com',
'company_id': parent_company_id,
})
self.partner.write(cr, bob, [partner_id], {'property_country': country_fr})
self.assertEqual(self.partner.browse(cr, bob, partner_id).property_country.id, country_fr, "Bob does not see the value he has set on the property field")
self.partner.write(cr, alice, [partner_id], {'property_country': country_be})
self.assertEqual(self.partner.browse(cr, alice, partner_id).property_country.id, country_be, "Alice does not see the value he has set on the property field")
self.assertEqual(self.partner.browse(cr, bob, partner_id).property_country.id, country_fr, "Changes made by Alice have overwritten Bob's value")

View File

@ -97,7 +97,8 @@ class TestServerActions(TestServerActionsBase):
self.ir_actions_server.write(cr, uid, self.act_id, {
'state': 'code',
'code': """partner_name = obj.name + '_code'
self.pool["res.partner"].create(cr, uid, {"name": partner_name}, context=context)"""
self.pool["res.partner"].create(cr, uid, {"name": partner_name}, context=context)
workflow"""
})
run_res = self.ir_actions_server.run(cr, uid, [self.act_id], context=self.context)
self.assertFalse(run_res, 'ir_actions_server: code server action correctly finished should return False')

View File

@ -417,6 +417,61 @@ class TestNoModel(common.TransactionCase):
ET.tostring(sarch, encoding='utf-8'),
ET.tostring(self.arch, encoding='utf-8'))
class TestTemplating(common.TransactionCase):
def setUp(self):
import openerp.modules
super(TestTemplating, self).setUp()
self._pool = openerp.modules.registry.RegistryManager.get(common.DB)
self._init = self._pool._init
# fuck off
self._pool._init = False
def tearDown(self):
self._pool._init = self._init
super(TestTemplating, self).tearDown()
def test_branding_inherit(self):
Views = self.registry('ir.ui.view')
id = Views.create(self.cr, self.uid, {
'name': "Base view",
'type': 'qweb',
'arch': """<root>
<item order="1"/>
</root>
"""
})
id2 = Views.create(self.cr, self.uid, {
'name': "Extension",
'type': 'qweb',
'inherit_id': id,
'arch': """<xpath expr="//item" position="before">
<item order="2"/>
</xpath>
"""
})
arch_string = Views.read_combined(
self.cr, self.uid, id, fields=['arch'],
context={'inherit_branding': True})['arch']
arch = ET.fromstring(arch_string)
Views.distribute_branding(arch)
[initial] = arch.xpath('//item[@order=1]')
self.assertEqual(
str(id),
initial.get('data-oe-id'),
"initial should come from the root view")
self.assertEqual(
'/root[1]/item[1]',
initial.get('data-oe-xpath'),
"initial's xpath should be within the root view only")
[second] = arch.xpath('//item[@order=2]')
self.assertEqual(
str(id2),
second.get('data-oe-id'),
"second should come from the extension view")
class test_views(common.TransactionCase):

View File

@ -1461,11 +1461,9 @@ class property(function):
def _get_by_id(self, obj, cr, uid, prop_name, ids, context=None):
prop = obj.pool.get('ir.property')
vids = [obj._name + ',' + str(oid) for oid in ids]
def_id = self._field_get(cr, uid, obj._name, prop_name[0])
company = obj.pool.get('res.company')
cid = company._company_default_get(cr, uid, obj._name, def_id, context=context)
domain = [('fields_id.model', '=', obj._name), ('fields_id.name', 'in', prop_name), ('company_id', '=', cid)]
#domain = prop._get_domain(cr, uid, prop_name, obj._name, context)
domain = [('fields_id.model', '=', obj._name), ('fields_id.name', 'in', prop_name)]
if context and context.get('company_id'):
domain += [('company_id', '=', context.get('company_id'))]
if vids:
domain = [('res_id', 'in', vids)] + domain
return prop.search(cr, uid, domain, context=context)
@ -1475,7 +1473,12 @@ class property(function):
if context is None:
context = {}
nids = self._get_by_id(obj, cr, uid, [prop_name], [id], context)
def_id = self._field_get(cr, uid, obj._name, prop_name)
company = obj.pool.get('res.company')
cid = company._company_default_get(cr, uid, obj._name, def_id, context=context)
# TODO for trunk: add new parameter company_id to _get_by_id method
context_company = dict(context, company_id=cid)
nids = self._get_by_id(obj, cr, uid, [prop_name], [id], context_company)
if nids:
cr.execute('DELETE FROM ir_property WHERE id IN %s', (tuple(nids),))
@ -1489,10 +1492,6 @@ class property(function):
property_create = True
if property_create:
def_id = self._field_get(cr, uid, obj._name, prop_name)
company = obj.pool.get('res.company')
cid = company._company_default_get(cr, uid, obj._name, def_id,
context=context)
propdef = obj.pool.get('ir.model.fields').browse(cr, uid, def_id,
context=context)
prop = obj.pool.get('ir.property')

View File

@ -770,8 +770,6 @@ class BaseModel(object):
(name_id, context['module'], 'ir.model', model_id)
)
cr.commit()
cr.execute("SELECT * FROM ir_model_fields WHERE model=%s", (self._name,))
cols = {}
for rec in cr.dictfetchall():
@ -838,7 +836,6 @@ class BaseModel(object):
for key, val in vals.items():
if cols[k][key] != vals[key]:
cr.execute('update ir_model_fields set field_description=%s where model=%s and name=%s', (vals['field_description'], vals['model'], vals['name']))
cr.commit()
cr.execute("""UPDATE ir_model_fields SET
model_id=%s, field_description=%s, ttype=%s, relation=%s,
select_level=%s, readonly=%s ,required=%s, selectable=%s, relation_field=%s, translate=%s, serialization_field_id=%s
@ -849,7 +846,6 @@ class BaseModel(object):
vals['select_level'], bool(vals['readonly']), bool(vals['required']), bool(vals['selectable']), vals['relation_field'], bool(vals['translate']), vals['serialization_field_id'], vals['model'], vals['name']
))
break
cr.commit()
#
# Goal: try to apply inheritance at the instanciation level and
@ -2189,6 +2185,37 @@ class BaseModel(object):
r['__fold'] = folded.get(r[groupby] and r[groupby][0], False)
return result
def _read_group_generate_order_by(self, orderby, aggregated_fields, groupby, query):
"""
Generates the ORDER BY sql clause for the read group method. Adds the missing JOIN clause
to the query if order should be computed against m2o field.
:param orderby: the orderby definition in the form "%(field)s %(order)s"
:param aggregated_fields: list of aggregated fields in the query
:param groupby: the current groupby field name
:param query: the query object used to construct the query afterwards
"""
orderby_list = []
ob = []
for order_splits in orderby.split(','):
order_split = order_splits.split()
orderby_field = order_split[0]
fields = openerp.osv.fields
if isinstance(self._all_columns[orderby_field].column, (fields.date, fields.datetime)):
continue
orderby_dir = len(order_split) == 2 and order_split[1].upper() == 'ASC' and 'ASC' or 'DESC'
if orderby_field == groupby:
orderby_item = self._generate_order_by(order_splits, query).replace('ORDER BY ', '')
if orderby_item:
orderby_list.append(orderby_item)
ob += [obi.split()[0] for obi in orderby_item.split(',')]
elif orderby_field in aggregated_fields:
orderby_list.append('%s %s' % (orderby_field,orderby_dir))
if orderby_list:
return ' ORDER BY %s' % (','.join(orderby_list)), ob and ','.join(ob) or ''
else:
return '', ''
def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False):
"""
Get the list of records in list view grouped by the given ``groupby`` fields
@ -2301,6 +2328,12 @@ class BaseModel(object):
qualified_field = self._inherits_join_calc(f, query)
flist += "%s(%s) AS %s" % (group_operator, qualified_field, f)
order = orderby or groupby
orderby_clause = ''
ob = ''
if order:
orderby_clause, ob = self._read_group_generate_order_by(order, aggregated_fields, groupby, query)
gb = groupby and (' GROUP BY ' + qualified_groupby_field) or ''
from_clause, where_clause, where_clause_params = query.get_sql()
@ -2309,20 +2342,21 @@ class BaseModel(object):
offset_str = offset and ' offset %d' % offset or ''
if len(groupby_list) < 2 and context.get('group_by_no_leaf'):
group_count = '_'
cr.execute('SELECT min(%s.id) AS id, count(%s.id) AS %s_count' % (self._table, self._table, group_count) + (flist and ',') + flist + ' FROM ' + from_clause + where_clause + gb + limit_str + offset_str, where_clause_params)
cr.execute('SELECT min(%s.id) AS id, count(%s.id) AS %s_count' % (self._table, self._table, group_count) + (flist and ',') + flist + ' FROM ' + from_clause + where_clause + gb + (ob and ',') + ob + orderby_clause + limit_str + offset_str, where_clause_params)
alldata = {}
groupby = group_by
for r in cr.dictfetchall():
fetched_data = cr.dictfetchall()
data_ids = []
for r in fetched_data:
for fld, val in r.items():
if val is None: r[fld] = False
alldata[r['id']] = r
data_ids.append(r['id'])
del r['id']
order = orderby or groupby
data_ids = self.search(cr, uid, [('id', 'in', alldata.keys())], order=order, context=context)
# the IDs of records that have groupby field value = False or '' should be included too
data_ids += set(alldata.keys()).difference(data_ids)
if groupby:
data = self.read(cr, uid, data_ids, [groupby], context=context)
@ -2716,10 +2750,16 @@ class BaseModel(object):
('float8', 'float', get_pg_type(f)[1], '::'+get_pg_type(f)[1]),
]
if f_pg_type == 'varchar' and f._type == 'char' and ((f.size is None and f_pg_size) or f_pg_size < f.size):
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size)))
cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size)))
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
try:
with cr.savepoint():
cr.execute('ALTER TABLE "%s" ALTER COLUMN "%s" TYPE %s' % (self._table, k, pg_varchar(f.size)))
except psycopg2.NotSupportedError:
# In place alter table cannot be done because a view is depending of this field.
# Do a manual copy. This will drop the view (that will be recreated later)
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, pg_varchar(f.size)))
cr.execute('UPDATE "%s" SET "%s"=temp_change_size::%s' % (self._table, k, pg_varchar(f.size)))
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
cr.commit()
_schema.debug("Table '%s': column '%s' (type varchar) changed size from %s to %s",
self._table, k, f_pg_size or 'unlimited', f.size or 'unlimited')
@ -2727,10 +2767,10 @@ class BaseModel(object):
if (f_pg_type==c[0]) and (f._type==c[1]):
if f_pg_type != f_obj_type:
ok = True
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO temp_change_size' % (self._table, k))
cr.execute('ALTER TABLE "%s" RENAME COLUMN "%s" TO __temp_type_cast' % (self._table, k))
cr.execute('ALTER TABLE "%s" ADD COLUMN "%s" %s' % (self._table, k, c[2]))
cr.execute(('UPDATE "%s" SET "%s"=temp_change_size'+c[3]) % (self._table, k))
cr.execute('ALTER TABLE "%s" DROP COLUMN temp_change_size CASCADE' % (self._table,))
cr.execute(('UPDATE "%s" SET "%s"= __temp_type_cast'+c[3]) % (self._table, k))
cr.execute('ALTER TABLE "%s" DROP COLUMN __temp_type_cast CASCADE' % (self._table,))
cr.commit()
_schema.debug("Table '%s': column '%s' changed type from %s to %s",
self._table, k, c[0], c[1])
@ -4622,24 +4662,22 @@ class BaseModel(object):
blacklist_given_fields(self)
fields_to_read = [f for f in self.check_field_access_rights(cr, uid, 'read', None)
if f not in blacklist]
data = self.read(cr, uid, [id], fields_to_read, context=context)
fields_to_copy = dict((f,fi) for f, fi in self._all_columns.iteritems()
if f not in default
if f not in blacklist
if not isinstance(fi.column, fields.function))
data = self.read(cr, uid, [id], fields_to_copy.keys(), context=context)
if data:
data = data[0]
else:
raise IndexError(_("Record #%d of %s not found, cannot copy!") % (id, self._name))
raise IndexError( _("Record #%d of %s not found, cannot copy!") %( id, self._name))
res = dict(default)
for f, colinfo in self._all_columns.items():
for f, colinfo in fields_to_copy.iteritems():
field = colinfo.column
if f in default:
pass
elif f in blacklist:
pass
elif isinstance(field, fields.function):
pass
elif field._type == 'many2one':
if field._type == 'many2one':
res[f] = data[f] and data[f][0]
elif field._type == 'one2many':
other = self.pool[field._obj]

View File

@ -311,7 +311,7 @@ def exp_list(document=False):
cr.execute("select datname from pg_database where datdba=(select usesysid from pg_user where usename=%s) and datname not in %s order by datname", (db_user, templates_list))
else:
cr.execute("select datname from pg_database where datname not in %s order by datname", (templates_list,))
res = [str(name) for (name,) in cr.fetchall()]
res = [openerp.tools.ustr(name) for (name,) in cr.fetchall()]
except Exception:
res = []
res.sort()

View File

@ -9,7 +9,6 @@ import os.path
import platform
import psutil
import random
import re
import resource
import select
import signal
@ -32,15 +31,14 @@ except ImportError:
setproctitle = lambda x: None
import openerp
import openerp.tools.config as config
from openerp.modules.registry import RegistryManager
from openerp.release import nt_service_name
import openerp.tools.config as config
from openerp.tools.misc import stripped_sys_argv, dumpstacks
import wsgi_server
_logger = logging.getLogger(__name__)
SLEEP_INTERVAL = 60 # 1 min
SLEEP_INTERVAL = 60 # 1 min
#----------------------------------------------------------
# Werkzeug WSGI servers patched
@ -126,7 +124,7 @@ class AutoReload(object):
if len(right) < 2:
continue
module = right[0]
self.modules[module]=1
self.modules[module] = 1
if self.modules:
_logger.info('autoreload: xml change detected, autoreload activated')
restart()
@ -146,7 +144,7 @@ class AutoReload(object):
if py_errors:
_logger.info('autoreload: python code change detected, errors found')
for i in py_errors:
_logger.info('autoreload: SyntaxError %s',i)
_logger.info('autoreload: SyntaxError %s', i)
else:
_logger.info('autoreload: python code updated, autoreload activated')
restart()
@ -213,7 +211,7 @@ class ThreadedServer(CommonServer):
self.httpd = None
def signal_handler(self, sig, frame):
if sig in [signal.SIGINT,signal.SIGTERM]:
if sig in [signal.SIGINT, signal.SIGTERM]:
# shutdown on kill -INT or -TERM
self.quit_signals_received += 1
if self.quit_signals_received > 1:
@ -227,7 +225,7 @@ class ThreadedServer(CommonServer):
def cron_thread(self, number):
while True:
time.sleep(SLEEP_INTERVAL + number) # Steve Reich timing style
time.sleep(SLEEP_INTERVAL + number) # Steve Reich timing style
registries = openerp.modules.registry.RegistryManager.registries
_logger.debug('cron%d polling for jobs', number)
for db_name, registry in registries.items():
@ -257,13 +255,15 @@ class ThreadedServer(CommonServer):
_logger.debug("cron%d started!" % i)
def http_thread(self):
def app(e,s):
return self.app(e,s)
def app(e, s):
return self.app(e, s)
self.httpd = ThreadedWSGIServerReloadable(self.interface, self.port, app)
self.httpd.serve_forever()
def http_spawn(self):
threading.Thread(target=self.http_thread).start()
t = threading.Thread(target=self.http_thread, name="openerp.service.httpd")
t.setDaemon(True)
t.start()
_logger.info('HTTP service (werkzeug) running on %s:%s', self.interface, self.port)
def start(self):
@ -276,7 +276,7 @@ class ThreadedServer(CommonServer):
signal.signal(signal.SIGQUIT, dumpstacks)
elif os.name == 'nt':
import win32api
win32api.SetConsoleCtrlHandler(lambda sig: signal_handler(sig, None), 1)
win32api.SetConsoleCtrlHandler(lambda sig: self.signal_handler(sig, None), 1)
self.cron_spawn()
self.http_spawn()
@ -316,12 +316,11 @@ class ThreadedServer(CommonServer):
"""
self.start()
preload_registries(preload)
rc = preload_registries(preload)
if stop:
self.stop()
return
return rc
# Wait for a first signal to be handled. (time.sleep will be interrupted
# by the signal handler.) The try/except is for the win32 case.
@ -438,7 +437,7 @@ class PreforkServer(CommonServer):
sys.exit(0)
def long_polling_spawn(self):
nargs = stripped_sys_argv('--pidfile','--workers')
nargs = stripped_sys_argv('--pidfile', '--workers')
cmd = nargs[0]
cmd = os.path.join(os.path.dirname(cmd), "openerp-gevent")
nargs[0] = cmd
@ -447,10 +446,10 @@ class PreforkServer(CommonServer):
def worker_pop(self, pid):
if pid in self.workers:
_logger.debug("Worker (%s) unregistered",pid)
_logger.debug("Worker (%s) unregistered", pid)
try:
self.workers_http.pop(pid,None)
self.workers_cron.pop(pid,None)
self.workers_http.pop(pid, None)
self.workers_cron.pop(pid, None)
u = self.workers.pop(pid)
u.close()
except OSError:
@ -466,7 +465,7 @@ class PreforkServer(CommonServer):
def process_signals(self):
while len(self.queue):
sig = self.queue.pop(0)
if sig in [signal.SIGINT,signal.SIGTERM]:
if sig in [signal.SIGINT, signal.SIGTERM]:
raise KeyboardInterrupt
elif sig == signal.SIGHUP:
# restart on kill -HUP
@ -502,8 +501,8 @@ class PreforkServer(CommonServer):
def process_timeout(self):
now = time.time()
for (pid, worker) in self.workers.items():
if (worker.watchdog_timeout is not None) and \
(now - worker.watchdog_time >= worker.watchdog_timeout):
if worker.watchdog_timeout is not None and \
(now - worker.watchdog_time) >= worker.watchdog_timeout:
_logger.error("Worker (%s) timeout", pid)
self.worker_kill(pid, signal.SIGKILL)
@ -518,7 +517,7 @@ class PreforkServer(CommonServer):
def sleep(self):
try:
# map of fd -> worker
fds = dict([(w.watchdog_pipe[0],w) for k,w in self.workers.items()])
fds = dict([(w.watchdog_pipe[0], w) for k, w in self.workers.items()])
fd_in = fds.keys() + [self.pipe[0]]
# check for ping or internal wakeups
ready = select.select(fd_in, [], [], self.beat)
@ -558,11 +557,12 @@ class PreforkServer(CommonServer):
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.setblocking(0)
self.socket.bind(self.address)
self.socket.listen(8*self.population)
self.socket.listen(8 * self.population)
def stop(self, graceful=True):
if self.long_polling_pid is not None:
self.worker_kill(self.long_polling_pid, signal.SIGKILL) # FIXME make longpolling process handle SIGTERM correctly
# FIXME make longpolling process handle SIGTERM correctly
self.worker_kill(self.long_polling_pid, signal.SIGKILL)
self.long_polling_pid = None
if graceful:
_logger.info("Stopping gracefully")
@ -581,11 +581,11 @@ class PreforkServer(CommonServer):
def run(self, preload, stop):
self.start()
preload_registries(preload)
rc = preload_registries(preload)
if stop:
self.stop()
return
return rc
_logger.debug("Multiprocess starting")
while 1:
@ -600,7 +600,7 @@ class PreforkServer(CommonServer):
_logger.debug("Multiprocess clean stop")
self.stop()
break
except Exception,e:
except Exception, e:
_logger.exception(e)
self.stop(False)
return -1
@ -632,7 +632,7 @@ class Worker(object):
def sleep(self):
try:
ret = select.select([self.multi.socket], [], [], self.multi.beat)
select.select([self.multi.socket], [], [], self.multi.beat)
except select.error, e:
if e[0] not in [errno.EINTR]:
raise
@ -650,7 +650,7 @@ class Worker(object):
rss, vms = psutil.Process(os.getpid()).get_memory_info()
if vms > config['limit_memory_soft']:
_logger.info('Worker (%d) virtual memory limit (%s) reached.', self.pid, vms)
self.alive = False # Commit suicide after the request.
self.alive = False # Commit suicide after the request.
# VMS and RLIMIT_AS are the same thing: virtual memory, a.k.a. address space
soft, hard = resource.getrlimit(resource.RLIMIT_AS)
@ -698,7 +698,7 @@ class Worker(object):
self.process_work()
_logger.info("Worker (%s) exiting. request_count: %s.", self.pid, self.request_count)
self.stop()
except Exception,e:
except Exception:
_logger.exception("Worker (%s) Exception occured, exiting..." % self.pid)
# should we use 3 to abort everything ?
sys.exit(1)
@ -716,7 +716,7 @@ class WorkerHTTP(Worker):
# tolerate broken pipe when the http client closes the socket before
# receiving the full reply
try:
self.server.process_request(client,addr)
self.server.process_request(client, addr)
except IOError, e:
if e.errno != errno.EPIPE:
raise
@ -747,7 +747,7 @@ class WorkerCron(Worker):
def sleep(self):
# Really sleep once all the databases have been processed.
if self.db_index == 0:
interval = SLEEP_INTERVAL + self.pid % 10 # chorus effect
interval = SLEEP_INTERVAL + self.pid % 10 # chorus effect
time.sleep(interval)
def _db_list(self):
@ -769,7 +769,7 @@ class WorkerCron(Worker):
if rpc_request_flag:
start_time = time.time()
start_rss, start_vms = psutil.Process(os.getpid()).get_memory_info()
import openerp.addons.base as base
base.ir.ir_cron.ir_cron._acquire_job(db_name)
openerp.modules.registry.RegistryManager.delete(db_name)
@ -778,16 +778,18 @@ class WorkerCron(Worker):
if len(db_names) > 1:
openerp.sql_db.close_db(db_name)
if rpc_request_flag:
end_time = time.time()
run_time = time.time() - start_time
end_rss, end_vms = psutil.Process(os.getpid()).get_memory_info()
logline = '%s time:%.3fs mem: %sk -> %sk (diff: %sk)' % (db_name, end_time - start_time, start_vms / 1024, end_vms / 1024, (end_vms - start_vms)/1024)
vms_diff = (end_vms - start_vms) / 1024
logline = '%s time:%.3fs mem: %sk -> %sk (diff: %sk)' % \
(db_name, run_time, start_vms / 1024, end_vms / 1024, vms_diff)
_logger.debug("WorkerCron (%s) %s", self.pid, logline)
self.request_count += 1
if self.request_count >= self.request_max and self.request_max < len(db_names):
_logger.error("There are more dabatases to process than allowed "
"by the `limit_request` configuration variable: %s more.",
len(db_names) - self.request_max)
"by the `limit_request` configuration variable: %s more.",
len(db_names) - self.request_max)
else:
self.db_index = 0
@ -820,18 +822,17 @@ def _reexec(updated_modules=None):
subprocess.call('net stop {0} && net start {0}'.format(nt_service_name), shell=True)
exe = os.path.basename(sys.executable)
args = stripped_sys_argv()
args += ["-u", ','.join(updated_modules)]
args += ["-u", ','.join(updated_modules)]
if not args or args[0] != exe:
args.insert(0, exe)
os.execv(sys.executable, args)
def load_test_file_yml(test_file):
cr = registry.db.cursor()
openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True)
cr.rollback()
cr.close()
def load_test_file_yml(registry, test_file):
with registry.cursor() as cr:
openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True)
cr.rollback()
def load_test_file_py(test_file):
def load_test_file_py(registry, test_file):
# Locate python module based on its filename and run the tests
test_path, _ = os.path.splitext(os.path.abspath(test_file))
for mod_name, mod_mod in sys.modules.items():
@ -842,9 +843,11 @@ def load_test_file_py(test_file):
for t in unittest2.TestLoader().loadTestsFromModule(mod_mod):
suite.addTest(t)
_logger.log(logging.INFO, 'running tests %s.', mod_mod.__name__)
result = unittest2.TextTestRunner(verbosity=2, stream=openerp.modules.module.TestStream()).run(suite)
if not result.wasSuccessful():
r = False
stream = openerp.modules.module.TestStream()
result = unittest2.TextTestRunner(verbosity=2, stream=stream).run(suite)
success = result.wasSuccessful()
registry._assertion_report.report_result(success)
if not success:
_logger.error('%s: at least one error occurred in a test', test_file)
def preload_registries(dbnames):
@ -853,20 +856,25 @@ def preload_registries(dbnames):
config = openerp.tools.config
test_file = config['test_file']
dbnames = dbnames or []
rc = 0
for dbname in dbnames:
try:
update_module = config['init'] or config['update']
registry = openerp.modules.registry.RegistryManager.new(dbname, update_module=update_module)
registry = RegistryManager.new(dbname, update_module=update_module)
# run test_file if provided
if test_file:
_logger.info('loading test file %s', test_file)
if test_file.endswith('yml'):
load_test_file_yml(test_file)
load_test_file_yml(registry, test_file)
elif test_file.endswith('py'):
load_test_file_py(test_file)
load_test_file_py(registry, test_file)
if registry._assertion_report.failures:
rc += 1
except Exception:
_logger.exception('Failed to initialize database `%s`.', dbname)
return
_logger.critical('Failed to initialize database `%s`.', dbname, exc_info=True)
return -1
return rc
def start(preload=None, stop=False):
""" Start the openerp http server and cron processor.

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
# Copyright (C) 2010-2014 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -27,8 +27,11 @@ the database, *not* a database abstraction toolkit. Database abstraction is what
the ORM does, in fact.
"""
from contextlib import contextmanager
from functools import wraps
import logging
import time
import uuid
import psycopg2.extensions
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT, ISOLATION_LEVEL_READ_COMMITTED, ISOLATION_LEVEL_REPEATABLE_READ
from psycopg2.pool import PoolError
@ -344,6 +347,19 @@ class Cursor(object):
"""
return self._cnx.rollback()
@contextmanager
@check
def savepoint(self):
"""context manager entering in a new savepoint"""
name = uuid.uuid1().hex
self.execute('SAVEPOINT "%s"' % name)
try:
yield
self.execute('RELEASE SAVEPOINT "%s"' % name)
except:
self.execute('ROLLBACK TO SAVEPOINT "%s"' % name)
raise
@check
def __getattr__(self, name):
return getattr(self._obj, name)

View File

@ -4,18 +4,16 @@ The module :mod:`openerp.tests.common` provides unittest2 test cases and a few
helpers and classes to write tests.
"""
import errno
import json
import logging
import os
import select
import subprocess
import sys
import threading
import time
import unittest2
import uuid
import xmlrpclib
import threading
import openerp
@ -191,28 +189,45 @@ class HttpCase(TransactionCase):
"""
t0 = time.time()
buf = bytearray()
while 1:
while True:
# timeout
self.assertLess(time.time(), t0 + timeout,
"PhantomJS tests should take less than %s seconds" % timeout)
# read a byte
ready, _, _ = select.select([phantom.stdout], [], [], 0.5)
try:
ready, _, _ = select.select([phantom.stdout], [], [], 0.5)
except select.error, e:
# In Python 2, select.error has no relation to IOError or
# OSError, and no errno/strerror/filename, only a pair of
# unnamed arguments (matching errno and strerror)
err, _ = e.args
if err == errno.EINTR: continue
raise
if ready:
s = phantom.stdout.read(1)
if s:
buf.append(s)
else:
if not s:
break
buf.append(s)
# process lines
if '\n' in buf:
line, buf = buf.split('\n', 1)
line = str(line)
if 'CoreText' in line:
continue
if line == "ok":
return
break
if line.startswith("error"):
# 'error $message' or use generic message
self.fail(line[6:] or "phantomjs test failed")
line_ = line[6:]
try: line_ = json.loads(line_)
except ValueError: pass
self.fail(line_ or "phantomjs test failed")
try: line = json.loads(line)
except ValueError: pass
_logger.info("phantomjs: %s", line)
def phantom_run(self, cmd, timeout):

View File

@ -10,10 +10,8 @@ function waitFor (ready, callback, timeout, timeoutMessageCallback) {
} else {
if(!condition) {
var message = timeoutMessageCallback ? timeoutMessageCallback() : "Timeout after "+timeout+" ms";
console.log(message);
console.log("Waiting for " + ready);
console.log("error");
phantom.exit(1);
error(message);
} else {
clearInterval(interval);
callback();
@ -22,6 +20,10 @@ function waitFor (ready, callback, timeout, timeoutMessageCallback) {
}, 250);
}
function error(message) {
console.log('error', message);
phantom.exit(1);
}
function PhantomTest() {
var self = this;
this.options = JSON.parse(phantom.args[phantom.args.length-1]);
@ -30,15 +32,6 @@ function PhantomTest() {
this.origin = 'http://localhost';
this.origin += this.options.port ? ':' + this.options.port : '';
// ----------------------------------------------------
// test reporting
// ----------------------------------------------------
this.error = function(message) {
console.log(message);
console.log("error");
phantom.exit(1);
};
// ----------------------------------------------------
// configure phantom and page
// ----------------------------------------------------
@ -50,10 +43,21 @@ function PhantomTest() {
this.page = require('webpage').create();
this.page.viewportSize = { width: 1366, height: 768 };
this.page.onError = function(message, trace) {
self.error(message + " " + trace);
var msg = [message];
if (trace && trace.length) {
msg.push.apply(msg, trace.map(function (frame) {
var result = [' at ', frame.file, ':', frame.line];
if (frame.function) {
result.push(' (in ', frame.function, ')');
}
return result.join('');
}));
msg.push('(leaf frame on top)')
}
error(JSON.stringify(msg.join('\n')));
};
this.page.onAlert = function(message) {
self.error(message);
error(message);
};
this.page.onConsoleMessage = function(message) {
console.log(message);
@ -79,7 +83,7 @@ function PhantomTest() {
if(!found) {
console.log('Injecting', src, 'needed for', need);
if(!self.page.injectJs(src)) {
self.error("Cannot inject " + src);
error("Cannot inject " + src);
}
}
}
@ -90,7 +94,7 @@ function PhantomTest() {
var message = ("Timeout\nhref: " + window.location.href
+ "\nreferrer: " + document.referrer
+ "\n\n" + document.body.innerHTML).replace(/[^a-z0-9\s~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, "*");
self.error(message);
error(message);
});
}, self.timeout);
@ -109,7 +113,7 @@ function PhantomTest() {
var url = self.origin + url_path;
self.page.open(url, function(status) {
if (status !== 'success') {
self.error("failed to load " + url)
error("failed to load " + url)
} else {
console.log('loaded', url, status);
// process ready

View File

@ -25,7 +25,7 @@ except ImportError:
import StringIO
from PIL import Image
from PIL import ImageOps
from PIL import ImageEnhance
from random import randint
# ----------------------------------------
@ -81,8 +81,13 @@ def image_resize_image(base64_source, size=(1024, 1024), encoding='base64', file
return base64_source
if image.size != size:
# If you need faster thumbnails you may use use Image.NEAREST
image = ImageOps.fit(image, size, Image.ANTIALIAS)
# create a thumbnail: will resize and keep ratios, then sharpen for better looking result
image.thumbnail(size, Image.ANTIALIAS)
sharpener = ImageEnhance.Sharpness(image.convert('RGBA'))
resized_image = sharpener.enhance(2.0)
# create a transparent image for background and paste the image on it
image = Image.new('RGBA', size, (255, 255, 255, 0))
image.paste(resized_image, ((size[0] - resized_image.size[0]) / 2, (size[1] - resized_image.size[1]) / 2))
if image.mode not in ["1", "L", "P", "RGB", "RGBA"]:
image = image.convert("RGB")