[MERGE]Merge trunk-website-al.
bzr revid: bth@tinyerp.com-20131017054433-5a8vax2nyuwwwzuw bzr revid: bth@tinyerp.com-20131021065916-qpffh3kfkz0n8v8k bzr revid: bth@tinyerp.com-20131022112314-50vj16z4rva3ngi9 bzr revid: bth@tinyerp.com-20131025073225-s8crvmd65oji11fl bzr revid: bth@tinyerp.com-20131028050304-2n6yktosjstlm45y bzr revid: bth@tinyerp.com-20131029045254-ggwaarzd6zsakq40
This commit is contained in:
@@ -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: 2013-10-11 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:33+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:34+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:34+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:34+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:35+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
+610
-393
File diff suppressed because it is too large
Load Diff
@@ -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: 2013-10-11 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:35+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:35+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
"X-Poedit-Language: Czech\n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -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: 2013-10-11 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:35+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
"X-Poedit-Country: GREECE\n"
|
||||
"X-Poedit-Language: Greek\n"
|
||||
"X-Poedit-SourceCharset: utf-8\n"
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
"Language: \n"
|
||||
|
||||
#. module: base
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -15,8 +15,8 @@ msgstr ""
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-11 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:34+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
"X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
|
||||
"X-Poedit-Language: Persian\n"
|
||||
|
||||
|
||||
@@ -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: 2013-10-11 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
"Language: hr\n"
|
||||
|
||||
#. module: base
|
||||
@@ -3994,7 +3994,7 @@ msgstr "12. %w ==> 5 ( Petak je 6ti dan)"
|
||||
#. module: base
|
||||
#: constraint:res.partner.category:0
|
||||
msgid "Error ! You can not create recursive categories."
|
||||
msgstr "Graška ! Ne može se stvoriti kategorije s rekurzijom."
|
||||
msgstr "Greška! Ne možete kreirati rekurzivne kategorije."
|
||||
|
||||
#. module: base
|
||||
#: view:res.lang:0
|
||||
@@ -8815,6 +8815,10 @@ msgid ""
|
||||
"\n"
|
||||
"(Document type: %s)"
|
||||
msgstr ""
|
||||
"Za ovu vrstu dokumenta imate pravo pristupa samo onima koje ste vi "
|
||||
"kreirali.\n"
|
||||
"\n"
|
||||
"(Vrstu dokumenta: %s)"
|
||||
|
||||
#. module: base
|
||||
#: view:base.language.export:0
|
||||
@@ -9872,7 +9876,7 @@ msgstr "Kreirano"
|
||||
#: help:ir.actions.server,model_id:0
|
||||
msgid ""
|
||||
"Select the object on which the action will work (read, write, create)."
|
||||
msgstr "Odaberite objekt na koje će akcija raditi (read, write, create)."
|
||||
msgstr "Odaberite objekt na koje će akcija raditi (čitaj, piši, kreiraj)."
|
||||
|
||||
#. module: base
|
||||
#: field:base.language.import,name:0
|
||||
|
||||
@@ -7,14 +7,14 @@ msgstr ""
|
||||
"Project-Id-Version: OpenERP Server 6.0\n"
|
||||
"Report-Msgid-Bugs-To: support@openerp.com\n"
|
||||
"POT-Creation-Date: 2012-12-21 17:04+0000\n"
|
||||
"PO-Revision-Date: 2013-03-14 10:08+0000\n"
|
||||
"Last-Translator: krnkris <Unknown>\n"
|
||||
"PO-Revision-Date: 2013-10-15 13:13+0000\n"
|
||||
"Last-Translator: tdombos <Unknown>\n"
|
||||
"Language-Team: Hungarian <openerp-hungarian-team@lists.launchpad.net>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-11 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
@@ -6230,7 +6230,7 @@ msgstr "Kenya"
|
||||
#: model:ir.actions.act_window,name:base.action_translation
|
||||
#: model:ir.ui.menu,name:base.menu_action_translation
|
||||
msgid "Translated Terms"
|
||||
msgstr "Lefordított feltételek"
|
||||
msgstr "Lefordított kifejezések"
|
||||
|
||||
#. module: base
|
||||
#: selection:base.language.install,lang:0
|
||||
@@ -12491,7 +12491,7 @@ msgstr "This method does not exist anymore"
|
||||
#: model:ir.actions.act_window,name:base.action_wizard_update_translations
|
||||
#: model:ir.ui.menu,name:base.menu_wizard_update_translations
|
||||
msgid "Synchronize Terms"
|
||||
msgstr "Feltételek szinkronizáása"
|
||||
msgstr "Kifejezések szinkronizáása"
|
||||
|
||||
#. module: base
|
||||
#: field:res.lang,thousands_sep:0
|
||||
@@ -13640,7 +13640,7 @@ msgstr "Érvénytelen adatbázis azonosító '%s' ehhez a mezőhöz '%%(field)s'
|
||||
#. module: base
|
||||
#: view:res.lang:0
|
||||
msgid "Update Languague Terms"
|
||||
msgstr "Nyelvi feltételek frissítése"
|
||||
msgstr "Nyelvi kifejezések frissítése"
|
||||
|
||||
#. module: base
|
||||
#: field:workflow.activity,join_mode:0
|
||||
|
||||
@@ -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: 2013-10-11 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:34+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:37+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
@@ -4448,7 +4448,7 @@ msgstr "メールサーバを特に指定しないメールは最も高い優先
|
||||
#. module: base
|
||||
#: model:ir.module.module,summary:base.module_sale
|
||||
msgid "Quotations, Sales Orders, Invoicing"
|
||||
msgstr ""
|
||||
msgstr "見積、受注、請求"
|
||||
|
||||
#. module: base
|
||||
#: field:res.partner,parent_id:0
|
||||
@@ -5037,7 +5037,7 @@ msgstr ""
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_event_sale
|
||||
msgid "Events Sales"
|
||||
msgstr ""
|
||||
msgstr "イベント販売"
|
||||
|
||||
#. module: base
|
||||
#: model:res.country,name:base.ls
|
||||
@@ -7967,7 +7967,7 @@ msgstr ""
|
||||
#: view:res.partner:0
|
||||
#: field:res.partner,user_id:0
|
||||
msgid "Salesperson"
|
||||
msgstr ""
|
||||
msgstr "営業担当者"
|
||||
|
||||
#. module: base
|
||||
#: view:res.lang:0
|
||||
@@ -9727,7 +9727,7 @@ msgstr "カスタム"
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_sale_margin
|
||||
msgid "Margins in Sales Orders"
|
||||
msgstr "受注オーダーのマージン"
|
||||
msgstr "受注マージン"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_purchase
|
||||
@@ -10478,7 +10478,7 @@ msgstr "この会社に関連した銀行口座"
|
||||
#: model:ir.ui.menu,name:base.menu_sales
|
||||
#: model:ir.ui.menu,name:base.next_id_64
|
||||
msgid "Sales"
|
||||
msgstr "受注"
|
||||
msgstr "販売"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.actions.server,child_ids:0
|
||||
@@ -10814,7 +10814,7 @@ msgstr "ユーザ自身がダッシュボードビュー(Webクライアント
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_sale_stock
|
||||
msgid "Sales and Warehouse Management"
|
||||
msgstr ""
|
||||
msgstr "販売・倉庫管理"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_hr_recruitment
|
||||
@@ -15538,7 +15538,7 @@ msgstr "コンテキスト"
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_sale_mrp
|
||||
msgid "Sales and MRP Management"
|
||||
msgstr "受注とMRP管理"
|
||||
msgstr "販売・MRP管理"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.actions.act_window,help:base.action_partner_form
|
||||
|
||||
@@ -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: 2013-10-11 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:36+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
@@ -12022,6 +12022,31 @@ msgid ""
|
||||
" Reporting / Accounting / **Follow-ups Analysis\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Төлөгдөөгүй нэхэмжлэлүүдэд олон шаттай дуудлаг хийх, захиадал явуулах ажлыг "
|
||||
"автоматжуулах модуль.\n"
|
||||
"=========================================================================\n"
|
||||
"\n"
|
||||
"Дараах менюгээр олон шатлалтай дуудлагуудыг тодорхойлж болно:\n"
|
||||
"---------------------------------------------------------------\n"
|
||||
" Тохиргоо / Мөшгөлтийн Түвшин\n"
|
||||
" \n"
|
||||
"Нэгэнт тодорхойлсон бол дараах менюгээр орж дуудлагуудын автоматаар тогтмол "
|
||||
"хэвлэж болно:\n"
|
||||
"-----------------------------------------------------------------------------"
|
||||
"-------------------------\n"
|
||||
" Төлбөрийн Мөшгөлт / Имэйл болон захидал илгээх\n"
|
||||
"\n"
|
||||
"Энэ нь PDF үүсгэх / имэйл илгээх / гар үйлдлүүдийг олон шатлалтай дуудлага "
|
||||
"дээр үндэслэн үүсгэдэг. \n"
|
||||
"Ялгаатай компаниудад ялгаатай бодлогыг тодорхойлж болно. \n"
|
||||
"\n"
|
||||
"Хэрэв тухайлсан харилцагч/дансны бичилт дээр мөшгөлтийг шалгахыг хүсвэл "
|
||||
"дараах менюгээр хийх боломжтой:\n"
|
||||
"-----------------------------------------------------------------------------"
|
||||
"-------------------------------------\n"
|
||||
" Тайлан / Санхүү / **Мөшгөлтийн шинжилгээ\n"
|
||||
"\n"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/base/ir/ir_model.py:735
|
||||
@@ -12196,6 +12221,20 @@ msgid ""
|
||||
"You can define the different phases of interviews and easily rate the "
|
||||
"applicant from the kanban view.\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Ажлын байр, ажилтан авах процессийг удирдана\n"
|
||||
"================================================\n"
|
||||
"\n"
|
||||
"Энэ модуль нь ажлыг хөтлөх, амралтыг хөтлөх, өргөдөл болон ярилцлагыг хөтлөх "
|
||||
"зэрэг ажлыг хялбараар хийх боломжийг олгодог...\n"
|
||||
"\n"
|
||||
"Энэ нь имэйл үүдтэй уялддаг бөгөөд <jobs@yourcompany.com> гэсэн хаяг руу "
|
||||
"ирсэн имэйлээс өргөдлүүдийг татан авдаг. Мөн баримтын модультай уялдсан "
|
||||
"байдаг бөгөөд файлаар ирсэн CV-үүдийг хадгалж дараа хайлт хийх боломжийг "
|
||||
"бүрдүүлдэг. Үүнтэй төстэйгээр Санал асуулга модультай уялдаж ярилцлагыг "
|
||||
"хөтлөдөг. \n"
|
||||
"Ярилцлагын ялгаатай шатуудыг тодорхойлж эдгээртээ үнэлгээ өгөх зэрэг ажлыг "
|
||||
"канбан харагдацаас хялбараар хийж болдог.\n"
|
||||
|
||||
#. module: base
|
||||
#: field:ir.model.fields,model:0
|
||||
@@ -12242,7 +12281,7 @@ msgstr ""
|
||||
#. module: base
|
||||
#: help:res.partner,ean13:0
|
||||
msgid "BarCode"
|
||||
msgstr ""
|
||||
msgstr "Зураасан код"
|
||||
|
||||
#. module: base
|
||||
#: help:ir.model.fields,model_id:0
|
||||
@@ -12423,7 +12462,7 @@ msgstr "Оффисын Хангамжууд"
|
||||
#. module: base
|
||||
#: field:ir.attachment,res_model:0
|
||||
msgid "Resource Model"
|
||||
msgstr "Нөөцийн модел"
|
||||
msgstr "Нөөц модел"
|
||||
|
||||
#. module: base
|
||||
#: code:addons/custom.py:555
|
||||
@@ -12721,6 +12760,9 @@ msgid ""
|
||||
"Allow users to sign up through OAuth2 Provider.\n"
|
||||
"===============================================\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"OAuth2-р хэрэглэгчид бүртгүүлэх, нэвтрэх боломжийг олгодог.\n"
|
||||
"===============================================\n"
|
||||
|
||||
#. module: base
|
||||
#: field:change.password.user,user_id:0
|
||||
@@ -12744,7 +12786,7 @@ msgstr "Пуэрто Рико"
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_web_tests_demo
|
||||
msgid "Demonstration of web/javascript tests"
|
||||
msgstr ""
|
||||
msgstr "Веб/javascript тестийн жишээ, үзүүлэн"
|
||||
|
||||
#. module: base
|
||||
#: field:workflow.transition,signal:0
|
||||
@@ -13076,6 +13118,13 @@ msgid ""
|
||||
"\n"
|
||||
"The decimal precision is configured per company.\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Үнийн нарийвчлалыг тохируулахыг олон зорилгоор ашиглаж болно: санхүү, "
|
||||
"борлуулалт, худалдан авалт\n"
|
||||
"============================================================================="
|
||||
"====================\n"
|
||||
"\n"
|
||||
"Аравны нарийвчлал нь компанийн хүрээнд хийгдэнэ.\n"
|
||||
|
||||
#. module: base
|
||||
#: selection:res.company,paper_format:0
|
||||
@@ -13175,6 +13224,9 @@ msgid ""
|
||||
"(if you delete a native ACL, it will be re-created when you reload the "
|
||||
"module."
|
||||
msgstr ""
|
||||
"Идэвхтэй талбарыг сонгоогүй тохиолдолд ACL-г устгалгүйгээр идэвхгүй болгоно. "
|
||||
"(Анхны эх ACL-г устгасан байлаа ч модулийг ахин ачаалахад дахин шинээр "
|
||||
"үүсдэг)"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.model,name:base.model_ir_fields_converter
|
||||
@@ -13230,6 +13282,17 @@ msgid ""
|
||||
"into mail.message with attachments.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Энэ модуль нь Outlook Залгаасыг өгдөг.\n"
|
||||
"=========================================\n"
|
||||
"\n"
|
||||
"Outlook залгаас нь MS Outlook дотороосоо имэйлдээ OpenERP обьекуудтыг \n"
|
||||
"сонгох хавсаргах боломжийг олгодог. Харилцагч, даалгавар, төсөл, "
|
||||
"шинжилгээний данс \n"
|
||||
"гэх мэт дуртай обьектоо сонгож имэйлдээ оруулж mail.message обьектот "
|
||||
"хавсралтын хамт\n"
|
||||
"архивладаг.\n"
|
||||
" "
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_l10n_bo
|
||||
@@ -17186,6 +17249,15 @@ msgid ""
|
||||
" </p>\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"<p class=\"oe_view_nocontent_create\">\n"
|
||||
" Хаягийн дэвтэртэй холбогч нэмэхээр бол дарна.\n"
|
||||
" </p><p>\n"
|
||||
" OpenERP нь захиалагчтай холбоотой бүх үйл ажиллагааг хялбар "
|
||||
"хөтлөдөг, үүнд: \n"
|
||||
" захиалагчтай харилцсан харилцаа, бизнес боломжийн түүх, "
|
||||
"баримтууд гэх мэт.\n"
|
||||
" </p>\n"
|
||||
" "
|
||||
|
||||
#. module: base
|
||||
#: model:res.partner.category,name:base.res_partner_category_2
|
||||
@@ -17228,6 +17300,17 @@ msgid ""
|
||||
"on a supplier purchase order into several accounts and analytic plans.\n"
|
||||
" "
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Шинжилгээний тархалт болон худалдан авалтын захиалгын менежментийг хийх "
|
||||
"суурь модуль.\n"
|
||||
"====================================================================\n"
|
||||
"\n"
|
||||
"Шинжилгээний хэд хэдэн төлөвлөгөөг үүсгэх боломжийг хэрэглэгчид олгодог. Энэ "
|
||||
"нь нийлүүлэгчийн\n"
|
||||
"худалдан авалтын захиалгын нэг мөр дээр олон данс болон шинжилгээний "
|
||||
"төлөвлөгөөг сонгож, хуваах \n"
|
||||
"боломжийг олгодог.\n"
|
||||
" "
|
||||
|
||||
#. module: base
|
||||
#: model:res.country,name:base.lk
|
||||
@@ -17247,7 +17330,7 @@ msgstr "Орос хэл / русский язык"
|
||||
#. module: base
|
||||
#: model:ir.module.module,shortdesc:base.module_auth_signup
|
||||
msgid "Signup"
|
||||
msgstr ""
|
||||
msgstr "Бүртгүүлэх"
|
||||
|
||||
#, python-format
|
||||
#~ msgid "new"
|
||||
|
||||
@@ -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: 2013-10-11 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:35+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:47+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:39+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:38+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:34+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:40+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:49+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:45+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:41+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:44+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:46+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:42+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -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: 2013-10-11 04:48+0000\n"
|
||||
"X-Generator: Launchpad (build 16799)\n"
|
||||
"X-Launchpad-Export-Date: 2013-10-24 04:43+0000\n"
|
||||
"X-Generator: Launchpad (build 16810)\n"
|
||||
|
||||
#. module: base
|
||||
#: model:ir.module.module,description:base.module_account_check_writing
|
||||
|
||||
@@ -262,10 +262,14 @@ class ir_attachment(osv.osv):
|
||||
return len(result) if count else list(result)
|
||||
|
||||
def read(self, cr, uid, ids, fields_to_read=None, context=None, load='_classic_read'):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
self.check(cr, uid, ids, 'read', context=context)
|
||||
return super(ir_attachment, self).read(cr, uid, ids, fields_to_read, context, load)
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
self.check(cr, uid, ids, 'write', context=context, values=vals)
|
||||
if 'file_size' in vals:
|
||||
del vals['file_size']
|
||||
@@ -276,6 +280,8 @@ class ir_attachment(osv.osv):
|
||||
return super(ir_attachment, self).copy(cr, uid, id, default, context)
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
self.check(cr, uid, ids, 'unlink', context=context)
|
||||
location = self.pool.get('ir.config_parameter').get_param(cr, uid, 'ir_attachment.location')
|
||||
if location:
|
||||
|
||||
@@ -192,7 +192,7 @@ class ir_fields_converter(orm.Model):
|
||||
|
||||
def _str_id(self, cr, uid, model, column, value, context=None):
|
||||
return value, []
|
||||
_str_to_char = _str_to_text = _str_to_binary = _str_id
|
||||
_str_to_reference = _str_to_char = _str_to_text = _str_to_binary = _str_id
|
||||
|
||||
def _str_to_date(self, cr, uid, model, column, value, context=None):
|
||||
try:
|
||||
|
||||
@@ -198,6 +198,7 @@ class ir_model(osv.osv):
|
||||
select=vals.get('select_level', '0'),
|
||||
update_custom_fields=True)
|
||||
self.pool[vals['model']]._auto_init(cr, ctx)
|
||||
self.pool[vals['model']]._auto_end(cr, ctx) # actually create FKs!
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
return res
|
||||
|
||||
@@ -356,6 +357,7 @@ class ir_model_fields(osv.osv):
|
||||
select=vals.get('select_level', '0'),
|
||||
update_custom_fields=True)
|
||||
self.pool[vals['model']]._auto_init(cr, ctx)
|
||||
self.pool[vals['model']]._auto_end(cr, ctx) # actually create FKs!
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
|
||||
return res
|
||||
@@ -470,6 +472,7 @@ class ir_model_fields(osv.osv):
|
||||
for col_name, col_prop, val in patch_struct[1]:
|
||||
setattr(obj._columns[col_name], col_prop, val)
|
||||
obj._auto_init(cr, ctx)
|
||||
obj._auto_end(cr, ctx) # actually create FKs!
|
||||
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
|
||||
return res
|
||||
|
||||
@@ -933,8 +936,8 @@ class ir_model_data(osv.osv):
|
||||
results = cr.fetchall()
|
||||
for imd_id2,res_id2,real_id2,real_model in results:
|
||||
if not real_id2:
|
||||
self._get_id.clear_cache(self, uid, module, xml_id)
|
||||
self.get_object_reference.clear_cache(self, uid, module, xml_id)
|
||||
self._get_id.clear_cache(self)
|
||||
self.get_object_reference.clear_cache(self)
|
||||
cr.execute('delete from ir_model_data where id=%s', (imd_id2,))
|
||||
res_id = False
|
||||
else:
|
||||
|
||||
@@ -2,17 +2,18 @@
|
||||
import cStringIO
|
||||
import json
|
||||
import datetime
|
||||
import dateutil
|
||||
import dateutil.relativedelta
|
||||
import logging
|
||||
import re
|
||||
import traceback
|
||||
import urllib
|
||||
import xml # FIXME use lxml and etree
|
||||
|
||||
import Image
|
||||
import math
|
||||
import werkzeug.utils
|
||||
|
||||
from openerp.osv import osv, orm, fields
|
||||
import openerp.tools
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -44,6 +45,13 @@ BUILTINS = {
|
||||
'relativedelta': lambda *a, **kw : dateutil.relativedelta.relativedelta(*a, **kw),
|
||||
}
|
||||
|
||||
class QWebException(Exception):
|
||||
def __init__(self, message, template=None, node=None, attribute=None):
|
||||
self.message = message
|
||||
self.template = template
|
||||
self.node = node
|
||||
self.attribute = attribute
|
||||
|
||||
## We use a jinja2 sandboxed environment to render qWeb templates.
|
||||
#from openerp.tools.safe_eval import safe_eval as eval
|
||||
#from jinja2.sandbox import SandboxedEnvironment
|
||||
@@ -52,9 +60,14 @@ BUILTINS = {
|
||||
#SAFE = ["_name"]
|
||||
|
||||
class QWebContext(dict):
|
||||
def __init__(self, data, undefined_handler=None, loader=None):
|
||||
def __init__(self, cr, uid, data, undefined_handler=None, loader=None,
|
||||
templates=None, context=None):
|
||||
self.cr = cr
|
||||
self.uid = uid
|
||||
self.loader = loader
|
||||
self.undefined_handler = undefined_handler
|
||||
self.templates = templates or {}
|
||||
self.context = context
|
||||
dic = BUILTINS.copy()
|
||||
dic.update(data)
|
||||
super(QWebContext, self).__init__(dic)
|
||||
@@ -90,9 +103,11 @@ class QWebContext(dict):
|
||||
return eval(expr, None, self)
|
||||
|
||||
def copy(self):
|
||||
return QWebContext(dict.copy(self),
|
||||
return QWebContext(self.cr, self.uid, dict.copy(self),
|
||||
undefined_handler=self.undefined_handler,
|
||||
loader=self.loader)
|
||||
loader=self.loader,
|
||||
templates=self.templates,
|
||||
context=self.context)
|
||||
|
||||
def __copy__(self):
|
||||
return self.copy()
|
||||
@@ -142,7 +157,6 @@ class QWeb(orm.AbstractModel):
|
||||
|
||||
def __init__(self, pool, cr):
|
||||
super(QWeb, self).__init__(pool, cr)
|
||||
self._t = {}
|
||||
|
||||
self._render_tag = self.prefixed_methods('render_tag_')
|
||||
self._render_att = self.prefixed_methods('render_att_')
|
||||
@@ -163,7 +177,7 @@ class QWeb(orm.AbstractModel):
|
||||
def register_tag(self, tag, func):
|
||||
self._render_tag[tag] = func
|
||||
|
||||
def load_document(self, x):
|
||||
def load_document(self, x, into):
|
||||
"""
|
||||
Loads an XML document and installs any contained template in the engine
|
||||
"""
|
||||
@@ -176,15 +190,15 @@ class QWeb(orm.AbstractModel):
|
||||
|
||||
for n in dom.documentElement.childNodes:
|
||||
if n.nodeType == self.node.ELEMENT_NODE and n.getAttribute('t-name'):
|
||||
self._t[str(n.getAttribute("t-name"))] = n
|
||||
into[str(n.getAttribute("t-name"))] = n
|
||||
|
||||
def get_template(self, name, context):
|
||||
if context.loader and name not in self._t:
|
||||
if context.loader and name not in context.templates:
|
||||
xml_doc = context.loader(name)
|
||||
self.load_document(xml_doc)
|
||||
self.load_document(xml_doc, into=context.templates)
|
||||
|
||||
if name in self._t:
|
||||
return self._t[name]
|
||||
if name in context.templates:
|
||||
return context.templates[name]
|
||||
|
||||
raise KeyError('qweb: template "%s" not found' % name)
|
||||
|
||||
@@ -194,7 +208,8 @@ class QWeb(orm.AbstractModel):
|
||||
except (osv.except_osv, orm.except_orm), err:
|
||||
raise orm.except_orm("QWeb Error", "Invalid expression %r while rendering template '%s'.\n\n%s" % (expr, v.get('__template__'), err[1]))
|
||||
except Exception:
|
||||
raise SyntaxError("QWeb: invalid expression %r while rendering template '%s'.\n\n%s" % (expr, v.get('__template__'), traceback.format_exc()))
|
||||
raise QWebException("QWeb: invalid expression %r while rendering template '%s'." % (expr, v.get('__template__')),
|
||||
template=v.get('__template__'))
|
||||
|
||||
def eval_object(self, expr, v):
|
||||
return self.eval(expr, v)
|
||||
@@ -227,11 +242,13 @@ class QWeb(orm.AbstractModel):
|
||||
else:
|
||||
return 0
|
||||
|
||||
def render(self, tname, v=None, out=None, loader=None, undefined_handler=None):
|
||||
def render(self, cr, uid, tname, v=None, loader=None,
|
||||
undefined_handler=None, context=None):
|
||||
if v is None:
|
||||
v = {}
|
||||
if not isinstance(v, QWebContext):
|
||||
v = QWebContext(v, undefined_handler=undefined_handler, loader=loader)
|
||||
v = QWebContext(cr, uid, v, undefined_handler=undefined_handler,
|
||||
loader=loader, context=context)
|
||||
v['__template__'] = tname
|
||||
stack = v.get('__stack__', [])
|
||||
if stack:
|
||||
@@ -289,7 +306,16 @@ class QWeb(orm.AbstractModel):
|
||||
else:
|
||||
g_inner = []
|
||||
for n in e.childNodes:
|
||||
g_inner.append(self.render_node(n, v))
|
||||
try:
|
||||
g_inner.append(self.render_node(n, v))
|
||||
except (osv.except_osv, orm.except_orm), err:
|
||||
raise err
|
||||
except QWebException, err:
|
||||
if not err.node:
|
||||
err.node = e
|
||||
raise err
|
||||
except Exception, err:
|
||||
raise QWebException("%s" % err, template=v.get('__template__'), node=e)
|
||||
name = str(e.nodeName)
|
||||
inner = "".join(g_inner)
|
||||
trim = t_att.get("trim", 0)
|
||||
@@ -402,7 +428,7 @@ class QWeb(orm.AbstractModel):
|
||||
d = v if 'import' in t_att else v.copy()
|
||||
d[0] = self.render_element(e, t_att, g_att, d)
|
||||
|
||||
return self.render(self.eval_format(t_att["call"], d), d)
|
||||
return self.render(None, None, self.eval_format(t_att["call"], d), d)
|
||||
|
||||
def render_tag_set(self, e, t_att, g_att, v):
|
||||
if "value" in t_att:
|
||||
@@ -431,8 +457,8 @@ class QWeb(orm.AbstractModel):
|
||||
|
||||
converter = self.get_converter_for(field_type)
|
||||
|
||||
return converter.to_html(record._cr, record._uid, field_name, record, options,
|
||||
e, t_att, g_att, v)
|
||||
return converter.to_html(v.cr, v.uid, field_name, record, options,
|
||||
e, t_att, g_att, v, context=v.context)
|
||||
|
||||
def get_converter_for(self, field_type):
|
||||
return self.pool.get('ir.qweb.field.' + field_type,
|
||||
@@ -452,7 +478,8 @@ class FieldConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field'
|
||||
|
||||
def attributes(self, cr, uid, field_name, record, options,
|
||||
source_element, g_att, t_att, qweb_context):
|
||||
source_element, g_att, t_att, qweb_context,
|
||||
context=None):
|
||||
"""
|
||||
Generates the metadata attributes (prefixed by ``data-oe-`` for the
|
||||
root node of the field conversion. Attribute values are escaped by the
|
||||
@@ -481,20 +508,20 @@ class FieldConverter(osv.AbstractModel):
|
||||
('data-oe-expression', t_att['field']),
|
||||
]
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None):
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
""" Converts a single value to its HTML version/output
|
||||
"""
|
||||
return werkzeug.utils.escape(value)
|
||||
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None):
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
|
||||
""" Converts the specified field of the browse_record ``record`` to
|
||||
HTML
|
||||
"""
|
||||
return self.value_to_html(
|
||||
cr, uid, record[field_name], column, options=None)
|
||||
cr, uid, record[field_name], column, options=None, context=context)
|
||||
|
||||
def to_html(self, cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context):
|
||||
source_element, t_att, g_att, qweb_context, context=None):
|
||||
""" Converts a ``t-field`` to its HTML output. A ``t-field`` may be
|
||||
extended by a ``t-field-options``, which is a JSON-serialized mapping
|
||||
of configuration values.
|
||||
@@ -507,7 +534,7 @@ class FieldConverter(osv.AbstractModel):
|
||||
content = self.record_to_html(
|
||||
cr, uid, field_name, record,
|
||||
record._model._all_columns[field_name].column,
|
||||
options)
|
||||
options, context=context)
|
||||
except Exception:
|
||||
_logger.warning("Could not get field %s for model %s",
|
||||
field_name, record._model._name, exc_info=True)
|
||||
@@ -532,22 +559,86 @@ class FieldConverter(osv.AbstractModel):
|
||||
return self.qweb_object().render_element(
|
||||
source_element, t_att, g_att, qweb_context, content or '')
|
||||
|
||||
def user_lang(self, cr, uid, context):
|
||||
"""
|
||||
Fetches the res.lang object corresponding to the language code stored
|
||||
in the user's context. Fallbacks to en_US if no lang is present in the
|
||||
context *or the language code is not valid*.
|
||||
|
||||
:returns: res.lang browse_record
|
||||
"""
|
||||
if context is None: context = {}
|
||||
|
||||
lang_code = context.get('lang') or 'en_US'
|
||||
Lang = self.pool['res.lang']
|
||||
|
||||
lang_ids = Lang.search(cr, uid, [('code', '=', lang_code)], context=context) \
|
||||
or Lang.search(cr, uid, [('code', '=', 'en_US')], context=context)
|
||||
|
||||
return Lang.browse(cr, uid, lang_ids[0], context=context)
|
||||
|
||||
class FloatConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.float'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None):
|
||||
width, precision = column.digits or (None, None)
|
||||
fmt = '{value}' if precision is None else '{value:.{precision}f}'
|
||||
def precision(self, cr, uid, column, options=None, context=None):
|
||||
_, precision = column.digits or (None, None)
|
||||
return precision
|
||||
|
||||
return werkzeug.utils.escape(
|
||||
fmt.format(value=value, width=width, precision=precision, ))
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
precision = self.precision(cr, uid, column, options=options, context=context)
|
||||
fmt = '%f' if precision is None else '%.{precision}f'
|
||||
|
||||
lang = self.user_lang(cr, uid, context)
|
||||
|
||||
formatted = lang.format(fmt.format(precision=precision),
|
||||
value, grouping=True)
|
||||
# %f does not strip trailing zeroes. %g does but its precision causes
|
||||
# it to switch to scientific notation starting at a million *and* to
|
||||
# strip decimals. So use %f and if no precision was specified manually
|
||||
# strip trailing 0.
|
||||
if not precision:
|
||||
formatted = re.sub(r'(?:(0|\d+?)0+)$', r'\1', formatted)
|
||||
return werkzeug.utils.escape(formatted)
|
||||
|
||||
class DateConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.date'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
parse_format = openerp.tools.DEFAULT_SERVER_DATE_FORMAT
|
||||
out_format = lang.date_format.encode('utf-8')
|
||||
|
||||
if isinstance(value, basestring):
|
||||
value = datetime.datetime.strptime(value, parse_format)
|
||||
|
||||
return value.strftime(out_format)
|
||||
|
||||
class DateTimeConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.datetime'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
|
||||
parse_format = openerp.tools.DEFAULT_SERVER_DATETIME_FORMAT
|
||||
out_format = (u"%s %s" % (lang.date_format, lang.time_format)).encode('utf-8')
|
||||
|
||||
if isinstance(value, basestring):
|
||||
value = datetime.datetime.strptime(value, parse_format)
|
||||
|
||||
value = column.context_timestamp(
|
||||
cr, uid, timestamp=value, context=context)
|
||||
|
||||
return value.strftime(out_format)
|
||||
|
||||
class TextConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.text'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None):
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
"""
|
||||
Escapes the value and converts newlines to br. This is bullshit.
|
||||
"""
|
||||
@@ -557,8 +648,7 @@ class SelectionConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.selection'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None):
|
||||
# FIXME: context
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options=None, context=None):
|
||||
value = record[field_name]
|
||||
selection = dict(fields.selection.reify(
|
||||
cr, uid, record._model, column))
|
||||
@@ -569,16 +659,18 @@ class ManyToOneConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.many2one'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None):
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
# value may be a browse_null
|
||||
if not value: return ''
|
||||
return werkzeug.utils.escape(value.name_get()[0][1]).replace('\n', '<br>\n')
|
||||
name_got = value._model.name_get(
|
||||
cr, openerp.SUPERUSER_ID, value.id, context=context)[0][1]
|
||||
return werkzeug.utils.escape(name_got).replace('\n', '<br>\n')
|
||||
|
||||
class HTMLConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.html'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None):
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
return value
|
||||
|
||||
class ImageConverter(osv.AbstractModel):
|
||||
@@ -593,7 +685,7 @@ class ImageConverter(osv.AbstractModel):
|
||||
_name = 'ir.qweb.field.image'
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def value_to_html(self, cr, uid, value, column, options=None):
|
||||
def value_to_html(self, cr, uid, value, column, options=None, context=None):
|
||||
try:
|
||||
image = Image.open(cStringIO.StringIO(value.decode('base64')))
|
||||
image.verify()
|
||||
@@ -608,6 +700,10 @@ class MonetaryConverter(osv.AbstractModel):
|
||||
""" ``monetary`` converter, has a mandatory option
|
||||
``display_currency``.
|
||||
|
||||
The currency is used for formatting *and rounding* of the float value. It
|
||||
is assumed that the linked res_currency has a non-empty rounding value and
|
||||
res.currency's ``round`` method is used to perform rounding.
|
||||
|
||||
.. note:: the monetary converter internally adds the qweb context to its
|
||||
options mapping, so that the context is available to callees.
|
||||
It's set under the ``_qweb_context`` key.
|
||||
@@ -616,32 +712,45 @@ class MonetaryConverter(osv.AbstractModel):
|
||||
_inherit = 'ir.qweb.field'
|
||||
|
||||
def to_html(self, cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context):
|
||||
source_element, t_att, g_att, qweb_context, context=None):
|
||||
options['_qweb_context'] = qweb_context
|
||||
return super(MonetaryConverter, self).to_html(
|
||||
cr, uid, field_name, record, options,
|
||||
source_element, t_att, g_att, qweb_context)
|
||||
source_element, t_att, g_att, qweb_context, context=context)
|
||||
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options):
|
||||
def record_to_html(self, cr, uid, field_name, record, column, options, context=None):
|
||||
Currency = self.pool['res.currency']
|
||||
display = self.display_currency(cr, uid, options)
|
||||
|
||||
symbol_pre = symbol_post = space_pre = space_post = u''
|
||||
if display.position == 'before':
|
||||
space_pre = u' '
|
||||
symbol_pre = display.symbol
|
||||
else:
|
||||
space_post = u' '
|
||||
symbol_post = display.symbol
|
||||
# lang.format mandates a sprintf-style format. These formats are non-
|
||||
# minimal (they have a default fixed precision instead), and
|
||||
# lang.format will not set one by default. currency.round will not
|
||||
# provide one either. So we need to generate a precision value
|
||||
# (integer > 0) from the currency's rounding (a float generally < 1.0).
|
||||
#
|
||||
# The log10 of the rounding should be the number of digits involved if
|
||||
# negative, if positive clamp to 0 digits and call it a day.
|
||||
# nb: int() ~ floor(), we want nearest rounding instead
|
||||
precision = int(round(math.log10(display.rounding)))
|
||||
fmt = "%.{0}f".format(-precision if precision < 0 else 0)
|
||||
|
||||
return u'{symbol_pre}{space_pre}' \
|
||||
u'<span class="oe_currency_value">{0}</span>' \
|
||||
u'{space_post}{symbol_post}'.format(
|
||||
Currency.round(cr, uid, display, record[field_name]),
|
||||
space_pre=space_pre,
|
||||
symbol_pre=symbol_pre,
|
||||
space_post=space_post,
|
||||
symbol_post=symbol_post,)
|
||||
lang = self.user_lang(cr, uid, context=context)
|
||||
formatted_amount = lang.format(
|
||||
fmt, Currency.round(cr, uid, display, record[field_name]),
|
||||
grouping=True, monetary=True)
|
||||
|
||||
pre = post = u''
|
||||
if display.position == 'before':
|
||||
pre = u'{symbol} '
|
||||
else:
|
||||
post = u' {symbol}'
|
||||
|
||||
return u'{pre}<span class="oe_currency_value">{0}</span>{post}'.format(
|
||||
formatted_amount,
|
||||
pre=pre, post=post,
|
||||
).format(
|
||||
symbol=display.symbol,
|
||||
)
|
||||
|
||||
def display_currency(self, cr, uid, options):
|
||||
return self.qweb_object().eval_object(
|
||||
|
||||
@@ -161,18 +161,18 @@ class ir_translation(osv.osv):
|
||||
'''
|
||||
if context is None:
|
||||
context = {}
|
||||
res = {}
|
||||
res = dict.fromkeys(ids, False)
|
||||
for record in self.browse(cr, uid, ids, context=context):
|
||||
if record.type != 'model':
|
||||
res[record.id] = record.src
|
||||
else:
|
||||
model_name, field = record.name.split(',')
|
||||
model = self.pool.get(model_name)
|
||||
#We need to take the context without the language information, because we want to read the
|
||||
#value store in db and not on the one associate with current language.
|
||||
context_wo_lang = context.copy()
|
||||
context_wo_lang.pop('lang', None)
|
||||
res[record.id] = model.read(cr, uid, record.res_id, [field], context=context_wo_lang)[field]
|
||||
if model and model.exists(cr, uid, record.res_id, context=context):
|
||||
# Pass context without lang, need to read real stored field, not translation
|
||||
context_no_lang = dict(context, lang=None)
|
||||
result = model.read(cr, uid, record.res_id, [field], context=context_no_lang)
|
||||
res[record.id] = result[field] if result else False
|
||||
return res
|
||||
|
||||
def _set_src(self, cr, uid, id, name, value, args, context=None):
|
||||
@@ -268,13 +268,8 @@ class ir_translation(osv.osv):
|
||||
return translations
|
||||
|
||||
def _set_ids(self, cr, uid, name, tt, lang, ids, value, src=None):
|
||||
# clear the caches
|
||||
tr = self._get_ids(cr, uid, name, tt, lang, ids)
|
||||
for res_id in tr:
|
||||
if tr[res_id]:
|
||||
self._get_source.clear_cache(self, uid, name, tt, lang, tr[res_id])
|
||||
self._get_ids.clear_cache(self, uid, name, tt, lang, res_id)
|
||||
self._get_source.clear_cache(self, uid, name, tt, lang)
|
||||
self._get_ids.clear_cache(self)
|
||||
self._get_source.clear_cache(self)
|
||||
|
||||
cr.execute('delete from ir_translation '
|
||||
'where lang=%s '
|
||||
@@ -346,8 +341,8 @@ class ir_translation(osv.osv):
|
||||
if context is None:
|
||||
context = {}
|
||||
ids = super(ir_translation, self).create(cr, uid, vals, context=context)
|
||||
self._get_source.clear_cache(self, uid, vals.get('name',0), vals.get('type',0), vals.get('lang',0), vals.get('src',0))
|
||||
self._get_ids.clear_cache(self, uid, vals.get('name',0), vals.get('type',0), vals.get('lang',0), vals.get('res_id',0))
|
||||
self._get_source.clear_cache(self)
|
||||
self._get_ids.clear_cache(self)
|
||||
return ids
|
||||
|
||||
def write(self, cursor, user, ids, vals, context=None):
|
||||
@@ -360,9 +355,8 @@ class ir_translation(osv.osv):
|
||||
if vals.get('value'):
|
||||
vals.update({'state':'translated'})
|
||||
result = super(ir_translation, self).write(cursor, user, ids, vals, context=context)
|
||||
for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
|
||||
self._get_source.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['src'])
|
||||
self._get_ids.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['res_id'])
|
||||
self._get_source.clear_cache(self)
|
||||
self._get_ids.clear_cache(self)
|
||||
return result
|
||||
|
||||
def unlink(self, cursor, user, ids, context=None):
|
||||
@@ -370,9 +364,9 @@ class ir_translation(osv.osv):
|
||||
context = {}
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
for trans_obj in self.read(cursor, user, ids, ['name','type','res_id','src','lang'], context=context):
|
||||
self._get_source.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['src'])
|
||||
self._get_ids.clear_cache(self, user, trans_obj['name'], trans_obj['type'], trans_obj['lang'], trans_obj['res_id'])
|
||||
|
||||
self._get_source.clear_cache(self)
|
||||
self._get_ids.clear_cache(self)
|
||||
result = super(ir_translation, self).unlink(cursor, user, ids, context=context)
|
||||
return result
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
<field name="lang"/>
|
||||
</group>
|
||||
<group>
|
||||
<field name="module" group="base.group_no_one"/>
|
||||
<field name="type"/>
|
||||
<field name="res_id"/>
|
||||
</group>
|
||||
|
||||
@@ -775,7 +775,7 @@ class view(osv.osv):
|
||||
for key in values:
|
||||
value = isinstance(values, (dict,)) and values[key] or key
|
||||
if isinstance(value, (browse_record,)):
|
||||
if value.__dict__.get('_uid') == openerp.SUPERUSER_ID and uid != openerp.SUPERUSER_ID:
|
||||
if getattr(value, '_uid', None) == openerp.SUPERUSER_ID and uid != openerp.SUPERUSER_ID:
|
||||
message = 'SUPERUSER_ID Access used for rendering "%s" in a xml view: %s' % (key, id_or_xml_id,)
|
||||
_logger.warn(message)
|
||||
elif isinstance(value, (dict, list, browse_record_list,)):
|
||||
@@ -786,8 +786,9 @@ class view(osv.osv):
|
||||
return self.read_template(cr, uid, name, context=context)
|
||||
|
||||
return self.pool[engine].render(
|
||||
id_or_xml_id, values,
|
||||
loader=loader, undefined_handler=lambda key, v: None)
|
||||
cr, uid, id_or_xml_id, values,
|
||||
loader=loader, undefined_handler=lambda key, v: None,
|
||||
context=context)
|
||||
|
||||
# maybe used to print the workflow ?
|
||||
|
||||
|
||||
@@ -47,33 +47,8 @@ class base_module_import(osv.osv_memory):
|
||||
}
|
||||
|
||||
def importzip(self, cr, uid, ids, context):
|
||||
(data,) = self.browse(cr, uid, ids , context=context)
|
||||
module_data = data.module_file
|
||||
zip_data = base64.decodestring(module_data)
|
||||
fp = StringIO()
|
||||
fp.write(zip_data)
|
||||
try:
|
||||
file_data = zipfile.ZipFile(fp, 'r')
|
||||
except zipfile.BadZipfile:
|
||||
raise osv.except_osv(_('Error!'), _('File is not a zip file!'))
|
||||
init_file_name = sorted(file_data.namelist())[0]
|
||||
module_name = os.path.split(init_file_name)[0]
|
||||
|
||||
file_path = os.path.join(ADDONS_PATH, '%s.zip' % module_name)
|
||||
try:
|
||||
zip_file = open(file_path, 'wb')
|
||||
except IOError:
|
||||
raise osv.except_osv(_('Error!'),
|
||||
_('Can not create the module file: %s!') % \
|
||||
(file_path,) )
|
||||
zip_file.write(zip_data)
|
||||
zip_file.close()
|
||||
|
||||
self.pool.get('ir.module.module').update_list(cr, uid,
|
||||
{'module_name': module_name,})
|
||||
self.write(cr, uid, ids, {'state':'done', 'module_name': module_name},
|
||||
context)
|
||||
return False
|
||||
#TODO: drop this model and the corresponding view/action in trunk
|
||||
raise NotImplementedError('This feature is not available')
|
||||
|
||||
def action_module_open(self, cr, uid, ids, context):
|
||||
(data,) = self.browse(cr, uid, ids , context=context)
|
||||
|
||||
@@ -194,30 +194,24 @@ class lang(osv.osv):
|
||||
|
||||
def format(self, cr, uid, ids, percent, value, grouping=False, monetary=False, context=None):
|
||||
""" Format() will return the language-specific output for float values"""
|
||||
|
||||
if percent[0] != '%':
|
||||
raise ValueError("format() must be given exactly one %char format specifier")
|
||||
|
||||
lang_grouping, thousands_sep, decimal_point = self._lang_data_get(cr, uid, ids[0], monetary)
|
||||
eval_lang_grouping = eval(lang_grouping)
|
||||
|
||||
formatted = percent % value
|
||||
|
||||
# floats and decimal ints need special action!
|
||||
if percent[-1] in 'eEfFgG':
|
||||
seps = 0
|
||||
parts = formatted.split('.')
|
||||
if grouping:
|
||||
lang_grouping, thousands_sep, decimal_point = \
|
||||
self._lang_data_get(cr, uid, ids[0], monetary)
|
||||
eval_lang_grouping = eval(lang_grouping)
|
||||
|
||||
if grouping:
|
||||
parts[0], seps = intersperse(parts[0], eval_lang_grouping, thousands_sep)
|
||||
if percent[-1] in 'eEfFgG':
|
||||
parts = formatted.split('.')
|
||||
parts[0], _ = intersperse(parts[0], eval_lang_grouping, thousands_sep)
|
||||
|
||||
formatted = decimal_point.join(parts)
|
||||
while seps:
|
||||
sp = formatted.find(' ')
|
||||
if sp == -1: break
|
||||
formatted = formatted[:sp] + formatted[sp+1:]
|
||||
seps -= 1
|
||||
elif percent[-1] in 'diu':
|
||||
if grouping:
|
||||
formatted = decimal_point.join(parts)
|
||||
|
||||
elif percent[-1] in 'diu':
|
||||
formatted = intersperse(formatted, eval_lang_grouping, thousands_sep)[0]
|
||||
|
||||
return formatted
|
||||
|
||||
@@ -171,13 +171,6 @@ class res_users(osv.osv):
|
||||
def on_change_login(self, cr, uid, ids, login, context=None):
|
||||
return {'value': {'email': login}}
|
||||
|
||||
def on_change_company_id(self, cr, uid, ids, company_id):
|
||||
return {'warning' : {
|
||||
'title': _("Company Switch Warning"),
|
||||
'message': _("Please keep in mind that documents currently displayed may not be relevant after switching to another company. If you have unsaved changes, please make sure to save and close all forms before switching to a different company. (You can click on Cancel in the User Preferences now)"),
|
||||
}
|
||||
}
|
||||
|
||||
def onchange_state(self, cr, uid, ids, state_id, context=None):
|
||||
partner_ids = [user.partner_id.id for user in self.browse(cr, uid, ids, context=context)]
|
||||
return self.pool.get('res.partner').onchange_state(cr, uid, partner_ids, state_id, context=context)
|
||||
|
||||
@@ -283,7 +283,7 @@
|
||||
<field name="lang" readonly="0"/>
|
||||
<field name="tz" readonly="0"/>
|
||||
<field name="company_id" widget="selection" readonly="0"
|
||||
groups="base.group_multi_company" on_change="on_change_company_id(company_id)"/>
|
||||
groups="base.group_multi_company"/>
|
||||
</group>
|
||||
<group string="Email Preferences">
|
||||
<field name="email" widget="email" readonly="0"/>
|
||||
|
||||
@@ -114,6 +114,8 @@
|
||||
access_ir_qweb,access_ir_qweb,model_ir_qweb,,0,0,0,0
|
||||
access_ir_qweb_field,access_ir_qweb_field,model_ir_qweb_field,,0,0,0,0
|
||||
access_ir_qweb_field_float,access_ir_qweb_field_float,model_ir_qweb_field_float,,0,0,0,0
|
||||
access_ir_qweb_field_date,access_ir_qweb_field_date,model_ir_qweb_field_date,,0,0,0,0
|
||||
access_ir_qweb_field_datetime,access_ir_qweb_field_datetime,model_ir_qweb_field_datetime,,0,0,0,0
|
||||
access_ir_qweb_field_text,access_ir_qweb_field_text,model_ir_qweb_field_text,,0,0,0,0
|
||||
access_ir_qweb_field_selection,access_ir_qweb_field_selection,model_ir_qweb_field_selection,,0,0,0,0
|
||||
access_ir_qweb_field_many2one,access_ir_qweb_field_many2one,model_ir_qweb_field_many2one,,0,0,0,0
|
||||
|
||||
|
+1098
-28
File diff suppressed because it is too large
Load Diff
@@ -166,11 +166,15 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
||||
# upgrading the module information
|
||||
modobj.write(cr, SUPERUSER_ID, [module_id], modobj.get_values_from_terp(package.data))
|
||||
_load_data(cr, module_name, idref, mode, kind='data')
|
||||
if hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed'):
|
||||
has_demo = hasattr(package, 'demo') or (package.dbdemo and package.state != 'installed')
|
||||
if has_demo:
|
||||
status['progress'] = (index + 0.75) / len(graph)
|
||||
_load_data(cr, module_name, idref, mode, kind='demo')
|
||||
cr.execute('update ir_module_module set demo=%s where id=%s', (True, module_id))
|
||||
|
||||
migrations.migrate_module(package, 'post')
|
||||
|
||||
if has_demo:
|
||||
# launch tests only in demo mode, as most tests will depend
|
||||
# on demo data. Other tests can be added into the regular
|
||||
# 'data' section, but should probably not alter the data,
|
||||
@@ -186,8 +190,6 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
|
||||
|
||||
processed_modules.append(package.name)
|
||||
|
||||
migrations.migrate_module(package, 'post')
|
||||
|
||||
ver = adapt_version(package.data['version'])
|
||||
# Set new modules and dependencies
|
||||
modobj.write(cr, SUPERUSER_ID, [module_id], {'state': 'installed', 'latest_version': ver})
|
||||
|
||||
@@ -305,18 +305,16 @@ class RegistryManager(object):
|
||||
r, c = cr.fetchone()
|
||||
# Check if the model registry must be reloaded (e.g. after the
|
||||
# database has been updated by another process).
|
||||
if registry.base_registry_signaling_sequence != r:
|
||||
if registry.base_registry_signaling_sequence > 1 and registry.base_registry_signaling_sequence != r:
|
||||
changed = True
|
||||
_logger.info("Reloading the model registry after database signaling.")
|
||||
registry = cls.new(db_name)
|
||||
registry.base_registry_signaling_sequence = r
|
||||
# Check if the model caches must be invalidated (e.g. after a write
|
||||
# occured on another process). Don't clear right after a registry
|
||||
# has been reload.
|
||||
elif registry.base_cache_signaling_sequence != c:
|
||||
elif registry.base_cache_signaling_sequence > 1 and registry.base_cache_signaling_sequence != c:
|
||||
changed = True
|
||||
_logger.info("Invalidating all model caches after database signaling.")
|
||||
registry.base_cache_signaling_sequence = c
|
||||
registry.clear_caches()
|
||||
registry.reset_any_cache_cleared()
|
||||
# One possible reason caches have been invalidated is the
|
||||
@@ -326,6 +324,8 @@ class RegistryManager(object):
|
||||
for column in model._columns.values():
|
||||
if hasattr(column, 'digits_change'):
|
||||
column.digits_change(cr)
|
||||
registry.base_registry_signaling_sequence = r
|
||||
registry.base_cache_signaling_sequence = c
|
||||
finally:
|
||||
cr.close()
|
||||
return changed
|
||||
|
||||
+24
-18
@@ -117,8 +117,7 @@ class _column(object):
|
||||
self.groups = False # CSV list of ext IDs of groups that can access this field
|
||||
self.deprecated = False # Optional deprecation warning
|
||||
for a in args:
|
||||
if args[a]:
|
||||
setattr(self, a, args[a])
|
||||
setattr(self, a, args[a])
|
||||
|
||||
def restart(self):
|
||||
pass
|
||||
@@ -208,27 +207,29 @@ class reference(_column):
|
||||
return model.name_get(cr, uid, [int(res_id)], context=context)[0][1]
|
||||
return tools.ustr(value)
|
||||
|
||||
# takes a string (encoded in utf8) and returns a string (encoded in utf8)
|
||||
def _symbol_set_char(self, symb):
|
||||
|
||||
#TODO:
|
||||
# * we need to remove the "symb==False" from the next line BUT
|
||||
# for now too many things rely on this broken behavior
|
||||
# * the symb==None test should be common to all data types
|
||||
if symb is None or symb == False:
|
||||
return None
|
||||
|
||||
# we need to convert the string to a unicode object to be able
|
||||
# to evaluate its length (and possibly truncate it) reliably
|
||||
u_symb = tools.ustr(symb)
|
||||
return u_symb[:self.size].encode('utf8')
|
||||
|
||||
class char(_column):
|
||||
_type = 'char'
|
||||
|
||||
def __init__(self, string="unknown", size=None, **args):
|
||||
_column.__init__(self, string=string, size=size or None, **args)
|
||||
self._symbol_set = (self._symbol_c, self._symbol_set_char)
|
||||
|
||||
# takes a string (encoded in utf8) and returns a string (encoded in utf8)
|
||||
def _symbol_set_char(self, symb):
|
||||
#TODO:
|
||||
# * we need to remove the "symb==False" from the next line BUT
|
||||
# for now too many things rely on this broken behavior
|
||||
# * the symb==None test should be common to all data types
|
||||
if symb is None or symb == False:
|
||||
return None
|
||||
|
||||
# we need to convert the string to a unicode object to be able
|
||||
# to evaluate its length (and possibly truncate it) reliably
|
||||
u_symb = tools.ustr(symb)
|
||||
|
||||
return u_symb[:self.size].encode('utf8')
|
||||
# self._symbol_set_char defined to keep the backward compatibility
|
||||
self._symbol_f = self._symbol_set_char = lambda x: _symbol_set_char(self, x)
|
||||
self._symbol_set = (self._symbol_c, self._symbol_f)
|
||||
|
||||
|
||||
class text(_column):
|
||||
@@ -1150,6 +1151,11 @@ class function(_column):
|
||||
self._symbol_f = integer._symbol_f
|
||||
self._symbol_set = integer._symbol_set
|
||||
|
||||
if type == 'char':
|
||||
self._symbol_c = char._symbol_c
|
||||
self._symbol_f = lambda x: _symbol_set_char(self, x)
|
||||
self._symbol_set = (self._symbol_c, self._symbol_f)
|
||||
|
||||
def digits_change(self, cr):
|
||||
if self._type == 'float':
|
||||
if self.digits_compute:
|
||||
|
||||
+35
-25
@@ -1010,8 +1010,10 @@ class BaseModel(object):
|
||||
raise except_orm('Error',
|
||||
('Invalid function definition %s in object %s !\nYou must use the definition: store={object:(fnct, fields, priority, time length)}.' % (store_field, self._name)))
|
||||
self.pool._store_function.setdefault(object, [])
|
||||
self.pool._store_function[object].append((self._name, store_field, fnct, tuple(fields2) if fields2 else None, order, length))
|
||||
self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4]))
|
||||
t = (self._name, store_field, fnct, tuple(fields2) if fields2 else None, order, length)
|
||||
if not t in self.pool._store_function[object]:
|
||||
self.pool._store_function[object].append((self._name, store_field, fnct, tuple(fields2) if fields2 else None, order, length))
|
||||
self.pool._store_function[object].sort(lambda x, y: cmp(x[4], y[4]))
|
||||
|
||||
for (key, _, msg) in self._sql_constraints:
|
||||
self.pool._sql_error[self._table+'_'+key] = msg
|
||||
@@ -2461,8 +2463,12 @@ class BaseModel(object):
|
||||
"""
|
||||
Record the creation of a constraint for this model, to make it possible
|
||||
to delete it later when the module is uninstalled. Type can be either
|
||||
'f' or 'u' depending on the constraing being a foreign key or not.
|
||||
'f' or 'u' depending on the constraint being a foreign key or not.
|
||||
"""
|
||||
if not self._module:
|
||||
# no need to save constraints for custom models as they're not part
|
||||
# of any module
|
||||
return
|
||||
assert type in ('f', 'u')
|
||||
cr.execute("""
|
||||
SELECT 1 FROM ir_model_constraint, ir_module_module
|
||||
@@ -4122,9 +4128,9 @@ class BaseModel(object):
|
||||
return browse_null()
|
||||
|
||||
def _store_get_values(self, cr, uid, ids, fields, context):
|
||||
"""Returns an ordered list of fields.functions to call due to
|
||||
"""Returns an ordered list of fields.function to call due to
|
||||
an update operation on ``fields`` of records with ``ids``,
|
||||
obtained by calling the 'store' functions of these fields,
|
||||
obtained by calling the 'store' triggers of these fields,
|
||||
as setup by their 'store' attribute.
|
||||
|
||||
:return: [(priority, model_name, [record_ids,], [function_fields,])]
|
||||
@@ -4133,42 +4139,46 @@ class BaseModel(object):
|
||||
stored_functions = self.pool._store_function.get(self._name, [])
|
||||
|
||||
# use indexed names for the details of the stored_functions:
|
||||
model_name_, func_field_to_compute_, id_mapping_fnct_, trigger_fields_, priority_ = range(5)
|
||||
model_name_, func_field_to_compute_, target_ids_func_, trigger_fields_, priority_ = range(5)
|
||||
|
||||
# only keep functions that should be triggered for the ``fields``
|
||||
# only keep store triggers that should be triggered for the ``fields``
|
||||
# being written to.
|
||||
to_compute = [f for f in stored_functions \
|
||||
triggers_to_compute = [f for f in stored_functions \
|
||||
if ((not f[trigger_fields_]) or set(fields).intersection(f[trigger_fields_]))]
|
||||
|
||||
mapping = {}
|
||||
for function in to_compute:
|
||||
# use admin user for accessing objects having rules defined on store fields
|
||||
target_ids = [id for id in function[id_mapping_fnct_](self, cr, SUPERUSER_ID, ids, context) if id]
|
||||
to_compute_map = {}
|
||||
target_id_results = {}
|
||||
for store_trigger in triggers_to_compute:
|
||||
target_func_id_ = id(store_trigger[target_ids_func_])
|
||||
if not target_func_id_ in target_id_results:
|
||||
# use admin user for accessing objects having rules defined on store fields
|
||||
target_id_results[target_func_id_] = [i for i in store_trigger[target_ids_func_](self, cr, SUPERUSER_ID, ids, context) if i]
|
||||
target_ids = target_id_results[target_func_id_]
|
||||
|
||||
# the compound key must consider the priority and model name
|
||||
key = (function[priority_], function[model_name_])
|
||||
key = (store_trigger[priority_], store_trigger[model_name_])
|
||||
for target_id in target_ids:
|
||||
mapping.setdefault(key, {}).setdefault(target_id,set()).add(tuple(function))
|
||||
to_compute_map.setdefault(key, {}).setdefault(target_id,set()).add(tuple(store_trigger))
|
||||
|
||||
# Here mapping looks like:
|
||||
# { (10, 'model_a') : { target_id1: [ (function_1_tuple, function_2_tuple) ], ... }
|
||||
# (20, 'model_a') : { target_id2: [ (function_3_tuple, function_4_tuple) ], ... }
|
||||
# (99, 'model_a') : { target_id1: [ (function_5_tuple, function_6_tuple) ], ... }
|
||||
# Here to_compute_map looks like:
|
||||
# { (10, 'model_a') : { target_id1: [ (trigger_1_tuple, trigger_2_tuple) ], ... }
|
||||
# (20, 'model_a') : { target_id2: [ (trigger_3_tuple, trigger_4_tuple) ], ... }
|
||||
# (99, 'model_a') : { target_id1: [ (trigger_5_tuple, trigger_6_tuple) ], ... }
|
||||
# }
|
||||
|
||||
# Now we need to generate the batch function calls list
|
||||
# call_map =
|
||||
# { (10, 'model_a') : [(10, 'model_a', [record_ids,], [function_fields,])] }
|
||||
call_map = {}
|
||||
for ((priority,model), id_map) in mapping.iteritems():
|
||||
functions_ids_maps = {}
|
||||
for ((priority,model), id_map) in to_compute_map.iteritems():
|
||||
trigger_ids_maps = {}
|
||||
# function_ids_maps =
|
||||
# { (function_1_tuple, function_2_tuple) : [target_id1, target_id2, ..] }
|
||||
for id, functions in id_map.iteritems():
|
||||
functions_ids_maps.setdefault(tuple(functions), []).append(id)
|
||||
for functions, ids in functions_ids_maps.iteritems():
|
||||
call_map.setdefault((priority,model),[]).append((priority, model, ids,
|
||||
[f[func_field_to_compute_] for f in functions]))
|
||||
for target_id, triggers in id_map.iteritems():
|
||||
trigger_ids_maps.setdefault(tuple(triggers), []).append(target_id)
|
||||
for triggers, target_ids in trigger_ids_maps.iteritems():
|
||||
call_map.setdefault((priority,model),[]).append((priority, model, target_ids,
|
||||
[t[func_field_to_compute_] for t in triggers]))
|
||||
ordered_keys = call_map.keys()
|
||||
ordered_keys.sort()
|
||||
result = []
|
||||
|
||||
@@ -53,6 +53,12 @@ class TestIntegerExport(TestBasicExport):
|
||||
self.assertEqual(value, "42")
|
||||
|
||||
class TestFloatExport(TestBasicExport):
|
||||
def setUp(self):
|
||||
super(TestFloatExport, self).setUp()
|
||||
self.registry('res.lang').write(self.cr, self.uid, [1], {
|
||||
'grouping': '[3,0]'
|
||||
})
|
||||
|
||||
def test_float(self):
|
||||
converter = self.get_converter('float')
|
||||
|
||||
@@ -65,6 +71,9 @@ class TestFloatExport(TestBasicExport):
|
||||
value = converter(42.01234)
|
||||
self.assertEqual(value, "42.01234")
|
||||
|
||||
value = converter(1234567.89)
|
||||
self.assertEqual(value, '1,234,567.89')
|
||||
|
||||
def test_numeric(self):
|
||||
converter = self.get_converter('numeric')
|
||||
|
||||
@@ -98,7 +107,7 @@ class TestCurrencyExport(TestExport):
|
||||
self.cr, self.uid, 'value', obj, options,
|
||||
doc.createElement('span'),
|
||||
{'field': 'obj.value', 'field-options': json.dumps(options)},
|
||||
'', ir_qweb.QWebContext({'obj': obj, 'c2': dest, }))
|
||||
'', ir_qweb.QWebContext(self.cr, self.uid, {'obj': obj, 'c2': dest, }))
|
||||
return converted
|
||||
|
||||
def test_currency_post(self):
|
||||
@@ -263,5 +272,30 @@ class TestHTMLExport(TestBasicExport):
|
||||
value = converter(input)
|
||||
self.assertEqual(value, input)
|
||||
|
||||
class TestDatetimeExport(TestBasicExport):
|
||||
def setUp(self):
|
||||
super(TestDatetimeExport, self).setUp()
|
||||
# set user tz to known value
|
||||
Users = self.registry('res.users')
|
||||
Users.write(self.cr, self.uid, self.uid, {
|
||||
'tz': 'Pacific/Niue'
|
||||
}, context=None)
|
||||
|
||||
def test_date(self):
|
||||
converter = self.get_converter('date')
|
||||
|
||||
value = converter('2011-05-03')
|
||||
|
||||
# default lang/format is US
|
||||
self.assertEqual(value, '05/03/2011')
|
||||
|
||||
def test_datetime(self):
|
||||
converter = self.get_converter('datetime')
|
||||
|
||||
value = converter('2011-05-03 11:12:13')
|
||||
|
||||
# default lang/format is US
|
||||
self.assertEqual(value, '05/03/2011 00:12:13')
|
||||
|
||||
# o2m, m2m?
|
||||
# reference?
|
||||
|
||||
@@ -149,6 +149,59 @@ class TestCleaner(unittest2.TestCase):
|
||||
for text in out_lst:
|
||||
self.assertNotIn(text, new_html, 'html_email_cleaner did not remove unwanted content')
|
||||
|
||||
def test_05_shorten(self):
|
||||
# TEST: shorten length
|
||||
test_str = '''<div>
|
||||
<span>
|
||||
</span>
|
||||
<p>Hello, <span>Raoul</span>
|
||||
<bold>You</bold> are
|
||||
pretty</p>
|
||||
<span>Really</span>
|
||||
</div>
|
||||
'''
|
||||
# shorten at 'H' of Hello -> should shorten after Hello,
|
||||
html = html_email_clean(test_str, shorten=True, max_length=1, remove=True)
|
||||
self.assertIn('Hello,', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertNotIn('Raoul', html, 'html_email_cleaner: shorten error or too long')
|
||||
self.assertIn('read more', html, 'html_email_cleaner: shorten error about read more inclusion')
|
||||
# shorten at 'are' -> should shorten after are
|
||||
html = html_email_clean(test_str, shorten=True, max_length=17, remove=True)
|
||||
self.assertIn('Hello,', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('Raoul', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('are', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertNotIn('pretty', html, 'html_email_cleaner: shorten error or too long')
|
||||
self.assertNotIn('Really', html, 'html_email_cleaner: shorten error or too long')
|
||||
self.assertIn('read more', html, 'html_email_cleaner: shorten error about read more inclusion')
|
||||
|
||||
# TEST: shorten in quote
|
||||
test_str = '''<div> Blahble
|
||||
bluih blouh
|
||||
<blockquote>This is a quote
|
||||
<span>And this is quite a long quote, after all.</span>
|
||||
</blockquote>
|
||||
</div>'''
|
||||
# shorten in the quote
|
||||
html = html_email_clean(test_str, shorten=True, max_length=25, remove=True)
|
||||
self.assertIn('Blahble', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('bluih', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('blouh', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertNotIn('quote', html, 'html_email_cleaner: shorten error or too long')
|
||||
self.assertIn('read more', html, 'html_email_cleaner: shorten error about read more inclusion')
|
||||
# shorten in second word
|
||||
html = html_email_clean(test_str, shorten=True, max_length=9, remove=True)
|
||||
self.assertIn('Blahble', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('bluih', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertNotIn('blouh', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertNotIn('quote', html, 'html_email_cleaner: shorten error or too long')
|
||||
self.assertIn('read more', html, 'html_email_cleaner: shorten error about read more inclusion')
|
||||
# shorten waaay too large
|
||||
html = html_email_clean(test_str, shorten=True, max_length=900, remove=True)
|
||||
self.assertIn('Blahble', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('bluih', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertIn('blouh', html, 'html_email_cleaner: shorten error or too short')
|
||||
self.assertNotIn('quote', html, 'html_email_cleaner: shorten error or too long')
|
||||
|
||||
def test_10_email_text(self):
|
||||
""" html_email_clean test for text-based emails """
|
||||
new_html = html_email_clean(test_mail_examples.TEXT_1, remove=True)
|
||||
@@ -257,6 +310,19 @@ class TestCleaner(unittest2.TestCase):
|
||||
'tasks using the gantt chart and control deadlines']:
|
||||
self.assertIn(ext, new_html, 'html_email_cleaner wrongly take into account specific expand options')
|
||||
|
||||
def test_70_read_more(self):
|
||||
new_html = html_email_clean(test_mail_examples.BUG1, remove=True, shorten=True, max_length=100)
|
||||
for ext in test_mail_examples.BUG_1_IN:
|
||||
self.assertIn(ext, new_html, 'html_email_cleaner wrongly removed valid content')
|
||||
for ext in test_mail_examples.BUG_1_OUT:
|
||||
self.assertNotIn(ext, new_html, 'html_email_cleaner did not removed invalid content')
|
||||
|
||||
new_html = html_email_clean(test_mail_examples.BUG2, remove=True, shorten=True, max_length=250)
|
||||
for ext in test_mail_examples.BUG_2_IN:
|
||||
self.assertIn(ext, new_html, 'html_email_cleaner wrongly removed valid content')
|
||||
for ext in test_mail_examples.BUG_2_OUT:
|
||||
self.assertNotIn(ext, new_html, 'html_email_cleaner did not removed invalid content')
|
||||
|
||||
def test_90_misc(self):
|
||||
# False boolean for text must return empty string
|
||||
new_html = html_email_clean(False)
|
||||
|
||||
@@ -785,3 +785,322 @@ MSOFFICE_3 = """<div>
|
||||
|
||||
MSOFFICE_3_IN = ['I saw your boss yesterday']
|
||||
MSOFFICE_3_OUT = ['I noticed you recently downloaded OpenERP.', 'You indicated that you wish', 'Belgium: +32.81.81.37.00']
|
||||
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# Test cases coming from bugs
|
||||
# ------------------------------------------------------------
|
||||
|
||||
# bug: read more not apparent, strange message in read more span
|
||||
BUG1 = """<pre>Hi Migration Team,
|
||||
|
||||
Paragraph 1, blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah.
|
||||
|
||||
Paragraph 2, blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah.
|
||||
|
||||
Paragraph 3, blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah blah blah blah blah blah blah
|
||||
blah blah blah blah blah blah blah blah.
|
||||
|
||||
Thanks.
|
||||
|
||||
Regards,
|
||||
|
||||
--
|
||||
Olivier Laurent
|
||||
Migration Manager
|
||||
OpenERP SA
|
||||
Chaussée de Namur, 40
|
||||
B-1367 Gérompont
|
||||
Tel: +32.81.81.37.00
|
||||
Web: http://www.openerp.com</pre>"""
|
||||
|
||||
BUG_1_IN = [
|
||||
'Hi Migration Team',
|
||||
'Paragraph 1'
|
||||
]
|
||||
BUG_1_OUT = [
|
||||
'Olivier Laurent',
|
||||
'Chaussée de Namur',
|
||||
'81.81.37.00',
|
||||
'openerp.com',
|
||||
]
|
||||
|
||||
|
||||
BUG2 = """
|
||||
<div>
|
||||
<br>
|
||||
<div class="moz-forward-container"><br>
|
||||
<br>
|
||||
-------- Original Message --------
|
||||
<table class="moz-email-headers-table" border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">Subject:
|
||||
</th>
|
||||
<td>Fwd: TR: OpenERP S.A. Payment Reminder</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">Date: </th>
|
||||
<td>Wed, 16 Oct 2013 14:11:13 +0200</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">From: </th>
|
||||
<td>Christine Herrmann <a class="moz-txt-link-rfc2396E" href="mailto:che@openerp.com"><che@openerp.com></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">To: </th>
|
||||
<td><a class="moz-txt-link-abbreviated" href="mailto:online@openerp.com">online@openerp.com</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
<br>
|
||||
<div class="moz-forward-container"><br>
|
||||
<br>
|
||||
-------- Message original --------
|
||||
<table class="moz-email-headers-table" border="0" cellpadding="0" cellspacing="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">Sujet:
|
||||
</th>
|
||||
<td>TR: OpenERP S.A. Payment Reminder</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">Date :
|
||||
</th>
|
||||
<td>Wed, 16 Oct 2013 10:34:45 -0000</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">De : </th>
|
||||
<td>Ida Siwatala <a class="moz-txt-link-rfc2396E" href="mailto:infos@inzoservices.com"><infos@inzoservices.com></a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">Répondre
|
||||
|
||||
à : </th>
|
||||
<td><a class="moz-txt-link-abbreviated" href="mailto:catchall@openerp.my.openerp.com">catchall@openerp.my.openerp.com</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th nowrap="" valign="BASELINE" align="RIGHT">Pour :
|
||||
</th>
|
||||
<td>Christine Herrmann (che) <a class="moz-txt-link-rfc2396E" href="mailto:che@openerp.com"><che@openerp.com></a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
<br>
|
||||
<div>
|
||||
<div class="WordSection1">
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Bonjour,</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Pourriez-vous
|
||||
|
||||
me faire un retour sur ce point.</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Cordialement</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<div>
|
||||
<div style="border:none;border-top:solid #B5C4DF
|
||||
1.0pt;padding:3.0pt 0cm 0cm 0cm">
|
||||
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">De :</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">
|
||||
Ida Siwatala [<a class="moz-txt-link-freetext" href="mailto:infos@inzoservices.com">mailto:infos@inzoservices.com</a>]
|
||||
<br>
|
||||
<b>Envoyé :</b> vendredi 4 octobre 2013 20:03<br>
|
||||
<b>À :</b> 'Followers of
|
||||
INZO-services-8-all-e-Maxime-Lisbonne-77176-Savigny-le-temple-France'<br>
|
||||
<b>Objet :</b> RE: OpenERP S.A. Payment Reminder</span></p>
|
||||
</div>
|
||||
</div>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Bonsoir,</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Je
|
||||
|
||||
me permets de revenir vers vous par écrit , car j’ai
|
||||
fait 2 appels vers votre service en exposant mon
|
||||
problème, mais je n’ai pas eu de retour.</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Cela
|
||||
|
||||
fait un mois que j’ai fait la souscription de votre
|
||||
produit, mais je me rends compte qu’il est pas adapté à
|
||||
ma situation ( fonctionnalité manquante et surtout je
|
||||
n’ai pas beaucoup de temps à passer à résoudre des
|
||||
bugs). </span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">C’est
|
||||
|
||||
pourquoi , j’ai demandé qu’un accord soit trouvé avec
|
||||
vous pour annuler le contrat (tout en vous payant le
|
||||
mois d’utilisation de septembre).</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Pourriez-vous
|
||||
|
||||
me faire un retour sur ce point.</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Cordialement,</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D">Ida
|
||||
|
||||
Siwatala</span></p>
|
||||
<p class="MsoNormal"><span style="font-size:11.0pt;font-family:"Calibri","sans-serif";color:#1F497D"></span></p>
|
||||
<p> </p>
|
||||
<p class="MsoNormal"><b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">De :</span></b><span style="font-size:10.0pt;font-family:"Tahoma","sans-serif"">
|
||||
<a href="mailto:che@openerp.com">che@openerp.com</a>
|
||||
[<a href="mailto:che@openerp.com">mailto:che@openerp.com</a>]
|
||||
<br>
|
||||
<b>Envoyé :</b> vendredi 4 octobre 2013 17:41<br>
|
||||
<b>À :</b> <a href="mailto:infos@inzoservices.com">infos@inzoservices.com</a><br>
|
||||
<b>Objet :</b> OpenERP S.A. Payment Reminder</span></p>
|
||||
<p> </p>
|
||||
<div>
|
||||
<p style="background:white"><span style="font-size:9.0pt;font-family:"Arial","sans-serif";color:#222222">Dear
|
||||
|
||||
INZO services,</span></p>
|
||||
<p style="background:white"><span style="font-size:9.0pt;font-family:"Arial","sans-serif";color:#222222">Exception
|
||||
|
||||
made if there was a mistake of ours, it seems that the
|
||||
following amount stays unpaid. Please, take
|
||||
appropriate measures in order to carry out this
|
||||
payment in the next 8 days. </span></p>
|
||||
<p class="MsoNormal" style="background:white"><span style="font-size:9.0pt;font-family:"Arial","sans-serif";color:#222222"></span></p>
|
||||
<p> </p>
|
||||
<table class="MsoNormalTable" style="width:100.0%;border:outset 1.5pt" width="100%" border="1" cellpadding="0">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal">Date de facturation</p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal">Description</p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal">Reference</p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal">Due Date</p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal">Amount (€)</p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal">Lit.</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal"><b>2013-09-24</b></p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal"><b>2013/1121</b></p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal"><b>Enterprise - Inzo Services
|
||||
- Juillet 2013</b></p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal"><b>2013-09-24</b></p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt">
|
||||
<p class="MsoNormal"><b>420.0</b></p>
|
||||
</td>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt"><br>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding:.75pt .75pt .75pt .75pt"><br>
|
||||
</td>
|
||||
<td style="border:none;padding:.75pt .75pt .75pt
|
||||
.75pt"><br>
|
||||
</td>
|
||||
<td style="border:none;padding:.75pt .75pt .75pt
|
||||
.75pt"><br>
|
||||
</td>
|
||||
<td style="border:none;padding:.75pt .75pt .75pt
|
||||
.75pt"><br>
|
||||
</td>
|
||||
<td style="border:none;padding:.75pt .75pt .75pt
|
||||
.75pt"><br>
|
||||
</td>
|
||||
<td style="border:none;padding:.75pt .75pt .75pt
|
||||
.75pt"><br>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p class="MsoNormal" style="text-align:center;background:white" align="center"><span style="font-size:9.0pt;font-family:"Arial","sans-serif";color:#222222">Amount
|
||||
|
||||
due : 420.00 € </span></p>
|
||||
<p style="background:white"><span style="font-size:9.0pt;font-family:"Arial","sans-serif";color:#222222">Would
|
||||
|
||||
your payment have been carried out after this mail was
|
||||
sent, please ignore this message. Do not hesitate to
|
||||
contact our accounting department. </span></p>
|
||||
<p class="MsoNormal" style="background:white"><span style="font-size:9.0pt;font-family:"Arial","sans-serif";color:#222222"><br>
|
||||
Best Regards, <br>
|
||||
Aurore Lesage <br>
|
||||
OpenERP<br>
|
||||
Chaussée de Namur, 40 <br>
|
||||
B-1367 Grand Rosières <br>
|
||||
Tel: +32.81.81.37.00 - Fax: +32.81.73.35.01 <br>
|
||||
E-mail : <a href="mailto:ale@openerp.com">ale@openerp.com</a> <br>
|
||||
Web: <a href="http://www.openerp.com">http://www.openerp.com</a></span></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
--<br>
|
||||
INZO services <small>Sent by <a style="color:inherit" href="http://www.openerp.com">OpenERP
|
||||
S.A.</a> using <a style="color:inherit" href="https://www.openerp.com/">OpenERP</a>.</small>
|
||||
<small>Access your messages and documents <a style="color:inherit" href="https://accounts.openerp.com?db=openerp#action=mail.action_mail_redirect&login=che&message_id=5750830">in
|
||||
|
||||
OpenERP</a></small> <br>
|
||||
<pre class="moz-signature" cols="72">--
|
||||
Christine Herrmann
|
||||
|
||||
OpenERP
|
||||
Chaussée de Namur, 40
|
||||
B-1367 Grand Rosières
|
||||
Tel: +32.81.81.37.00 - Fax: +32.81.73.35.01
|
||||
|
||||
Web: <a class="moz-txt-link-freetext" href="http://www.openerp.com">http://www.openerp.com</a> </pre>
|
||||
<br>
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
</div>
|
||||
<br>
|
||||
|
||||
</div>"""
|
||||
|
||||
BUG_2_IN = [
|
||||
'read more',
|
||||
'...',
|
||||
]
|
||||
BUG_2_OUT = [
|
||||
'Fwd: TR: OpenERP S.A'
|
||||
'fait un mois'
|
||||
]
|
||||
|
||||
+14
-11
@@ -4,7 +4,6 @@ from xml.dom import minidom as dom
|
||||
|
||||
import common
|
||||
from openerp.addons.base.ir import ir_qweb
|
||||
import openerp.addons.base.ir.ir_qweb
|
||||
|
||||
impl = dom.getDOMImplementation()
|
||||
document = impl.createDocument(None, None, None)
|
||||
@@ -14,6 +13,9 @@ class TestQWebTField(common.TransactionCase):
|
||||
super(TestQWebTField, self).setUp()
|
||||
self.engine = self.registry('ir.qweb')
|
||||
|
||||
def context(self, values):
|
||||
return ir_qweb.QWebContext(self.cr, self.uid, values)
|
||||
|
||||
def test_trivial(self):
|
||||
field = document.createElement('span')
|
||||
field.setAttribute('t-field', u'company.name')
|
||||
@@ -22,10 +24,8 @@ class TestQWebTField(common.TransactionCase):
|
||||
company_id = Companies.create(self.cr, self.uid, {
|
||||
'name': "My Test Company"
|
||||
})
|
||||
root_company = Companies.browse(self.cr, self.uid, company_id)
|
||||
|
||||
result = self.engine.render_node(field, ir_qweb.QWebContext({
|
||||
'company': root_company,
|
||||
result = self.engine.render_node(field, self.context({
|
||||
'company': Companies.browse(self.cr, self.uid, company_id),
|
||||
}))
|
||||
|
||||
self.assertEqual(
|
||||
@@ -45,11 +45,10 @@ class TestQWebTField(common.TransactionCase):
|
||||
company_id = Companies.create(self.cr, self.uid, {
|
||||
'name': s,
|
||||
})
|
||||
root_company = Companies.browse(self.cr, self.uid, company_id)
|
||||
|
||||
result = self.engine.render_node(field, ir_qweb.QWebContext({
|
||||
'company': root_company,
|
||||
result = self.engine.render_node(field, self.context({
|
||||
'company': Companies.browse(self.cr, self.uid, company_id),
|
||||
}))
|
||||
|
||||
self.assertEqual(
|
||||
result,
|
||||
'<span data-oe-model="res.company" data-oe-id="%d" '
|
||||
@@ -65,7 +64,9 @@ class TestQWebTField(common.TransactionCase):
|
||||
with self.assertRaisesRegexp(
|
||||
AssertionError,
|
||||
r'^RTE widgets do not work correctly'):
|
||||
self.engine.render_node(field, ir_qweb.QWebContext({'company': None}))
|
||||
self.engine.render_node(field, self.context({
|
||||
'company': None
|
||||
}))
|
||||
|
||||
def test_reject_t_tag(self):
|
||||
field = document.createElement('t')
|
||||
@@ -74,4 +75,6 @@ class TestQWebTField(common.TransactionCase):
|
||||
with self.assertRaisesRegexp(
|
||||
AssertionError,
|
||||
r'^t-field can not be used on a t element'):
|
||||
self.engine.render_node(field, ir_qweb.QWebContext({'company': None}))
|
||||
self.engine.render_node(field, self.context({
|
||||
'company': None
|
||||
}))
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import lru
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class ormcache(object):
|
||||
""" LRU cache decorator for orm methods,
|
||||
@@ -54,15 +57,11 @@ class ormcache(object):
|
||||
"""
|
||||
d = self.lru(self2)
|
||||
if args:
|
||||
try:
|
||||
key = args[self.skiparg-2:]
|
||||
del d[key]
|
||||
self2.pool._any_cache_cleared = True
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
d.clear()
|
||||
self2.pool._any_cache_cleared = True
|
||||
logger.warn("ormcache.clear arguments are deprecated and ignored "
|
||||
"(while clearing caches on (%s).%s)",
|
||||
self2._name, self.method.__name__)
|
||||
d.clear()
|
||||
self2.pool._any_cache_cleared = True
|
||||
|
||||
class ormcache_multi(ormcache):
|
||||
def __init__(self, skiparg=2, size=8192, multi=3):
|
||||
|
||||
+60
-38
@@ -203,17 +203,39 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
iteration += 1
|
||||
new_node = _insert_new_node(node, -1, new_node_tag, text[idx:] + (cur_node.tail or ''), None, {})
|
||||
|
||||
def _truncate_node(node, position, find_first_blank=True):
|
||||
# truncate text
|
||||
innertext = node.text[0:position]
|
||||
outertext = node.text[position:]
|
||||
if find_first_blank:
|
||||
stop_idx = outertext.find(' ')
|
||||
if stop_idx == -1:
|
||||
stop_idx = len(outertext)
|
||||
def _truncate_node(node, position, simplify_whitespaces=True):
|
||||
""" Truncate a node text at a given position. This algorithm will shorten
|
||||
at the end of the word whose ending character exceeds position.
|
||||
|
||||
:param bool simplify_whitespaces: whether to try to count all successive
|
||||
whitespaces as one character. This
|
||||
option should not be True when trying
|
||||
to keep 'pre' consistency.
|
||||
"""
|
||||
if node.text is None:
|
||||
node.text = ''
|
||||
|
||||
truncate_idx = -1
|
||||
if simplify_whitespaces:
|
||||
cur_char_nbr = 0
|
||||
word = None
|
||||
node_words = node.text.strip(' \t\r\n').split()
|
||||
for word in node_words:
|
||||
cur_char_nbr += len(word)
|
||||
if cur_char_nbr >= position:
|
||||
break
|
||||
if word:
|
||||
truncate_idx = node.text.find(word) + len(word)
|
||||
else:
|
||||
stop_idx = 0
|
||||
node.text = innertext + outertext[0:stop_idx]
|
||||
truncate_idx = position
|
||||
if truncate_idx == -1 or truncate_idx > len(node.text):
|
||||
truncate_idx = len(node.text)
|
||||
|
||||
# compose new text bits
|
||||
innertext = node.text[0:truncate_idx]
|
||||
outertext = node.text[truncate_idx:]
|
||||
node.text = innertext
|
||||
|
||||
# create <span> ... <a href="#">read more</a></span> node
|
||||
read_more_node = _create_node(
|
||||
expand_options.get('oe_expand_container_tag', 'span'),
|
||||
@@ -240,7 +262,7 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
)
|
||||
read_more_node.append(read_more_link_node)
|
||||
# create outertext node
|
||||
overtext_node = _create_node('span', outertext[stop_idx:])
|
||||
overtext_node = _create_node('span', outertext)
|
||||
# tag node
|
||||
overtext_node.set('in_overlength', '1')
|
||||
# add newly created nodes in dom
|
||||
@@ -272,17 +294,16 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
html = '<div>%s</div>' % html
|
||||
root = lxml.html.fromstring(html)
|
||||
|
||||
# remove all tails and replace them by a span element, because managing text and tails can be a pain in the ass
|
||||
for node in root.getiterator():
|
||||
quote_tags = re.compile(r'(\n(>)+[^\n\r]*)')
|
||||
signature = re.compile(r'([-]{2,}[\s]?[\r\n]{1,2}[\s\S]+)')
|
||||
for node in root.iter():
|
||||
# remove all tails and replace them by a span element, because managing text and tails can be a pain in the ass
|
||||
if node.tail:
|
||||
tail_node = _create_node('span', node.tail)
|
||||
node.tail = None
|
||||
node.addnext(tail_node)
|
||||
|
||||
# form node and tag text-based quotes and signature
|
||||
quote_tags = re.compile(r'(\n(>)+[^\n\r]*)')
|
||||
signature = re.compile(r'([-]{2,}[\s]?[\r\n]{1,2}[^.]+)')
|
||||
for node in root.getiterator():
|
||||
# form node and tag text-based quotes and signature
|
||||
_tag_matching_regex_in_text(quote_tags, node, 'span', {'text_quote': '1'})
|
||||
_tag_matching_regex_in_text(signature, node, 'span', {'text_signature': '1'})
|
||||
|
||||
@@ -296,11 +317,9 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
overlength_section_id = None
|
||||
overlength_section_count = 0
|
||||
cur_char_nbr = 0
|
||||
# for node in root.getiterator():
|
||||
for node in root.iter():
|
||||
# update: add a text argument
|
||||
if node.text is None:
|
||||
node.text = ''
|
||||
# do not take into account multiple spaces that are displayed as max 1 space in html
|
||||
node_text = ' '.join((node.text and node.text.strip(' \t\r\n') or '').split())
|
||||
|
||||
# root: try to tag the client used to write the html
|
||||
if 'WordSection1' in node.get('class', '') or 'MsoNormal' in node.get('class', ''):
|
||||
@@ -347,22 +366,22 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
# 3/ add the truncated text in a new node, next to 'read more' node
|
||||
node_text = (node.text or '').strip().strip('\n').strip()
|
||||
if shorten and not overlength and cur_char_nbr + len(node_text) > max_length:
|
||||
overlength = True
|
||||
if protect_sections:
|
||||
node_to_truncate = node
|
||||
while node_to_truncate.getparent() is not None and \
|
||||
(node_to_truncate.getparent().get('section_inner') or node_to_truncate.getparent().get('section_closure')):
|
||||
node_to_truncate = node
|
||||
while node_to_truncate.getparent() is not None:
|
||||
if node_to_truncate.get('in_quote'):
|
||||
node_to_truncate = node_to_truncate.getparent()
|
||||
overlength_section_id = node_to_truncate.get('section_closure')
|
||||
position = len(node_to_truncate.text)
|
||||
find_first_blank = False
|
||||
else:
|
||||
node_to_truncate = node
|
||||
position = max_length - cur_char_nbr
|
||||
find_first_blank = True
|
||||
elif protect_sections and (node_to_truncate.getparent().get('section_inner') or node_to_truncate.getparent().get('section_closure')):
|
||||
node_to_truncate = node_to_truncate.getparent()
|
||||
overlength_section_id = node_to_truncate.get('section_closure')
|
||||
else:
|
||||
break
|
||||
|
||||
overlength = True
|
||||
node_to_truncate.set('truncate', '1')
|
||||
node_to_truncate.set('truncate_position', str(position))
|
||||
node_to_truncate.set('truncate_blank', str(find_first_blank))
|
||||
if node_to_truncate == node:
|
||||
node_to_truncate.set('truncate_position', str(max_length - cur_char_nbr))
|
||||
else:
|
||||
node_to_truncate.set('truncate_position', str(len(node.text or '')))
|
||||
cur_char_nbr += len(node_text)
|
||||
|
||||
# Tree modification
|
||||
@@ -370,7 +389,7 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
|
||||
for node in root.iter():
|
||||
if node.get('truncate'):
|
||||
_truncate_node(node, int(node.get('truncate_position', '0')), bool(node.get('truncate_blank', 'True')))
|
||||
_truncate_node(node, int(node.get('truncate_position', '0')), node.tag != 'pre')
|
||||
|
||||
# Post processing
|
||||
# ------------------------------------------------------------
|
||||
@@ -385,17 +404,20 @@ def html_email_clean(html, remove=False, shorten=False, max_length=300, expand_o
|
||||
to_remove.append(node)
|
||||
if node.get('tail_remove'):
|
||||
node.tail = ''
|
||||
# clean node
|
||||
for attribute_name in ['in_quote', 'tail_remove', 'in_overlength', 'msoffice', 'hotmail', 'truncate', 'truncate_position']:
|
||||
node.attrib.pop(attribute_name, None)
|
||||
for node in to_remove:
|
||||
if remove:
|
||||
node.getparent().remove(node)
|
||||
else:
|
||||
if not expand_options.get('oe_expand_a_class', 'oe_mail_expand') in node.get('class', ''): # trick: read more link should be displayed even if it's in overlength
|
||||
node_class = node.get('class', '') + ' ' + 'oe_mail_cleaned'
|
||||
node_class = node.get('class', '') + ' oe_mail_cleaned'
|
||||
node.set('class', node_class)
|
||||
|
||||
# html: \n that were tail of elements have been encapsulated into <span> -> back to \n
|
||||
html = etree.tostring(root, pretty_print=False)
|
||||
linebreaks = re.compile(r'<span>([\s]*[\r\n]+[\s]*)<\/span>', re.IGNORECASE | re.DOTALL)
|
||||
linebreaks = re.compile(r'<span[^>]*>([\s]*[\r\n]+[\s]*)<\/span>', re.IGNORECASE | re.DOTALL)
|
||||
html = _replace_matching_regex(linebreaks, html, '\n')
|
||||
|
||||
return html
|
||||
|
||||
Reference in New Issue
Block a user