[MERGE] from trunk

bzr revid: chm@openerp.com-20130530135242-6nmbjvixrst9llsh
This commit is contained in:
Christophe Matthieu 2013-05-30 15:52:42 +02:00
commit 9f8d8b82c0
119 changed files with 19216 additions and 1826 deletions

View File

@ -19,7 +19,7 @@
#
##############################################################################
""" OpenERP core library.
""" OpenERP core library..
"""

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:17+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:34+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:17+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:34+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:36+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:19+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:36+0000\n"
"X-Generator: Launchpad (build 16652)\n"
"X-Poedit-Language: Czech\n"
#. module: base

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:19+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:36+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -12,8 +12,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:20+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:37+0000\n"
"X-Generator: Launchpad (build 16652)\n"
"X-Poedit-Country: GREECE\n"
"X-Poedit-Language: Greek\n"
"X-Poedit-SourceCharset: utf-8\n"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:41+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -13866,7 +13866,7 @@ msgstr "Tipo de informe"
#: view:res.partner.bank:0
#: view:res.users:0
msgid "State"
msgstr "Estado"
msgstr "Provincia"
#. module: base
#: selection:base.language.install,lang:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
"Language: \n"
#. module: base
@ -26,6 +26,10 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"Módulo para la creación e impresión de cheques\n"
"================================================\n"
" "
#. module: base
#: model:res.country,name:base.sh
@ -40,7 +44,7 @@ msgstr "Otra configuración"
#. module: base
#: selection:ir.property,type:0
msgid "DateTime"
msgstr "FechaHora"
msgstr "Fecha y hora"
#. module: base
#: code:addons/fields.py:652
@ -49,8 +53,8 @@ msgid ""
"The second argument of the many2many field %s must be a SQL table !You used "
"%s, which is not a valid SQL table name."
msgstr ""
"¡El segundo argumento del campo many2many %s debe ser una tabla SQL! Has "
"utilizado %s, que no es un nombre de tabla SQL válido."
"¡El segundo argumento del campo many2many %s debe ser una tabla SQL! Ha "
"utilizado %s, el cual no es un nombre de tabla SQL válido."
#. module: base
#: field:ir.ui.view,arch:0
@ -61,12 +65,12 @@ msgstr "Estructura de la vista"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
msgstr ""
msgstr "Gestión de Presupuestos, Órdenes de venta, Entregas y Facturación"
#. module: base
#: selection:ir.sequence,implementation:0
msgid "No gap"
msgstr "No hay diferencia"
msgstr "Sin espacios vacíos"
#. module: base
#: selection:base.language.install,lang:0
@ -84,18 +88,18 @@ msgid ""
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
"Le ayuda a gestionar sus proyectos y tareas realizando un seguimiento de los "
"mismos, generando planificaciones, ..."
"Le ayuda a gestionar sus proyectos y tareas mediante el seguimiento de "
"ellas, generando planificaciones, ..."
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr ""
msgstr "Interfaz de pantalla táctil para tiendas"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
msgid "Indian Payroll"
msgstr ""
msgstr "Nomina de la India"
#. module: base
#: help:ir.cron,model:0
@ -125,6 +129,17 @@ msgid ""
" * Product Attributes\n"
" "
msgstr ""
"\n"
"Módulo que añade fabricantes y atributos en el formulario de producto.\n"
"===========================================================\n"
"\n"
"Puede definir los siguientes campos para un producto:\n"
"-------------------------------------------------\n"
" * Fabricante\n"
" * Nombre del producto del fabricante\n"
" * Código del producto del fabricante\n"
" * Atributos del producto\n"
" "
#. module: base
#: field:ir.actions.client,params:0
@ -138,11 +153,14 @@ msgid ""
"The module adds google user in res user.\n"
"========================================\n"
msgstr ""
"\n"
"El módulo añade usuarios de Google a la tabla res.user.\n"
"================================================\n"
#. module: base
#: help:res.partner,employee:0
msgid "Check this box if this contact is an Employee."
msgstr ""
msgstr "Marque si el contacto es un empleado"
#. module: base
#: help:ir.model.fields,domain:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:27+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:44+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:27+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:44+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:25+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:42+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:19+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:36+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -33,7 +33,7 @@ msgstr "Saint Helena"
#. module: base
#: view:ir.actions.report.xml:0
msgid "Other Configuration"
msgstr ""
msgstr "Muu Konfiguratsioon"
#. module: base
#: selection:ir.property,type:0
@ -84,7 +84,7 @@ msgstr ""
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr ""
msgstr "Puutetundlik liides kauplustele"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
@ -100,7 +100,7 @@ msgstr ""
#. module: base
#: view:ir.module.module:0
msgid "Created Views"
msgstr "Loodud vaated"
msgstr "Loodud Vaated"
#. module: base
#: model:ir.module.module,description:base.module_product_manufacturer
@ -121,7 +121,7 @@ msgstr ""
#. module: base
#: field:ir.actions.client,params:0
msgid "Supplementary arguments"
msgstr ""
msgstr "Täiendavad argumendid"
#. module: base
#: model:ir.module.module,description:base.module_google_base_account

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -9,8 +9,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:23+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:39+0000\n"
"X-Generator: Launchpad (build 16652)\n"
"X-Poedit-Country: IRAN, ISLAMIC REPUBLIC OF\n"
"X-Poedit-Language: Persian\n"

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:27+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:44+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:19+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:36+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:20+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:37+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:20+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:37+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:20+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:37+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,11 +25,14 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"רכיב לכתיבת והדפסת המחאות\n"
" "
#. module: base
#: model:res.country,name:base.sh
msgid "Saint Helena"
msgstr "סנט הלנה"
msgstr "סיינט הלנה"
#. module: base
#: view:ir.actions.report.xml:0
@ -48,6 +51,8 @@ msgid ""
"The second argument of the many2many field %s must be a SQL table !You used "
"%s, which is not a valid SQL table name."
msgstr ""
"הארגומנט השני של השדה many2many %s חייב להיות טבלת SQL! השתמשת ב-%s, שאינו "
"שם תקף של טבלת SQL."
#. module: base
#: field:ir.ui.view,arch:0
@ -58,12 +63,12 @@ msgstr "הצג ארכיטקטורה"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
msgstr ""
msgstr "ניהול הצעות מחיר, הזמנות, תעודות משלוח וחשבוניות"
#. module: base
#: selection:ir.sequence,implementation:0
msgid "No gap"
msgstr ""
msgstr "ללא פער"
#. module: base
#: selection:base.language.install,lang:0
@ -80,7 +85,7 @@ msgstr "Spanish (PY) / ספרדית (PY)"
msgid ""
"Helps you manage your projects and tasks by tracking them, generating "
"plannings, etc..."
msgstr ""
msgstr "עזרה בניהול פרויקטים ומשימות על ידי מעקב, יצירת תכנונים ועוד ..."
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
@ -90,13 +95,13 @@ msgstr "ממשק מסך מגע לחנויות"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
msgid "Indian Payroll"
msgstr ""
msgstr "משכורות הודיות"
#. module: base
#: help:ir.cron,model:0
msgid ""
"Model name on which the method to be called is located, e.g. 'res.partner'."
msgstr ""
msgstr "שם המודול שבו נמצאת המתודה שלה קוראים, למשל: 'res.partner'."
#. module: base
#: view:ir.module.module:0
@ -133,7 +138,7 @@ msgstr ""
#. module: base
#: field:ir.actions.client,params:0
msgid "Supplementary arguments"
msgstr ""
msgstr "טיעונים\\משתנים משלימים"
#. module: base
#: model:ir.module.module,description:base.module_google_base_account
@ -142,11 +147,14 @@ msgid ""
"The module adds google user in res user.\n"
"========================================\n"
msgstr ""
"\n"
"רכיב זה מוסיף משתמש גוגל in res user.\n"
"========================================\n"
#. module: base
#: help:res.partner,employee:0
msgid "Check this box if this contact is an Employee."
msgstr ""
msgstr "נא לסמן את התיבה אם אשת\\איש קשר זו עובד\\ת בחברה"
#. module: base
#: help:ir.model.fields,domain:0
@ -155,6 +163,8 @@ msgid ""
"specified as a Python expression defining a list of triplets. For example: "
"[('color','=','red')]"
msgstr ""
"הדומיין החלופי להגבלת ערכים אפשריים לשדות יחסים, המוגדר כביטוי של פייטון "
"המגדיר רשימה של שלשות. לדוגמא: [('אדום','=','צבע')]"
#. module: base
#: field:res.partner,ref:0
@ -174,7 +184,7 @@ msgstr "חלון מטרה"
#. module: base
#: field:ir.actions.report.xml,report_rml:0
msgid "Main Report File Path"
msgstr ""
msgstr "נתיב קובץ לדוח ראשי"
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale_analytic_plans
@ -195,6 +205,13 @@ msgid ""
"revenue\n"
"reports."
msgstr ""
"\n"
"הנפקת חשבוניות מתוך הוצאות, רשומות שעות עבודה\n"
"========================================================\n"
"\n"
"רכיב להנפקת חשבוניות על פי הוצאות (שעות עבודה, הוצאות, וכו')\n"
"\n"
"באפשרותך להגדיר רשימות מחירים בניתוח חשבון, וליצור דוחות רווח צפוי"
#. module: base
#: code:addons/base/ir/ir_sequence.py:104
@ -211,12 +228,14 @@ msgid ""
"Properties of base fields cannot be altered in this manner! Please modify "
"them through Python code, preferably through a custom addon!"
msgstr ""
"לא ניתן לשנות את תכונות הבסיס באופן זה ! נא לשנות אותם ברמת הקוד, רצוי "
"באמצעות תוסף ייעודי"
#. module: base
#: code:addons/osv.py:151
#, python-format
msgid "Constraint Error"
msgstr ""
msgstr "שגיאת אילוץ"
#. module: base
#: model:ir.model,name:base.model_ir_ui_view_custom
@ -227,7 +246,7 @@ msgstr "ir.ui.view.custom"
#: code:addons/base/ir/ir_model.py:375
#, python-format
msgid "Renaming sparse field \"%s\" is not allowed"
msgstr ""
msgstr "אין אישור לשינוי שם שדה \"%s\""
#. module: base
#: model:res.country,name:base.sz
@ -269,7 +288,7 @@ msgstr ""
#. module: base
#: model:res.groups,name:base.group_multi_currency
msgid "Multi Currencies"
msgstr ""
msgstr "ריבוי מטבעות"
#. module: base
#: model:ir.module.module,description:base.module_l10n_cl
@ -281,6 +300,10 @@ msgid ""
"\n"
" "
msgstr ""
"\n"
"טבלאת חשבונאות ומס צ'יליאני\n"
"\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale
@ -292,12 +315,12 @@ msgstr "ניהול מכירות"
msgid ""
"The internal user that is in charge of communicating with this contact if "
"any."
msgstr ""
msgstr "המשתמש הפנימי האחראי לתקשורת עם איש קשר זה, אם קיים."
#. module: base
#: view:res.partner:0
msgid "Search Partner"
msgstr ""
msgstr "חפש שותף (ספק/לקוח)"
#. module: base
#: field:ir.module.category,module_nr:0
@ -331,6 +354,12 @@ msgid ""
" - tree_but_open\n"
"For defaults, an optional condition"
msgstr ""
"לעולות, אחת ממשבצות הפעולה האפשריות:\n"
" - לקוח_פעולה_מרובה\n"
" - לקוח_הדפסה_מרובה\n"
" - לקוח_ פעולה_קשורה\n"
" - עץ_אבל_פתוח\n"
"לברירות מחדל, תנאי חלופי"
#. module: base
#: sql_constraint:res.lang:0
@ -377,6 +406,14 @@ msgid ""
"invoices from picking, OpenERP is able to add and compute the shipping "
"line.\n"
msgstr ""
"\n"
"מאפשר הוספת שיטות משלוח להזמנה ובחירתן\n"
"==============================================================\n"
"\n"
"You can define your own carrier and delivery grids for prices. When creating "
"\n"
"invoices from picking, OpenERP is able to add and compute the shipping "
"line.\n"
#. module: base
#: code:addons/base/ir/ir_filters.py:80
@ -385,6 +422,8 @@ msgid ""
"There is already a shared filter set as default for %(model)s, delete or "
"change it before setting a new default"
msgstr ""
"כבר הוגדר מסנן משותף כברירת מחדל עבור %(model)s, יש למחוק או לשנות אותו לפני "
"בחירת מסנן ברירת מחדל חדש"
#. module: base
#: code:addons/orm.py:2649
@ -452,7 +491,7 @@ msgstr "קבוצה"
msgid ""
"Invalid date/time format directive specified. Please refer to the list of "
"allowed directives, displayed when you edit a language."
msgstr ""
msgstr "פורמט תאריך\\שעה לא תקין. נא להיעזר בהנחיות המוצגות בעריכת שפה."
#. module: base
#: code:addons/orm.py:4153
@ -474,7 +513,7 @@ msgstr ""
#. module: base
#: field:ir.model.relation,name:0
msgid "Relation Name"
msgstr ""
msgstr "שם היחס"
#. module: base
#: view:ir.rule:0
@ -529,7 +568,7 @@ msgstr "הגויאנה הצרפתית"
#. module: base
#: model:ir.module.module,summary:base.module_hr
msgid "Jobs, Departments, Employees Details"
msgstr "עבודות, מחלקות, פרטי עובדים"
msgstr "משרות, מחלקות, פרטי עובדים"
#. module: base
#: model:ir.module.module,description:base.module_analytic
@ -545,6 +584,16 @@ msgid ""
"that have no counterpart in the general financial accounts.\n"
" "
msgstr ""
"\n"
"רכיב להגדרת עצמים לחישובי עלות (Analytic Accounts).\n"
"===============================================\n"
"\n"
"In OpenERP, analytic accounts are linked to general accounts but are "
"treated\n"
"totally independently. So, you can enter various different analytic "
"operations\n"
"that have no counterpart in the general financial accounts.\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_idea
@ -568,6 +617,17 @@ msgid ""
"* Use emails to automatically confirm and send acknowledgements for any "
"event registration\n"
msgstr ""
"\n"
"ארגון וניהול אירועים\n"
"======================================\n"
"\n"
"רכיב האירועים מאפשר את ניהול כל המשימות המשוייכות לאירוע בצורה יעילה: תכנון, "
"ניהול הרשמות, הגעה וכו'.\n"
"\n"
"תכונות עיקריות\n"
"------------\n"
"* ניהול אירועים והרשמות לאירועים\n"
"* שליחה אוטומטית של בקשות אישור הגעה בדוא\"ל\n"
#. module: base
#: selection:base.language.install,lang:0
@ -622,7 +682,7 @@ msgstr ""
#. module: base
#: selection:base.language.install,lang:0
msgid "Spanish (VE) / Español (VE)"
msgstr ""
msgstr "ספרדית(VE) / Español (VE)"
#. module: base
#: model:ir.module.module,shortdesc:base.module_hr_timesheet_invoice
@ -632,7 +692,7 @@ msgstr "חשבונית על גליון שעות"
#. module: base
#: view:base.module.upgrade:0
msgid "Your system will be updated."
msgstr ""
msgstr "המערכת תעודכן"
#. module: base
#: field:ir.actions.todo,note:0
@ -648,7 +708,7 @@ msgstr "שם מדינה"
#. module: base
#: model:res.country,name:base.co
msgid "Colombia"
msgstr "Colombia"
msgstr "קולומביה"
#. module: base
#: model:res.partner.title,name:base.res_partner_title_mister
@ -661,7 +721,7 @@ msgid ""
"The ISO country code in two chars.\n"
"You can use this field for quick search."
msgstr ""
"צופן ה-ISO בשתי אותיות.\n"
"קוד מדינה ISO בשתי אותיות.\n"
"ניתן להשתמש בשדה זה לחיפוש מהיר."
#. module: base
@ -705,22 +765,22 @@ msgstr "שדות מותאמים אישית חייבים להתחיל ב 'x_' !"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_mx
msgid "Mexico - Accounting"
msgstr ""
msgstr "מקסיקו - חשבונאות"
#. module: base
#: help:ir.actions.server,action_id:0
msgid "Select the Action Window, Report, Wizard to be executed."
msgstr "בחר בחלון הפעלה,דוח,אשף שתרצה לבצע."
msgstr "בחלון ההפעלה ניתן להפעיל אשף או דו\"ח להפעלה ."
#. module: base
#: sql_constraint:ir.config_parameter:0
msgid "Key must be unique."
msgstr ""
msgstr "יש לבחור מפתח ייחודי"
#. module: base
#: model:ir.module.module,shortdesc:base.module_plugin_outlook
msgid "Outlook Plug-In"
msgstr ""
msgstr "תוסף Outlook"
#. module: base
#: model:ir.module.module,description:base.module_account
@ -770,6 +830,12 @@ msgid ""
"Contains the installer for marketing-related modules.\n"
" "
msgstr ""
"\n"
"רכיב שיווק.\n"
"===================\n"
"\n"
"מכיל את ההתקנות לרכיבי שיווק.\n"
" "
#. module: base
#: model:ir.module.module,description:base.module_web_linkedin
@ -795,7 +861,7 @@ msgstr ""
#. module: base
#: model:res.country,name:base.jo
msgid "Jordan"
msgstr "Jordan"
msgstr "ירדן"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_hr
@ -815,7 +881,7 @@ msgstr "ir.ui.view"
#. module: base
#: model:res.country,name:base.er
msgid "Eritrea"
msgstr "Eritrea"
msgstr "אריתריאה"
#. module: base
#: sql_constraint:res.company:0
@ -934,7 +1000,7 @@ msgstr ""
#. module: base
#: model:ir.ui.menu,name:base.menu_crm_config_opportunity
msgid "Opportunities"
msgstr ""
msgstr "הזדמנויות"
#. module: base
#: model:ir.model,name:base.model_base_language_export
@ -950,6 +1016,7 @@ msgstr "Papua New Guinea"
#: help:ir.actions.report.xml,report_type:0
msgid "Report Type, e.g. pdf, html, raw, sxw, odt, html2html, mako2html, ..."
msgstr ""
"סוג (פורמט) הדו\"ח, כגון: pdf, html, raw, sxw, odt, html2html, mako2html..."
#. module: base
#: model:ir.module.module,shortdesc:base.module_document_webdav
@ -970,7 +1037,7 @@ msgstr ""
#. module: base
#: view:res.partner:0
msgid "My Partners"
msgstr ""
msgstr "השותפים שלי"
#. module: base
#: model:res.country,name:base.zw
@ -986,7 +1053,7 @@ msgstr ""
#. module: base
#: view:ir.actions.report.xml:0
msgid "XML Report"
msgstr ""
msgstr "דו\"ח XML"
#. module: base
#: model:res.country,name:base.es
@ -1002,7 +1069,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_base_module_upgrade
msgid "Module Upgrade"
msgstr ""
msgstr "שדרוג הרכיב"
#. module: base
#: selection:base.language.install,lang:0
@ -1244,6 +1311,8 @@ msgid ""
"Language with code \"%s\" is not defined in your system !\n"
"Define it through the Administration menu."
msgstr ""
"שפה עם קוד \"%s\" אינה מוגדרת במערכת שלך!\n"
"הגדר אותה באמצעות תפריט הניהול."
#. module: base
#: model:res.country,name:base.gu
@ -1280,7 +1349,7 @@ msgstr "מדומה"
#. module: base
#: constraint:ir.ui.view:0
msgid "Invalid XML for View Architecture!"
msgstr "XML לא בתוקף להצגת ארכיטקטורה"
msgstr "XML לא חוקי להצגת ארכיטקטורה"
#. module: base
#: model:res.country,name:base.ky
@ -2597,7 +2666,7 @@ msgstr "שער נוכחי"
#. module: base
#: selection:base.language.install,lang:0
msgid "Greek / Ελληνικά"
msgstr ""
msgstr "יוונית / Ελληνικά"
#. module: base
#: field:res.company,custom_footer:0
@ -5688,7 +5757,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_base_language_import
msgid "Language Import"
msgstr ""
msgstr "ייבוא שפה"
#. module: base
#: help:workflow.transition,act_from:0
@ -7906,7 +7975,7 @@ msgstr ""
#: code:addons/base/res/res_users.py:473
#, python-format
msgid "Setting empty passwords is not allowed for security reasons!"
msgstr ""
msgstr "לא ניתן להגדיר סיסמה ריקה מטעמי אבטחה !"
#. module: base
#: help:ir.mail_server,smtp_pass:0
@ -11018,7 +11087,7 @@ msgstr "הערה"
#: field:ir.rule,domain_force:0
#: field:res.partner.title,domain:0
msgid "Domain"
msgstr "מתחם"
msgstr "שם-מתחם (דומיין)"
#. module: base
#: code:addons/base/ir/ir_fields.py:166

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:40+0000\n"
"X-Generator: Launchpad (build 16652)\n"
"Language: hr\n"
#. module: base

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -3274,7 +3274,7 @@ msgstr ""
"==============================================\n"
" * Felhasználó azonosítás\n"
" * Dokumentum indexálás:- .pptx és .docx fájlok nem támogatottak Windows "
"oprendszeren.\n"
"operációs rendszeren.\n"
" * Dashboard / Műszerfal a dokumentumokhoz mely magában foglalja:\n"
" * Új fájl (lista)\n"
" * Fájlok a forrás típusa szerint (grafikon)\n"
@ -3334,7 +3334,7 @@ msgstr ""
"==================================\n"
"\n"
"Ez az alkalmazás lehetővé teszi a célul kitűzött eladások eredményes és "
"hatékony kezelését figyelembevéve a megrendelések és annak régebbi "
"hatékony kezelését figyelembe véve a megrendelések és annak régebbi "
"történetének nyomon követését.\n"
"\n"
"Kezeli a teljes eladási munkafolyamatot:\n"
@ -3351,7 +3351,7 @@ msgstr ""
"* Incoterms: International Commercial terms /Nemzetközi szállítási "
"feltételek pl.:EXW/\n"
"\n"
"Használható rugalmas számlázáasi módszer:\n"
"Használható rugalmas számlázási módszer:\n"
"\n"
"* *Igényléskori*: Ha szükséges a számlák kézzel létrehozhatók a megrendelés "
"alapján\n"
@ -3361,7 +3361,7 @@ msgstr ""
"egyenlíteni a szállítás előtt\n"
"\n"
"\n"
"A kereskedő vezérklő műszerfala a következőket tartalmazza\n"
"A kereskedő vezérlő műszerfala a következőket tartalmazza\n"
"------------------------------------------------\n"
"* Az árajánlataim\n"
"* Havi forgótőke (Grafikon)\n"
@ -3555,7 +3555,7 @@ msgstr ""
"automatikusan tud hozzárendelni emlékeztetőt.\n"
"\n"
"OpenERP alkatrész kezelés szabálya megengedi a rendszernek, hogy sablonból "
"rendelést generáljon autómatikusan, vagy beállíthatja, hogy az egészet a "
"rendelést generáljon automatikusan, vagy beállíthatja, hogy az egészet a "
"termelés tényleges igénynek megfelelően folyamat vezérléssel hajtsa végre.\n"
"\n"
"Dashboard / Műszerfal a beszerzés kezelés kimutatásához ezt tartalmazza:\n"
@ -4457,7 +4457,7 @@ msgstr ""
"Támogatja a raktározott termékek, fogyóeszközök vagy szolgáltatások "
"integrációját. Szolgáltatások teljesen integráltak a szoftver teljes "
"egységével. Például, beállíthat egy alvállalkozói szolgáltatást a "
"darabjegyzékben az autómatikus anyag beszerzéshez egy összeszerelni kívánt "
"darabjegyzékben az automatikus anyag beszerzéshez egy összeszerelni kívánt "
"termék megrendelésénél.\n"
"\n"
"Fő tulajdonságok\n"
@ -4465,8 +4465,8 @@ msgstr ""
"* Raktár létrehozás/Megrendelés létrehozás\n"
"* Több szintű darabjegyzés, nincs határ\n"
"* Több szintű útvonal, nincs határ\n"
"* Útvonal és munka központ integrálva az analitikai könyvitellel\n"
"* Periódikus ütemező számítás \n"
"* Útvonal és munka központ integrálva az analitikai könyvvitellel\n"
"* Periodikus ütemező számítás \n"
"* Lehetővé teszi a darabjegyzékek böngészését komplett szerkezetben ami "
"magában foglalja az al- és a fantom darabjegyzékeket\n"
"\n"
@ -18709,7 +18709,7 @@ msgid ""
" "
msgstr ""
"\n"
"Több-raktár kezelése, többes- és struktúrált/rendezett raktár helyek\n"
"Több-raktár kezelése, többes- és strukturált/rendezett raktár helyek\n"
"==============================================================\n"
"\n"
"A raktár és raktárkészlet kezelés a hierarchikus elhelyezkedési szerkezeten "
@ -18721,7 +18721,7 @@ msgstr ""
"lehetőségével a nyomon követhetőség biztosításához, mely követelmény nagyobb "
"vállalkozásoknál.\n"
"\n"
"Fó jellemzők\n"
"Fő jellemzők\n"
"------------\n"
"* A mozgások előzményei és tervezése,\n"
"* Raktár értékelés (alap vagy átlag ár, ...)\n"

View File

@ -9,8 +9,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:18+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,6 +25,9 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"Modul untuk menulis dan mencetak Cek\n"
" "
#. module: base
#: model:res.country,name:base.sh
@ -58,7 +61,7 @@ msgstr "Arsitektur View"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
msgstr ""
msgstr "Kontrol Penawaran, Pesanan Penjualan, Pengiriman & Faktur"
#. module: base
#: selection:ir.sequence,implementation:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:20+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:37+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:21+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:38+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:22+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:39+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -124,6 +124,16 @@ msgid ""
" * Product Attributes\n"
" "
msgstr ""
"\n"
"제품양식에 특성과 제조회사를 추가하는 모듈\n"
"====================================================================\n"
"제품에 아래 내용을 정의할 수 있습니다.\n"
"-----------------------------------------------\n"
" * 제조회사\n"
" * 제조회사 제품명칭\n"
" * 제조회사 제품코드\n"
" * 제품 특성\n"
" "
#. module: base
#: field:ir.actions.client,params:0
@ -546,6 +556,14 @@ msgid ""
"that have no counterpart in the general financial accounts.\n"
" "
msgstr ""
"\n"
"관리회계 객체를 지정하기 위한 모듈\n"
"===============================================\n"
"\n"
"OpenERP에서는 관리회계가 일반회계와 연계되지만 완전히\n"
"독립적으로 취급됩니다. 따라서, 일반 재무회계에는 영향을 주지\n"
"않으면서 다양하고 차별화된 분석 작업을 수행할 수 있습니다.\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_idea

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:22+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:39+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:22+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:39+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -4153,6 +4153,7 @@ msgstr "Титула"
#: help:ir.property,res_id:0
msgid "If not set, acts as a default value for new resources"
msgstr ""
"Доколку не е подесено, се однесува како стандардна вредност за новите ресурси"
#. module: base
#: code:addons/orm.py:4246
@ -4560,7 +4561,7 @@ msgstr "EAN13"
#: code:addons/orm.py:2247
#, python-format
msgid "Invalid Architecture!"
msgstr ""
msgstr "Погрешна архитектура!"
#. module: base
#: model:res.country,name:base.pt
@ -4703,13 +4704,13 @@ msgstr ""
#. module: base
#: view:ir.cron:0
msgid "Action to Trigger"
msgstr ""
msgstr "Акција за активирање"
#. module: base
#: field:ir.model.constraint,name:0
#: selection:ir.translation,type:0
msgid "Constraint"
msgstr ""
msgstr "Ограничување"
#. module: base
#: selection:ir.values,key:0
@ -4827,7 +4828,7 @@ msgstr "Телеком сектор"
#. module: base
#: field:workflow.transition,trigger_model:0
msgid "Trigger Object"
msgstr ""
msgstr "Активирај објект"
#. module: base
#: sql_constraint:ir.sequence.type:0
@ -4848,7 +4849,7 @@ msgstr "Дојдовни премини"
#. module: base
#: field:ir.values,value_unpickle:0
msgid "Default value or action reference"
msgstr ""
msgstr "Стандардна вредност или референца на акцијата"
#. module: base
#: model:ir.module.module,description:base.module_note_pad
@ -4920,7 +4921,7 @@ msgstr "Шпански (HN) / Español (HN)"
#. module: base
#: view:ir.sequence.type:0
msgid "Sequence Type"
msgstr ""
msgstr "Тип на секвенца"
#. module: base
#: view:base.language.export:0
@ -4973,7 +4974,7 @@ msgstr "Url"
#. module: base
#: selection:ir.translation,type:0
msgid "SQL Constraint"
msgstr ""
msgstr "SQL ограничување"
#. module: base
#: help:ir.ui.menu,groups_id:0
@ -5179,7 +5180,7 @@ msgstr ""
#. module: base
#: model:ir.module.category,description:base.module_category_marketing
msgid "Helps you manage your marketing campaigns step by step."
msgstr ""
msgstr "Ви помага да ги менаџирате вашите маркетинг кампањи чекор по чекор."
#. module: base
#: selection:base.language.install,lang:0
@ -5324,7 +5325,7 @@ msgstr "Интеграција на Google Docs"
#. module: base
#: help:ir.attachment,res_model:0
msgid "The database object this attachment will be attached to"
msgstr ""
msgstr "Објектот на базата на податоци на кој овој прилог ќе биде прикачен"
#. module: base
#: code:addons/base/ir/ir_fields.py:327
@ -5391,7 +5392,7 @@ msgstr ", или друг текст едитор"
#. module: base
#: model:ir.module.module,shortdesc:base.module_crm_partner_assign
msgid "Partners Geo-Localization"
msgstr ""
msgstr "Географска локализација на партнери"
#. module: base
#: model:res.country,name:base.ke
@ -5448,7 +5449,7 @@ msgstr "Перу"
#. module: base
#: selection:ir.model.fields,on_delete:0
msgid "Set NULL"
msgstr ""
msgstr "Подеси Нула"
#. module: base
#: view:res.users:0
@ -5479,7 +5480,7 @@ msgstr ""
#. module: base
#: help:ir.mail_server,smtp_user:0
msgid "Optional username for SMTP authentication"
msgstr ""
msgstr "Опционо корисничко име за SMTP автентификација"
#. module: base
#: model:ir.model,name:base.model_ir_actions_actions
@ -5552,6 +5553,7 @@ msgstr "Португалски / Português"
#, python-format
msgid "Changing the storing system for field \"%s\" is not allowed."
msgstr ""
"Поврзувањето на системот за складирање за полето \"%s\" не е дозволено."
#. module: base
#: help:res.partner.bank,company_id:0
@ -5775,6 +5777,7 @@ msgstr "Име на сопственикот на сметката"
#, python-format
msgid "Cannot rename column to %s, because that column already exists!"
msgstr ""
"Не може да се преименува колоната во %s, бидејќи колоната веќе постои!"
#. module: base
#: view:ir.attachment:0
@ -5790,7 +5793,7 @@ msgstr "Децимален знак"
#: code:addons/orm.py:5319
#, python-format
msgid "Missing required value for the field '%s'."
msgstr ""
msgstr "Недостига потребната вредност за полето '%s'."
#. module: base
#: view:ir.rule:0
@ -5845,7 +5848,7 @@ msgstr "Буве Остров"
#. module: base
#: field:ir.model.constraint,type:0
msgid "Constraint Type"
msgstr ""
msgstr "Тип на ограничување"
#. module: base
#: field:res.company,child_ids:0
@ -6172,7 +6175,7 @@ msgstr ""
#. module: base
#: model:ir.model,name:base.model_ir_actions_act_window_view
msgid "ir.actions.act_window.view"
msgstr ""
msgstr "ir.actions.act_window.view"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web
@ -6183,7 +6186,7 @@ msgstr "Веб"
#. module: base
#: model:ir.module.module,shortdesc:base.module_lunch
msgid "Lunch Orders"
msgstr ""
msgstr "Нарачки за ручек"
#. module: base
#: selection:base.language.install,lang:0
@ -6229,7 +6232,7 @@ msgstr "Етиопија"
#. module: base
#: model:ir.module.category,name:base.module_category_authentication
msgid "Authentication"
msgstr ""
msgstr "Автентикација"
#. module: base
#: model:res.country,name:base.sj
@ -6240,7 +6243,7 @@ msgstr ""
#: model:ir.model,name:base.model_ir_actions_wizard
#: selection:ir.ui.menu,action:0
msgid "ir.actions.wizard"
msgstr ""
msgstr "ir.actions.wizard"
#. module: base
#: model:ir.module.module,shortdesc:base.module_web_kanban
@ -6252,7 +6255,7 @@ msgstr ""
#: view:ir.actions.report.xml:0
#: view:ir.actions.server:0
msgid "Group By"
msgstr ""
msgstr "Групирај по"
#. module: base
#: view:res.config.installer:0
@ -6303,7 +6306,7 @@ msgstr "Семтководство и финансии"
#. module: base
#: field:ir.actions.server,write_id:0
msgid "Write Id"
msgstr ""
msgstr "Напиши ID"
#. module: base
#: model:ir.ui.menu,name:base.menu_product
@ -6330,12 +6333,12 @@ msgstr ""
#: model:ir.module.category,name:base.module_category_usability
#: view:res.users:0
msgid "Usability"
msgstr ""
msgstr "Употребливост"
#. module: base
#: field:ir.actions.act_window,domain:0
msgid "Domain Value"
msgstr ""
msgstr "Вредност на домен"
#. module: base
#: model:ir.module.module,description:base.module_association
@ -6386,7 +6389,7 @@ msgstr ""
#: code:addons/base/ir/workflow/workflow.py:99
#, python-format
msgid "Operation forbidden"
msgstr ""
msgstr "Забранета операција"
#. module: base
#: view:ir.actions.server:0
@ -6444,7 +6447,7 @@ msgstr "Тип на банка"
#: code:addons/base/res/res_users.py:99
#, python-format
msgid "The name of the group can not start with \"-\""
msgstr ""
msgstr "Името на групата не може да почнува со \"-\""
#. module: base
#: model:ir.actions.client,name:base.modules_act_cl
@ -6484,7 +6487,7 @@ msgstr ""
#: view:workflow.activity:0
#: field:workflow.activity,flow_start:0
msgid "Flow Start"
msgstr ""
msgstr "Почеток на тек"
#. module: base
#: model:ir.model,name:base.model_res_partner_title
@ -6823,7 +6826,7 @@ msgstr ""
#: code:addons/orm.py:2247
#, python-format
msgid "There is no view of type '%s' defined for the structure!"
msgstr ""
msgstr "Нема приказ од типот \\%s\\ дефинирано за структурата!"
#. module: base
#: help:ir.values,key:0
@ -6964,7 +6967,7 @@ msgstr ""
#. module: base
#: sql_constraint:ir.rule:0
msgid "Rule must have at least one checked access right !"
msgstr ""
msgstr "Правилото мора да има барем едно означено право за пристап !"
#. module: base
#: field:res.partner.bank.type,format_layout:0
@ -7402,7 +7405,7 @@ msgstr "Датотеката од модулот е успешно увезен
#: view:ir.model.constraint:0
#: model:ir.ui.menu,name:base.ir_model_constraint_menu
msgid "Model Constraints"
msgstr ""
msgstr "Ограничувања на модулот"
#. module: base
#: model:ir.actions.act_window,name:base.action_workflow_transition_form
@ -7415,7 +7418,7 @@ msgstr "Транзиции"
#: model:ir.module.module,shortdesc:base.module_hr_timesheet
#: model:ir.module.module,shortdesc:base.module_hr_timesheet_sheet
msgid "Timesheets"
msgstr ""
msgstr "Временски таблици"
#. module: base
#: help:ir.values,company_id:0
@ -7449,6 +7452,9 @@ msgid ""
"password, otherwise leave empty. After a change of password, the user has to "
"login again."
msgstr ""
"Специфицирајте вредност единствено кога креирате корисник или ја менувате "
"корисничката лозинка, во спротивно оставете празно. После промената на "
"лозинката, корисникот треба повторно да се најави."
#. module: base
#: model:res.country,name:base.so
@ -7613,7 +7619,7 @@ msgstr "на"
#. module: base
#: view:ir.property:0
msgid "Parameters that are used by all resources."
msgstr ""
msgstr "Параметри кои се користат од сите расурси."
#. module: base
#: model:res.country,name:base.mz
@ -15713,7 +15719,7 @@ msgstr "Северна Кореа"
#. module: base
#: selection:ir.actions.server,state:0
msgid "Create Object"
msgstr ""
msgstr "Креирај објект"
#. module: base
#: model:res.country,name:base.ss
@ -15728,7 +15734,7 @@ msgstr "Контекст"
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale_mrp
msgid "Sales and MRP Management"
msgstr ""
msgstr "Управување со продажби и производство"
#. module: base
#: model:ir.actions.act_window,help:base.action_partner_form
@ -15742,6 +15748,14 @@ msgid ""
" </p>\n"
" "
msgstr ""
"<p class=\"oe_view_nocontent_create\">\n"
"Кликнете за да додадете контакт во вашиот именик.\n"
"</p><p>\n"
"OpenERP ви помага полесно да ги следите сите активности поврзани со\n"
"купувач; дискусии, историја на бизнис можности,\n"
"документи, итн.\n"
"</p>\n"
" "
#. module: base
#: model:res.partner.category,name:base.res_partner_category_2
@ -15769,6 +15783,8 @@ msgid ""
"Used to select automatically the right address according to the context in "
"sales and purchases documents."
msgstr ""
"Се користи за автоматски да се избере вистинската адреса според контекстот "
"во документите за продажби и набавки."
#. module: base
#: model:ir.module.module,description:base.module_purchase_analytic_plans
@ -15801,7 +15817,7 @@ msgstr "Руски / русский язык"
#. module: base
#: model:ir.module.module,shortdesc:base.module_auth_signup
msgid "Signup"
msgstr ""
msgstr "Регистрација"
#~ msgid "Code (eg:en__US)"
#~ msgstr "Код (пр. en_US)"

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:22+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:39+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -609,8 +609,8 @@ msgstr ""
"===============================================\n"
"\n"
"OpenERP-д шинжилгээний дансд нь ерөнхий дансдадтай холбогддог боловч \n"
"бүрэн үл хамаарах байдаг. Иймээс ерөнхий санхүүгийн данс эсрэг тал нь болгох "
"албагүй \n"
"бүрэн үл хамаарах байдаг. Иймээс ерөнхий санхүүгийн данс харьцах тал нь "
"болгох албагүй \n"
"бөгөөд төрөл бүрийн шинжилгээний үйлдлүүдийг оруулж болно.\n"
" "
@ -919,7 +919,7 @@ msgstr "Иордан"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_hr
msgid "Croatia - RRIF 2012 COA"
msgstr ""
msgstr "Croatia - RRIF 2012 COA"
#. module: base
#: help:ir.cron,nextcall:0
@ -2373,9 +2373,9 @@ msgstr ""
"\n"
" * Дансны Мод, Татвар, Татварын Код, Журналь, Дансны Үлгэр, Шинжилгээний "
"Дансны Мод, Шинжилгээний Журналиудад олон хэлийг нэмдэг.\n"
" * Тохируулах харилцах нь дараахыг өөрчилдөг.\n"
" - Үлгэрээс авагдсан Дансны Модт, Татвар, Татварын Код, Мөчлөг зэрэгт "
"орчуулгыг хуулна.\n"
" * Тохируулах харилцах цонх нь дараахыг өөрчилдөг.\n"
" - Үлгэрээс авагдсан Дансны Мод, Татвар, Татварын Код, Санхүүгийн "
"харгалзаа зэрэгт орчуулгыг хуулна.\n"
" "
#. module: base
@ -2564,7 +2564,7 @@ msgstr "Солонгос хэл (KP) / 한국어 (KP)"
#. module: base
#: model:res.country,name:base.ax
msgid "Åland Islands"
msgstr ""
msgstr "Аландийн Арлууд"
#. module: base
#: field:res.company,logo:0
@ -4210,22 +4210,22 @@ msgstr ""
"\n"
"Энэ модуль нь төлөвлөлт, захиалга, нөөцлөлт, бүтээгдэхүүний түүхий эд, дэд "
"хэсгүүдээс угсрах зэрэгийг үйлдвэрлэлийн процессыг хамардаг. Түүнчлэн "
"бүтээгдэхүүний орц, жор, дамжлагын хүний нөөц, машин тоног төхөөрөмж "
"зэрэгийг таамагладаг.\n"
"бүтээгдэхүүний орц, дамжлагын хүний нөөц, машин тоног төхөөрөмж зэрэгийг "
"таамагладаг.\n"
"\n"
"Түүхийн эд нөөцлөл, хангамж, үйлчилгээний бүрэн төлөвлөлтийг дэмждэг. "
"Үйлчилгээ нь програм хангамжийн бусад бүх хэсэгтэй бүрэн уялддаг. Тухайлбал, "
"үйлдвэрлэлийг явуулахдаа жор дотор нь дэд гэрээгээр авах үйлчилгээг "
"үйлдвэрлэлийг явуулахдаа орц дотор нь дэд гэрээгээр авах үйлчилгээг "
"тодорхойлж өгөх боломжтой байдаг.\n"
"\n"
"Онцлог:\n"
"---------\n"
" * Хадгалуулах / Захиалуулах (мөр бүрээр)\n"
" * Олон түвшний жор, хязгааргүй\n"
" * Олон түвшний орц, хязгааргүй\n"
" * Олон түвшний урсгал, хязгааргүй\n"
" * Шинжилгээний санхүүтэй уялдсан үйлдвэрлэлийн урсгал болон дамжлага\n"
" * Тогтол хугацааны тооцоолол / Яг Хугацаандааа модуль\n"
" * Жоруудыг бүтцээр нь, завсрынхаар нь гэх мэт гүйцэд шинжилгээ, үзлэг\n"
" * Орцуудыг бүтцээр нь, завсрынхаар нь гэх мэт гүйцэд шинжилгээ, үзлэг\n"
"\n"
"Үйлдвэрлэлийн модулийн Хянах самбар / Тайлангууд нь дараах зүйлсийг "
"агуулдаг:\n"
@ -6404,7 +6404,7 @@ msgstr "Ачаалах Тохиргооны Визард"
#. module: base
#: model:ir.module.module,summary:base.module_mrp
msgid "Manufacturing Orders, Bill of Materials, Routing"
msgstr "Үйлдвэрлэлийн захиалгууд, Жор, Дамжлагын цуваа"
msgstr "Үйлдвэрлэлийн захиалгууд, Орц, Шугам"
#. module: base
#: field:ir.attachment,name:0

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:22+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:39+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:19+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:36+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:23+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:40+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -398,6 +398,12 @@ msgid ""
"invoices from picking, OpenERP is able to add and compute the shipping "
"line.\n"
msgstr ""
"\n"
"Pozwala dodać rodzaj przesyłki w zamówieniu sprzedaży\n"
"==============================================================\n"
"Możesz zdefiniować twojego własnego przewoźnika i siatkę przesyłek. Kiedy "
"tworzysz fakturę \n"
"z przyjęć, OpenERP jest w stanie dodać i przeliczyć długość przesyłki.\n"
#. module: base
#: code:addons/base/ir/ir_filters.py:80
@ -526,7 +532,7 @@ msgstr "Format daty"
#. module: base
#: model:ir.module.module,shortdesc:base.module_base_report_designer
msgid "OpenOffice Report Designer"
msgstr ""
msgstr "Kreator Wydruków OpenOffice"
#. module: base
#: model:res.country,name:base.an
@ -572,6 +578,16 @@ msgid ""
"that have no counterpart in the general financial accounts.\n"
" "
msgstr ""
"\n"
"Moduł do definiowania kont analitycznych.\n"
"===============================================\n"
"\n"
"W OpenERP, konta analityczne są powiązane z kontami ogólnymi lecz są\n"
"traktowane całkiem oddzielnie. Zatem możesz stworzyć całkiem różne operacje "
"analityczne\n"
"różnego rodzaju lecz one nie będą odpowiednikami z ogólnych kont "
"księgowych.\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_idea
@ -707,7 +723,7 @@ msgstr ""
#. module: base
#: field:res.company,logo_web:0
msgid "Logo Web"
msgstr ""
msgstr "Logo"
#. module: base
#: code:addons/base/ir/ir_model.py:345
@ -783,6 +799,12 @@ msgid ""
"Contains the installer for marketing-related modules.\n"
" "
msgstr ""
"\n"
"Menu Marketingowe\n"
"===================\n"
"\n"
"Zawiera instalator dla marketingowych modułów.\n"
" "
#. module: base
#: model:ir.module.module,description:base.module_web_linkedin
@ -793,6 +815,11 @@ msgid ""
"This module provides the Integration of the LinkedIn with OpenERP.\n"
" "
msgstr ""
"\n"
"Moduł LinkedIn OpenERP Web.\n"
"============================\n"
"Zapewnia integrację LinkedIn z OpenERP.\n"
" "
#. module: base
#: help:ir.actions.act_window,src_model:0

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:23+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:40+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:25+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:42+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:23+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:40+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -25,7 +25,7 @@ msgid ""
" "
msgstr ""
"\n"
"Модуль для проверки написания и проверки печати.\n"
"Модуль для составления и распечатки квитанций.\n"
"================================================\n"
" "
@ -882,7 +882,7 @@ msgstr ""
#. module: base
#: help:ir.cron,nextcall:0
msgid "Next planned execution date for this job."
msgstr "Следующая запланированная дата выполнения для данной работы."
msgstr "Следующая дата выполнения задачи планировщиком."
#. module: base
#: model:ir.model,name:base.model_ir_ui_view
@ -11026,7 +11026,7 @@ msgstr ""
#: model:ir.actions.act_window,name:base.action_view_base_module_upgrade
#, python-format
msgid "Apply Schedule Upgrade"
msgstr "Применить запланированные обновления"
msgstr "Выполнить обновление"
#. module: base
#: view:workflow.activity:0
@ -14840,7 +14840,7 @@ msgstr "Файл веб-значка"
#. module: base
#: model:ir.ui.menu,name:base.menu_view_base_module_upgrade
msgid "Apply Scheduled Upgrades"
msgstr "Выполнить запланированные обновления"
msgstr "Выполнить обновления"
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale_journal
@ -15165,7 +15165,7 @@ msgstr "Лимит"
#. module: base
#: model:res.groups,name:base.group_hr_user
msgid "Officer"
msgstr "Сотрудник"
msgstr "Кадровик"
#. module: base
#: code:addons/orm.py:787

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:41+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:41+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -11315,9 +11315,12 @@ msgid ""
"Thank you in advance for your cooperation.\n"
"Best Regards,"
msgstr ""
"Spoštovani,\n"
"Iz naših poslovnih knjig je razvidno,da imate zapadle obveznosti do našega "
"podjetja.\n"
"\n"
"Naši podatki kažejo , da nam dolgujete spodaj navedeni znesek."
"Prosimo, da svoj dolg takoj poravnate na naš račun.\n"
"\n"
"Če ste svoj dolg že poravnali, upoštevajte opomin za brezpredmeten."
#. module: base
#: view:ir.module.category:0

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:17+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:35+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:23+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:40+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:27+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:44+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:41+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:41+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:24+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:41+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

File diff suppressed because it is too large Load Diff

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:25+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:42+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:25+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:42+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:25+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:42+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:27+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:44+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -575,6 +575,14 @@ msgid ""
"that have no counterpart in the general financial accounts.\n"
" "
msgstr ""
"\n"
"用于定义财务分析项目的模块。\n"
"================================================\n"
"\n"
"在OpenERP中财务分析虽与常规财务相连但却是\n"
"完全独立的。因此,可以使用许多不同的分析操作,\n"
"即使在常规财务会计模块中没有对应功能。\n"
" "
#. module: base
#: model:ir.module.module,shortdesc:base.module_idea
@ -837,7 +845,7 @@ msgstr ""
"\n"
"OpenERP Web LinkedIn 模块.\n"
"============================\n"
"这个模块在OpenERP上提供了一体化的Linke dIn\n"
"此模块用于在OpenERP中集成LinkedIn.\n"
" "
#. module: base
@ -864,7 +872,7 @@ msgstr ""
#. module: base
#: help:ir.cron,nextcall:0
msgid "Next planned execution date for this job."
msgstr "此任务的下一次执行时间"
msgstr "该任务的下次执行日期"
#. module: base
#: model:ir.model,name:base.model_ir_ui_view
@ -1094,7 +1102,10 @@ msgid ""
" "
msgstr ""
"\n"
"这模块目的是管理员工的考勤 根据执行的签入/签出的动作保存员工帐户的考勤记录。\n"
"此模块用于管理员工的考勤.\n"
"==================================================\n"
"\n"
"以员工的登入/退出时间为准,记录员工考勤.\n"
" "
#. module: base
@ -1215,7 +1226,7 @@ msgstr "TGZ 压缩包"
#: view:res.groups:0
msgid ""
"Users added to this group are automatically added in the following groups."
msgstr "若有用户添加至本组时自动将用户添加到下面的组。"
msgstr "加入本群组的用户也将自动加入以下群组."
#. module: base
#: code:addons/base/ir/ir_model.py:733
@ -1768,6 +1779,20 @@ msgid ""
"in their pockets, this module is essential.\n"
" "
msgstr ""
"\n"
"管理午餐的基本模块\n"
"================================\n"
"\n"
"许多公司为给员工提供便利,会从熟悉的餐厅为其员工预定象三明治、披萨饼或其它形式的午餐。\n"
"\n"
"然而公司内部的午餐预定需要适当的管理,尤其是当员工和餐厅数量比较多的情况下。\n"
"\n"
"我们开发的“午餐订购”模块会使这个管理工作变得简单,并给员工提供了更多的工具盒便利。 \n"
"\n"
"除了提供完备的餐食和餐厅管理,本模块还可以根据员工的喜好提供快速订餐选项和显示提示信息。 \n"
"\n"
"如果想节省员工的时间,避免他们总是要准备很多零钱,这个模块就是必须的。\n"
" "
#. module: base
#: view:wizard.ir.model.menu.create:0
@ -1810,7 +1835,7 @@ msgstr "该业务伙伴或者公司的网站"
msgid ""
"If you check this box, your customized translations will be overwritten and "
"replaced by the official ones."
msgstr "如果勾上这个勾数据库中的翻译将被服务器上的po文件中的翻译覆盖"
msgstr "如果选定,则定制翻译会被系统翻译覆盖替换。"
#. module: base
#: model:ir.actions.act_window,name:base.ir_action_report_xml
@ -2791,6 +2816,9 @@ msgid ""
"==================================\n"
" "
msgstr ""
"\n"
"美国 - 会计科目\n"
" "
#. module: base
#: field:ir.actions.act_url,target:0
@ -2847,6 +2875,16 @@ msgid ""
" * Files by Partner (graph)\n"
" * Files Size by Month (graph)\n"
msgstr ""
"\n"
"这是一个完整的文档管理系统。\n"
"================================================\n"
" * 用户身份验证\n"
" * 文档索引在Windows平台上不支持pptx和docx格式文件。\n"
" * 文档面板包含:\n"
" * 新文件列表\n"
" * 按资源类型的文件图表\n"
" * 按合作者的文件图表\n"
" * 按月的文件大小图表\n"
#. module: base
#: view:ir.actions.report.xml:0
@ -2998,6 +3036,14 @@ msgid ""
"This module is currently not compatible with the ``user_ldap`` module and\n"
"will disable LDAP authentication completely if installed at the same time.\n"
msgstr ""
"\n"
"加密密码\n"
"===================\n"
"\n"
"LDAP身份验证的内部功能\n"
"-------------------------------\n"
"当前该模块与``user_ldap``模块并不兼容\n"
"如果二者同时安装会禁用LDAP身份验证。\n"
#. module: base
#: model:res.groups,name:base.group_hr_manager
@ -12206,7 +12252,7 @@ msgstr "报表类型"
#: view:res.partner.bank:0
#: view:res.users:0
msgid "State"
msgstr "状态"
msgstr ""
#. module: base
#: selection:base.language.install,lang:0
@ -14559,7 +14605,7 @@ msgstr "源模型"
#. module: base
#: view:ir.sequence:0
msgid "Day of the Week (0:Monday): %(weekday)s"
msgstr ""
msgstr "一周的第几天 (0:星期一):%(weekday)s"
#. module: base
#: code:addons/base/module/wizard/base_module_upgrade.py:84

View File

@ -14,8 +14,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:25+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:42+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -13,8 +13,8 @@ msgstr ""
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2013-03-31 05:26+0000\n"
"X-Generator: Launchpad (build 16546)\n"
"X-Launchpad-Export-Date: 2013-05-30 05:43+0000\n"
"X-Generator: Launchpad (build 16652)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing

View File

@ -185,9 +185,9 @@ class act_window(osv.osv):
def _check_model(self, cr, uid, ids, context=None):
for action in self.browse(cr, uid, ids, context):
if not self.pool.get(action.res_model):
if action.res_model not in self.pool:
return False
if action.src_model and not self.pool.get(action.src_model):
if action.src_model and action.src_model not in self.pool:
return False
return True
@ -560,7 +560,7 @@ class actions_server(osv.osv):
}
def get_email(self, cr, uid, action, context):
obj_pool = self.pool.get(action.model_id.model)
obj_pool = self.pool[action.model_id.model]
id = context.get('active_id')
obj = obj_pool.browse(cr, uid, id)
@ -580,7 +580,7 @@ class actions_server(osv.osv):
return obj
def get_mobile(self, cr, uid, action, context):
obj_pool = self.pool.get(action.model_id.model)
obj_pool = self.pool[action.model_id.model]
id = context.get('active_id')
obj = obj_pool.browse(cr, uid, id)
@ -604,7 +604,7 @@ class actions_server(osv.osv):
context = {}
def merge(match):
obj_pool = self.pool.get(action.model_id.model)
obj_pool = self.pool[action.model_id.model]
id = context.get('active_id')
obj = obj_pool.browse(cr, uid, id)
exp = str(match.group()[2:-2]).strip()
@ -637,7 +637,7 @@ class actions_server(osv.osv):
user = self.pool.get('res.users').browse(cr, uid, uid)
for action in self.browse(cr, uid, ids, context):
obj = None
obj_pool = self.pool.get(action.model_id.model)
obj_pool = self.pool[action.model_id.model]
if context.get('active_model') == action.model_id.model and context.get('active_id'):
obj = obj_pool.browse(cr, uid, context['active_id'], context=context)
cxt = {
@ -658,8 +658,7 @@ class actions_server(osv.osv):
if action.state=='client_action':
if not action.action_id:
raise osv.except_osv(_('Error'), _("Please specify an action to launch !"))
return self.pool.get(action.action_id.type)\
.read(cr, uid, action.action_id.id, context=context)
return self.pool[action.action_id.type].read(cr, uid, action.action_id.id, context=context)
if action.state=='code':
eval(action.code.strip(), cxt, mode="exec", nocopy=True) # nocopy allows to return 'action'
@ -738,16 +737,16 @@ class actions_server(osv.osv):
if not action.write_id:
if not action.srcmodel_id:
obj_pool = self.pool.get(action.model_id.model)
obj_pool = self.pool[action.model_id.model]
obj_pool.write(cr, uid, [context.get('active_id')], res)
else:
write_id = context.get('active_id')
obj_pool = self.pool.get(action.srcmodel_id.model)
obj_pool = self.pool[action.srcmodel_id.model]
obj_pool.write(cr, uid, [write_id], res)
elif action.write_id:
obj_pool = self.pool.get(action.srcmodel_id.model)
rec = self.pool.get(action.model_id.model).browse(cr, uid, context.get('active_id'))
obj_pool = self.pool[action.srcmodel_id.model]
rec = self.pool[action.model_id.model].browse(cr, uid, context.get('active_id'))
id = eval(action.write_id, {'object': rec})
try:
id = int(id)
@ -769,10 +768,10 @@ class actions_server(osv.osv):
expr = exp.value
res[exp.col1.name] = expr
obj_pool = self.pool.get(action.srcmodel_id.model)
obj_pool = self.pool[action.srcmodel_id.model]
res_id = obj_pool.create(cr, uid, res)
if action.record_id:
self.pool.get(action.model_id.model).write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})
self.pool[action.model_id.model].write(cr, uid, [context.get('active_id')], {action.record_id.name:res_id})
if action.state == 'object_copy':
res = {}
@ -786,7 +785,7 @@ class actions_server(osv.osv):
model = action.copy_object.split(',')[0]
cid = action.copy_object.split(',')[1]
obj_pool = self.pool.get(model)
obj_pool = self.pool[model]
obj_pool.copy(cr, uid, int(cid), res)
return False
@ -843,7 +842,7 @@ Launch Manually Once: after having been launched manually, it sets automatically
# Load action
act_type = self.pool.get('ir.actions.actions').read(cr, uid, wizard.action_id.id, ['type'], context=context)
res = self.pool.get(act_type['type']).read(cr, uid, wizard.action_id.id, [], context=context)
res = self.pool[act_type['type']].read(cr, uid, wizard.action_id.id, [], context=context)
if act_type['type'] != 'ir.actions.act_window':
return res
res.setdefault('context','{}')

View File

@ -50,7 +50,7 @@ class ir_attachment(osv.osv):
model_object = attachment.res_model
res_id = attachment.res_id
if model_object and res_id:
model_pool = self.pool.get(model_object)
model_pool = self.pool[model_object]
res = model_pool.name_get(cr,uid,[res_id],context)
res_name = res and res[0][1] or False
if res_name:
@ -205,9 +205,9 @@ class ir_attachment(osv.osv):
for model, mids in res_ids.items():
# ignore attachments that are not attached to a resource anymore when checking access rights
# (resource was deleted but attachment was not)
mids = self.pool.get(model).exists(cr, uid, mids)
mids = self.pool[model].exists(cr, uid, mids)
ima.check(cr, uid, model, mode)
self.pool.get(model).check_access_rule(cr, uid, mids, mode, context=context)
self.pool[model].check_access_rule(cr, uid, mids, mode, context=context)
def _search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
ids = super(ir_attachment, self)._search(cr, uid, args, offset=offset,
@ -250,7 +250,7 @@ class ir_attachment(osv.osv):
# filter ids according to what access rules permit
target_ids = targets.keys()
allowed_ids = self.pool.get(model).search(cr, uid, [('id', 'in', target_ids)], context=context)
allowed_ids = self.pool[model].search(cr, uid, [('id', 'in', target_ids)], context=context)
disallowed_ids = set(target_ids).difference(allowed_ids)
for res_id in disallowed_ids:
for attach_id in targets[res_id]:

View File

@ -31,9 +31,12 @@ from openerp.osv import fields, osv
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
from openerp.modules import load_information_from_description_file
_logger = logging.getLogger(__name__)
BASE_VERSION = load_information_from_description_file('base')['version']
def str2tuple(s):
return eval('tuple(%s)' % (s or ''))
@ -125,21 +128,23 @@ class ir_cron(osv.osv):
args = str2tuple(args)
openerp.modules.registry.RegistryManager.check_registry_signaling(cr.dbname)
registry = openerp.registry(cr.dbname)
model = registry.get(model_name)
if model and hasattr(model, method_name):
method = getattr(model, method_name)
log_depth = (None if _logger.isEnabledFor(logging.DEBUG) else 1)
netsvc.log(_logger, logging.DEBUG, 'cron.object.execute', (cr.dbname,uid,'*',model_name,method_name)+tuple(args), depth=log_depth)
if _logger.isEnabledFor(logging.DEBUG):
start_time = time.time()
method(cr, uid, *args)
if _logger.isEnabledFor(logging.DEBUG):
end_time = time.time()
_logger.debug('%.3fs (%s, %s)' % (end_time - start_time, model_name, method_name))
openerp.modules.registry.RegistryManager.signal_caches_change(cr.dbname)
if model_name in registry:
model = registry[model_name]
if hasattr(model, method_name):
log_depth = (None if _logger.isEnabledFor(logging.DEBUG) else 1)
netsvc.log(_logger, logging.DEBUG, 'cron.object.execute', (cr.dbname,uid,'*',model_name,method_name)+tuple(args), depth=log_depth)
if _logger.isEnabledFor(logging.DEBUG):
start_time = time.time()
getattr(model, method_name)(cr, uid, *args)
if _logger.isEnabledFor(logging.DEBUG):
end_time = time.time()
_logger.debug('%.3fs (%s, %s)' % (end_time - start_time, model_name, method_name))
openerp.modules.registry.RegistryManager.signal_caches_change(cr.dbname)
else:
msg = "Method `%s.%s` does not exist." % (model_name, method_name)
_logger.warning(msg)
else:
msg = "Method `%s.%s` does not exist." % (model_name, method_name) \
if model else "Model `%s` does not exist." % model_name
msg = "Model `%s` does not exist." % model_name
_logger.warning(msg)
except Exception, e:
self._handle_callback_exception(cr, uid, model_name, method_name, args, job_id, e)
@ -193,12 +198,17 @@ class ir_cron(osv.osv):
cr = db.cursor()
jobs = []
try:
# Careful to compare timestamps with 'UTC' - everything is UTC as of v6.1.
cr.execute("""SELECT * FROM ir_cron
WHERE numbercall != 0
AND active AND nextcall <= (now() at time zone 'UTC')
ORDER BY priority""")
jobs = cr.dictfetchall()
# Make sure the database we poll has the same version as the code of base
cr.execute("SELECT 1 FROM ir_module_module WHERE name=%s AND latest_version=%s", ('base', BASE_VERSION))
if cr.fetchone():
# Careful to compare timestamps with 'UTC' - everything is UTC as of v6.1.
cr.execute("""SELECT * FROM ir_cron
WHERE numbercall != 0
AND active AND nextcall <= (now() at time zone 'UTC')
ORDER BY priority""")
jobs = cr.dictfetchall()
else:
_logger.warning('Skipping database %s as its base version is not %s.', db_name, BASE_VERSION)
except psycopg2.ProgrammingError, e:
if e.pgcode == '42P01':
# Class 42 — Syntax Error or Access Rule Violation; 42P01: undefined_table

View File

@ -71,7 +71,7 @@ class ir_model(osv.osv):
models = self.browse(cr, uid, ids, context=context)
res = dict.fromkeys(ids)
for model in models:
if self.pool.get(model.model):
if model.model in self.pool:
res[model.id] = self.pool[model.model].is_transient()
else:
_logger.error('Missing model %s' % (model.model, ))
@ -346,7 +346,7 @@ class ir_model_fields(osv.osv):
if vals.get('relation',False) and not self.pool['ir.model'].search(cr, user, [('model','=',vals['relation'])]):
raise except_orm(_('Error'), _("Model %s does not exist!") % vals['relation'])
if self.pool.get(vals['model']):
if vals['model'] in self.pool:
self.pool[vals['model']].__init__(self.pool, cr)
#Added context to _auto_init for special treatment to custom field for select_level
ctx = dict(context,
@ -374,7 +374,6 @@ class ir_model_fields(osv.osv):
raise except_orm(_('Error!'), _('Renaming sparse field "%s" is not allowed')%field.name)
column_rename = None # if set, *one* column can be renamed here
obj = None
models_patch = {} # structs of (obj, [(field, prop, change_to),..])
# data to be updated on the orm model
@ -397,8 +396,7 @@ class ir_model_fields(osv.osv):
checked_selection = False # need only check it once, so defer
for item in self.browse(cr, user, ids, context=context):
if not (obj and obj._name == item.model):
obj = self.pool.get(item.model)
obj = self.pool.get(item.model)
if item.state != 'manual':
raise except_orm(_('Error!'),
@ -434,7 +432,7 @@ class ir_model_fields(osv.osv):
# We don't check the 'state', because it might come from the context
# (thus be set for multiple fields) and will be ignored anyway.
if obj:
if obj is not None:
models_patch.setdefault(obj._name, (obj,[]))
# find out which properties (per model) we need to update
for field_name, field_property, set_fn in model_props:
@ -515,7 +513,7 @@ class ir_model_constraint(Model):
ids.reverse()
for data in self.browse(cr, uid, ids, context):
model = data.model.model
model_obj = self.pool.get(model)
model_obj = self.pool[model]
name = openerp.tools.ustr(data.name)
typ = data.type
@ -690,7 +688,7 @@ class ir_model_access(osv.osv):
model_name = model
# TransientModel records have no access rights, only an implicit access rule
if not self.pool.get(model_name):
if model_name not in self.pool:
_logger.error('Missing model %s' % (model_name, ))
elif self.pool[model_name].is_transient():
return True
@ -754,9 +752,8 @@ class ir_model_access(osv.osv):
def call_cache_clearing_methods(self, cr):
self.check.clear_cache(self) # clear the cache of check function
for model, method in self.__cache_clearing_methods:
object_ = self.pool.get(model)
if object_:
getattr(object_, method)()
if model in self.pool:
getattr(self.pool[model], method)()
#
# Check rights on actions
@ -866,11 +863,24 @@ class ir_model_data(osv.osv):
def get_object_reference(self, cr, uid, module, xml_id):
"""Returns (model, res_id) corresponding to a given module and xml_id (cached) or raise ValueError if not found"""
data_id = self._get_id(cr, uid, module, xml_id)
#assuming data_id is not False, as it was checked upstream
res = self.read(cr, uid, data_id, ['model', 'res_id'])
if not res['res_id']:
raise ValueError('No such external ID currently defined in the system: %s.%s' % (module, xml_id))
return res['model'], res['res_id']
def check_object_reference(self, cr, uid, module, xml_id, raise_on_access_error=False):
"""Returns (model, res_id) corresponding to a given module and xml_id (cached), if and only if the user has the necessary access rights
to see that object, otherwise raise a ValueError if raise_on_access_error is True or returns a tuple (model found, False)"""
model, res_id = self.get_object_reference(cr, uid, module, xml_id)
#search on id found in result to check if current user has read access right
check_right = self.pool.get(model).search(cr, uid, [('id', '=', res_id)])
if check_right:
return model, res_id
if raise_on_access_error:
raise ValueError('Not enough access rights on the external ID: %s.%s' % (module, xml_id))
return model, False
def get_object(self, cr, uid, module, xml_id, context=None):
"""Returns a browsable record for the given module name and xml_id or raise ValueError if not found"""
res_model, res_id = self.get_object_reference(cr, uid, module, xml_id)
@ -904,7 +914,7 @@ class ir_model_data(osv.osv):
return super(ir_model_data,self).unlink(cr, uid, ids, context=context)
def _update(self,cr, uid, model, module, values, xml_id=False, store=True, noupdate=False, mode='init', res_id=False, context=None):
model_obj = self.pool.get(model)
model_obj = self.pool[model]
if not context:
context = {}
# records created during module install should not display the messages of OpenChatter
@ -1122,7 +1132,7 @@ class ir_model_data(osv.osv):
to_unlink.append((model,res_id))
if not config.get('import_partial'):
for (model, res_id) in to_unlink:
if self.pool.get(model):
if model in self.pool:
_logger.info('Deleting %s@%s', res_id, model)
self.pool[model].unlink(cr, uid, [res_id])

View File

@ -65,7 +65,7 @@ class ir_rule(osv.osv):
return res
def _check_model_obj(self, cr, uid, ids, context=None):
return not any(self.pool.get(rule.model_id.model).is_transient() for rule in self.browse(cr, uid, ids, context))
return not any(self.pool[rule.model_id.model].is_transient() for rule in self.browse(cr, uid, ids, context))
def _check_model_name(self, cr, uid, ids, context=None):
# Don't allow rules on rules records (this model).
@ -153,9 +153,9 @@ class ir_rule(osv.osv):
# involve objects on which the real uid has no acces rights.
# This means also there is no implicit restriction (e.g. an object
# references another object the user can't see).
query = self.pool.get(model_name)._where_calc(cr, SUPERUSER_ID, dom, active_test=False)
query = self.pool[model_name]._where_calc(cr, SUPERUSER_ID, dom, active_test=False)
return query.where_clause, query.where_clause_params, query.tables
return [], [], ['"'+self.pool.get(model_name)._table+'"']
return [], [], ['"' + self.pool[model_name]._table + '"']
def unlink(self, cr, uid, ids, context=None):
res = super(ir_rule, self).unlink(cr, uid, ids, context=context)

View File

@ -217,7 +217,7 @@ class ir_sequence(openerp.osv.osv.osv):
def next_by_id(self, cr, uid, sequence_id, context=None):
""" Draw an interpolated string using the specified sequence."""
self.check_access_rights(cr, uid, 'read')
company_ids = self.pool.get('res.company').search(cr, uid, [], order='company_id', context=context) + [False]
company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) + [False]
ids = self.search(cr, uid, ['&',('id','=', sequence_id),('company_id','in',company_ids)])
return self._next(cr, uid, ids, context)
@ -234,8 +234,8 @@ class ir_sequence(openerp.osv.osv.osv):
specific company will get higher priority.
"""
self.check_access_rights(cr, uid, 'read')
company_ids = self.pool.get('res.company').search(cr, uid, [], order='company_id', context=context) + [False]
ids = self.search(cr, uid, ['&',('code','=', sequence_code),('company_id','in',company_ids)])
company_ids = self.pool.get('res.company').search(cr, uid, [], context=context) + [False]
ids = self.search(cr, uid, ['&', ('code', '=', sequence_code), ('company_id', 'in', company_ids)])
return self._next(cr, uid, ids, context)
def get_id(self, cr, uid, sequence_code_or_id, code_or_id='id', context=None):

View File

@ -155,12 +155,51 @@ class ir_translation(osv.osv):
lang_data = lang_model.read(cr, uid, lang_ids, ['code', 'name'], context=context)
return [(d['code'], d['name']) for d in lang_data]
def _get_src(self, cr, uid, ids, name, arg, context=None):
''' Get source name for the translation. If object type is model then
return the value store in db. Otherwise return value store in src field
'''
if context is None:
context = {}
res = {}
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]
return res
def _set_src(self, cr, uid, id, name, value, args, context=None):
''' When changing source term of a translation, change its value in db for
the associated object, and the src field
'''
if context is None:
context = {}
record = self.browse(cr, uid, id, context=context)
if value and record.type == 'model':
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 write on the
#value store in db and not on the one associate with current language.
#Also not removing lang from context trigger an error when lang is different
context_wo_lang = context.copy()
context_wo_lang.pop('lang', None)
model.write(cr, uid, record.res_id, {field: value}, context=context_wo_lang)
return self.write(cr, uid, id, {'src': value}, context=context)
_columns = {
'name': fields.char('Translated field', required=True),
'res_id': fields.integer('Record ID', select=True),
'lang': fields.selection(_get_language, string='Language'),
'type': fields.selection(TRANSLATION_TYPE, string='Type', select=True),
'src': fields.text('Source'),
'src': fields.text('Old source'),
'source': fields.function(_get_src, fnct_inv=_set_src, type='text', string='Source'),
'value': fields.text('Translation Value'),
'module': fields.char('Module', help="Module this term belongs to", select=True),
@ -300,7 +339,7 @@ class ir_translation(osv.osv):
return trad
def create(self, cr, uid, vals, context=None):
if not context:
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))
@ -308,7 +347,7 @@ class ir_translation(osv.osv):
return ids
def write(self, cursor, user, ids, vals, context=None):
if not context:
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
@ -323,7 +362,7 @@ class ir_translation(osv.osv):
return result
def unlink(self, cursor, user, ids, context=None):
if not context:
if context is None:
context = {}
if isinstance(ids, (int, long)):
ids = [ids]
@ -334,7 +373,7 @@ class ir_translation(osv.osv):
return result
def translate_fields(self, cr, uid, model, id, field=None, context=None):
trans_model = self.pool.get(model)
trans_model = self.pool[model]
domain = ['&', ('res_id', '=', id), ('name', '=like', model + ',%')]
langs_ids = self.pool.get('res.lang').search(cr, uid, [('code', '!=', 'en_US')], context=context)
if not langs_ids:

View File

@ -14,7 +14,7 @@
domain="[('comments', 'like', 'openerp-web')]"/>
<field name="name" operator="="/>
<field name="lang"/>
<field name="src"/>
<field name="source"/>
<field name="value"/>
</search>
</field>
@ -38,7 +38,7 @@
<field name="res_id"/>
</group>
<group string="Source Term">
<field name="src" nolabel="1" height="400"/>
<field name="source" nolabel="1" height="400"/>
</group>
<group string="Translation">
<field name="value" nolabel="1" height="400"/>
@ -55,7 +55,7 @@
<field name="model">ir.translation</field>
<field name="arch" type="xml">
<tree string="Translations" editable="top">
<field name="src"/>
<field name="source"/>
<field name="value"/>
<field name="name"/>
<field name="lang"/>

View File

@ -289,8 +289,7 @@ class ir_ui_menu(osv.osv):
res = dict.fromkeys(ids, False)
for menu in self.browse(cr, uid, ids, context=context):
if menu.action and menu.action.type in ('ir.actions.act_window', 'ir.actions.client') and menu.action.res_model:
obj = self.pool.get(menu.action.res_model)
if obj and obj._needaction:
if menu.action.res_model in self.pool and self.pool[menu.action.res_model]._needaction:
res[menu.id] = True
return res
@ -300,21 +299,47 @@ class ir_ui_menu(osv.osv):
- the needaction counter of the related action, taking into account
the action domain
"""
if context is None:
context = {}
res = {}
menu_ids = set()
for menu in self.browse(cr, uid, ids, context=context):
menu_ids.add(menu.id)
ctx = None
if menu.action and menu.action.type in ('ir.actions.act_window', 'ir.actions.client') and menu.action.context:
try:
# use magical UnquoteEvalContext to ignore undefined client-side variables such as `active_id`
eval_ctx = tools.UnquoteEvalContext(**context)
ctx = eval(menu.action.context, locals_dict=eval_ctx, nocopy=True) or None
except Exception:
# if the eval still fails for some reason, we'll simply skip this menu
pass
menu_ref = ctx and ctx.get('needaction_menu_ref')
if menu_ref:
if not isinstance(menu_ref, list):
menu_ref = [menu_ref]
model_data_obj = self.pool.get('ir.model.data')
for menu_data in menu_ref:
model, id = model_data_obj.get_object_reference(cr, uid, menu_data.split('.')[0], menu_data.split('.')[1])
if (model == 'ir.ui.menu'):
menu_ids.add(id)
menu_ids = list(menu_ids)
for menu in self.browse(cr, uid, menu_ids, context=context):
res[menu.id] = {
'needaction_enabled': False,
'needaction_counter': False,
}
if menu.action and menu.action.type in ('ir.actions.act_window', 'ir.actions.client') and menu.action.res_model:
obj = self.pool.get(menu.action.res_model)
if obj and obj._needaction:
if menu.action.type == 'ir.actions.act_window':
dom = menu.action.domain and eval(menu.action.domain, {'uid': uid}) or []
else:
dom = eval(menu.action.params_store or '{}', {'uid': uid}).get('domain')
res[menu.id]['needaction_enabled'] = obj._needaction
res[menu.id]['needaction_counter'] = obj._needaction_count(cr, uid, dom, context=context)
if menu.action.res_model in self.pool:
obj = self.pool[menu.action.res_model]
if obj._needaction:
if menu.action.type == 'ir.actions.act_window':
dom = menu.action.domain and eval(menu.action.domain, {'uid': uid}) or []
else:
dom = eval(menu.action.params_store or '{}', {'uid': uid}).get('domain')
res[menu.id]['needaction_enabled'] = obj._needaction
res[menu.id]['needaction_counter'] = obj._needaction_count(cr, uid, dom, context=context)
return res
_columns = {

View File

@ -100,7 +100,7 @@ class view(osv.osv):
else:
inferred_type = etree.fromstring(values['arch'].encode('utf8')).tag
values['name'] = "%s %s" % (values['model'], inferred_type)
return super(osv.osv, self).create(cr, uid, values, context)
return super(view, self).create(cr, uid, values, context)
def _relaxng(self):
if not self._relaxng_validator:
@ -123,7 +123,7 @@ class view(osv.osv):
if no error occurred, else False.
"""
try:
fvg = self.pool.get(view.model).fields_view_get(cr, uid, view_id=view.id, view_type=view.type, context=context)
fvg = self.pool[view.model].fields_view_get(cr, uid, view_id=view.id, view_type=view.type, context=context)
return fvg['arch']
except:
_logger.exception("Can't render view %s for model: %s", view.xml_id, view.model)
@ -217,9 +217,9 @@ class view(osv.osv):
no_ancester=[]
blank_nodes = []
_Model_Obj=self.pool.get(model)
_Node_Obj=self.pool.get(node_obj)
_Arrow_Obj=self.pool.get(conn_obj)
_Model_Obj = self.pool[model]
_Node_Obj = self.pool[node_obj]
_Arrow_Obj = self.pool[conn_obj]
for model_key,model_value in _Model_Obj._columns.items():
if model_value._type=='one2many':
@ -293,7 +293,7 @@ class view_sc(osv.osv):
def get_sc(self, cr, uid, user_id, model='ir.ui.menu', context=None):
ids = self.search(cr, uid, [('user_id','=',user_id),('resource','=',model)], context=context)
results = self.read(cr, uid, ids, ['res_id'], context=context)
name_map = dict(self.pool.get(model).name_get(cr, uid, [x['res_id'] for x in results], context=context))
name_map = dict(self.pool[model].name_get(cr, uid, [x['res_id'] for x in results], context=context))
# Make sure to return only shortcuts pointing to exisintg menu items.
filtered_results = filter(lambda result: result['res_id'] in name_map, results)
for result in filtered_results:

View File

@ -397,11 +397,11 @@ class ir_values(osv.osv):
action_model,id = action['value'].split(',')
fields = [
field
for field in self.pool.get(action_model)._all_columns
for field in self.pool[action_model]._all_columns
if field not in EXCLUDED_FIELDS]
# FIXME: needs cleanup
try:
action_def = self.pool.get(action_model).read(cr, uid, int(id), fields, context)
action_def = self.pool[action_model].read(cr, uid, int(id), fields, context)
if action_def:
if action_model in ('ir.actions.report.xml','ir.actions.act_window',
'ir.actions.wizard'):

View File

@ -486,6 +486,7 @@ class module(osv.osv):
function(cr, uid, ids, context=context)
cr.commit()
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
registry = openerp.modules.registry.RegistryManager.new(cr.dbname, update_module=True)
config = registry['res.config'].next(cr, uid, [], context=context) or {}

View File

@ -246,7 +246,7 @@
</para>
</section>
<section>
<para style="P1">[[ repeatIn(findflds(object.model), 'field') ]]</para>
<para style="P1">[[ repeatIn(findflds(object.model, module.name), 'field') ]]</para>
<blockTable colWidths="113.0,397.0" repeatRows="1" style="Table2">
<tr>
<td>

View File

@ -34,7 +34,7 @@ class ir_module_reference_print(report_sxw.rml_parse):
'findflds': self._fields_find,
})
def _object_doc(self, obj):
modobj = self.pool.get(obj)
modobj = self.pool[obj]
strdocs= modobj.__doc__
if not strdocs:
return None
@ -48,7 +48,7 @@ class ir_module_reference_print(report_sxw.rml_parse):
return res
def _object_doc2(self, obj):
modobj = self.pool.get(obj)
modobj = self.pool[obj]
strdocs= modobj.__doc__
if not strdocs:
return None
@ -64,17 +64,24 @@ class ir_module_reference_print(report_sxw.rml_parse):
return res
def _object_find(self, module):
ids2 = self.pool.get('ir.model.data').search(self.cr, self.uid, [('module','=',module), ('model','=','ir.model')])
ids2 = self.pool['ir.model.data'].search(self.cr, self.uid, [('module','=',module), ('model','=','ir.model')])
ids = []
for mod in self.pool.get('ir.model.data').browse(self.cr, self.uid, ids2):
for mod in self.pool['ir.model.data'].browse(self.cr, self.uid, ids2):
ids.append(mod.res_id)
modobj = self.pool.get('ir.model')
modobj = self.pool['ir.model']
return modobj.browse(self.cr, self.uid, ids)
def _fields_find(self, obj):
modobj = self.pool.get(obj)
res = modobj.fields_get(self.cr, self.uid).items()
res.sort()
def _fields_find(self, obj, module):
res = []
data_obj = self.pool['ir.model.data']
modobj = self.pool[obj]
fname_wildcard = 'field_' + modobj._name.replace('.', '_') + '_%'
module_fields_ids = data_obj.search(self.cr, self.uid, [('model', '=', 'ir.model.fields'), ('module', '=', module), ('name', 'like', fname_wildcard)])
if module_fields_ids:
module_fields_res_ids = [x['res_id'] for x in data_obj.read(self.cr, self.uid, module_fields_ids, ['res_id'])]
module_fields_names = [x['name'] for x in self.pool['ir.model.fields'].read(self.cr, self.uid, module_fields_res_ids, ['name'])]
res = modobj.fields_get(self.cr, self.uid, allfields=module_fields_names).items()
res.sort()
return res
report_sxw.report_sxw('report.ir.module.reference', 'ir.module.module',

View File

@ -158,8 +158,8 @@ class res_partner_bank(osv.osv):
'name': '/'
}
def fields_get(self, cr, uid, fields=None, context=None):
res = super(res_partner_bank, self).fields_get(cr, uid, fields, context)
def fields_get(self, cr, uid, allfields=None, context=None):
res = super(res_partner_bank, self).fields_get(cr, uid, allfields=allfields, context=context)
bank_type_obj = self.pool.get('res.partner.bank.type')
type_ids = bank_type_obj.search(cr, uid, [])
types = bank_type_obj.browse(cr, uid, type_ids)

View File

@ -97,7 +97,7 @@ class res_company(osv.osv):
address_data = part_obj.address_get(cr, uid, [company.partner_id.id], adr_pref=['default'])
address = address_data['default']
if address:
part_obj.write(cr, uid, [address], {name: value or False})
part_obj.write(cr, uid, [address], {name: value or False}, context=context)
else:
part_obj.create(cr, uid, {name: value or False, 'parent_id': company.partner_id.id}, context=context)
return True
@ -253,7 +253,7 @@ class res_company(osv.osv):
vals.update({'partner_id': partner_id})
self.cache_restart(cr)
company_id = super(res_company, self).create(cr, uid, vals, context=context)
obj_partner.write(cr, uid, partner_id, {'company_id': company_id}, context=context)
obj_partner.write(cr, uid, [partner_id], {'company_id': company_id}, context=context)
return company_id
def write(self, cr, uid, ids, values, context=None):

View File

@ -31,6 +31,37 @@ from openerp import exceptions
_logger = logging.getLogger(__name__)
class res_config_module_installation_mixin(object):
def _install_modules(self, cr, uid, modules, context):
"""Install the requested modules.
return the next action to execute
modules is a list of tuples
(mod_name, browse_record | None)
"""
ir_module = self.pool.get('ir.module.module')
to_install_ids = []
to_install_missing_names = []
for name, module in modules:
if not module:
to_install_missing_names.append(name)
elif module.state == 'uninstalled':
to_install_ids.append(module.id)
if to_install_ids:
ir_module.button_immediate_install(cr, uid, to_install_ids, context=context)
if to_install_missing_names:
return {
'type': 'ir.actions.client',
'tag': 'apps',
'params': {'modules': to_install_missing_names},
}
return None
class res_config_configurable(osv.osv_memory):
''' Base classes for new-style configuration items
@ -155,7 +186,7 @@ class res_config_configurable(osv.osv_memory):
res_config_configurable()
class res_config_installer(osv.osv_memory):
class res_config_installer(osv.osv_memory, res_config_module_installation_mixin):
""" New-style configuration base specialized for addons selection
and installation.
@ -353,17 +384,18 @@ class res_config_installer(osv.osv_memory):
return fields
def execute(self, cr, uid, ids, context=None):
modules = self.pool['ir.module.module']
to_install = list(self.modules_to_install(
cr, uid, ids, context=context))
_logger.info('Selecting addons %s to install', to_install)
modules.state_update(
cr, uid,
modules.search(cr, uid, [('name','in',to_install)]),
'to install', ['uninstalled'], context=context)
cr.commit()
openerp.modules.registry.RegistryManager.signal_registry_change(cr.dbname)
openerp.modules.registry.RegistryManager.new(cr.dbname, update_module=True)
ir_module = self.pool.get('ir.module.module')
modules = []
for name in to_install:
mod_ids = ir_module.search(cr, uid, [('name', '=', name)])
record = ir_module.browse(cr, uid, mod_ids[0], context) if mod_ids else None
modules.append((name, record))
return self._install_modules(cr, uid, modules, context=context)
res_config_installer()
@ -404,8 +436,7 @@ class ir_actions_configuration_wizard(osv.osv_memory):
ir_actions_configuration_wizard()
class res_config_settings(osv.osv_memory):
class res_config_settings(osv.osv_memory, res_config_module_installation_mixin):
""" Base configuration wizard for application settings. It provides support for setting
default values, assigning groups to employee users, and installing modules.
To make such a 'settings' wizard, define a model like::
@ -529,33 +560,22 @@ class res_config_settings(osv.osv_memory):
getattr(self, method)(cr, uid, ids, context)
# module fields: install/uninstall the selected modules
to_install_missing_names = []
to_install = []
to_uninstall_ids = []
to_install_ids = []
lm = len('module_')
for name, module in classified['module']:
if config[name]:
if not module:
# missing module, will be provided by apps.openerp.com
to_install_missing_names.append(name[lm:])
elif module.state == 'uninstalled':
# local module, to be installed
to_install_ids.append(module.id)
to_install.append((name[lm:], module))
else:
if module and module.state in ('installed', 'to upgrade'):
to_uninstall_ids.append(module.id)
if to_uninstall_ids:
ir_module.button_immediate_uninstall(cr, uid, to_uninstall_ids, context=context)
if to_install_ids:
ir_module.button_immediate_install(cr, uid, to_install_ids, context=context)
if to_install_missing_names:
return {
'type': 'ir.actions.client',
'tag': 'apps',
'params': {'modules': to_install_missing_names},
}
action = self._install_modules(cr, uid, to_install, context=context)
if action:
return action
# After the uninstall/install calls, the self.pool is no longer valid.
# So we reach into the RegistryManager directly.
@ -603,7 +623,7 @@ class res_config_settings(osv.osv_memory):
structured as follows: module_name.menuitem_xml_id (e.g.: "base.menu_sale_config")
:return tuple:
- t[0]: string: full path to the menuitem (e.g.: "Settings/Configuration/Sales")
- t[1]: long: id of the menuitem's action
- t[1]: int or long: id of the menuitem's action
"""
module_name, menu_xml_id = menu_xml_id.split('.')
dummy, menu_id = self.pool['ir.model.data'].get_object_reference(cr, uid, module_name, menu_xml_id)

View File

@ -30,7 +30,11 @@ from openerp.tools.translate import _
CURRENCY_DISPLAY_PATTERN = re.compile(r'(\w+)\s*(?:\((.*)\))?')
class res_currency(osv.osv):
def _current_rate(self, cr, uid, ids, name, arg, context=None):
return self._get_current_rate(cr, uid, ids, name, arg, context=context)
def _get_current_rate(self, cr, uid, ids, name, arg, context=None):
if context is None:
context = {}
res = {}

View File

@ -30,6 +30,7 @@ from openerp import SUPERUSER_ID
from openerp import tools
from openerp.osv import osv, fields
from openerp.tools.translate import _
from openerp.tools.yaml_import import is_comment
class format_address(object):
def fields_view_get_address(self, cr, uid, arch, context={}):
@ -159,8 +160,8 @@ def _lang_get(self, cr, uid, context=None):
res = lang_pool.read(cr, uid, ids, ['code', 'name'], context)
return [(r['code'], r['name']) for r in res]
POSTAL_ADDRESS_FIELDS = ('street', 'street2', 'zip', 'city', 'state_id', 'country_id')
ADDRESS_FIELDS = POSTAL_ADDRESS_FIELDS + ('email', 'phone', 'fax', 'mobile', 'website', 'ref', 'lang')
# fields copy if 'use_parent_address' is checked
ADDRESS_FIELDS = ('street', 'street2', 'zip', 'city', 'state_id', 'country_id')
class res_partner(osv.osv, format_address):
_description = 'Partner'
@ -193,13 +194,42 @@ class res_partner(osv.osv, format_address):
result[obj.id] = obj.image != False
return result
_order = "name"
def _commercial_partner_compute(self, cr, uid, ids, name, args, context=None):
""" Returns the partner that is considered the commercial
entity of this partner. The commercial entity holds the master data
for all commercial fields (see :py:meth:`~_commercial_fields`) """
result = dict.fromkeys(ids, False)
for partner in self.browse(cr, uid, ids, context=context):
current_partner = partner
while not current_partner.is_company and current_partner.parent_id:
current_partner = current_partner.parent_id
result[partner.id] = current_partner.id
return result
def _display_name_compute(self, cr, uid, ids, name, args, context=None):
return dict(self.name_get(cr, uid, ids, context=context))
# indirections to avoid passing a copy of the overridable method when declaring the function field
_commercial_partner_id = lambda self, *args, **kwargs: self._commercial_partner_compute(*args, **kwargs)
_display_name = lambda self, *args, **kwargs: self._display_name_compute(*args, **kwargs)
_commercial_partner_store_triggers = {
'res.partner': (lambda self,cr,uid,ids,context=None: self.search(cr, uid, [('id','child_of',ids)]),
['parent_id', 'is_company'], 10)
}
_display_name_store_triggers = {
'res.partner': (lambda self,cr,uid,ids,context=None: self.search(cr, uid, [('id','child_of',ids)]),
['parent_id', 'is_company', 'name'], 10)
}
_order = "display_name"
_columns = {
'name': fields.char('Name', size=128, required=True, select=True),
'display_name': fields.function(_display_name, type='char', string='Name', store=_display_name_store_triggers),
'date': fields.date('Date', select=1),
'title': fields.many2one('res.partner.title', 'Title'),
'parent_id': fields.many2one('res.partner', 'Related Company'),
'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts'),
'child_ids': fields.one2many('res.partner', 'parent_id', 'Contacts', domain=[('active','=',True)]), # force "active_test" domain to bypass _search() override
'ref': fields.char('Reference', size=64, select=1),
'lang': fields.selection(_lang_get, 'Language',
help="If the selected language is loaded in the system, all documents related to this contact will be printed in this language. If not, it will be English."),
@ -264,6 +294,9 @@ class res_partner(osv.osv, format_address):
'color': fields.integer('Color Index'),
'user_ids': fields.one2many('res.users', 'partner_id', 'Users'),
'contact_address': fields.function(_address_display, type='char', string='Complete Address'),
# technical field used for managing commercial fields
'commercial_partner_id': fields.function(_commercial_partner_id, type='many2one', relation='res.partner', string='Commercial Entity', store=_commercial_partner_store_triggers)
}
def _default_category(self, cr, uid, context=None):
@ -302,11 +335,15 @@ class res_partner(osv.osv, format_address):
'company_id': lambda self, cr, uid, ctx: self.pool['res.company']._company_default_get(cr, uid, 'res.partner', context=ctx),
'color': 0,
'is_company': False,
'type': 'default',
'use_parent_address': True,
'type': 'contact', # type 'default' is wildcard and thus inappropriate
'use_parent_address': False,
'image': False,
}
_constraints = [
(osv.osv._check_recursion, 'You cannot create recursive Partner hierarchies.', ['parent_id']),
]
def copy(self, cr, uid, id, default=None, context=None):
if default is None:
default = {}
@ -318,7 +355,6 @@ class res_partner(osv.osv, format_address):
value = {}
value['title'] = False
if is_company:
value['parent_id'] = False
domain = {'title': [('domain', '=', 'partner')]}
else:
domain = {'title': [('domain', '=', 'contact')]}
@ -328,11 +364,22 @@ class res_partner(osv.osv, format_address):
def value_or_id(val):
""" return val or val.id if val is a browse record """
return val if isinstance(val, (bool, int, long, float, basestring)) else val.id
if use_parent_address and parent_id:
result = {}
if parent_id:
if ids:
partner = self.browse(cr, uid, ids[0], context=context)
if partner.parent_id and partner.parent_id.id != parent_id:
result['warning'] = {'title': _('Warning'),
'message': _('Changing the company of a contact should only be done if it '
'was never correctly set. If an existing contact starts working for a new '
'company then a new contact should be created under that new '
'company. You can use the "Discard" button to abandon this change.')}
parent = self.browse(cr, uid, parent_id, context=context)
return {'value': dict((key, value_or_id(parent[key])) for key in ADDRESS_FIELDS)}
return {}
address_fields = self._address_fields(cr, uid, context=context)
result['value'] = dict((key, value_or_id(parent[key])) for key in address_fields)
else:
result['value'] = {'use_parent_address': False}
return result
def onchange_state(self, cr, uid, ids, state_id, context=None):
if state_id:
@ -358,50 +405,134 @@ class res_partner(osv.osv, format_address):
# _constraints = [(_check_ean_key, 'Error: Invalid ean code', ['ean13'])]
def write(self, cr, uid, ids, vals, context=None):
# Update parent and siblings or children records
if isinstance(ids, (int, long)):
ids = [ids]
for partner in self.browse(cr, uid, ids, context=context):
update_ids = []
if partner.is_company:
domain_children = [('parent_id', 'child_of', partner.id), ('use_parent_address', '=', True)]
update_ids = self.search(cr, uid, domain_children, context=context)
elif partner.parent_id and vals.get('use_parent_address', partner.use_parent_address):
domain_siblings = [('parent_id', '=', partner.parent_id.id), ('use_parent_address', '=', True)]
update_ids = [partner.parent_id.id] + self.search(cr, uid, domain_siblings, context=context)
self.update_address(cr, uid, update_ids, vals, context)
return super(res_partner,self).write(cr, uid, ids, vals, context=context)
def create(self, cr, uid, vals, context=None):
if context is None:
context = {}
# Update parent and siblings records
if vals.get('parent_id'):
if 'use_parent_address' in vals:
use_parent_address = vals['use_parent_address']
def _update_fields_values(self, cr, uid, partner, fields, context=None):
""" Returns dict of write() values for synchronizing ``fields`` """
values = {}
for field in fields:
column = self._all_columns[field].column
if column._type == 'one2many':
raise AssertionError('One2Many fields cannot be synchronized as part of `commercial_fields` or `address fields`')
if column._type == 'many2one':
values[field] = partner[field].id if partner[field] else False
elif column._type == 'many2many':
values[field] = [(6,0,[r.id for r in partner[field] or []])]
else:
use_parent_address = self.default_get(cr, uid, ['use_parent_address'], context=context)['use_parent_address']
values[field] = partner[field]
return values
if use_parent_address:
domain_siblings = [('parent_id', '=', vals['parent_id']), ('use_parent_address', '=', True)]
update_ids = [vals['parent_id']] + self.search(cr, uid, domain_siblings, context=context)
self.update_address(cr, uid, update_ids, vals, context)
# add missing address keys
onchange_values = self.onchange_address(cr, uid, [], use_parent_address,
vals['parent_id'], context=context).get('value') or {}
vals.update(dict((key, value)
for key, value in onchange_values.iteritems()
if key in ADDRESS_FIELDS and key not in vals))
return super(res_partner, self).create(cr, uid, vals, context=context)
def _address_fields(self, cr, uid, context=None):
""" Returns the list of address fields that are synced from the parent
when the `use_parent_address` flag is set. """
return list(ADDRESS_FIELDS)
def update_address(self, cr, uid, ids, vals, context=None):
addr_vals = dict((key, vals[key]) for key in POSTAL_ADDRESS_FIELDS if key in vals)
address_fields = self._address_fields(cr, uid, context=context)
addr_vals = dict((key, vals[key]) for key in address_fields if key in vals)
if addr_vals:
return super(res_partner, self).write(cr, uid, ids, addr_vals, context)
def _commercial_fields(self, cr, uid, context=None):
""" Returns the list of fields that are managed by the commercial entity
to which a partner belongs. These fields are meant to be hidden on
partners that aren't `commercial entities` themselves, and will be
delegated to the parent `commercial entity`. The list is meant to be
extended by inheriting classes. """
return ['vat']
def _commercial_sync_from_company(self, cr, uid, partner, context=None):
""" Handle sync of commercial fields when a new parent commercial entity is set,
as if they were related fields """
if partner.commercial_partner_id != partner:
commercial_fields = self._commercial_fields(cr, uid, context=context)
sync_vals = self._update_fields_values(cr, uid, partner.commercial_partner_id,
commercial_fields, context=context)
partner.write(sync_vals)
def _commercial_sync_to_children(self, cr, uid, partner, context=None):
""" Handle sync of commercial fields to descendants """
commercial_fields = self._commercial_fields(cr, uid, context=context)
sync_vals = self._update_fields_values(cr, uid, partner.commercial_partner_id,
commercial_fields, context=context)
sync_children = [c for c in partner.child_ids if not c.is_company]
for child in sync_children:
self._commercial_sync_to_children(cr, uid, child, context=context)
return self.write(cr, uid, [c.id for c in sync_children], sync_vals, context=context)
def _fields_sync(self, cr, uid, partner, update_values, context=None):
""" Sync commercial fields and address fields from company and to children after create/update,
just as if those were all modeled as fields.related to the parent """
# 1. From UPSTREAM: sync from parent
if update_values.get('parent_id') or update_values.get('use_parent_address'):
# 1a. Commercial fields: sync if parent changed
if update_values.get('parent_id'):
self._commercial_sync_from_company(cr, uid, partner, context=context)
# 1b. Address fields: sync if parent or use_parent changed *and* both are now set
if partner.parent_id and partner.use_parent_address:
onchange_vals = self.onchange_address(cr, uid, [partner.id],
use_parent_address=partner.use_parent_address,
parent_id=partner.parent_id.id,
context=context).get('value', {})
partner.update_address(onchange_vals)
# 2. To DOWNSTREAM: sync children
if partner.child_ids:
# 2a. Commercial Fields: sync if commercial entity
if partner.commercial_partner_id == partner:
self._commercial_sync_to_children(cr, uid, partner, context=context)
# 2b. Address fields: sync if address changed
address_fields = self._address_fields(cr, uid, context=context)
if any(field in update_values for field in address_fields):
domain_children = [('parent_id', '=', partner.id), ('use_parent_address', '=', True)]
update_ids = self.search(cr, uid, domain_children, context=context)
self.update_address(cr, uid, update_ids, update_values, context=context)
def _handle_first_contact_creation(self, cr, uid, partner, context=None):
""" On creation of first contact for a company (or root) that has no address, assume contact address
was meant to be company address """
parent = partner.parent_id
address_fields = self._address_fields(cr, uid, context=context)
if parent and (parent.is_company or not parent.parent_id) and len(parent.child_ids) == 1 and \
any(partner[f] for f in address_fields) and not any(parent[f] for f in address_fields):
addr_vals = self._update_fields_values(cr, uid, partner, address_fields, context=context)
parent.update_address(addr_vals)
if not parent.is_company:
parent.write({'is_company': True})
def write(self, cr, uid, ids, vals, context=None):
if isinstance(ids, (int, long)):
ids = [ids]
result = super(res_partner,self).write(cr, uid, ids, vals, context=context)
for partner in self.browse(cr, uid, ids, context=context):
self._fields_sync(cr, uid, partner, vals, context)
return result
def create(self, cr, uid, vals, context=None):
new_id = super(res_partner, self).create(cr, uid, vals, context=context)
partner = self.browse(cr, uid, new_id, context=context)
self._fields_sync(cr, uid, partner, vals, context)
self._handle_first_contact_creation(cr, uid, partner, context)
return new_id
def open_commercial_entity(self, cr, uid, ids, context=None):
""" Utility method used to add an "Open Company" button in partner views """
partner = self.browse(cr, uid, ids[0], context=context)
return {'type': 'ir.actions.act_window',
'res_model': 'res.partner',
'view_mode': 'form',
'res_id': partner.commercial_partner_id.id,
'target': 'new',
'flags': {'form': {'action_buttons': True}}}
def open_parent(self, cr, uid, ids, context=None):
""" Utility method used to add an "Open Parent" button in partner views """
partner = self.browse(cr, uid, ids[0], context=context)
return {'type': 'ir.actions.act_window',
'res_model': 'res.partner',
'view_mode': 'form',
'res_id': partner.parent_id.id,
'target': 'new',
'flags': {'form': {'action_buttons': True}}}
def name_get(self, cr, uid, ids, context=None):
if context is None:
context = {}
@ -410,8 +541,8 @@ class res_partner(osv.osv, format_address):
res = []
for record in self.browse(cr, uid, ids, context=context):
name = record.name
if record.parent_id:
name = "%s (%s)" % (name, record.parent_id.name)
if record.parent_id and not record.is_company:
name = "%s, %s" % (record.parent_id.name, name)
if context.get('show_address'):
name = name + "\n" + self._display_address(cr, uid, record, without_company=True, context=context)
name = name.replace('\n\n','\n')
@ -450,6 +581,15 @@ class res_partner(osv.osv, format_address):
rec_id = self.create(cr, uid, {self._rec_name: name or email, 'email': email or False}, context=context)
return self.name_get(cr, uid, [rec_id], context)[0]
def _search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None):
""" Override search() to always show inactive children when searching via ``child_of`` operator. The ORM will
always call search() with a simple domain of the form [('parent_id', 'in', [ids])]. """
# a special ``domain`` is set on the ``child_ids`` o2m to bypass this logic, as it uses similar domain expressions
if len(args) == 1 and len(args[0]) == 3 and args[0][:2] == ('parent_id','in'):
context = dict(context or {}, active_test=False)
return super(res_partner, self)._search(cr, user, args, offset=offset, limit=limit, order=order, context=context,
count=count, access_rights_uid=access_rights_uid)
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100):
if not args:
args = []
@ -510,25 +650,42 @@ class res_partner(osv.osv, format_address):
ids = ids[16:]
return True
def address_get(self, cr, uid, ids, adr_pref=None):
if adr_pref is None:
adr_pref = ['default']
def address_get(self, cr, uid, ids, adr_pref=None, context=None):
""" Find contacts/addresses of the right type(s) by doing a depth-first-search
through descendants within company boundaries (stop at entities flagged ``is_company``)
then continuing the search at the ancestors that are within the same company boundaries.
Defaults to partners of type ``'default'`` when the exact type is not found, or to the
provided partner itself if no type ``'default'`` is found either. """
adr_pref = set(adr_pref or [])
if 'default' not in adr_pref:
adr_pref.add('default')
result = {}
# retrieve addresses from the partner itself and its children
res = []
# need to fix the ids ,It get False value in list like ids[False]
if ids and ids[0]!=False:
for p in self.browse(cr, uid, ids):
res.append((p.type, p.id))
res.extend((c.type, c.id) for c in p.child_ids)
address_dict = dict(reversed(res))
# get the id of the (first) default address if there is one,
# otherwise get the id of the first address in the list
default_address = False
if res:
default_address = address_dict.get('default', res[0][1])
for adr in adr_pref:
result[adr] = address_dict.get(adr, default_address)
visited = set()
for partner in self.browse(cr, uid, filter(None, ids), context=context):
current_partner = partner
while current_partner:
to_scan = [current_partner]
# Scan descendants, DFS
while to_scan:
record = to_scan.pop(0)
visited.add(record)
if record.type in adr_pref and not result.get(record.type):
result[record.type] = record.id
if len(result) == len(adr_pref):
return result
to_scan = [c for c in record.child_ids
if c not in visited
if not c.is_company] + to_scan
# Continue scanning at ancestor if current_partner is not a commercial entity
if current_partner.is_company or not current_partner.parent_id:
break
current_partner = current_partner.parent_id
# default to type 'default' or the partner itself
default = result.get('default', partner.id)
for adr_type in adr_pref:
result[adr_type] = result.get(adr_type) or default
return result
def view_header_get(self, cr, uid, view_id, view_type, context):
@ -570,8 +727,7 @@ class res_partner(osv.osv, format_address):
'country_name': address.country_id and address.country_id.name or '',
'company_name': address.parent_id and address.parent_id.name or '',
}
address_field = ['title', 'street', 'street2', 'zip', 'city']
for field in address_field :
for field in self._address_fields(cr, uid, context=context):
args[field] = getattr(address, field) or ''
if without_company:
args['company_name'] = ''

View File

@ -77,7 +77,7 @@
<field eval="8" name="priority"/>
<field name="arch" type="xml">
<tree string="Contacts">
<field name="name"/>
<field name="display_name"/>
<field name="function" invisible="1"/>
<field name="phone"/>
<field name="email"/>
@ -138,8 +138,8 @@
</h1>
<field name="parent_id"
placeholder="Company"
domain="[('is_company', '=', True)]" context="{'default_is_company': True}"
attrs="{'invisible': [('is_company','=', True)]}"
domain="[('is_company', '=', True)]" context="{'default_is_company': True, 'default_supplier': supplier}"
attrs="{'invisible': [('is_company','=', True),('parent_id', '=', False)]}"
on_change="onchange_address(use_parent_address, parent_id)"/>
<field name="category_id" widget="many2many_tags" placeholder="Tags..."/>
</div>
@ -151,21 +151,24 @@
<div attrs="{'invisible': [('parent_id','=', False)]}" name="div_type">
<field class="oe_inline"
name="type"/>
<label for="use_parent_address" class="oe_edit_only"/>
<field name="use_parent_address" class="oe_edit_only oe_inline"
on_change="onchange_address(use_parent_address, parent_id)"/>
</div>
<label for="street" string="Address"/>
<div>
<field name="street" placeholder="Street..."/>
<field name="street2"/>
<field name="use_parent_address" class="oe_edit_only oe_inline"
on_change="onchange_address(use_parent_address, parent_id)"
attrs="{'invisible': [('parent_id','=', False),('use_parent_address','=',False)]}"/>
<label for="use_parent_address" class="oe_edit_only" attrs="{'invisible': [('parent_id','=', False),('use_parent_address','=',False)]}"/>
<button name="open_parent" type="object" string="(edit company address)" class="oe_link oe_edit_only"
attrs="{'invisible': ['|',('parent_id','=', False),('use_parent_address','=',False)]}"/>
<field name="street" placeholder="Street..." attrs="{'readonly': [('use_parent_address','=',True)]}"/>
<field name="street2" attrs="{'readonly': [('use_parent_address','=',True)]}"/>
<div class="address_format">
<field name="city" placeholder="City" style="width: 40%%"/>
<field name="state_id" class="oe_no_button" placeholder="State" style="width: 37%%" options='{"no_open": True}' on_change="onchange_state(state_id)"/>
<field name="zip" placeholder="ZIP" style="width: 20%%"/>
<field name="city" placeholder="City" style="width: 40%%" attrs="{'readonly': [('use_parent_address','=',True)]}"/>
<field name="state_id" class="oe_no_button" placeholder="State" style="width: 37%%" options='{"no_open": True}' on_change="onchange_state(state_id)" attrs="{'readonly': [('use_parent_address','=',True)]}"/>
<field name="zip" placeholder="ZIP" style="width: 20%%" attrs="{'readonly': [('use_parent_address','=',True)]}"/>
</div>
<field name="country_id" placeholder="Country" class="oe_no_button" options='{"no_open": True}'/>
<field name="country_id" placeholder="Country" class="oe_no_button" options='{"no_open": True}' attrs="{'readonly': [('use_parent_address','=',True)]}"/>
</div>
<field name="website" widget="url" placeholder="e.g. www.openerp.com"/>
</group>
@ -182,8 +185,8 @@
</group>
<notebook colspan="4">
<page string="Contacts" attrs="{'invisible': [('is_company','=',False)]}">
<field name="child_ids" context="{'default_parent_id': active_id}" mode="kanban">
<page string="Contacts" attrs="{'invisible': [('is_company','=',False), ('child_ids', '=', [])]}" autofocus="autofocus">
<field name="child_ids" mode="kanban" context="{'default_parent_id': active_id, 'default_street': street, 'default_street2': street2, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_supplier': supplier}">
<kanban>
<field name="color"/>
<field name="name"/>
@ -249,17 +252,41 @@
</templates>
</kanban>
<form string="Contact" version="7.0">
<field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_medium"}'/>
<div class="oe_title">
<sheet>
<field name="image" widget='image' class="oe_avatar oe_left" options='{"preview_image": "image_medium"}'/>
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<h1><field name="name" style="width: 70%%"/></h1>
<field name="category_id" widget="many2many_tags" placeholder="Tags..." style="width: 70%%"/>
</div>
<group>
<field name="name"/>
<field name="category_id" widget="many2many_tags" placeholder="Tags..."/>
<field name="function" placeholder="e.g. Sales Director"/>
<field name="email"/>
<field name="phone"/>
<field name="mobile"/>
</group>
</div>
<div>
<field name="use_parent_address"/><label for="use_parent_address"/>
</div>
<group>
<label for="type"/>
<div name="div_type">
<field class="oe_inline" name="type"/>
</div>
<label for="street" string="Address" attrs="{'invisible': [('use_parent_address','=', True)]}"/>
<div attrs="{'invisible': [('use_parent_address','=', True)]}" name="div_address">
<field name="street" placeholder="Street..."/>
<field name="street2"/>
<div class="address_format">
<field name="city" placeholder="City" style="width: 40%%"/>
<field name="state_id" class="oe_no_button" placeholder="State" style="width: 37%%" options='{"no_open": True}' on_change="onchange_state(state_id)"/>
<field name="zip" placeholder="ZIP" style="width: 20%%"/>
</div>
<field name="country_id" placeholder="Country" class="oe_no_button" options='{"no_open": True}'/>
</div>
</group>
<field name="supplier" invisible="True"/>
</sheet>
</form>
</field>
</page>
@ -330,7 +357,7 @@
<field name="arch" type="xml">
<kanban>
<field name="color"/>
<field name="name"/>
<field name="display_name"/>
<field name="title"/>
<field name="email"/>
<field name="parent_id"/>
@ -363,7 +390,7 @@
</t>
</a>
<div class="oe_kanban_details">
<h4 class="oe_partner_heading"><a type="open"><field name="name"/></a></h4>
<h4 class="oe_partner_heading"><a type="open"><field name="display_name"/></a></h4>
<div class="oe_kanban_partner_categories"/>
<div class="oe_kanban_partner_links"/>
<ul>

View File

@ -44,7 +44,7 @@ openerp.base = function(instance) {
} else {
sessionStorage.removeItem('apps.login');
sessionStorage.removeItem('apps.access_token');
client.bind_crendentials(client.dbname, 'anonymous', 'anonymous');
client.bind_credentials(client.dbname, 'anonymous', 'anonymous');
client.authenticate().then(
function() { /* done */
d.resolve(client);

View File

@ -1,6 +1,7 @@
import unittest2
import openerp.tests.common as common
from openerp.osv.orm import except_orm
class test_base(common.TransactionCase):
@ -39,5 +40,269 @@ class test_base(common.TransactionCase):
self.assertTrue(new_id2 > new_id, 'find_or_create failed - should have created new one again')
def test_20_res_partner_address_sync(self):
cr, uid = self.cr, self.uid
ghoststep = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
{'name': 'GhostStep',
'is_company': True,
'street': 'Main Street, 10',
'phone': '123456789',
'email': 'info@ghoststep.com',
'vat': 'BE0477472701',
'type': 'default'}))
p1 = self.res_partner.browse(cr, uid, self.res_partner.name_create(cr, uid, 'Denis Bladesmith <denis.bladesmith@ghoststep.com>')[0])
self.assertEqual(p1.type, 'contact', 'Default type must be "contact"')
p1phone = '123456789#34'
p1.write({'phone': p1phone,
'parent_id': ghoststep.id,
'use_parent_address': True})
p1.refresh()
self.assertEqual(p1.street, ghoststep.street, 'Address fields must be synced')
self.assertEqual(p1.phone, p1phone, 'Phone should be preserved after address sync')
self.assertEqual(p1.type, 'contact', 'Type should be preserved after address sync')
self.assertEqual(p1.email, 'denis.bladesmith@ghoststep.com', 'Email should be preserved after sync')
# turn off sync
p1street = 'Different street, 42'
p1.write({'street': p1street,
'use_parent_address': False})
p1.refresh(), ghoststep.refresh()
self.assertEqual(p1.street, p1street, 'Address fields must not be synced after turning sync off')
self.assertNotEqual(ghoststep.street, p1street, 'Parent address must never be touched')
# turn on sync again
p1.write({'use_parent_address': True})
p1.refresh()
self.assertEqual(p1.street, ghoststep.street, 'Address fields must be synced again')
self.assertEqual(p1.phone, p1phone, 'Phone should be preserved after address sync')
self.assertEqual(p1.type, 'contact', 'Type should be preserved after address sync')
self.assertEqual(p1.email, 'denis.bladesmith@ghoststep.com', 'Email should be preserved after sync')
# Modify parent, sync to children
ghoststreet = 'South Street, 25'
ghoststep.write({'street': ghoststreet})
p1.refresh()
self.assertEqual(p1.street, ghoststreet, 'Address fields must be synced automatically')
self.assertEqual(p1.phone, p1phone, 'Phone should not be synced')
self.assertEqual(p1.email, 'denis.bladesmith@ghoststep.com', 'Email should be preserved after sync')
p1street = 'My Street, 11'
p1.write({'street': p1street})
ghoststep.refresh()
self.assertEqual(ghoststep.street, ghoststreet, 'Touching contact should never alter parent')
def test_30_res_partner_first_contact_sync(self):
""" Test initial creation of company/contact pair where contact address gets copied to
company """
cr, uid = self.cr, self.uid
ironshield = self.res_partner.browse(cr, uid, self.res_partner.name_create(cr, uid, 'IronShield')[0])
self.assertFalse(ironshield.is_company, 'Partners are not companies by default')
self.assertFalse(ironshield.use_parent_address, 'use_parent_address defaults to False')
self.assertEqual(ironshield.type, 'contact', 'Default type must be "contact"')
ironshield.write({'type': 'default'}) # force default type to double-check sync
p1 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
{'name': 'Isen Hardearth',
'street': 'Strongarm Avenue, 12',
'parent_id': ironshield.id}))
self.assertEquals(p1.type, 'contact', 'Default type must be "contact", not the copied parent type')
ironshield.refresh()
self.assertEqual(ironshield.street, p1.street, 'Address fields should be copied to company')
self.assertTrue(ironshield.is_company, 'Company flag should be turned on after first contact creation')
def test_40_res_partner_address_getc(self):
""" Test address_get address resolution mechanism: it should first go down through descendants,
stopping when encountering another is_copmany entity, then go up, stopping again at the first
is_company entity or the root ancestor and if nothing matches, it should use the provided partner
itself """
cr, uid = self.cr, self.uid
elmtree = self.res_partner.browse(cr, uid, self.res_partner.name_create(cr, uid, 'Elmtree')[0])
branch1 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Branch 1',
'parent_id': elmtree.id,
'is_company': True}))
leaf10 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 10',
'parent_id': branch1.id,
'type': 'invoice'}))
branch11 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Branch 11',
'parent_id': branch1.id,
'type': 'other'}))
leaf111 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 111',
'parent_id': branch11.id,
'type': 'delivery'}))
branch11.write({'is_company': False}) # force is_company after creating 1rst child
branch2 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Branch 2',
'parent_id': elmtree.id,
'is_company': True}))
leaf21 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 21',
'parent_id': branch2.id,
'type': 'delivery'}))
leaf22 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 22',
'parent_id': branch2.id}))
leaf23 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid, {'name': 'Leaf 23',
'parent_id': branch2.id,
'type': 'default'}))
# go up, stop at branch1
self.assertEqual(self.res_partner.address_get(cr, uid, [leaf111.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf111.id,
'invoice': leaf10.id,
'contact': branch1.id,
'other': branch11.id,
'default': leaf111.id}, 'Invalid address resolution')
self.assertEqual(self.res_partner.address_get(cr, uid, [branch11.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf111.id,
'invoice': leaf10.id,
'contact': branch1.id,
'other': branch11.id,
'default': branch11.id}, 'Invalid address resolution')
# go down, stop at at all child companies
self.assertEqual(self.res_partner.address_get(cr, uid, [elmtree.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': elmtree.id,
'invoice': elmtree.id,
'contact': elmtree.id,
'other': elmtree.id,
'default': elmtree.id}, 'Invalid address resolution')
# go down through children
self.assertEqual(self.res_partner.address_get(cr, uid, [branch1.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf111.id,
'invoice': leaf10.id,
'contact': branch1.id,
'other': branch11.id,
'default': branch1.id}, 'Invalid address resolution')
self.assertEqual(self.res_partner.address_get(cr, uid, [branch2.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf21.id,
'invoice': leaf23.id,
'contact': branch2.id,
'other': leaf23.id,
'default': leaf23.id}, 'Invalid address resolution')
# go up then down through siblings
self.assertEqual(self.res_partner.address_get(cr, uid, [leaf21.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf21.id,
'invoice': leaf23.id,
'contact': branch2.id,
'other': leaf23.id,
'default': leaf23.id
}, 'Invalid address resolution, should scan commercial entity ancestor and its descendants')
self.assertEqual(self.res_partner.address_get(cr, uid, [leaf22.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf21.id,
'invoice': leaf23.id,
'contact': leaf22.id,
'other': leaf23.id,
'default': leaf23.id}, 'Invalid address resolution, should scan commercial entity ancestor and its descendants')
self.assertEqual(self.res_partner.address_get(cr, uid, [leaf23.id], ['delivery', 'invoice', 'contact', 'other', 'default']),
{'delivery': leaf21.id,
'invoice': leaf23.id,
'contact': branch2.id,
'other': leaf23.id,
'default': leaf23.id}, 'Invalid address resolution, `default` should only override if no partner with specific type exists')
# empty adr_pref means only 'default'
self.assertEqual(self.res_partner.address_get(cr, uid, [elmtree.id], []),
{'default': elmtree.id}, 'Invalid address resolution, no default means commercial entity ancestor')
self.assertEqual(self.res_partner.address_get(cr, uid, [leaf111.id], []),
{'default': leaf111.id}, 'Invalid address resolution, no default means contact itself')
branch11.write({'type': 'default'})
self.assertEqual(self.res_partner.address_get(cr, uid, [leaf111.id], []),
{'default': branch11.id}, 'Invalid address resolution, branch11 should now be default')
def test_50_res_partner_commercial_sync(self):
cr, uid = self.cr, self.uid
p0 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
{'name': 'Sigurd Sunknife',
'email': 'ssunknife@gmail.com'}))
sunhelm = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
{'name': 'Sunhelm',
'is_company': True,
'street': 'Rainbow Street, 13',
'phone': '1122334455',
'email': 'info@sunhelm.com',
'vat': 'BE0477472701',
'child_ids': [(4, p0.id),
(0, 0, {'name': 'Alrik Greenthorn',
'email': 'agr@sunhelm.com'})],
}))
p1 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
{'name': 'Otto Blackwood',
'email': 'otto.blackwood@sunhelm.com',
'parent_id': sunhelm.id}))
p11 = self.res_partner.browse(cr, uid, self.res_partner.create(cr, uid,
{'name': 'Gini Graywool',
'email': 'ggr@sunhelm.com',
'parent_id': p1.id}))
p2 = self.res_partner.browse(cr, uid, self.res_partner.search(cr, uid,
[('email', '=', 'agr@sunhelm.com')])[0])
for p in (p0, p1, p11, p2):
p.refresh()
self.assertEquals(p.commercial_partner_id, sunhelm, 'Incorrect commercial entity resolution')
self.assertEquals(p.vat, sunhelm.vat, 'Commercial fields must be automatically synced')
sunhelmvat = 'BE0123456789'
sunhelm.write({'vat': sunhelmvat})
for p in (p0, p1, p11, p2):
p.refresh()
self.assertEquals(p.vat, sunhelmvat, 'Commercial fields must be automatically and recursively synced')
p1vat = 'BE0987654321'
p1.write({'vat': p1vat})
for p in (sunhelm, p0, p11, p2):
p.refresh()
self.assertEquals(p.vat, sunhelmvat, 'Sync to children should only work downstream and on commercial entities')
# promote p1 to commercial entity
vals = p1.onchange_type(is_company=True)['value']
p1.write(dict(vals, parent_id=sunhelm.id,
is_company=True,
name='Sunhelm Subsidiary'))
p1.refresh()
self.assertEquals(p1.vat, p1vat, 'Setting is_company should stop auto-sync of commercial fields')
self.assertEquals(p1.commercial_partner_id, p1, 'Incorrect commercial entity resolution after setting is_company')
# writing on parent should not touch child commercial entities
sunhelmvat2 = 'BE0112233445'
sunhelm.write({'vat': sunhelmvat2})
p1.refresh()
self.assertEquals(p1.vat, p1vat, 'Setting is_company should stop auto-sync of commercial fields')
p0.refresh()
self.assertEquals(p0.vat, sunhelmvat2, 'Commercial fields must be automatically synced')
class test_partner_recursion(common.TransactionCase):
def setUp(self):
super(test_partner_recursion,self).setUp()
self.res_partner = self.registry('res.partner')
cr, uid = self.cr, self.uid
self.p1 = self.res_partner.name_create(cr, uid, 'Elmtree')[0]
self.p2 = self.res_partner.create(cr, uid, {'name': 'Elmtree Child 1', 'parent_id': self.p1})
self.p3 = self.res_partner.create(cr, uid, {'name': 'Elmtree Grand-Child 1.1', 'parent_id': self.p2})
# split 101, 102, 103 tests to force SQL rollback between them
def test_101_res_partner_recursion(self):
cr, uid, p1, p3 = self.cr, self.uid, self.p1, self.p3
self.assertRaises(except_orm, self.res_partner.write, cr, uid, [p1], {'parent_id': p3})
def test_102_res_partner_recursion(self):
cr, uid, p2, p3 = self.cr, self.uid, self.p2, self.p3
self.assertRaises(except_orm, self.res_partner.write, cr, uid, [p2], {'parent_id': p3})
def test_103_res_partner_recursion(self):
cr, uid, p3 = self.cr, self.uid, self.p3
self.assertRaises(except_orm, self.res_partner.write, cr, uid, [p3], {'parent_id': p3})
def test_104_res_partner_recursion_indirect_cycle(self):
""" Indirect hacky write to create cycle in children """
cr, uid, p2, p3 = self.cr, self.uid, self.p2, self.p3
p3b = self.res_partner.create(cr, uid, {'name': 'Elmtree Grand-Child 1.2', 'parent_id': self.p2})
self.assertRaises(except_orm, self.res_partner.write, cr, uid, [p2],
{'child_ids': [(1, p3, {'parent_id': p3b}), (1, p3b, {'parent_id': p3})]})
def test_110_res_partner_recursion_multi_update(self):
""" multi-write on several partners in same hierarchy must not trigger a false cycle detection """
cr, uid, p1, p2, p3 = self.cr, self.uid, self.p1, self.p2, self.p3
self.assertTrue(self.res_partner.write(cr, uid, [p1,p2,p3], {'phone': '123456'}))
if __name__ == '__main__':
unittest2.main()

View File

@ -263,7 +263,7 @@ class test_expression(common.TransactionCase):
"_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition")
self.assertIn('"res_partner__child_ids"."id"="res_partner__child_ids__bank_ids"."partner_id"', sql_query[1],
"_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect join condition")
self.assertEqual(set([b_aa, b_ba]), set(sql_query[2]),
self.assertEqual(set([b_aa, b_ba]), set(sql_query[2][-2:]),
"_auto_join on: ('child_ids.bank_ids.id', 'in', [..]) query incorrect parameter")
# --------------------------------------------------

View File

@ -42,7 +42,7 @@ class test_res_config(common.TransactionCase):
self.assertIsInstance(res, tuple)
self.assertEqual(len(res), 2, "The result should contain 2 elements")
self.assertIsInstance(res[0], basestring)
self.assertIsInstance(res[1], long)
self.assertIsInstance(res[1], (int, long))
# Check returned values
self.assertEqual(res[0], self.expected_path)

View File

@ -98,6 +98,8 @@ def preload_registry(dbname):
openerp.modules.registry.RegistryManager.new(dbname, update_module=update_module)
except Exception:
_logger.exception('Failed to initialize database `%s`.', dbname)
return False
return True
def run_test_file(dbname, test_file):
""" Preload a registry, possibly run a test file, and start the cron."""
@ -261,12 +263,14 @@ def main(args):
else:
openerp.service.start_services()
rc = 0
if config['db_name']:
for dbname in config['db_name'].split(','):
preload_registry(dbname)
if not preload_registry(dbname):
rc += 1
if config["stop_after_init"]:
sys.exit(0)
sys.exit(rc)
_logger.info('OpenERP server is running, waiting for connections...')
quit_on_signals()

View File

@ -96,10 +96,7 @@ def load_module_graph(cr, graph, status=None, perform_checks=True, skip_modules=
"""
for filename in package.data[kind]:
if kind == 'test':
_test_logger.info("module %s: loading %s", module_name, filename)
else:
_logger.info("module %s: loading %s", module_name, filename)
_logger.info("module %s: loading %s", module_name, filename)
_, ext = os.path.splitext(filename)
pathname = os.path.join(module_name, filename)
fp = tools.file_open(pathname)
@ -349,8 +346,7 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
if processed_modules:
cr.execute("""select model,name from ir_model where id NOT IN (select distinct model_id from ir_model_access)""")
for (model, name) in cr.fetchall():
model_obj = registry.get(model)
if model_obj and not model_obj.is_transient():
if model in registry and not registry[model].is_transient():
_logger.warning('The model %s has no access rules, consider adding one. E.g. access_%s,access_%s,model_%s,,1,1,1,1',
model, model.replace('.', '_'), model.replace('.', '_'), model.replace('.', '_'))
@ -358,15 +354,13 @@ def load_modules(db, force_demo=False, status=None, update_module=False):
# been replaced by owner-only access rights
cr.execute("""select distinct mod.model, mod.name from ir_model_access acc, ir_model mod where acc.model_id = mod.id""")
for (model, name) in cr.fetchall():
model_obj = registry.get(model)
if model_obj and model_obj.is_transient():
if model in registry and registry[model].is_transient():
_logger.warning('The transient model %s (%s) should not have explicit access rules!', model, name)
cr.execute("SELECT model from ir_model")
for (model,) in cr.fetchall():
obj = registry.get(model)
if obj:
obj._check_removed_columns(cr, log=True)
if model in registry:
registry[model]._check_removed_columns(cr, log=True)
else:
_logger.warning("Model %s is declared but cannot be loaded! (Perhaps a module was partially removed or renamed)", model)

View File

@ -3,7 +3,7 @@
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
# Copyright (C) 2010-2011 OpenERP s.a. (<http://openerp.com>).
# Copyright (C) 2010-2013 OpenERP s.a. (<http://openerp.com>).
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
@ -22,31 +22,15 @@
""" Modules migration handling. """
import os, sys, imp
import imp
import logging
import os
from os.path import join as opj
import itertools
import zipimport
import openerp
import openerp.osv as osv
import openerp.tools as tools
import openerp.tools.osutil as osutil
from openerp.tools.safe_eval import safe_eval as eval
from openerp.tools.translate import _
import zipfile
import openerp.release as release
import openerp.tools as tools
import re
import base64
from zipfile import PyZipFile, ZIP_DEFLATED
from cStringIO import StringIO
import logging
import openerp.modules.db
import openerp.modules.graph
_logger = logging.getLogger(__name__)
@ -100,9 +84,10 @@ class MigrationManager(object):
def migrate_module(self, pkg, stage):
assert stage in ('pre', 'post')
stageformat = {'pre': '[>%s]',
'post': '[%s>]',
}
stageformat = {
'pre': '[>%s]',
'post': '[%s>]',
}
if not (hasattr(pkg, 'update') or pkg.state == 'to upgrade'):
return
@ -129,9 +114,10 @@ class MigrationManager(object):
m = self.migrations[pkg.name]
lst = []
mapping = {'module': opj(pkg.name, 'migrations'),
'maintenance': opj('base', 'maintenance', 'migrations', pkg.name),
}
mapping = {
'module': opj(pkg.name, 'migrations'),
'maintenance': opj('base', 'maintenance', 'migrations', pkg.name),
}
for x in mapping.keys():
if version in m[x]:
@ -180,14 +166,14 @@ class MigrationManager(object):
try:
mod = imp.load_source(name, pyfile, fp2)
_logger.info('module %(addon)s: Running migration %(version)s %(name)s' % mergedict({'name': mod.__name__}, strfmt))
mod.migrate(self.cr, pkg.installed_version)
migrate = mod.migrate
except ImportError:
_logger.error('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % mergedict({'file': pyfile}, strfmt))
_logger.exception('module %(addon)s: Unable to load %(stage)s-migration file %(file)s' % mergedict({'file': pyfile}, strfmt))
raise
except AttributeError:
_logger.error('module %(addon)s: Each %(stage)s-migration file must have a "migrate(cr, installed_version)" function' % strfmt)
except:
raise
else:
migrate(self.cr, pkg.installed_version)
finally:
if fp:
fp.close()

View File

@ -22,6 +22,7 @@
""" Models registries.
"""
from collections import Mapping
from contextlib import contextmanager
import logging
import threading
@ -35,7 +36,7 @@ from openerp.tools import assertion_report
_logger = logging.getLogger(__name__)
class Registry(object):
class Registry(Mapping):
""" Model registry for a particular database.
The registry is essentially a mapping between model names and model
@ -44,6 +45,7 @@ class Registry(object):
"""
def __init__(self, db_name):
super(Registry, self).__init__()
self.models = {} # model name/model instance mapping
self._sql_error = {}
self._store_function = {}
@ -80,6 +82,26 @@ class Registry(object):
self.has_unaccent = openerp.tools.config['unaccent'] and has_unaccent
cr.close()
#
# Mapping abstract methods implementation
# => mixin provides methods keys, items, values, get, __eq__, and __ne__
#
def __len__(self):
""" Return the size of the registry. """
return len(self.models)
def __iter__(self):
""" Return an iterator over all model names. """
return iter(self.models)
def __contains__(self, model_name):
""" Test whether the model with the given name exists. """
return model_name in self.models
def __getitem__(self, model_name):
""" Return the model with the given name or raise KeyError if it doesn't exist."""
return self.models[model_name]
def do_parent_store(self, cr):
for o in self._init_parent:
self.get(o)._parent_store_compute(cr)
@ -87,20 +109,12 @@ class Registry(object):
def obj_list(self):
""" Return the list of model names in this registry."""
return self.models.keys()
return self.keys()
def add(self, model_name, model):
""" Add or replace a model in the registry."""
self.models[model_name] = model
def get(self, model_name):
""" Return a model for a given name or None if it doesn't exist."""
return self.models.get(model_name)
def __getitem__(self, model_name):
""" Return a model for a given name or raise KeyError if it doesn't exist."""
return self.models[model_name]
def load(self, cr, module):
""" Load a given module in the registry.

View File

@ -757,7 +757,7 @@ class expression(object):
field_path = left.split('.', 1)
field = working_model._columns.get(field_path[0])
if field and field._obj:
relational_model = working_model.pool.get(field._obj)
relational_model = working_model.pool[field._obj]
else:
relational_model = None
@ -786,11 +786,11 @@ class expression(object):
# comments about inherits'd fields
# { 'field_name': ('parent_model', 'm2o_field_to_reach_parent',
# field_column_obj, origina_parent_model), ... }
next_model = working_model.pool.get(working_model._inherit_fields[field_path[0]][0])
next_model = working_model.pool[working_model._inherit_fields[field_path[0]][0]]
leaf.add_join_context(next_model, working_model._inherits[next_model._name], 'id', working_model._inherits[next_model._name])
push(leaf)
elif not field and left == 'id' and operator == 'child_of':
elif left == 'id' and operator == 'child_of':
ids2 = to_ids(right, working_model, context)
dom = child_of_domain(left, ids2, working_model)
for dom_leaf in reversed(dom):

View File

@ -193,7 +193,7 @@ class reference(_column):
result[value['id']] = value[name]
if value[name]:
model, res_id = value[name].split(',')
if not obj.pool.get(model).exists(cr, uid, [int(res_id)], context=context):
if not obj.pool[model].exists(cr, uid, [int(res_id)], context=context):
result[value['id']] = False
return result
@ -203,8 +203,8 @@ class reference(_column):
# reference fields have a 'model,id'-like value, that we need to convert
# to a real name
model_name, res_id = value.split(',')
model = obj.pool.get(model_name)
if model and res_id:
if model_name in obj.pool and res_id:
model = obj.pool[model_name]
return model.name_get(cr, uid, [int(res_id)], context=context)[0][1]
return tools.ustr(value)
@ -456,7 +456,7 @@ class many2one(_column):
res[r['id']] = r[name]
for id in ids:
res.setdefault(id, '')
obj = obj.pool.get(self._obj)
obj = obj.pool[self._obj]
# build a dictionary of the form {'id_of_distant_resource': name_of_distant_resource}
# we use uid=1 because the visibility of a many2one field value (just id and name)
@ -474,8 +474,8 @@ class many2one(_column):
def set(self, cr, obj_src, id, field, values, user=None, context=None):
if not context:
context = {}
obj = obj_src.pool.get(self._obj)
self._table = obj_src.pool.get(self._obj)._table
obj = obj_src.pool[self._obj]
self._table = obj._table
if type(values) == type([]):
for act in values:
if act[0] == 0:
@ -496,7 +496,7 @@ class many2one(_column):
cr.execute('update '+obj_src._table+' set '+field+'=null where id=%s', (id,))
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, context=None):
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', 'like', value)], offset, limit, context=context)
return obj.pool[self._obj].search(cr, uid, args+self._domain+[('name', 'like', value)], offset, limit, context=context)
@classmethod
@ -533,8 +533,9 @@ class one2many(_column):
res[id] = []
domain = self._domain(obj) if callable(self._domain) else self._domain
ids2 = obj.pool.get(self._obj).search(cr, user, domain + [(self._fields_id, 'in', ids)], limit=self._limit, context=context)
for r in obj.pool.get(self._obj)._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
model = obj.pool[self._obj]
ids2 = model.search(cr, user, domain + [(self._fields_id, 'in', ids)], limit=self._limit, context=context)
for r in model._read_flat(cr, user, ids2, [self._fields_id], context=context, load='_classic_write'):
if r[self._fields_id] in res:
res[r[self._fields_id]].append(r['id'])
return res
@ -549,8 +550,8 @@ class one2many(_column):
context['no_store_function'] = True
if not values:
return
_table = obj.pool.get(self._obj)._table
obj = obj.pool.get(self._obj)
obj = obj.pool[self._obj]
_table = obj._table
for act in values:
if act[0] == 0:
act[2][self._fields_id] = id
@ -595,7 +596,7 @@ class one2many(_column):
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None):
domain = self._domain(obj) if callable(self._domain) else self._domain
return obj.pool.get(self._obj).name_search(cr, uid, value, domain, operator, context=context,limit=limit)
return obj.pool[self._obj].name_search(cr, uid, value, domain, operator, context=context,limit=limit)
@classmethod
@ -666,7 +667,7 @@ class many2many(_column):
tbl, col1, col2 = self._rel, self._id1, self._id2
if not all((tbl, col1, col2)):
# the default table name is based on the stable alphabetical order of tables
dest_model = source_model.pool.get(self._obj)
dest_model = source_model.pool[self._obj]
tables = tuple(sorted([source_model._table, dest_model._table]))
if not tbl:
assert tables[0] != tables[1], 'Implicit/Canonical naming of m2m relationship table '\
@ -707,7 +708,7 @@ class many2many(_column):
_logger.warning(
"Specifying offset at a many2many.get() is deprecated and may"
" produce unpredictable results.")
obj = model.pool.get(self._obj)
obj = model.pool[self._obj]
rel, id1, id2 = self._sql_names(model)
# static domains are lists, and are evaluated both here and on client-side, while string
@ -749,7 +750,7 @@ class many2many(_column):
if not values:
return
rel, id1, id2 = self._sql_names(model)
obj = model.pool.get(self._obj)
obj = model.pool[self._obj]
for act in values:
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
continue
@ -785,7 +786,7 @@ class many2many(_column):
# TODO: use a name_search
#
def search(self, cr, obj, args, name, value, offset=0, limit=None, uid=None, operator='like', context=None):
return obj.pool.get(self._obj).search(cr, uid, args+self._domain+[('name', operator, value)], offset, limit, context=context)
return obj.pool[self._obj].search(cr, uid, args+self._domain+[('name', operator, value)], offset, limit, context=context)
@classmethod
def _as_display_name(cls, field, cr, uid, obj, value, context=None):
@ -1107,7 +1108,7 @@ class function(_column):
if field_type == "many2one":
# make the result a tuple if it is not already one
if isinstance(value, (int,long)) and hasattr(obj._columns[field], 'relation'):
obj_model = obj.pool.get(obj._columns[field].relation)
obj_model = obj.pool[obj._columns[field].relation]
dict_names = dict(obj_model.name_get(cr, uid, [value], context))
result = (value, dict_names[value])
@ -1204,7 +1205,7 @@ class related(function):
# Perform name_get as root, as seeing the name of a related object depends on
# access right of source document, not target, so user may not have access.
value_ids = list(set(value.id for value in res.itervalues() if value))
value_name = dict(obj.pool.get(self._obj).name_get(cr, SUPERUSER_ID, value_ids, context=context))
value_name = dict(obj.pool[self._obj].name_get(cr, SUPERUSER_ID, value_ids, context=context))
res = dict((id, value and (value.id, value_name[value.id])) for id, value in res.iteritems())
elif self._type in ('one2many', 'many2many'):
@ -1258,7 +1259,7 @@ class sparse(function):
elif self._type == 'one2many':
if not read_value:
read_value = []
relation_obj = obj.pool.get(self.relation)
relation_obj = obj.pool[self.relation]
for vals in value:
assert vals[0] in (0,1,2), 'Unsupported o2m value for sparse field: %s' % vals
if vals[0] == 0:
@ -1301,10 +1302,10 @@ class sparse(function):
value = value or []
if value:
# filter out deleted records as superuser
relation_obj = obj.pool.get(obj._columns[field_name].relation)
relation_obj = obj.pool[obj._columns[field_name].relation]
value = relation_obj.exists(cr, openerp.SUPERUSER_ID, value)
if type(value) in (int,long) and field_type == 'many2one':
relation_obj = obj.pool.get(obj._columns[field_name].relation)
relation_obj = obj.pool[obj._columns[field_name].relation]
# check for deleted record as superuser
if not relation_obj.exists(cr, openerp.SUPERUSER_ID, [value]):
value = False
@ -1452,7 +1453,7 @@ class property(function):
# not target, so user may not have access) in order to avoid
# pointing on an unexisting record.
if property_destination_obj:
if res[id][prop_name] and obj.pool.get(property_destination_obj).exists(cr, SUPERUSER_ID, res[id][prop_name].id):
if res[id][prop_name] and obj.pool[property_destination_obj].exists(cr, SUPERUSER_ID, res[id][prop_name].id):
name_get_ids[id] = res[id][prop_name].id
else:
res[id][prop_name] = False
@ -1460,7 +1461,7 @@ class property(function):
# name_get as root (as seeing the name of a related
# object depends on access right of source document,
# not target, so user may not have access.)
name_get_values = dict(obj.pool.get(property_destination_obj).name_get(cr, SUPERUSER_ID, name_get_ids.values(), context=context))
name_get_values = dict(obj.pool[property_destination_obj].name_get(cr, SUPERUSER_ID, name_get_ids.values(), context=context))
# the property field is a m2o, we need to return a tuple with (id, name)
for k, v in name_get_ids.iteritems():
if res[k][prop_name]:

View File

@ -420,7 +420,7 @@ class browse_record(object):
for field_name, field_column in fields_to_fetch:
if field_column._type == 'many2one':
if result_line[field_name]:
obj = self._table.pool.get(field_column._obj)
obj = self._table.pool[field_column._obj]
if isinstance(result_line[field_name], (list, tuple)):
value = result_line[field_name][0]
else:
@ -450,7 +450,7 @@ class browse_record(object):
else:
new_data[field_name] = browse_null()
elif field_column._type in ('one2many', 'many2many') and len(result_line[field_name]):
new_data[field_name] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool.get(field_column._obj), self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in result_line[field_name]], self._context)
new_data[field_name] = self._list_class([browse_record(self._cr, self._uid, id, self._table.pool[field_column._obj], self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process) for id in result_line[field_name]], self._context)
elif field_column._type == 'reference':
if result_line[field_name]:
if isinstance(result_line[field_name], browse_record):
@ -459,7 +459,7 @@ class browse_record(object):
ref_obj, ref_id = result_line[field_name].split(',')
ref_id = long(ref_id)
if ref_id:
obj = self._table.pool.get(ref_obj)
obj = self._table.pool[ref_obj]
new_data[field_name] = browse_record(self._cr, self._uid, ref_id, obj, self._cache, context=self._context, list_class=self._list_class, fields_process=self._fields_process)
else:
new_data[field_name] = browse_null()
@ -867,10 +867,10 @@ class BaseModel(object):
raise TypeError('_name is mandatory in case of multiple inheritance')
for parent_name in ((type(parent_names)==list) and parent_names or [parent_names]):
parent_model = pool.get(parent_name)
if not parent_model:
if parent_name not in pool:
raise TypeError('The model "%s" specifies an unexisting parent class "%s"\n'
'You may need to add a dependency on the parent class\' module.' % (name, parent_name))
parent_model = pool[parent_name]
if not getattr(cls, '_original_module', None) and name == parent_model._name:
cls._original_module = parent_model._original_module
parent_class = parent_model.__class__
@ -1095,7 +1095,7 @@ class BaseModel(object):
return ''
def selection_field(in_field):
col_obj = self.pool.get(in_field.keys()[0])
col_obj = self.pool[in_field.keys()[0]]
if f[i] in col_obj._columns.keys():
return col_obj._columns[f[i]]
elif f[i] in col_obj._inherits.keys():
@ -1183,10 +1183,10 @@ class BaseModel(object):
if not data[fpos]:
dt = ''
for rr in r:
name_relation = self.pool.get(rr._table_name)._rec_name
name_relation = self.pool[rr._table_name]._rec_name
if isinstance(rr[name_relation], browse_record):
rr = rr[name_relation]
rr_name = self.pool.get(rr._table_name).name_get(cr, uid, [rr.id], context=context)
rr_name = self.pool[rr._table_name].name_get(cr, uid, [rr.id], context=context)
rr_name = rr_name and rr_name[0] and rr_name[0][1] or ''
dt += tools.ustr(rr_name or '') + ','
data[fpos] = dt[:-1]
@ -1199,7 +1199,7 @@ class BaseModel(object):
i += 1
if i == len(f):
if isinstance(r, browse_record):
r = self.pool.get(r._table_name).name_get(cr, uid, [r.id], context=context)
r = self.pool[r._table_name].name_get(cr, uid, [r.id], context=context)
r = r and r[0] and r[0][1] or ''
data[fpos] = tools.ustr(r or '')
return [data] + lines
@ -1570,8 +1570,7 @@ class BaseModel(object):
# get the default values for the inherited fields
for t in self._inherits.keys():
defaults.update(self.pool.get(t).default_get(cr, uid, fields_list,
context))
defaults.update(self.pool[t].default_get(cr, uid, fields_list, context))
# get the default values defined in the object
for f in fields_list:
@ -1605,11 +1604,11 @@ class BaseModel(object):
if field in fields_list:
fld_def = (field in self._columns) and self._columns[field] or self._inherit_fields[field][2]
if fld_def._type == 'many2one':
obj = self.pool.get(fld_def._obj)
obj = self.pool[fld_def._obj]
if not obj.search(cr, uid, [('id', '=', field_value or False)]):
continue
if fld_def._type == 'many2many':
obj = self.pool.get(fld_def._obj)
obj = self.pool[fld_def._obj]
field_value2 = []
for i in range(len(field_value or [])):
if not obj.search(cr, uid, [('id', '=',
@ -1618,18 +1617,18 @@ class BaseModel(object):
field_value2.append(field_value[i])
field_value = field_value2
if fld_def._type == 'one2many':
obj = self.pool.get(fld_def._obj)
obj = self.pool[fld_def._obj]
field_value2 = []
for i in range(len(field_value or [])):
field_value2.append({})
for field2 in field_value[i]:
if field2 in obj._columns.keys() and obj._columns[field2]._type == 'many2one':
obj2 = self.pool.get(obj._columns[field2]._obj)
obj2 = self.pool[obj._columns[field2]._obj]
if not obj2.search(cr, uid,
[('id', '=', field_value[i][field2])]):
continue
elif field2 in obj._inherit_fields.keys() and obj._inherit_fields[field2][2]._type == 'many2one':
obj2 = self.pool.get(obj._inherit_fields[field2][2]._obj)
obj2 = self.pool[obj._inherit_fields[field2][2]._obj]
if not obj2.search(cr, uid,
[('id', '=', field_value[i][field2])]):
continue
@ -1649,7 +1648,7 @@ class BaseModel(object):
# TODO I believe this loop can be replace by
# res.extend(self._inherit_fields.key())
for parent in self._inherits:
res.extend(self.pool.get(parent).fields_get_keys(cr, user, context))
res.extend(self.pool[parent].fields_get_keys(cr, user, context))
return res
def _rec_name_fallback(self, cr, uid, context=None):
@ -1745,7 +1744,7 @@ class BaseModel(object):
new_xml = etree.fromstring(encode(xml))
ctx = context.copy()
ctx['base_model_name'] = self._name
xarch, xfields = self.pool.get(node.get('object')).__view_look_dom_arch(cr, user, new_xml, view_id, ctx)
xarch, xfields = self.pool[node.get('object')].__view_look_dom_arch(cr, user, new_xml, view_id, ctx)
views['form'] = {
'arch': xarch,
'fields': xfields
@ -1763,7 +1762,7 @@ class BaseModel(object):
column = False
if column:
relation = self.pool.get(column._obj)
relation = self.pool[column._obj] if column._obj else None
children = False
views = {}
@ -1899,13 +1898,13 @@ class BaseModel(object):
fields = {}
if node.tag == 'diagram':
if node.getchildren()[0].tag == 'node':
node_model = self.pool.get(node.getchildren()[0].get('object'))
node_model = self.pool[node.getchildren()[0].get('object')]
node_fields = node_model.fields_get(cr, user, None, context)
fields.update(node_fields)
if not node.get("create") and not node_model.check_access_rights(cr, user, 'create', raise_exception=False):
node.set("create", 'false')
if node.getchildren()[1].tag == 'arrow':
arrow_fields = self.pool.get(node.getchildren()[1].get('object')).fields_get(cr, user, None, context)
arrow_fields = self.pool[node.getchildren()[1].get('object')].fields_get(cr, user, None, context)
fields.update(arrow_fields)
else:
fields = self.fields_get(cr, user, None, context)
@ -2446,7 +2445,7 @@ class BaseModel(object):
res[lang][f] = self._columns[f].string
for table in self._inherits:
cols = intersect(self._inherit_fields.keys(), fields)
res2 = self.pool.get(table).read_string(cr, uid, id, langs, cols, context)
res2 = self.pool[table].read_string(cr, uid, id, langs, cols, context)
for lang in res2:
if lang in res:
res[lang]['code'] = lang
@ -2465,7 +2464,7 @@ class BaseModel(object):
for table in self._inherits:
cols = intersect(self._inherit_fields.keys(), vals)
if cols:
self.pool.get(table).write_string(cr, uid, id, langs, vals, context)
self.pool[table].write_string(cr, uid, id, langs, vals, context)
return True
def _add_missing_default_values(self, cr, uid, values, context=None):
@ -2726,7 +2725,7 @@ class BaseModel(object):
:param query: query object on which the JOIN should be added
"""
inherits_field = current_model._inherits[parent_model_name]
parent_model = self.pool.get(parent_model_name)
parent_model = self.pool[parent_model_name]
parent_alias, parent_alias_statement = query.add_join((current_model._table, parent_model._table, inherits_field, 'id', inherits_field), implicit=True)
return parent_alias
@ -2743,7 +2742,7 @@ class BaseModel(object):
parent_alias = '"%s"' % current_table._table
while field in current_table._inherit_fields and not field in current_table._columns:
parent_model_name = current_table._inherit_fields[field][0]
parent_table = self.pool.get(parent_model_name)
parent_table = self.pool[parent_model_name]
parent_alias = self._inherits_join_add(current_table, parent_model_name, query)
current_table = parent_table
return '%s."%s"' % (parent_alias, field)
@ -3142,7 +3141,7 @@ class BaseModel(object):
_schema.debug(msg, self._table, k, f._type)
if isinstance(f, fields.many2one):
dest_model = self.pool.get(f._obj)
dest_model = self.pool[f._obj]
if dest_model._table != 'ir_actions':
self._m2o_fix_foreign_key(cr, self._table, k, dest_model, f.ondelete)
@ -3177,9 +3176,9 @@ class BaseModel(object):
# and add constraints if needed
if isinstance(f, fields.many2one):
if not self.pool.get(f._obj):
if f._obj not in self.pool:
raise except_orm('Programming Error', 'There is no reference available for %s' % (f._obj,))
dest_model = self.pool.get(f._obj)
dest_model = self.pool[f._obj]
ref = dest_model._table
# ir_actions is inherited so foreign key doesn't work on it
if ref != 'ir_actions':
@ -3299,9 +3298,8 @@ class BaseModel(object):
def _o2m_raise_on_missing_reference(self, cr, f):
# TODO this check should be a method on fields.one2many.
other = self.pool.get(f._obj)
if other:
if f._obj in self.pool:
other = self.pool[f._obj]
# TODO the condition could use fields_get_keys().
if f._fields_id not in other._columns.keys():
if f._fields_id not in other._inherit_fields.keys():
@ -3312,9 +3310,9 @@ class BaseModel(object):
self._save_relation_table(cr, m2m_tbl)
cr.execute("SELECT relname FROM pg_class WHERE relkind IN ('r','v') AND relname=%s", (m2m_tbl,))
if not cr.dictfetchall():
if not self.pool.get(f._obj):
if f._obj not in self.pool:
raise except_orm('Programming Error', 'Many2Many destination model does not exist: `%s`' % (f._obj,))
dest_model = self.pool.get(f._obj)
dest_model = self.pool[f._obj]
ref = dest_model._table
cr.execute('CREATE TABLE "%s" ("%s" INTEGER NOT NULL, "%s" INTEGER NOT NULL, UNIQUE("%s","%s"))' % (m2m_tbl, col1, col2, col1, col2))
# create foreign key references with ondelete=cascade, unless the targets are SQL views
@ -3419,7 +3417,7 @@ class BaseModel(object):
"""
res = {}
for table in self._inherits:
other = self.pool.get(table)
other = self.pool[table]
for col in other._columns.keys():
res[col] = (table, self._inherits[table], other._columns[col], table)
for col in other._inherit_fields.keys():
@ -3503,7 +3501,7 @@ class BaseModel(object):
translation_obj = self.pool.get('ir.translation')
for parent in self._inherits:
res.update(self.pool.get(parent).fields_get(cr, user, allfields, context))
res.update(self.pool[parent].fields_get(cr, user, allfields, context))
for f, field in self._columns.iteritems():
if (allfields and f not in allfields) or \
@ -3677,7 +3675,7 @@ class BaseModel(object):
cols = [x for x in intersect(self._inherit_fields.keys(), fields_to_read) if x not in self._columns.keys()]
if not cols:
continue
res2 = self.pool.get(table).read(cr, user, [x[col] for x in res], cols, context, load)
res2 = self.pool[table].read(cr, user, [x[col] for x in res], cols, context, load)
res3 = {}
for r in res2:
@ -4017,9 +4015,9 @@ class BaseModel(object):
if ir_value_ids:
ir_values_obj.unlink(cr, uid, ir_value_ids, context=context)
for order, object, store_ids, fields in result_store:
if object != self._name:
obj = self.pool.get(object)
for order, obj_name, store_ids, fields in result_store:
if obj_name != self._name:
obj = self.pool[obj_name]
cr.execute('select id from '+obj._table+' where id IN %s', (tuple(store_ids),))
rids = map(lambda x: x[0], cr.fetchall())
if rids:
@ -4183,7 +4181,7 @@ class BaseModel(object):
# TODO: optimize
for f in direct:
if self._columns[f].translate:
src_trans = self.pool.get(self._name).read(cr, user, ids, [f])[0][f]
src_trans = self.pool[self._name].read(cr, user, ids, [f])[0][f]
if not src_trans:
src_trans = vals[f]
# Inserting value to DB
@ -4219,7 +4217,7 @@ class BaseModel(object):
v[val] = vals[val]
unknown_fields.remove(val)
if v:
self.pool.get(table).write(cr, user, nids, v, context)
self.pool[table].write(cr, user, nids, v, context)
if unknown_fields:
_logger.warning(
@ -4285,8 +4283,8 @@ class BaseModel(object):
result.sort()
done = {}
for order, object, ids_to_update, fields_to_recompute in result:
key = (object, tuple(fields_to_recompute))
for order, model_name, ids_to_update, fields_to_recompute in result:
key = (model_name, tuple(fields_to_recompute))
done.setdefault(key, {})
# avoid to do several times the same computation
todo = []
@ -4294,7 +4292,7 @@ class BaseModel(object):
if id not in done[key]:
done[key][id] = True
todo.append(id)
self.pool.get(object)._store_set_values(cr, user, todo, fields_to_recompute, context)
self.pool[model_name]._store_set_values(cr, user, todo, fields_to_recompute, context)
self.step_workflow(cr, user, ids, context=context)
return True
@ -4387,9 +4385,9 @@ class BaseModel(object):
parent_context.pop('no_store_function', None)
if record_id is None or not record_id:
record_id = self.pool.get(table).create(cr, user, tocreate[table], context=parent_context)
record_id = self.pool[table].create(cr, user, tocreate[table], context=parent_context)
else:
self.pool.get(table).write(cr, user, [record_id], tocreate[table], context=parent_context)
self.pool[table].write(cr, user, [record_id], tocreate[table], context=parent_context)
upd0 += ',' + self._inherits[table]
upd1 += ',%s'
@ -4500,10 +4498,10 @@ class BaseModel(object):
result += self._store_get_values(cr, user, [id_new], vals.keys(), context)
result.sort()
done = []
for order, object, ids, fields2 in result:
if not (object, ids, fields2) in done:
self.pool.get(object)._store_set_values(cr, user, ids, fields2, context)
done.append((object, ids, fields2))
for order, model_name, ids, fields2 in result:
if not (model_name, ids, fields2) in done:
self.pool[model_name]._store_set_values(cr, user, ids, fields2, context)
done.append((model_name, ids, fields2))
if self._log_create and not (context and context.get('no_store_function', False)):
message = self._description + \
@ -4728,7 +4726,7 @@ class BaseModel(object):
# to reach the parent table (if it was not JOINed yet in the query)
parent_alias = child_object._inherits_join_add(child_object, parent_model, query)
# inherited rules are applied on the external table -> need to get the alias and replace
parent_table = self.pool.get(parent_model)._table
parent_table = self.pool[parent_model]._table
added_clause = [clause.replace('"%s"' % parent_table, '"%s"' % parent_alias) for clause in added_clause]
# change references to parent_table to parent_alias, because we now use the alias to refer to the table
new_tables = []
@ -4783,7 +4781,7 @@ class BaseModel(object):
return
# figure out the applicable order_by for the m2o
dest_model = self.pool.get(order_field_column._obj)
dest_model = self.pool[order_field_column._obj]
m2o_order = dest_model._order
if not regex_order.match(m2o_order):
# _order is complex, can't use it here, so we default to _rec_name
@ -4819,8 +4817,8 @@ class BaseModel(object):
order_field = order_split[0].strip()
order_direction = order_split[1].strip() if len(order_split) == 2 else ''
inner_clause = None
if order_field == 'id':
order_by_elements.append('"%s"."id" %s' % (self._table, order_direction))
if order_field == 'id' or (self._log_access and order_field in LOG_ACCESS_COLUMNS.keys()):
order_by_elements.append('"%s"."%s" %s' % (self._table, order_field, order_direction))
elif order_field in self._columns:
order_column = self._columns[order_field]
if order_column._classic_read:
@ -4830,7 +4828,7 @@ class BaseModel(object):
else:
continue # ignore non-readable or "non-joinable" fields
elif order_field in self._inherit_fields:
parent_obj = self.pool.get(self._inherit_fields[order_field][3])
parent_obj = self.pool[self._inherit_fields[order_field][3]]
order_column = parent_obj._columns[order_field]
if order_column._classic_read:
inner_clause = self._inherits_join_calc(order_field, query)
@ -4838,6 +4836,8 @@ class BaseModel(object):
inner_clause = self._generate_m2o_order_by(order_field, query)
else:
continue # ignore non-readable or "non-joinable" fields
else:
raise ValueError( _("Sorting field %s not found on model %s") %( order_field, self._name))
if inner_clause:
if isinstance(inner_clause, list):
for clause in inner_clause:
@ -4903,7 +4903,7 @@ class BaseModel(object):
if not args:
args = []
if field in self._inherit_fields:
return self.pool.get(self._inherit_fields[field][0]).distinct_field_get(cr, uid, field, value, args, offset, limit)
return self.pool[self._inherit_fields[field][0]].distinct_field_get(cr, uid, field, value, args, offset, limit)
else:
return self._columns[field].search(cr, self, args, field, value, offset, limit, uid)
@ -4957,9 +4957,9 @@ class BaseModel(object):
if field_to_other in default:
# all the fields of 'other' are given by the record: default[field_to_other],
# except the ones redefined in self
blacklist.update(set(self.pool.get(other)._all_columns) - set(self._columns))
blacklist.update(set(self.pool[other]._all_columns) - set(self._columns))
else:
blacklist_given_fields(self.pool.get(other))
blacklist_given_fields(self.pool[other])
blacklist_given_fields(self)
res = dict(default)
@ -4974,7 +4974,7 @@ class BaseModel(object):
elif field._type == 'many2one':
res[f] = data[f] and data[f][0]
elif field._type == 'one2many':
other = self.pool.get(field._obj)
other = self.pool[field._obj]
# duplicate following the order of the ids because we'll rely on
# it later for copying translations in copy_translation()!
lines = [other.copy_data(cr, uid, line_id, context=context) for line_id in sorted(data[f])]
@ -5006,7 +5006,7 @@ class BaseModel(object):
for field_name, field_def in fields.items():
# we must recursively copy the translations for o2o and o2m
if field_def['type'] == 'one2many':
target_obj = self.pool.get(field_def['relation'])
target_obj = self.pool[field_def['relation']]
old_record, new_record = self.read(cr, uid, [old_id, new_id], [field_name], context=context)
# here we rely on the order of the ids to match the translations
# as foreseen in copy_data()
@ -5094,20 +5094,18 @@ class BaseModel(object):
:param parent: optional parent field name (default: ``self._parent_name = parent_id``)
:return: **True** if the operation can proceed safely, or **False** if an infinite loop is detected.
"""
if not parent:
parent = self._parent_name
ids_parent = ids[:]
query = 'SELECT distinct "%s" FROM "%s" WHERE id IN %%s' % (parent, self._table)
while ids_parent:
ids_parent2 = []
for i in range(0, len(ids), cr.IN_MAX):
sub_ids_parent = ids_parent[i:i+cr.IN_MAX]
cr.execute(query, (tuple(sub_ids_parent),))
ids_parent2.extend(filter(None, map(lambda x: x[0], cr.fetchall())))
ids_parent = ids_parent2
for i in ids_parent:
if i in ids:
# must ignore 'active' flag, ir.rules, etc. => direct SQL query
query = 'SELECT "%s" FROM "%s" WHERE id = %%s' % (parent, self._table)
for id in ids:
current_id = id
while current_id is not None:
cr.execute(query, (current_id,))
result = cr.fetchone()
current_id = result[0] if result else None
if current_id == id:
return False
return True
@ -5275,7 +5273,7 @@ class BaseModel(object):
result, record_ids = [], list(command[2])
# read the records and apply the updates
other_model = self.pool.get(self._all_columns[field_name].column._obj)
other_model = self.pool[self._all_columns[field_name].column._obj]
for record in other_model.read(cr, uid, record_ids, fields=fields, context=context):
record.update(updates.get(record['id'], {}))
result.append(record)

Some files were not shown because too many files have changed in this diff Show More