diff --git a/.bzrignore b/.bzrignore index 1e0564801ab..e7618c7b0ce 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1,14 +1,21 @@ -.* -*.egg-info -*.orig -*.vim +.*.swp +.bzrignore +.idea +.project +.pydevproject +.ropeproject +.settings +.DS_Store +openerp/addons/* +openerp/filestore* +.Python +*.pyc +*.pyo +bin/* build/ -RE:^bin/ -RE:^dist/ -RE:^include/ - -RE:^share/ -RE:^man/ -RE:^lib/ - -RE:^addons/\w+/doc/_build/ +include/ +lib/ +share/ +doc/_build/* +win32/*.bat +win32/meta.py diff --git a/openerp/addons/base/__openerp__.py b/openerp/addons/base/__openerp__.py index d400b28a729..f2df88506f5 100644 --- a/openerp/addons/base/__openerp__.py +++ b/openerp/addons/base/__openerp__.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010, 2012 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -80,6 +80,7 @@ The kernel of OpenERP, needed for all installation. 'res/res_bank_view.xml', 'res/res_country_view.xml', 'res/res_currency_view.xml', + 'res/wizard/change_password_wizard_view.xml', 'res/res_users_view.xml', 'res/res_partner_data.xml', 'res/ir_property_view.xml', @@ -102,5 +103,8 @@ The kernel of OpenERP, needed for all installation. 'installable': True, 'auto_install': True, 'css': ['static/src/css/modules.css'], + 'js': [ + 'static/src/js/apps.js', + ], } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/i18n/es.po b/openerp/addons/base/i18n/es.po index 9730848f44d..2a50ce20df6 100644 --- a/openerp/addons/base/i18n/es.po +++ b/openerp/addons/base/i18n/es.po @@ -13,7 +13,7 @@ msgstr "" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-20 04:42+0000\n" +"X-Launchpad-Export-Date: 2012-12-21 04:39+0000\n" "X-Generator: Launchpad (build 16378)\n" #. module: base diff --git a/openerp/addons/base/i18n/es_EC.po b/openerp/addons/base/i18n/es_EC.po index 2d08fbd47ef..ce83e828fae 100644 --- a/openerp/addons/base/i18n/es_EC.po +++ b/openerp/addons/base/i18n/es_EC.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0.0-rc1\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-03 16:01+0000\n" -"PO-Revision-Date: 2012-12-20 02:14+0000\n" +"PO-Revision-Date: 2012-12-20 19:00+0000\n" "Last-Translator: Cristian Salamea (Gnuthink) \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-20 04:43+0000\n" +"X-Launchpad-Export-Date: 2012-12-21 04:39+0000\n" "X-Generator: Launchpad (build 16378)\n" #. module: base @@ -210,6 +210,15 @@ msgid "" "revenue\n" "reports." msgstr "" +"\n" +"Genere facturas desde los gastos y partes de horas.\n" +"========================================================\n" +"\n" +"Módulo para generar facturas basadas en los costes (recursos humanos, " +"gastos, ...).\n" +"\n" +"Puede definir tarifas en la contabilidad analítica, realizando algún informe " +"teórico de beneficios." #. module: base #: model:ir.module.module,description:base.module_crm @@ -378,6 +387,15 @@ msgid "" " * Commitment Date\n" " * Effective Date\n" msgstr "" +"\n" +"Añade información adicional al pedido de venta.\n" +"===================================================\n" +"\n" +"Puede añadir las siguientes fechas adicionales a un pedido de venta:\n" +"-----------------------------------------------------------\n" +" * Fecha solicitada\n" +" * Fecha de confirmación\n" +" * Fecha efectiva\n" #. module: base #: help:ir.actions.act_window,res_id:0 @@ -385,6 +403,8 @@ msgid "" "Database ID of record to open in form view, when ``view_mode`` is set to " "'form' only" msgstr "" +"Id. de la base datos del registro para abrir en el formulario de vista, " +"cuando se establece el modo de visto únicamente a 'formulario'" #. module: base #: field:res.partner.address,name:0 @@ -460,6 +480,8 @@ msgid "" "There is already a shared filter set as default for %(model)s, delete or " "change it before setting a new default" msgstr "" +"Ya existe un filtro compartido por defecto para %(model)s, elimínelo o " +"cámbielo antes de configurar uno nuevo" #. module: base #: code:addons/orm.py:2648 @@ -554,12 +576,12 @@ msgstr "" #. module: base #: field:ir.model.relation,name:0 msgid "Relation Name" -msgstr "" +msgstr "Nombre de relación" #. module: base #: view:ir.rule:0 msgid "Create Access Right" -msgstr "" +msgstr "Crear permisos de acceso" #. module: base #: model:res.country,name:base.tv @@ -599,7 +621,7 @@ msgstr "" #. module: base #: view:workflow.transition:0 msgid "Workflow Transition" -msgstr "" +msgstr "Transición del flujo de trabajo" #. module: base #: model:res.country,name:base.gf @@ -722,7 +744,7 @@ msgstr "Colombia" #. module: base #: model:res.partner.title,name:base.res_partner_title_mister msgid "Mister" -msgstr "" +msgstr "Señor" #. module: base #: help:res.country,code:0 @@ -751,7 +773,7 @@ msgstr "Untranslated" #. module: base #: view:ir.mail_server:0 msgid "Outgoing Mail Server" -msgstr "" +msgstr "Servidor de correo saliente" #. module: base #: help:ir.actions.act_window,context:0 @@ -845,6 +867,14 @@ msgid "" "

\n" " " msgstr "" +"

\n" +"Pulse para añadir un contacto en la libreta de direcciones.\n" +"

\n" +"OpenERP le ayuda a gestionar todas las actividades relacionadas con los " +"clientes: discusiones, historial de oportunidades de negocio, documentos, " +"etc.\n" +"

\n" +" " #. module: base #: model:ir.module.module,description:base.module_web_linkedin @@ -901,7 +931,7 @@ msgstr "Rumanía - Contabilidad" #. module: base #: model:ir.model,name:base.model_res_config_settings msgid "res.config.settings" -msgstr "" +msgstr "Parámetros de configuración" #. module: base #: help:res.partner,image_small:0 @@ -910,6 +940,9 @@ msgid "" "image, with aspect ratio preserved. Use this field anywhere a small image is " "required." msgstr "" +"Imagen de tamaño pequeño de este contacto. Se redimensiona automáticamente a " +"64x64 px, con el ratio de aspecto preservado. Use este campo donde se " +"requiera una imagen pequeña." #. module: base #: help:ir.actions.server,mobile:0 @@ -931,7 +964,7 @@ msgstr "Seguridad y autenticación" #. module: base #: model:ir.module.module,shortdesc:base.module_web_calendar msgid "Web Calendar" -msgstr "" +msgstr "Calendario web" #. module: base #: selection:base.language.install,lang:0 @@ -942,7 +975,7 @@ msgstr "Swedish / svenska" #: field:base.language.export,name:0 #: field:ir.attachment,datas_fname:0 msgid "File Name" -msgstr "" +msgstr "Nombre de Archivo" #. module: base #: model:res.country,name:base.rs @@ -1038,7 +1071,7 @@ msgstr "Preferencias de email" #: code:addons/base/ir/ir_fields.py:196 #, python-format msgid "'%s' does not seem to be a valid date for field '%%(field)s'" -msgstr "" +msgstr "'%s' no parece ser una fecha valida para el campo '%%(field)s'" #. module: base #: view:res.partner:0 @@ -1055,6 +1088,7 @@ msgstr "Zimbabwe" msgid "" "Type of the constraint: `f` for a foreign key, `u` for other constraints." msgstr "" +"Tipo de restricción: 'f' para un clave foránea, 'u' para otras restricciones." #. module: base #: view:ir.actions.report.xml:0 @@ -1136,7 +1170,7 @@ msgstr "Otra licencia OSI Aprobada" #. module: base #: model:ir.module.module,shortdesc:base.module_web_gantt msgid "Web Gantt" -msgstr "" +msgstr "Diagrama Gantt web" #. module: base #: model:ir.actions.act_window,name:base.act_menu_create @@ -1163,7 +1197,7 @@ msgstr "Usuarios google" #. module: base #: model:ir.module.module,shortdesc:base.module_fleet msgid "Fleet Management" -msgstr "" +msgstr "Gestión de Flotas" #. module: base #: help:ir.server.object.lines,value:0 @@ -1189,7 +1223,7 @@ msgstr "Principado de Andorra" #. module: base #: field:ir.rule,perm_read:0 msgid "Apply for Read" -msgstr "" +msgstr "Aplicar para lectura" #. module: base #: model:res.country,name:base.mn @@ -1219,7 +1253,7 @@ msgstr "" #: code:addons/base/ir/ir_model.py:727 #, python-format msgid "Document model" -msgstr "" +msgstr "Modelo de documento" #. module: base #: view:res.lang:0 @@ -1269,12 +1303,12 @@ msgstr "El nombre del país debe ser único" #. module: base #: field:ir.module.module,installed_version:0 msgid "Latest Version" -msgstr "" +msgstr "Última versión" #. module: base #: view:ir.rule:0 msgid "Delete Access Right" -msgstr "" +msgstr "Eliminar permiso de acceso" #. module: base #: code:addons/base/ir/ir_mail_server.py:213 @@ -1301,7 +1335,7 @@ msgstr "Islas Caimán" #. module: base #: view:ir.rule:0 msgid "Record Rule" -msgstr "" +msgstr "Regla de registro" #. module: base #: model:res.country,name:base.kr @@ -1329,7 +1363,7 @@ msgstr "Contribuyentes" #. module: base #: field:ir.rule,perm_unlink:0 msgid "Apply for Delete" -msgstr "" +msgstr "Aplicar para eliminación" #. module: base #: selection:ir.property,type:0 @@ -1344,7 +1378,7 @@ msgstr "Visible" #. module: base #: model:ir.actions.client,name:base.action_client_base_menu msgid "Open Settings Menu" -msgstr "" +msgstr "Abrir menú 'Configuración'" #. module: base #: selection:base.language.install,lang:0 @@ -1430,7 +1464,7 @@ msgstr "Tests" #. module: base #: field:ir.actions.report.xml,attachment:0 msgid "Save as Attachment Prefix" -msgstr "" +msgstr "Prefijo del adjunto al guardar como" #. module: base #: field:ir.ui.view_sc,res_id:0 @@ -1467,7 +1501,7 @@ msgstr "Haití" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_fr_hr_payroll msgid "French Payroll" -msgstr "" +msgstr "Nomina de Francia" #. module: base #: view:ir.ui.view:0 @@ -1587,6 +1621,12 @@ msgid "" "=============\n" " " msgstr "" +"\n" +"Este módulo añade el menú y características de reclamaciones al portal si " +"los módulos 'claim' y 'portal' están instalados.\n" +"=============================================================================" +"====================\n" +" " #. module: base #: model:ir.actions.act_window,help:base.action_res_partner_bank_account_form @@ -1618,7 +1658,7 @@ msgstr "" #. module: base #: model:res.country,name:base.mf msgid "Saint Martin (French part)" -msgstr "" +msgstr "San Martín (zona francesa)" #. module: base #: model:ir.model,name:base.model_ir_exports @@ -1635,7 +1675,7 @@ msgstr "Ninguna lengua con el código \"%s\" existe" #: model:ir.module.category,name:base.module_category_social_network #: model:ir.module.module,shortdesc:base.module_mail msgid "Social Network" -msgstr "" +msgstr "Red Social" #. module: base #: view:res.lang:0 @@ -1645,12 +1685,12 @@ msgstr "%Y - Año con siglo." #. module: base #: view:res.company:0 msgid "Report Footer Configuration" -msgstr "" +msgstr "Configuración de pie de informe" #. module: base #: field:ir.translation,comments:0 msgid "Translation comments" -msgstr "" +msgstr "Comentarios de traducción" #. module: base #: model:ir.module.module,description:base.module_lunch @@ -1715,7 +1755,7 @@ msgstr "" #. module: base #: help:res.partner,website:0 msgid "Website of Partner or Company" -msgstr "" +msgstr "Sitio web de la empresa o compañía" #. module: base #: help:base.language.install,overwrite:0 @@ -1762,7 +1802,7 @@ msgstr "" #. module: base #: model:ir.module.module,summary:base.module_sale msgid "Quotations, Sale Orders, Invoicing" -msgstr "" +msgstr "Presupuestos, órdenes de venta, facturación" #. module: base #: field:res.users,login:0 diff --git a/openerp/addons/base/i18n/et.po b/openerp/addons/base/i18n/et.po index a722c4c7e65..c6053f615b7 100644 --- a/openerp/addons/base/i18n/et.po +++ b/openerp/addons/base/i18n/et.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-03 16:01+0000\n" -"PO-Revision-Date: 2012-12-19 19:49+0000\n" +"PO-Revision-Date: 2012-12-20 18:03+0000\n" "Last-Translator: Ahti Hinnov \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-20 04:41+0000\n" +"X-Launchpad-Export-Date: 2012-12-21 04:38+0000\n" "X-Generator: Launchpad (build 16378)\n" #. module: base @@ -1355,7 +1355,7 @@ msgstr "" #: code:addons/base/module/wizard/base_language_install.py:53 #, python-format msgid "Language Pack" -msgstr "" +msgstr "Keelepakett" #. module: base #: model:ir.module.module,shortdesc:base.module_web_tests @@ -2005,7 +2005,7 @@ msgstr "Valem" #: code:addons/base/res/res_users.py:311 #, python-format msgid "Can not remove root user!" -msgstr "Ei saa eemaldada root kasutajat!" +msgstr "Ei saa eemaldada juurkasutajat!" #. module: base #: model:res.country,name:base.mw @@ -2750,7 +2750,7 @@ msgstr "Ekspordi tõlked" #: model:res.groups,name:base.group_sale_manager #: model:res.groups,name:base.group_tool_manager msgid "Manager" -msgstr "" +msgstr "Juht" #. module: base #: code:addons/base/ir/ir_model.py:718 @@ -3055,7 +3055,7 @@ msgstr "Viga! Sa ei saa luua rekursiivseid ettevõtteid." #: view:res.users:0 #, python-format msgid "Application" -msgstr "" +msgstr "Rakendamine" #. module: base #: model:res.groups,comment:base.group_hr_manager @@ -4467,6 +4467,8 @@ msgid "" "The selected language has been successfully installed. You must change the " "preferences of the user and open a new menu to view the changes." msgstr "" +"Valitud keel on edukalt paigaldatud. Muudatuste nägemiseks pead sa muutma " +"kasutaja eelistusi ja avama uue menüü." #. module: base #: field:ir.actions.act_window.view,view_id:0 @@ -5694,7 +5696,7 @@ msgstr "Omadus kustutamisel many2one väljadel" #. module: base #: model:ir.module.category,name:base.module_category_accounting_and_finance msgid "Accounting & Finance" -msgstr "" +msgstr "Raamatupidamine ja rahandus" #. module: base #: field:ir.actions.server,write_id:0 @@ -5717,7 +5719,7 @@ msgstr "" #: model:ir.module.category,name:base.module_category_usability #: view:res.users:0 msgid "Usability" -msgstr "" +msgstr "Kasutatavus" #. module: base #: field:ir.actions.act_window,domain:0 @@ -5836,7 +5838,7 @@ msgstr "Grupi nimi ei tohi alata \"-\" märgiga" #. module: base #: view:ir.module.module:0 msgid "Apps" -msgstr "" +msgstr "Rakendused" #. module: base #: view:ir.ui.view_sc:0 @@ -6508,7 +6510,7 @@ msgstr "" #. module: base #: model:res.groups,name:base.group_partner_manager msgid "Contact Creation" -msgstr "" +msgstr "Kontaktide loomine" #. module: base #: view:ir.module.module:0 @@ -9180,7 +9182,7 @@ msgstr "Gambia" #: view:res.partner:0 #: field:res.users,company_ids:0 msgid "Companies" -msgstr "Firmad" +msgstr "Ettevõtted" #. module: base #: help:res.currency,symbol:0 @@ -9249,7 +9251,7 @@ msgstr "" #: view:res.users:0 #: view:wizard.ir.model.menu.create:0 msgid "Cancel" -msgstr "Tühista" +msgstr "Loobu" #. module: base #: code:addons/orm.py:1509 @@ -9665,7 +9667,7 @@ msgstr "Kuvamine" #. module: base #: model:res.groups,name:base.group_multi_company msgid "Multi Companies" -msgstr "" +msgstr "Mitu ettevõtet" #. module: base #: help:res.users,menu_id:0 @@ -10034,7 +10036,7 @@ msgstr "Ettevõttega seotud pangakontod" #: model:ir.ui.menu,name:base.next_id_64 #: view:res.users:0 msgid "Sales" -msgstr "Müügid" +msgstr "Müük" #. module: base #: field:ir.actions.server,child_ids:0 @@ -10321,7 +10323,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_stock msgid "Sales and Warehouse Management" -msgstr "" +msgstr "Müük ja laohaldus" #. module: base #: field:ir.model.fields,model:0 @@ -12095,7 +12097,7 @@ msgstr "ir.values" #. module: base #: model:res.groups,name:base.group_no_one msgid "Technical Features" -msgstr "" +msgstr "Tehnilised funktsioonid" #. module: base #: selection:base.language.install,lang:0 @@ -14247,7 +14249,7 @@ msgstr "Faks" #: view:res.users:0 #: field:res.users,company_id:0 msgid "Company" -msgstr "Firma" +msgstr "Ettevõte" #. module: base #: model:ir.module.category,name:base.module_category_report_designer diff --git a/openerp/addons/base/i18n/hu.po b/openerp/addons/base/i18n/hu.po index 514bc4d3a8a..3808cfd8516 100644 --- a/openerp/addons/base/i18n/hu.po +++ b/openerp/addons/base/i18n/hu.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 6.0\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-03 16:01+0000\n" -"PO-Revision-Date: 2012-12-19 16:59+0000\n" +"PO-Revision-Date: 2012-12-20 15:01+0000\n" "Last-Translator: krnkris \n" "Language-Team: Hungarian \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-20 04:41+0000\n" +"X-Launchpad-Export-Date: 2012-12-21 04:38+0000\n" "X-Generator: Launchpad (build 16378)\n" #. module: base @@ -15914,6 +15914,10 @@ msgid "" " the rightmost column (value) contains the " "translations" msgstr "" +"CSV formátum: szerkessze egyenesen a megszokott táblázatkezelő " +"alkalmazásával,\n" +" a leg jobboldalt lévő oszlop (érték) " +"tartalmazza a fordításokat" #. module: base #: model:ir.module.module,description:base.module_account_chart @@ -15924,11 +15928,16 @@ msgid "" "\n" "Deactivates minimal chart of accounts.\n" msgstr "" +"\n" +"a minimum számlatükör kikapcsolása.\n" +"=============================\n" +"\n" +"Kikapcsolja a minimum számlatükröket.\n" #. module: base #: model:ir.module.module,shortdesc:base.module_base_crypt msgid "DB Password Encryption" -msgstr "" +msgstr "DB adatbázis jelszó titkosítás" #. module: base #: help:workflow.transition,act_to:0 @@ -15938,7 +15947,7 @@ msgstr "A cél tevékenység." #. module: base #: model:ir.module.module,shortdesc:base.module_project_issue msgid "Issue Tracker" -msgstr "" +msgstr "Ügy nyomonkövetése" #. module: base #: view:base.module.update:0 @@ -15954,6 +15963,9 @@ msgid "" "The common interface for plug-in.\n" "=================================\n" msgstr "" +"\n" +"A plug-in általános intefész\n" +"============================\n" #. module: base #: model:ir.module.module,description:base.module_sale_crm @@ -15972,11 +15984,26 @@ msgid "" "modules.\n" " " msgstr "" +"\n" +"Ez a modul útvonal rövidítéseket ad meg egy vagy több lehetséges eseményhez " +"a CRM (ügyfélkapcsolat kezelőben).\n" +"===========================================================================\n" +"\n" +"Ezek a rövidebb utak lehetővé teszik a kiválasztott esemény alapján generált " +"megrendelések létrehozását.\n" +"Különböző eseményekhez megnyílik (egy lista), ez generálja az események " +"szerinti megrendeléseket.\n" +"Az esemény ezután lezárásra kerül és hozzá lesz csatolva egy generált " +"megrendeléshez.\n" +"\n" +"Ajánljuk ennek a modulnak a telepítését, ha az eladás és a crm modult is " +"telepítette már.\n" +" " #. module: base #: model:res.country,name:base.bq msgid "Bonaire, Sint Eustatius and Saba" -msgstr "" +msgstr "Karib tengeri Bonaire, Sint Eustatius and Saba" #. module: base #: model:ir.actions.report.xml,name:base.ir_module_reference_print @@ -16011,6 +16038,10 @@ msgid "" "your home page.\n" "You can track your suppliers, customers and other contacts.\n" msgstr "" +"\n" +"Ez a modul egy gyors áttekintést tesz lehetővé a címjegyzékén, ami elérhető " +"a saját oldaláról.\n" +"Nyomon követheti a beszállítóit, vásárlóit és egyéb ügyfeleit.\n" #. module: base #: help:res.company,custom_footer:0 @@ -16018,6 +16049,8 @@ msgid "" "Check this to define the report footer manually. Otherwise it will be " "filled in automatically." msgstr "" +"Jelölje be a kimutatás lábjegyzet kézi meghatározásához. Egyébként " +"automatikusan ki lesz töltve." #. module: base #: view:res.partner:0 @@ -16032,7 +16065,7 @@ msgstr "Modulok telepítése" #. module: base #: model:ir.ui.menu,name:base.menu_import_crm msgid "Import & Synchronize" -msgstr "" +msgstr "Import & Szinkronizáció" #. module: base #: view:res.partner:0 @@ -16065,7 +16098,7 @@ msgstr "Forrás" #: field:ir.model.constraint,date_init:0 #: field:ir.model.relation,date_init:0 msgid "Initialization Date" -msgstr "" +msgstr "Alap adatok" #. module: base #: model:res.country,name:base.vu @@ -16096,6 +16129,26 @@ msgid "" " Unit price=225, Discount=0,00, Net price=225.\n" " " msgstr "" +"\n" +"Ez a modul lehetővé teszi az árengedmények számítását a megrendelések és " +"számlák sorain a partner árlistája alapján.\n" +"=============================================================================" +"==================================\n" +"\n" +"Ehhez egy új jelölő négyzet lesz, melynek neve 'látható árengedmény', hozzá " +"lesz adva az árlista formához.\n" +"\n" +"**Például:**\n" +" A PC1 termékhez és az \"ASUSTEK\" partnerhez: ha a listaár=450, és az ár " +"az \n" +" Asustek árlista ár=255 árból lett kalkulálva. Ha be van jelölve a " +"négyzet akkor\n" +" megrendelés sorához ez lesz jelölve: Egységár=450, Árengedmény=50,00, " +"Nettó ár=225.\n" +" Ha nincs bejelölve a négyzet akkor a megrendelés és a számla sorain a " +"következő lesz:\n" +" Egységár=225, Árengedmény=0,00, Nettó ár=225.\n" +" " #. module: base #: model:ir.module.module,shortdesc:base.module_crm @@ -16113,6 +16166,13 @@ msgid "" "OpenOffice. \n" "Once you have modified it you can upload the report using the same wizard.\n" msgstr "" +"\n" +"Ez a modul együtt lesz használva az OpenERP OpenOffice Pluginnal.\n" +"=========================================================\n" +"\n" +"Ez a modul az Import/Export .sxw kimutatáshoz varázsló ad amit az OpenOffice-" +"al tud módosítani.. \n" +"módosítás után ezzel a varázslóval újra fel tudja tölteni a kimutatást.\n" #. module: base #: view:base.module.upgrade:0 @@ -16147,7 +16207,7 @@ msgstr "" #. module: base #: selection:ir.mail_server,smtp_encryption:0 msgid "TLS (STARTTLS)" -msgstr "" +msgstr "TLS (STARTTLS)" #. module: base #: help:ir.actions.act_window,usage:0 @@ -16818,6 +16878,38 @@ msgid "" "* Moves Analysis\n" " " msgstr "" +"\n" +"Több-raktárhely kezelése, multi- és struktúrált raktár helyek\n" +"==============================================================\n" +"\n" +"A raktár és leltár kezelés a hierarchikus elhelyezkedés struktúrán alapul, a " +"raktárhelyből a raktárba kapcsolattal. \n" +"A dupla bevitelű raktár rendszer lehetővé teszi a vevők és beszállítók " +"kezelését beleértve a gyártási raktárkészletet is. \n" +"\n" +"OpenERP-ben megvan a lehetőség a köteg és gyáriszám kezelésre biztosítva a " +"nyomon követhetőséget, ami a gyártást szavatolja.\n" +"\n" +"Fő jellemzők\n" +"-------------\n" +"* Mozgások előzményei és tervezése,\n" +"* Raktár értékelése (alapár vagy átlagár, ...)\n" +"* Erőteljesség a raktárkészlet különbségek tükrében\n" +"* Automata újrarendelés szabályok\n" +"* Bárkódok támogatása\n" +"* Gyors hiba érzékelés a dupla beviteli rendszer miatt\n" +"* Nyomon követhetőség (ellentétes irányú / Folyamat irányú, Széria számok, " +"...)\n" +"\n" +"Dashboard / Műszerfal kimutatások a Raktárhely kezeléshez ideérve:\n" +"----------------------------------------------------------\n" +"* Bejövő áruk (Grafikon)\n" +"* Kimenő áruk (Grafikon)\n" +"* Lehetséges beszerzés\n" +"* Raktári tételek analízisei / elemzései\n" +"* Záró tételek raktárhelyei\n" +"* Mozgás analízis, elemzés\n" +" " #. module: base #: model:ir.module.module,description:base.module_document_page @@ -16866,7 +16958,7 @@ msgstr "Gyermek elem mező" #. module: base #: view:ir.rule:0 msgid "Detailed algorithm:" -msgstr "" +msgstr "Részletes algoritmus:" #. module: base #: field:ir.actions.act_url,usage:0 @@ -16883,7 +16975,7 @@ msgstr "Művelet használata" #. module: base #: field:ir.module.module,name:0 msgid "Technical Name" -msgstr "" +msgstr "Technikai név" #. module: base #: model:ir.model,name:base.model_workflow_workitem @@ -16922,7 +17014,7 @@ msgstr "Automatikus betöltés bézet" #. module: base #: view:res.users:0 msgid "Allowed Companies" -msgstr "" +msgstr "Engedélyezett vállalatok" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_de @@ -16932,7 +17024,7 @@ msgstr "Németország - Könyvelés" #. module: base #: view:ir.sequence:0 msgid "Day of the Year: %(doy)s" -msgstr "" +msgstr "Az év napja: %(doy)s" #. module: base #: field:ir.ui.menu,web_icon:0 @@ -16955,6 +17047,8 @@ msgid "" "If this field is empty, the view applies to all users. Otherwise, the view " "applies to the users of those groups only." msgstr "" +"Ha ez a mező üres, akkor a nézet az összes felhasználóra érvényes. " +"Egyébként, csak arra a kijelölt csoport felhasználóra vonatkozik a nézet." #. module: base #: selection:base.language.install,lang:0 @@ -16988,21 +17082,44 @@ msgid "" "customers' expenses if your work by project.\n" " " msgstr "" +"\n" +"Munkavállalók szerinti kiadások kezelése\n" +"============================\n" +"\n" +"Ez az alkalmazás lehetővé teszi a munkavállalók napi kiadásait. Hozzáférést " +"biztosít a munkavállalói kiadási jegyzeteihez és azok kiegészítésének és " +"érvényesítésének jogához vagy érvénytelenítheti is a jegyzeteket. Az " +"érvényesítés után egy számlát készít a munkavállaló részére.\n" +"A munkavállalók bevihetik a saját kiadásaikat amit az érvényesítési út " +"automatikusan felad könyvelésre az osztályvezető érvényesítése után.\n" +"\n" +"\n" +"A teljes folyamat a következő:\n" +"----------------------------------\n" +"* Kiadás terve\n" +"* a munkavállaló visszaigazolása a listára\n" +"* az osztályvezetője általi érvényesítés\n" +"* a könyvelő érvényesítése és számla készítés\n" +"\n" +"Ez a modul használja az analitikai, elemző számlát és kompatibilis az " +"időbeosztásos számlázás modullal így automatikus munkavállalói kiadás újra-" +"számlázást készíthet ha projektenként dolgozik.\n" +" " #. module: base #: view:base.language.export:0 msgid "Export Settings" -msgstr "" +msgstr "A beállítások exportálása" #. module: base #: field:ir.actions.act_window,src_model:0 msgid "Source Model" -msgstr "" +msgstr "Modell forrás" #. module: base #: view:ir.sequence:0 msgid "Day of the Week (0:Monday): %(weekday)s" -msgstr "" +msgstr "A hét napja (0:Hétfő): %(weekday)s" #. module: base #: code:addons/base/module/wizard/base_module_upgrade.py:84 @@ -17016,7 +17133,7 @@ msgstr "Függőség nem teljesült !" #: code:addons/base/ir/ir_model.py:1023 #, python-format msgid "Administrator access is required to uninstall a module" -msgstr "" +msgstr "Adminisztrátori hozzáférés szükséges a modul törléséhez" #. module: base #: model:ir.model,name:base.model_base_module_configuration @@ -17032,6 +17149,10 @@ msgid "" "\n" "(Document type: %s, Operation: %s)" msgstr "" +"Az igényelt műveletet nem lehetett végrehajtani biztonsági korlátok miatt. " +"Kérem vegye fel a kapcsolatot a rendszer adminisztrátorral.\n" +"\n" +"(Dokumentum típus: %s, Művelet: %s)" #. module: base #: model:ir.module.module,description:base.module_idea @@ -17048,6 +17169,19 @@ msgid "" "The managers can obtain an easy view of best ideas from all the users.\n" "Once installed, check the menu 'Ideas' in the 'Tools' main menu." msgstr "" +"\n" +"Ez a modul lehetővé teszi a felhasználók könnyű és hatékony vállalati " +"fejlesztéshez való csatlakozását.\n" +"=============================================================================" +"==========\n" +"\n" +"Lehetővé teszi mindenki számára az ötleteinek közzétételét a különböző " +"témákban.\n" +"Ezután, a többi felhasználó megjegyzéseket fűzhet hozzá és szavazhat egy " +"bizonyos ötletre.\n" +"Minden ötletnek van egy pontértékelése a szavazatok alapján.\n" +"A vezető rálát az összes felhasználóra és az ötleteikre.\n" +"Ha telepítve lett, az 'eszközök' menü 'ötletek' címszó alatt találja az meg." #. module: base #: code:addons/orm.py:5248 @@ -17056,6 +17190,8 @@ msgid "" "%s This might be '%s' in the current model, or a field of the same name in " "an o2m." msgstr "" +"%s Ez lehet, hogy '%s' a jelenlegi modellben, vagy egy mező ugyanazzal a " +"névvel az o2m-ben." #. module: base #: model:ir.module.module,description:base.module_account_payment @@ -17087,6 +17223,29 @@ msgid "" "have a new option to import payment orders as bank statement lines.\n" " " msgstr "" +"\n" +"Modul a beszállítók számlái kifizetésének kezeléséhez.\n" +"=======================================================\n" +"\n" +"Ez a modul lehetővé teszi a kifizetések létrehozását és kezelését, a " +"következő szándékkal\n" +"-----------------------------------------------------------------------------" +"---- \n" +" * egy a könnyű plug-in alap variációkból az automatikus kifizetés " +"működtetésre.\n" +" * lehetővé teszi a hatékonyabb számla kifizetés szervezést.\n" +"\n" +"Figyelem:\n" +"~~~~~~~~\n" +"A kifizetés megbízás visszaigazolása nem készít könyvelés bejegyzést, csak " +"rögzíti a \n" +"tényt ,hogy elkészítette a bankhoz a megbízást. A megbízás bevitelét\n" +"el kell végezni a szokásos módon a banki kivonattal. Azonban, ezt csak\n" +"akkor, ha megjött a banktól a kivonat, hogy azt a bank befogadta \n" +"azt és ekkor beviheti azt a könyvelésébe is. Ennek a műveletnek a " +"segítségéhez, lesz\n" +"egy új lehetősége a fizetési megbízás importálása mint banki kivonat sorok.\n" +" " #. module: base #: field:ir.model,access_ids:0 @@ -17099,7 +17258,7 @@ msgstr "Hozzáférés" #: field:res.partner,vat:0 #, python-format msgid "TIN" -msgstr "" +msgstr "TIN" #. module: base #: model:res.country,name:base.aw @@ -17110,7 +17269,7 @@ msgstr "Aruba" #: code:addons/base/module/wizard/base_module_import.py:58 #, python-format msgid "File is not a zip file!" -msgstr "" +msgstr "A fájl nem zip fájl!" #. module: base #: model:res.country,name:base.ar @@ -17164,7 +17323,7 @@ msgstr "Haladó kimutatás" #. module: base #: model:ir.module.module,summary:base.module_purchase msgid "Purchase Orders, Receptions, Supplier Invoices" -msgstr "" +msgstr "Megrendelések, Átvétel igazolások, Beszállítói számlák" #. module: base #: model:ir.module.module,description:base.module_hr_payroll @@ -17183,6 +17342,19 @@ msgid "" " * Integrated with Holiday Management\n" " " msgstr "" +"\n" +"Általános bérszámfejtői rendszer\n" +"=======================\n" +"\n" +" * Munkavállalók adatai\n" +" * Munkavállalók szerződései\n" +" * Útlevél alapú szerződés\n" +" * Engedmények/Levonások\n" +" * Lehetőség az alap/Bruttó/Nettó fizetés beállításához\n" +" * Munkavállalók fizetési papírjai\n" +" * Havi bérszámfejtési regiszter\n" +" * Integrálva a szabadság szervezővel\n" +" " #. module: base #: model:ir.model,name:base.model_ir_model_data @@ -17202,7 +17374,7 @@ msgstr "Értékesítés utáni szolgáltatások" #. module: base #: field:base.language.import,code:0 msgid "ISO Code" -msgstr "" +msgstr "ISO Kód" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_fr @@ -17217,7 +17389,7 @@ msgstr "Indítás" #. module: base #: selection:res.partner,type:0 msgid "Shipping" -msgstr "" +msgstr "Szállítás" #. module: base #: model:ir.module.module,description:base.module_project_mrp @@ -17252,6 +17424,30 @@ msgid "" "the\n" "task is completed.\n" msgstr "" +"\n" +"Az beszerzéssoraiból automatikusan készít projekt/terv feladatot.\n" +"===========================================================\n" +"\n" +"Ez a modul minden beszerzés igény sorból elkészít egy új feladatot\n" +"(pl.: a megrendelés sorait), ha a szóban forgó termék kielégíti a következő\n" +"jellemzőket:\n" +"\n" +" * Termék típusa = Szolgáltatás\n" +" * Beszerzés módszere (Megrendelés végrehajtás) = MTO (Rendelés " +"előkészítése)\n" +" * Ellátás/Beszerzés módszer = Gyártás\n" +"\n" +"Ezen felül, ha a tervet a termék leírásban meghatározták (a beszerzés " +"fülön), \n" +"akkor egy új munka lesz létrehozva ehhez a tervhez. Máskülönben, az új\n" +"feladat nem függ egyik tervtől sem, és később hozzáadható egy másik tervhez " +"kézzel.\n" +"\n" +"Ha a terv feladat el lett végezve vagy törölve lett, akkor a kapcsolódó " +"beszerzés \n" +"munkafolyamat frissítve lesz annak megfelelően. Például, ha ez a beszerzés \n" +"egy megrendelés sorához tartozik, akkor a megrendelés sora leszállításként \n" +"értendő, ha a feladatot elvégezték.\n" #. module: base #: field:ir.actions.act_window,limit:0 @@ -17261,13 +17457,13 @@ msgstr "Limit" #. module: base #: model:res.groups,name:base.group_hr_user msgid "Officer" -msgstr "" +msgstr "Hivatalnok" #. module: base #: code:addons/orm.py:789 #, python-format msgid "Serialization field `%s` not found for sparse field `%s`!" -msgstr "" +msgstr "Soros művelet mező `%s` nem található az elszórt mezőkhöz `%s`!" #. module: base #: model:res.country,name:base.jm @@ -17278,7 +17474,7 @@ msgstr "Jamaika" #: field:res.partner,color:0 #: field:res.partner.address,color:0 msgid "Color Index" -msgstr "" +msgstr "Szín mutató" #. module: base #: model:ir.actions.act_window,help:base.action_partner_category_form @@ -17312,12 +17508,26 @@ msgid "" "user name and password for the invitation of the survey.\n" " " msgstr "" +"\n" +"Ez a modul felmérésekhez használható.\n" +"==================================\n" +"\n" +"Ez a különböző felhasználók egyes kérdéseinek a válaszán vagy vizsgálati " +"szempontjain alapul.\n" +"Egy felmérésnek több oldala lehet. Mindegyik oldal több kérdést tartalmazhat " +"és mindegyik\n" +"kérdésre több választ is tartalmazhat. Különböző felhasználó különböző " +"választ adhat a \n" +"különböző kérdésekre ha a felmérés elkészült. Partnerek is küldhetnek emailt " +"a felhasználó\n" +"nevével és jelszóval meghívásként a felmérésben való részvételhez.\n" +" " #. module: base #: code:addons/base/ir/ir_model.py:163 #, python-format msgid "Model '%s' contains module data and cannot be removed!" -msgstr "" +msgstr "Modell '%s' modul adatokat tartalmaz és ezért nem lehet törölni!" #. module: base #: model:res.country,name:base.az @@ -17334,12 +17544,12 @@ msgstr "Figyelem" #. module: base #: model:ir.module.module,shortdesc:base.module_edi msgid "Electronic Data Interchange (EDI)" -msgstr "" +msgstr "Elektormos adat kicserélés (EDI)" #. module: base #: model:ir.module.module,shortdesc:base.module_account_anglo_saxon msgid "Anglo-Saxon Accounting" -msgstr "" +msgstr "Angolszász könyvelés" #. module: base #: model:res.country,name:base.vg @@ -17365,12 +17575,12 @@ msgstr "Cseh / Čeština" #. module: base #: model:ir.module.category,name:base.module_category_generic_modules msgid "Generic Modules" -msgstr "" +msgstr "Általános modulok" #. module: base #: model:res.country,name:base.mk msgid "Macedonia, the former Yugoslav Republic of" -msgstr "" +msgstr "Macedónia, korábban Jugoszláv Köztársaság" #. module: base #: model:res.country,name:base.rw @@ -17384,11 +17594,14 @@ msgid "" "Allow users to login through OpenID.\n" "====================================\n" msgstr "" +"\n" +"Engedélyezi a felhasználók OpenID általi belépését.\n" +"====================================\n" #. module: base #: help:ir.mail_server,smtp_port:0 msgid "SMTP Port. Usually 465 for SSL, and 25 or 587 for other cases." -msgstr "" +msgstr "SMTP Port. Rendszerint 465 az SSL, és 25 vagy 587 egyéb esetben." #. module: base #: model:res.country,name:base.ck @@ -17419,7 +17632,7 @@ msgstr "Jelenlegi ablak" #: model:ir.module.category,name:base.module_category_hidden #: view:res.users:0 msgid "Technical Settings" -msgstr "" +msgstr "Műszaki beállítások" #. module: base #: model:ir.module.category,description:base.module_category_accounting_and_finance @@ -17427,16 +17640,18 @@ msgid "" "Helps you handle your accounting needs, if you are not an accountant, we " "suggest you to install only the Invoicing." msgstr "" +"Segít a könyvelés igényeinek kezelésében, ha Ön nem könyvelő, akkor azt " +"ajánljuk, hogy csak a számlázást telepítse." #. module: base #: model:ir.module.module,shortdesc:base.module_plugin_thunderbird msgid "Thunderbird Plug-In" -msgstr "" +msgstr "Thunderbird kiegészítő plug-in" #. module: base #: model:ir.module.module,summary:base.module_event msgid "Trainings, Conferences, Meetings, Exhibitions, Registrations" -msgstr "" +msgstr "Képzések, Konferenciák, Találkozók, Kiállítások, Regisztrációk" #. module: base #: model:ir.model,name:base.model_res_country @@ -17454,7 +17669,7 @@ msgstr "Ország" #. module: base #: model:res.partner.category,name:base.res_partner_category_15 msgid "Wholesaler" -msgstr "" +msgstr "Nagykereskedő" #. module: base #: model:ir.module.module,shortdesc:base.module_base_vat @@ -17478,7 +17693,7 @@ msgstr "" #. module: base #: view:ir.values:0 msgid "Action Bindings/Defaults" -msgstr "" +msgstr "Foglalások/alapértelmezett tevékenységek" #. module: base #: view:base.language.export:0 @@ -17486,6 +17701,8 @@ msgid "" "file encoding, please be sure to view and edit\n" " using the same encoding." msgstr "" +"fájl kódolás, kérem nézze meg és szerkessze\n" +" ugyanazzal a kódolással." #. module: base #: view:ir.rule:0 @@ -17504,7 +17721,7 @@ msgstr "Hollandia - Könyvelés" #. module: base #: model:res.country,name:base.gs msgid "South Georgia and the South Sandwich Islands" -msgstr "" +msgstr "Dél-Georgia és a Dél-Sandwich-szigetek" #. module: base #: view:res.lang:0 @@ -17519,12 +17736,12 @@ msgstr "Spanyol (SV) / Español (SV)" #. module: base #: model:ir.actions.act_window,name:base.open_module_tree msgid "Install a Module" -msgstr "" +msgstr "Egy modul telepítése" #. module: base #: field:ir.module.module,auto_install:0 msgid "Automatic Installation" -msgstr "" +msgstr "Automata telepítés" #. module: base #: model:ir.module.module,description:base.module_l10n_hn @@ -17539,6 +17756,18 @@ msgid "" "taxes\n" "and the Lempira currency." msgstr "" +"\n" +"Hondurasz számlatükör\n" +"\n" +"\n" +"This is the base module to manage the accounting chart for Honduras.\n" +"====================================================================\n" +" \n" +"Agrega una nomenclatura contable para Honduras. También incluye impuestos y " +"la\n" +"moneda Lempira. -- Adds accounting chart for Honduras. It also includes " +"taxes\n" +"and the Lempira currency." #. module: base #: model:res.country,name:base.jp @@ -17589,6 +17818,29 @@ msgid "" "gives \n" " the spreading, for the selected Analytic Accounts of Budgets.\n" msgstr "" +"\n" +"Ez a modul lehetővé teszi könyvelők részére az analitika/elemzés szervezést " +"és a keresztváltós költségvetéseket.\n" +"==========================================================================\n" +"\n" +"Ha már a költségvetés meg van határozva (a " +"Számlák/Költségvetés/Költségvetések alatt), a terv irányító vezető " +"beállíthatja a tervezett összeget mindegyik analitikai/elemző számlán.\n" +"\n" +"A könyvelő láthatja a teljes tervezetet mindegyik költségvetésre annak " +"biztosítására, hogy ne legyen több/kevesebb költségvetés mint amennyi a " +"tervezett volt.\n" +"\n" +"Három kimutatás lehetséges:\n" +"----------------------------\n" +" 1. Az első a költségvetés listákból áll elő. Ez az elemző számlák " +"költségeinek a kiterjesztése.\n" +"\n" +" 2. A második az első összegzése, ez csak az válogatott elemző számlák " +"költségeinek a kiterjesztése.\n" +"\n" +" 3. Az utolsó az elérhető az analitikus/elemző számlatükörből .Ez a " +"költségek kiterjesztése a válogatott elemző számlákon.\n" #. module: base #: selection:ir.actions.act_window.view,view_mode:0 @@ -17637,11 +17889,13 @@ msgid "" "Ambiguous specification for field '%(field)s', only provide one of name, " "external id or database id" msgstr "" +"Kétértelmű meghatározás a mezőre '%(field)s', csak egy nevet adjon meg, " +"külső azonosító vagy adatbázis azonosító" #. module: base #: field:ir.sequence,implementation:0 msgid "Implementation" -msgstr "" +msgstr "Végrehajtás" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_ve @@ -17656,7 +17910,7 @@ msgstr "Chile" #. module: base #: model:ir.module.module,shortdesc:base.module_web_view_editor msgid "View Editor" -msgstr "" +msgstr "Nézet szerkesztő" #. module: base #: view:ir.cron:0 @@ -17673,7 +17927,7 @@ msgstr "Feltétel" #. module: base #: help:res.currency,rate:0 msgid "The rate of the currency to the currency of rate 1." -msgstr "" +msgstr "Deviza árfolyam az 1 deviza árfolyamához." #. module: base #: field:ir.ui.view,name:0 @@ -17683,7 +17937,7 @@ msgstr "Nézet neve" #. module: base #: model:ir.model,name:base.model_res_groups msgid "Access Groups" -msgstr "" +msgstr "Csoportok hozzáférése" #. module: base #: selection:base.language.install,lang:0 @@ -17718,6 +17972,22 @@ msgid "" "In that case, you can not use priorities any more on the different picking.\n" " " msgstr "" +"\n" +"Ez a modul lehetővé teszi a Just In Time számítást a beszerzési " +"megrendelésekhez.\n" +"==================================================================\n" +"\n" +"Ha telepíti ezt a modult, akkor nem kell az általános beszerzési ütemezőt\n" +"futtatnia többé (de még mindig kell a minimum rendelési pont szabály\n" +"ütemező, vagy például futtassa naponta).\n" +"Minden beszerzési megrendelés azonnal futtatva lesz, ami egyes esetekben\n" +"teljesítmény eséshez vezethet.\n" +"\n" +"Ez megemelheti a raktárkészletet mivel a termék le lesz foglalva amint " +"lehet\n" +"és az ütemezési idő nem lesz figyelembe véve többé.\n" +"Ebben az esetben, nem használhat prioritásokat a különböző kiválogatásokon.\n" +" " #. module: base #: model:res.country,name:base.hr @@ -17746,7 +18016,7 @@ msgstr "Rendszer frissítés" #: field:ir.actions.report.xml,report_sxw_content:0 #: field:ir.actions.report.xml,report_sxw_content_data:0 msgid "SXW Content" -msgstr "" +msgstr "SXW tartalom" #. module: base #: help:ir.sequence,prefix:0 @@ -17761,7 +18031,7 @@ msgstr "Seychelle-szigetek" #. module: base #: model:res.partner.category,name:base.res_partner_category_4 msgid "Gold" -msgstr "" +msgstr "Arany" #. module: base #: code:addons/base/res/res_company.py:159 @@ -17788,7 +18058,7 @@ msgstr "Általános információk" #. module: base #: field:ir.model.data,complete_name:0 msgid "Complete ID" -msgstr "" +msgstr "Teljes azonosító" #. module: base #: model:res.country,name:base.tc @@ -17801,6 +18071,8 @@ msgid "" "Tax Identification Number. Check the box if this contact is subjected to " "taxes. Used by the some of the legal statements." msgstr "" +"Adó azonosító szám. Jelölje be a négyzetet, ha a kapcsolat adóköteles. Egyes " +"jogi kifejezések használják." #. module: base #: field:res.partner.bank,partner_id:0 @@ -17827,6 +18099,26 @@ msgid "" "depending on the product's configuration.\n" " " msgstr "" +"\n" +"A beszerzések kiszámítására használ modul.\n" +"==============================================\n" +"\n" +"Az MRP eljárásban, beszerzési rendeléseket a gyártási rendelések, " +"megrendelések, \n" +"raktári elhelyezés elindításához használják. Beszerzési rendelések " +"automatikusan\n" +"generáltak a rendszerből és ha hiba nem jön közbe, a felhasználó nem\n" +"is lesz figyelmeztetve. Hiba esetén a rendszer egyes beszerzési kivételt " +"visz\n" +"fel az akadályozó problémáról információt küldve a felhasználónak, hogy azt\n" +"kézzel kell megoldani (mint, darabjegyzék BoM hiánya vagy nem létező " +"beszállító).\n" +"\n" +"A beszerzési rendelés elindít egy javaslatot a feltölteni kívánt termék\n" +"automatikus beszerzésére. Ez a beszerzés elindít egy tervet, \n" +"ami vagy a szállító felé egy beszerzés, vagy a termék beállítása szerinti \n" +"beszerzést.\n" +" " #. module: base #: code:addons/base/res/res_users.py:174 @@ -17887,7 +18179,7 @@ msgstr "" #. module: base #: view:res.partner:0 msgid "Internal Notes" -msgstr "" +msgstr "Belső jegyzetek" #. module: base #: selection:res.partner.address,type:0 @@ -17903,12 +18195,12 @@ msgstr "NyRt." #. module: base #: model:ir.module.module,shortdesc:base.module_purchase_requisition msgid "Purchase Requisitions" -msgstr "" +msgstr "Beszerzési igénylések" #. module: base #: selection:ir.actions.act_window,target:0 msgid "Inline Edit" -msgstr "" +msgstr "Lineáris szerkesztés" #. module: base #: selection:ir.cron,interval_type:0 @@ -17951,7 +18243,7 @@ msgstr "Objektum létrehozása" #. module: base #: model:res.country,name:base.ss msgid "South Sudan" -msgstr "" +msgstr "Dél-Szudán" #. module: base #: field:ir.filters,context:0 @@ -17961,7 +18253,7 @@ msgstr "Kontextus" #. module: base #: model:ir.module.module,shortdesc:base.module_sale_mrp msgid "Sales and MRP Management" -msgstr "" +msgstr "Eladás és MRP (Anyagszükséglet Tervezés) szervezése" #. module: base #: model:ir.actions.act_window,help:base.action_partner_form @@ -17975,6 +18267,15 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Kattintson egy kapcsolat hozzáadásához a címtárba.\n" +"

\n" +" OpenERP segítséget nyújt az ügyfél tevékenységek könnyű " +"nyomon követéséhez; \n" +" megbeszélések, az üzleti lehetőségek története,\n" +" dokumentumok, stb.\n" +"

\n" +" " #. module: base #: model:res.partner.category,name:base.res_partner_category_2 @@ -17984,7 +18285,7 @@ msgstr "Érdeklődő" #. module: base #: model:ir.module.module,shortdesc:base.module_stock_invoice_directly msgid "Invoice Picking Directly" -msgstr "" +msgstr "Árukiválogatás számlázása közvetlenül" #. module: base #: selection:base.language.install,lang:0 @@ -18018,6 +18319,15 @@ msgid "" "on a supplier purchase order into several accounts and analytic plans.\n" " " msgstr "" +"\n" +"alap modul az elemző megoszlások és beszerzési megrendelésekhez.\n" +"====================================================================\n" +"\n" +"Lehetővé teszi a felhasználók egyes elemző terveinek karbantartását. Ez " +"lehetővé\n" +"teszi a beszállító beszerzési megrendelés sorainak szétválasztását több " +"számlára és elemző tervekre.\n" +" " #. module: base #: model:res.country,name:base.lk diff --git a/openerp/addons/base/i18n/it.po b/openerp/addons/base/i18n/it.po index 69035022b92..3aad5ecfc8d 100644 --- a/openerp/addons/base/i18n/it.po +++ b/openerp/addons/base/i18n/it.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-03 16:01+0000\n" -"PO-Revision-Date: 2012-12-18 23:39+0000\n" +"PO-Revision-Date: 2012-12-20 23:39+0000\n" "Last-Translator: Sergio Corato \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-20 04:42+0000\n" +"X-Launchpad-Export-Date: 2012-12-21 04:38+0000\n" "X-Generator: Launchpad (build 16378)\n" #. module: base @@ -158,7 +158,7 @@ msgstr "" #. module: base #: help:res.partner,employee:0 msgid "Check this box if this contact is an Employee." -msgstr "Seleziona questo box se il contatto è un Impiegato." +msgstr "Seleziona questo box se il contatto è un Dipendente." #. module: base #: help:ir.model.fields,domain:0 diff --git a/openerp/addons/base/i18n/ro.po b/openerp/addons/base/i18n/ro.po index 837d51ef1f6..e265e9878d4 100644 --- a/openerp/addons/base/i18n/ro.po +++ b/openerp/addons/base/i18n/ro.po @@ -7,13 +7,13 @@ msgstr "" "Project-Id-Version: OpenERP Server 5.0.4\n" "Report-Msgid-Bugs-To: support@openerp.com\n" "POT-Creation-Date: 2012-12-03 16:01+0000\n" -"PO-Revision-Date: 2012-12-19 19:34+0000\n" +"PO-Revision-Date: 2012-12-20 20:38+0000\n" "Last-Translator: Fekete Mihai \n" "Language-Team: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Launchpad-Export-Date: 2012-12-20 04:42+0000\n" +"X-Launchpad-Export-Date: 2012-12-21 04:38+0000\n" "X-Generator: Launchpad (build 16378)\n" #. module: base @@ -375,7 +375,7 @@ msgstr "" #. module: base #: model:ir.module.module,shortdesc:base.module_sale msgid "Sales Management" -msgstr "" +msgstr "Gestionarea vanzarilor" #. module: base #: help:res.partner,user_id:0 @@ -647,7 +647,7 @@ msgstr "Wizardul urmator" #. module: base #: field:res.lang,date_format:0 msgid "Date Format" -msgstr "Format data" +msgstr "Formatul Datei" #. module: base #: model:ir.module.module,shortdesc:base.module_base_report_designer @@ -833,7 +833,7 @@ msgstr "Columbia" #. module: base #: model:res.partner.title,name:base.res_partner_title_mister msgid "Mister" -msgstr "" +msgstr "Domnul" #. module: base #: help:res.country,code:0 @@ -862,7 +862,7 @@ msgstr "Netradus(e)" #. module: base #: view:ir.mail_server:0 msgid "Outgoing Mail Server" -msgstr "" +msgstr "Server Iesire E-mail-uri" #. module: base #: help:ir.actions.act_window,context:0 @@ -896,7 +896,7 @@ msgstr "Mexic - Contabilitate" #: help:ir.actions.server,action_id:0 msgid "Select the Action Window, Report, Wizard to be executed." msgstr "" -"Selectati Fereastra de Actiune, Raport sau Asistent care urmeaza a fi " +"Selectati Fereastra de Actiune, Raportul sau Asistentul care urmeaza a fi " "executat(a)." #. module: base @@ -940,6 +940,33 @@ msgid "" "module named account_voucher.\n" " " msgstr "" +"\n" +"Contabilitate si Management Financiar.\n" +"====================================\n" +"\n" +"Modulul Finante si contabilitate acopera:\n" +"--------------------------------------------\n" +" * Contabilitatea Generala\n" +" * Costuri/Contabilitatea analitica\n" +" * Contabilitatea partii terte\n" +" * Gestonarea taxelor si impozitelor\n" +" * Bugete\n" +" * Facturile Clientului si ale Furnizorului\n" +" * Extrase bancare\n" +" * Procesul de reconciliere dupa partener\n" +"\n" +"Creeaza un panou pentru contabili care include:\n" +"--------------------------------------------------\n" +" Lista cu Facturile Clientilor care trebuie aprobate\n" +" Analiza Companiei\n" +" Grafic Trezorerie\n" +"\n" +"Procesele precum pastrarea unui registru contabil general sunt efectuate " +"prin Jurnalele financiare definite (linia inregistrarii sau gruparea se face " +"prin jurnal) \n" +"pentru un anumit an financiar, iar pentru pregatirea voucher-elor exista un " +"modul numit account_voucher (cont_voucher).\n" +" " #. module: base #: view:ir.model:0 @@ -959,6 +986,16 @@ msgid "" "

\n" " " msgstr "" +"

\n" +" Faceti click pentru a adauga un contact in agenda " +"dumneavoastra.\n" +"

\n" +" OpenERP va ajuta sa tineti evidenta cu usurinta a tuturor " +"activitatilor legate de\n" +" un client: discutii, istoricul oportunitatilor de afaceri,\n" +" documente, etc.\n" +"

\n" +" " #. module: base #: model:ir.module.module,description:base.module_web_linkedin @@ -969,6 +1006,11 @@ msgid "" "This module provides the Integration of the LinkedIn with OpenERP.\n" " " msgstr "" +"\n" +"Modulul OpenERP Web LinkedIn.\n" +"============================\n" +"Acest modul asigura Integrarea lui LinkedIn in OpenERP.\n" +" " #. module: base #: help:ir.actions.act_window,src_model:0 @@ -991,7 +1033,7 @@ msgstr "Iordania" #. module: base #: help:ir.cron,nextcall:0 msgid "Next planned execution date for this job." -msgstr "Data urmatoarei executii planificate pentru acest proiect" +msgstr "Data urmatoarei executii planificate pentru aceasta sarcina." #. module: base #: model:res.country,name:base.er @@ -1006,7 +1048,7 @@ msgstr "Numele companiei trebuie sa fie unic !" #. module: base #: model:ir.ui.menu,name:base.menu_base_action_rule_admin msgid "Automated Actions" -msgstr "Actiuni automate" +msgstr "Actiuni Automate" #. module: base #: model:ir.module.module,shortdesc:base.module_l10n_ro @@ -1016,7 +1058,7 @@ msgstr "Romania - Contabilitate" #. module: base #: model:ir.model,name:base.model_res_config_settings msgid "res.config.settings" -msgstr "" +msgstr "res.configurare.setari" #. module: base #: help:res.partner,image_small:0 @@ -1025,6 +1067,9 @@ msgid "" "image, with aspect ratio preserved. Use this field anywhere a small image is " "required." msgstr "" +"Imagine de dimensiune mica a acestui contact. Este redimensionata automat ca " +"o imagine de 64x64px, cu raportul aspect pastrat. Folositi acest camp " +"oriunde este necesara o imagine mica." #. module: base #: help:ir.actions.server,mobile:0 @@ -1046,7 +1091,7 @@ msgstr "Securitate si Autentificare" #. module: base #: model:ir.module.module,shortdesc:base.module_web_calendar msgid "Web Calendar" -msgstr "" +msgstr "Calendar Web" #. module: base #: selection:base.language.install,lang:0 @@ -1057,7 +1102,7 @@ msgstr "Suedeza / svenska" #: field:base.language.export,name:0 #: field:ir.attachment,datas_fname:0 msgid "File Name" -msgstr "" +msgstr "Nume Fisier" #. module: base #: model:res.country,name:base.rs @@ -1108,6 +1153,33 @@ msgid "" "also possible in order to automatically create a meeting when a holiday " "request is accepted by setting up a type of meeting in Leave Type.\n" msgstr "" +"\n" +"Gestioneaza concediile si cererile de alocare\n" +"=====================================\n" +"\n" +"Aceasta aplicatie controleaza programul de concedii al companiei " +"dumneavoastra. Le permite angajatilor sa solicite concedii. Astfel, " +"managerii pot verifica cererile pentru concedii si le pot aproba sau " +"respinge. In acest mod puteti controla planificarea in ansamblu a " +"concediilor pentru companie sau departament.\n" +"\n" +"Puteti configura diverse tipuri de concedii (de boala, de odihna, zile " +"platite, ...) si aloca repede concedii unui angajat sau departament folosind " +"cererile de alocare. Un angajat poate de asemenea sa faca o cerere pentru " +"mai multe zile libere facand o noua ALocare. Acest lucru va mari totalul " +"zilelor disponibile pentru acel tip de concediu (daca cererea este " +"acceptata).\n" +"\n" +"Puteti tine evidenta concediilor in diverse moduri urmarind rapoartele: \n" +"\n" +"* Rezumat Concedii \n" +"* Concedii pe Departamente\n" +"* Analiza Concediilor\n" +"\n" +"O sincronizare cu o agenda interna (Intalnirile modulului MRC) este de " +"asemenea posibila pentru a crea in mod automat o intalnire atunci cand o " +"cerere de concediu este acceptata prin setarea unui tip de intalnire in " +"Tipul Concediului.\n" #. module: base #: selection:base.language.install,lang:0 @@ -1155,7 +1227,7 @@ msgstr "Preferinte email" #: code:addons/base/ir/ir_fields.py:196 #, python-format msgid "'%s' does not seem to be a valid date for field '%%(field)s'" -msgstr "" +msgstr "'%s' nu pare a fi o data valabila pentru campul '%%(field)s'" #. module: base #: view:res.partner:0 diff --git a/openerp/addons/base/module/module.py b/openerp/addons/base/module/module.py index a10b38cf586..47a4cfc8174 100644 --- a/openerp/addons/base/module/module.py +++ b/openerp/addons/base/module/module.py @@ -24,12 +24,22 @@ from docutils.transforms import Transform, writer_aux from docutils.writers.html4css1 import Writer import imp import logging +import os import re +import shutil +import tempfile import urllib +import urllib2 +import zipfile import zipimport +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO # NOQA + import openerp -from openerp import modules, pooler, release, tools, addons +from openerp import modules, pooler, tools, addons from openerp.modules.db import create_categories from openerp.tools.parse_version import parse_version from openerp.tools.translate import _ @@ -43,14 +53,29 @@ ACTION_DICT = { 'res_model': 'base.module.upgrade', 'target': 'new', 'type': 'ir.actions.act_window', - 'nodestroy':True, + 'nodestroy': True, } +def backup(path, raise_exception=True): + path = os.path.normpath(path) + if not os.path.exists(path): + if not raise_exception: + return None + raise OSError('path does not exists') + cnt = 1 + while True: + bck = '%s~%d' % (path, cnt) + if not os.path.exists(bck): + shutil.move(path, bck) + return bck + cnt += 1 + + class module_category(osv.osv): _name = "ir.module.category" _description = "Application" - def _module_nbr(self,cr,uid, ids, prop, unknow_none, context): + def _module_nbr(self, cr, uid, ids, prop, unknow_none, context): cr.execute('SELECT category_id, COUNT(*) \ FROM ir_module_module \ WHERE category_id IN %(ids)s \ @@ -58,7 +83,7 @@ class module_category(osv.osv): FROM ir_module_category \ WHERE parent_id IN %(ids)s) \ GROUP BY category_id', {'ids': tuple(ids)} - ) + ) result = dict(cr.fetchall()) for id in ids: cr.execute('select id from ir_module_category where parent_id=%s', (id,)) @@ -71,16 +96,16 @@ class module_category(osv.osv): 'parent_id': fields.many2one('ir.module.category', 'Parent Application', select=True), 'child_ids': fields.one2many('ir.module.category', 'parent_id', 'Child Applications'), 'module_nr': fields.function(_module_nbr, string='Number of Modules', type='integer'), - 'module_ids' : fields.one2many('ir.module.module', 'category_id', 'Modules'), - 'description' : fields.text("Description", translate=True), - 'sequence' : fields.integer('Sequence'), - 'visible' : fields.boolean('Visible'), + 'module_ids': fields.one2many('ir.module.module', 'category_id', 'Modules'), + 'description': fields.text("Description", translate=True), + 'sequence': fields.integer('Sequence'), + 'visible': fields.boolean('Visible'), 'xml_id': fields.function(osv.osv.get_external_id, type='char', size=128, string="External ID"), } _order = 'name' _defaults = { - 'visible' : 1, + 'visible': 1, } class MyFilterMessages(Transform): @@ -119,7 +144,6 @@ class module(osv.osv): info = {} try: info = modules.load_information_from_description_file(name) - info['version'] = release.major_version + '.' + info['version'] except Exception: _logger.debug('Error when trying to fetch informations for ' 'module %s', name, exc_info=True) @@ -134,9 +158,10 @@ class module(osv.osv): return res def _get_latest_version(self, cr, uid, ids, field_name=None, arg=None, context=None): - res = dict.fromkeys(ids, '') + default_version = modules.adapt_version('1.0') + res = dict.fromkeys(ids, default_version) for m in self.browse(cr, uid, ids): - res[m.id] = self.get_module_info(m.name).get('version', '') + res[m.id] = self.get_module_info(m.name).get('version', default_version) return res def _get_views(self, cr, uid, ids, field_name=None, arg=None, context=None): @@ -167,9 +192,11 @@ class module(osv.osv): continue # then, search and group ir.model.data records - imd_models = dict( [(m,[]) for m in dmodels]) - imd_ids = model_data_obj.search(cr,uid,[('module','=', module_rec.name), - ('model','in',tuple(dmodels))]) + imd_models = dict([(m, []) for m in dmodels]) + imd_ids = model_data_obj.search(cr, uid, [ + ('module', '=', module_rec.name), + ('model', 'in', tuple(dmodels)) + ]) for imd_res in model_data_obj.read(cr, uid, imd_ids, ['model', 'res_id'], context=context): imd_models[imd_res['model']].append(imd_res['res_id']) @@ -181,7 +208,7 @@ class module(osv.osv): view_ids = imd_models.get('ir.ui.view', []) for v in view_obj.browse(cr, uid, view_ids, context=context): aa = v.inherit_id and '* INHERIT ' or '' - res_mod_dic['views_by_module'].append(aa + v.name + '('+v.type+')') + res_mod_dic['views_by_module'].append('%s%s (%s)' % (aa, v.name, v.type)) report_ids = imd_models.get('ir.actions.report.xml', []) for rx in report_obj.browse(cr, uid, report_ids, context=context): @@ -191,15 +218,13 @@ class module(osv.osv): for um in menu_obj.browse(cr, uid, menu_ids, context=context): res_mod_dic['menus_by_module'].append(um.complete_name) except KeyError, e: - _logger.warning( - 'Data not found for items of %s', module_rec.name) + _logger.warning('Data not found for items of %s', module_rec.name) except AttributeError, e: - _logger.warning( - 'Data not found for items of %s %s', module_rec.name, str(e)) + _logger.warning('Data not found for items of %s %s', module_rec.name, str(e)) except Exception, e: - _logger.warning('Unknown error while fetching data of %s', - module_rec.name, exc_info=True) - for key, _ in res.iteritems(): + _logger.warning('Unknown error while fetching data of %s', module_rec.name, exc_info=True) + + for key in res.iterkeys(): for k, v in res[key].iteritems(): res[key][k] = "\n".join(sorted(v)) return res @@ -232,36 +257,34 @@ class module(osv.osv): # installed_version refer the latest version (the one on disk) # latest_version refer the installed version (the one in database) # published_version refer the version available on the repository - 'installed_version': fields.function(_get_latest_version, - string='Latest Version', type='char'), + 'installed_version': fields.function(_get_latest_version, string='Latest Version', type='char'), 'latest_version': fields.char('Installed Version', size=64, readonly=True), 'published_version': fields.char('Published Version', size=64, readonly=True), 'url': fields.char('URL', size=128, readonly=True), 'sequence': fields.integer('Sequence'), - 'dependencies_id': fields.one2many('ir.module.module.dependency', - 'module_id', 'Dependencies', readonly=True), + 'dependencies_id': fields.one2many('ir.module.module.dependency', 'module_id', 'Dependencies', readonly=True), 'auto_install': fields.boolean('Automatic Installation', - help='An auto-installable module is automatically installed by the ' - 'system when all its dependencies are satisfied. ' - 'If the module has no dependency, it is always installed.'), + help='An auto-installable module is automatically installed by the ' + 'system when all its dependencies are satisfied. ' + 'If the module has no dependency, it is always installed.'), 'state': fields.selection([ - ('uninstallable','Not Installable'), - ('uninstalled','Not Installed'), - ('installed','Installed'), - ('to upgrade','To be upgraded'), - ('to remove','To be removed'), - ('to install','To be installed') + ('uninstallable', 'Not Installable'), + ('uninstalled', 'Not Installed'), + ('installed', 'Installed'), + ('to upgrade', 'To be upgraded'), + ('to remove', 'To be removed'), + ('to install', 'To be installed') ], string='Status', readonly=True, select=True), 'demo': fields.boolean('Demo Data', readonly=True), 'license': fields.selection([ - ('GPL-2', 'GPL Version 2'), - ('GPL-2 or any later version', 'GPL-2 or later version'), - ('GPL-3', 'GPL Version 3'), - ('GPL-3 or any later version', 'GPL-3 or later version'), - ('AGPL-3', 'Affero GPL-3'), - ('Other OSI approved licence', 'Other OSI Approved Licence'), - ('Other proprietary', 'Other Proprietary') + ('GPL-2', 'GPL Version 2'), + ('GPL-2 or any later version', 'GPL-2 or later version'), + ('GPL-3', 'GPL Version 3'), + ('GPL-3 or any later version', 'GPL-3 or later version'), + ('AGPL-3', 'Affero GPL-3'), + ('Other OSI approved licence', 'Other OSI Approved Licence'), + ('Other proprietary', 'Other Proprietary') ], string='License', readonly=True), 'menus_by_module': fields.function(_get_views, string='Menus', type='text', multi="meta", store=True), 'reports_by_module': fields.function(_get_views, string='Reports', type='text', multi="meta", store=True), @@ -283,7 +306,7 @@ class module(osv.osv): return _('The name of the module must be unique !') _sql_constraints = [ - ('name_uniq', 'UNIQUE (name)',_name_uniq_msg ), + ('name_uniq', 'UNIQUE (name)', _name_uniq_msg), ] def unlink(self, cr, uid, ids, context=None): @@ -292,10 +315,9 @@ class module(osv.osv): if isinstance(ids, (int, long)): ids = [ids] mod_names = [] - for mod in self.read(cr, uid, ids, ['state','name'], context): + for mod in self.read(cr, uid, ids, ['state', 'name'], context): if mod['state'] in ('installed', 'to upgrade', 'to remove', 'to install'): - raise orm.except_orm(_('Error'), - _('You try to remove a module that is installed or will be installed')) + raise orm.except_orm(_('Error'), _('You try to remove a module that is installed or will be installed')) mod_names.append(mod['name']) #Removing the entry from ir_model_data #ids_meta = self.pool.get('ir.model.data').search(cr, uid, [('name', '=', 'module_meta_information'), ('module', 'in', mod_names)]) @@ -340,7 +362,7 @@ class module(osv.osv): raise orm.except_orm(_('Error'), msg % (module_name, e.args[0])) def state_update(self, cr, uid, ids, newstate, states_to_update, context=None, level=100): - if level<1: + if level < 1: raise orm.except_orm(_('Error'), _('Recursion error in modules dependencies !')) demo = False for module in self.browse(cr, uid, ids, context=context): @@ -348,9 +370,9 @@ class module(osv.osv): for dep in module.dependencies_id: if dep.state == 'unknown': raise orm.except_orm(_('Error'), _("You try to install module '%s' that depends on module '%s'.\nBut the latter module is not available in your system.") % (module.name, dep.name,)) - ids2 = self.search(cr, uid, [('name','=',dep.name)]) + ids2 = self.search(cr, uid, [('name', '=', dep.name)]) if dep.state != newstate: - mdemo = self.state_update(cr, uid, ids2, newstate, states_to_update, context, level-1,) or mdemo + mdemo = self.state_update(cr, uid, ids2, newstate, states_to_update, context, level - 1) or mdemo else: od = self.browse(cr, uid, ids2)[0] mdemo = od.demo or mdemo @@ -359,7 +381,7 @@ class module(osv.osv): if not module.dependencies_id: mdemo = module.demo if module.state in states_to_update: - self.write(cr, uid, [module.id], {'state': newstate, 'demo':mdemo}) + self.write(cr, uid, [module.id], {'state': newstate, 'demo': mdemo}) demo = demo or mdemo return demo @@ -403,7 +425,7 @@ class module(osv.osv): return self._button_immediate_function(cr, uid, ids, self.button_install, context=context) def button_install_cancel(self, cr, uid, ids, context=None): - self.write(cr, uid, ids, {'state': 'uninstalled', 'demo':False}) + self.write(cr, uid, ids, {'state': 'uninstalled', 'demo': False}) return True def module_uninstall(self, cr, uid, ids, context=None): @@ -421,12 +443,13 @@ class module(osv.osv): return True def downstream_dependencies(self, cr, uid, ids, known_dep_ids=None, - exclude_states=['uninstalled','uninstallable','to remove'], + exclude_states=['uninstalled', 'uninstallable', 'to remove'], context=None): """Return the ids of all modules that directly or indirectly depend on the given module `ids`, and that satisfy the `exclude_states` filter""" - if not ids: return [] + if not ids: + return [] known_dep_ids = set(known_dep_ids or []) cr.execute('''SELECT DISTINCT m.id FROM @@ -437,13 +460,13 @@ class module(osv.osv): d.name IN (SELECT name from ir_module_module where id in %s) AND m.state NOT IN %s AND m.id NOT IN %s ''', - (tuple(ids),tuple(exclude_states), tuple(known_dep_ids or ids))) + (tuple(ids), tuple(exclude_states), tuple(known_dep_ids or ids))) new_dep_ids = set([m[0] for m in cr.fetchall()]) missing_mod_ids = new_dep_ids - known_dep_ids known_dep_ids |= new_dep_ids if missing_mod_ids: known_dep_ids |= set(self.downstream_dependencies(cr, uid, list(missing_mod_ids), - known_dep_ids, exclude_states,context)) + known_dep_ids, exclude_states, context)) return list(known_dep_ids) def _button_immediate_function(self, cr, uid, ids, function, context=None): @@ -460,9 +483,9 @@ class module(osv.osv): menu_obj = self.pool.get('ir.ui.menu') menu_ids = menu_obj.search(cr, uid, [('parent_id', '=', False)], context=context) return { - 'type' : 'ir.actions.client', - 'tag' : 'reload', - 'params' : {'menu_id' : menu_ids and menu_ids[0] or False} + 'type': 'ir.actions.client', + 'tag': 'reload', + 'params': {'menu_id': menu_ids and menu_ids[0] or False} } def button_immediate_uninstall(self, cr, uid, ids, context=None): @@ -496,20 +519,19 @@ class module(osv.osv): self.update_list(cr, uid) i = 0 - while i parse_version(mod.latest_version or ''): + if parse_version(terp.get('version', default_version)) > parse_version(mod.latest_version or default_version): res[0] += 1 if updated_values: self.write(cr, uid, mod.id, updated_values) @@ -587,24 +610,32 @@ class module(osv.osv): self._update_dependencies(cr, uid, mod, terp.get('depends', [])) self._update_category(cr, uid, mod, terp.get('category', 'Uncategorized')) + # Trigger load_addons if new module have been discovered it exists on + # wsgi handlers, so they can react accordingly + if tuple(res) != (0, 0): + for handler in openerp.service.wsgi_server.module_handlers: + if hasattr(handler,'load_addons'): + handler.load_addons() + return res def download(self, cr, uid, ids, download=True, context=None): res = [] + default_version = modules.adapt_version('1.0') for mod in self.browse(cr, uid, ids, context=context): if not mod.url: continue match = re.search('-([a-zA-Z0-9\._-]+)(\.zip)', mod.url, re.I) - version = '0' + version = default_version if match: version = match.group(1) - if parse_version(mod.installed_version or '0') >= parse_version(version): + if parse_version(mod.installed_version) >= parse_version(version): continue res.append(mod.url) if not download: continue zip_content = urllib.urlopen(mod.url).read() - fname = modules.get_module_path(str(mod.name)+'.zip', downloaded=True) + fname = modules.get_module_path(str(mod.name) + '.zip', downloaded=True) try: with open(fname, 'wb') as fp: fp.write(zip_content) @@ -614,17 +645,77 @@ class module(osv.osv): raise orm.except_orm(_('Error'), _('Can not create the module file:\n %s') % (fname,)) terp = self.get_module_info(mod.name) self.write(cr, uid, mod.id, self.get_values_from_terp(terp)) - cr.execute('DELETE FROM ir_module_module_dependency ' \ - 'WHERE module_id = %s', (mod.id,)) - self._update_dependencies(cr, uid, mod, terp.get('depends', - [])) - self._update_category(cr, uid, mod, terp.get('category', - 'Uncategorized')) + cr.execute('DELETE FROM ir_module_module_dependency WHERE module_id = %s', (mod.id,)) + self._update_dependencies(cr, uid, mod, terp.get('depends', [])) + self._update_category(cr, uid, mod, terp.get('category', 'Uncategorized')) # Import module zimp = zipimport.zipimporter(fname) zimp.load_module(mod.name) return res + def install_from_urls(self, cr, uid, urls, context=None): + OPENERP = 'openerp' + tmp = tempfile.mkdtemp() + try: + for module_name, url in urls.items(): + if not url: + continue # nothing to download, local version is already the last one + try: + content = urllib2.urlopen(url).read() + except Exception, e: + _logger.exception('ggr') + raise osv.except_osv('grrr', e) + else: + zipfile.ZipFile(StringIO(content)).extractall(tmp) + assert os.path.isdir(os.path.join(tmp, module_name)) + + for module_name in urls: + if module_name == OPENERP: + continue # special case. handled below + module_path = modules.get_module_path(module_name, downloaded=True, display_warning=False) + bck = backup(module_path, False) + shutil.move(os.path.join(tmp, module_name), module_path) + if bck: + shutil.rmtree(bck) + + if urls.get(OPENERP, None): + # special case. it containt the server and the base module. + # extract path is not the same + + base_path = os.path.dirname(modules.get_module_path('base')) + + # copy all modules in the SERVER/openerp/addons directory to the new "openerp" module (except base itself) + for d in os.listdir(base_path): + if d != 'base' and os.path.isdir(os.path.join(base_path, d)): + destdir = os.path.join(tmp, OPENERP, 'addons', d) # XXX 'openerp' subdirectory ? + shutil.copytree(os.path.join(base_path, d), destdir) + + # then replace the server by the new "base" module + server_dir = openerp.tools.config['root_path'] # XXX or dirname() + bck = backup(server_dir) + shutil.move(os.path.join(tmp, OPENERP), server_dir) + #if bck: + # shutil.rmtree(bck) + + self.update_list(cr, uid, context=context) + + ids = self.search(cr, uid, [('name', 'in', urls.keys())], context=context) + if self.search_count(cr, uid, [('id', 'in', ids), ('state', '=', 'installed')], context=context): + # if any to update + cr.commit() + openerp.service.restart_server() + return { + 'type': 'ir.actions.client', + 'tag': 'home', + 'params': {'wait': True}, + } + return self.button_immediate_install(cr, uid, ids, context=context) + finally: + shutil.rmtree(tmp) + + def install_by_names(self, cr, uid, names, context=None): + raise NotImplementedError('# TODO') + def _update_dependencies(self, cr, uid, mod_browse, depends=None): if depends is None: depends = [] @@ -679,20 +770,20 @@ class module_dependency(osv.osv): _columns = { # The dependency name - 'name': fields.char('Name', size=128, select=True), + 'name': fields.char('Name', size=128, select=True), # The module that depends on it 'module_id': fields.many2one('ir.module.module', 'Module', select=True, ondelete='cascade'), 'state': fields.function(_state, type='selection', selection=[ - ('uninstallable','Uninstallable'), - ('uninstalled','Not Installed'), - ('installed','Installed'), - ('to upgrade','To be upgraded'), - ('to remove','To be removed'), - ('to install','To be installed'), + ('uninstallable', 'Uninstallable'), + ('uninstalled', 'Not Installed'), + ('installed', 'Installed'), + ('to upgrade', 'To be upgraded'), + ('to remove', 'To be removed'), + ('to install', 'To be installed'), ('unknown', 'Unknown'), - ], string='Status', readonly=True, select=True), + ], string='Status', readonly=True, select=True), } # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/module/module_view.xml b/openerp/addons/base/module/module_view.xml index 5f33a437f08..3a43a2591ba 100644 --- a/openerp/addons/base/module/module_view.xml +++ b/openerp/addons/base/module/module_view.xml @@ -1,9 +1,7 @@ - - ir.module.category.form ir.module.category @@ -32,7 +30,6 @@ - ir.module.module.list.select ir.module.module @@ -43,7 +40,7 @@ - + @@ -53,37 +50,6 @@ - - - Modules Kanban - ir.module.module - - - - - - - - -
- - -
-

-

-
- -

- - -
-
-
-
-
-
-
- Modules ir.module.module @@ -100,7 +66,6 @@ - ir.module.module.form ir.module.module @@ -176,20 +141,74 @@ + + Modules Kanban + ir.module.module + + + + + + + + +
+ + +
+

+

+
+ +

+ + +
+
+
+
+
+
+
- Install a Module + + Modules ir.module.module form kanban,tree,form - {'search_default_app':1} +

No module found!

You should try others search criteria.

- + + + + + + Apps + apps + + + + + + Updates + apps.updates + {} + + +
diff --git a/openerp/addons/base/module/wizard/base_export_language_view.xml b/openerp/addons/base/module/wizard/base_export_language_view.xml index cbf7104f957..f184186a500 100644 --- a/openerp/addons/base/module/wizard/base_export_language_view.xml +++ b/openerp/addons/base/module/wizard/base_export_language_view.xml @@ -11,7 +11,7 @@ - +

Export Complete

diff --git a/openerp/addons/base/module/wizard/base_module_import_view.xml b/openerp/addons/base/module/wizard/base_module_import_view.xml index 192bf6c2a92..d9d6bb6ee78 100644 --- a/openerp/addons/base/module/wizard/base_module_import_view.xml +++ b/openerp/addons/base/module/wizard/base_module_import_view.xml @@ -43,7 +43,7 @@ id="menu_view_base_module_import" parent="menu_management" groups="base.group_no_one" - sequence="1"/> + sequence="6"/> --> diff --git a/openerp/addons/base/module/wizard/base_module_update_view.xml b/openerp/addons/base/module/wizard/base_module_update_view.xml index 75d2b1316a6..cb9b9090294 100644 --- a/openerp/addons/base/module/wizard/base_module_update_view.xml +++ b/openerp/addons/base/module/wizard/base_module_update_view.xml @@ -18,17 +18,17 @@
-
-
- + Module Update @@ -45,7 +45,7 @@ id="menu_view_base_module_update" groups="base.group_no_one" parent="menu_management" - sequence="2" + sequence="40" icon="STOCK_CONVERT"/> diff --git a/openerp/addons/base/module/wizard/base_module_upgrade_view.xml b/openerp/addons/base/module/wizard/base_module_upgrade_view.xml index afd3a2e17b1..1a1225befcb 100644 --- a/openerp/addons/base/module/wizard/base_module_upgrade_view.xml +++ b/openerp/addons/base/module/wizard/base_module_upgrade_view.xml @@ -35,7 +35,7 @@ groups="base.group_no_one" id="menu_view_base_module_upgrade" parent="menu_management" - sequence="3"/> + sequence="50"/> Module Upgrade Install diff --git a/openerp/addons/base/res/__init__.py b/openerp/addons/base/res/__init__.py index 752bb03033a..59403545112 100644 --- a/openerp/addons/base/res/__init__.py +++ b/openerp/addons/base/res/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -32,6 +32,7 @@ import res_lang import ir_property import report +import wizard # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/res/res_config.py b/openerp/addons/base/res/res_config.py index 9513f48a27e..e9c813c19c9 100644 --- a/openerp/addons/base/res/res_config.py +++ b/openerp/addons/base/res/res_config.py @@ -466,7 +466,8 @@ class res_config_settings(osv.osv_memory): groups.append((name, ref(field_group), ref(field.implied_group))) elif name.startswith('module_') and isinstance(field, fields.boolean): mod_ids = ir_module.search(cr, uid, [('name', '=', name[7:])]) - modules.append((name, ir_module.browse(cr, uid, mod_ids[0], context))) + record = ir_module.browse(cr, uid, mod_ids[0], context) if mod_ids else None + modules.append((name, record)) else: others.append(name) @@ -490,7 +491,7 @@ class res_config_settings(osv.osv_memory): # modules: which modules are installed/to install for name, module in classified['module']: - res[name] = module.state in ('installed', 'to install', 'to upgrade') + res[name] = module and module.state in ('installed', 'to install', 'to upgrade') # other fields: call all methods that start with 'get_default_' for method in dir(self): @@ -501,9 +502,7 @@ class res_config_settings(osv.osv_memory): def execute(self, cr, uid, ids, context=None): ir_values = self.pool.get('ir.values') - ir_model_data = self.pool.get('ir.model.data') ir_module = self.pool.get('ir.module.module') - res_groups = self.pool.get('res.groups') classified = self._get_classified_fields(cr, uid, context) config = self.browse(cr, uid, ids[0], context) @@ -526,17 +525,26 @@ class res_config_settings(osv.osv_memory): getattr(self, method)(cr, uid, ids, context) # module fields: install/uninstall the selected modules - to_install_ids = [] + to_install_names = [] to_uninstall_ids = [] + lm = len('module_') for name, module in classified['module']: if config[name]: - if module.state == 'uninstalled': to_install_ids.append(module.id) + if not module or module.state == 'uninstalled': + to_install_names.append(name[lm:]) else: - if module.state in ('installed','upgrade'): to_uninstall_ids.append(module.id) + if module and module.state in ('installed', 'to upgrade'): + to_uninstall_ids.append(module.id) - if to_install_ids or to_uninstall_ids: - ir_module.button_uninstall(cr, uid, to_uninstall_ids, context=context) - ir_module.button_immediate_install(cr, uid, to_install_ids, context=context) + if to_uninstall_ids: + ir_module.button_immediate_uninstall(cr, uid, to_uninstall_ids, context=context) + + if to_install_names: + return { + 'type': 'ir.actions.client', + 'tag': 'apps', + 'params': {'modules': to_install_names}, + } config = self.pool.get('res.config').next(cr, uid, [], context=context) or {} if config.get('type') not in ('ir.actions.act_window_close',): diff --git a/openerp/addons/base/res/res_partner.py b/openerp/addons/base/res/res_partner.py index d236d867795..65bcf18653e 100644 --- a/openerp/addons/base/res/res_partner.py +++ b/openerp/addons/base/res/res_partner.py @@ -402,6 +402,8 @@ class res_partner(osv.osv, format_address): name = name + "\n" + self._display_address(cr, uid, record, without_company=True, context=context) name = name.replace('\n\n','\n') name = name.replace('\n\n','\n') + if context.get('show_email') and record.email: + name = "%s <%s>" % (name, record.email) res.append((record.id, name)) return res @@ -437,18 +439,23 @@ class res_partner(osv.osv, format_address): def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100): if not args: args = [] - if name and operator in ('=', 'ilike', '=ilike', 'like'): + if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): # search on the name of the contacts and of its company - name2 = operator == '=' and name or '%' + name + '%' + search_name = name + if operator in ('ilike', 'like'): + search_name = '%%%s%%' % name + if operator in ('=ilike', '=like'): + operator = operator[1:] + query_args = {'name': search_name} limit_str = '' - query_args = [name2] if limit: - limit_str = ' limit %s' - query_args += [limit] + limit_str = ' limit %(limit)s' + query_args['limit'] = limit cr.execute('''SELECT partner.id FROM res_partner partner LEFT JOIN res_partner company ON partner.parent_id = company.id - WHERE partner.name || ' (' || COALESCE(company.name,'') || ')' - ''' + operator + ''' %s ''' + limit_str, query_args) + WHERE partner.email ''' + operator +''' %(name)s + OR partner.name || ' (' || COALESCE(company.name,'') || ')' + ''' + operator + ' %(name)s ' + limit_str, query_args) ids = map(lambda x: x[0], cr.fetchall()) if args: ids = self.search(cr, uid, [('id', 'in', ids)] + args, limit=limit, context=context) diff --git a/openerp/addons/base/res/res_users_view.xml b/openerp/addons/base/res/res_users_view.xml index 9a4f88cd1fc..7e83b43179f 100644 --- a/openerp/addons/base/res/res_users_view.xml +++ b/openerp/addons/base/res/res_users_view.xml @@ -136,6 +136,10 @@
+
+
- diff --git a/openerp/addons/base/res/wizard/__init__.py b/openerp/addons/base/res/wizard/__init__.py new file mode 100644 index 00000000000..f572814a2cf --- /dev/null +++ b/openerp/addons/base/res/wizard/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2011 OpenERP S.A (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +import change_password_wizard \ No newline at end of file diff --git a/openerp/addons/base/res/wizard/change_password_wizard.py b/openerp/addons/base/res/wizard/change_password_wizard.py new file mode 100644 index 00000000000..4d1bfe67fce --- /dev/null +++ b/openerp/addons/base/res/wizard/change_password_wizard.py @@ -0,0 +1,81 @@ +# -*- coding: utf-8 -*- +############################################################################## +# +# OpenERP, Open Source Management Solution +# Copyright (C) 2004-2011 OpenERP S.A (). +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . +# +############################################################################## + +from openerp.osv import fields, osv + +class change_password_wizard(osv.TransientModel): + """ + A wizard to manage the change of users' passwords + """ + + _name = "change.password.wizard" + _description = "Change Password Wizard" + _columns = { + 'user_ids': fields.one2many('change.password.user', 'wizard_id', string='Users'), + } + + def default_get(self, cr, uid, fields, context=None): + if context == None: + context = {} + user_ids = context.get('active_ids', []) + wiz_id = context.get('active_id', None) + res = [] + users = self.pool.get('res.users').browse(cr, uid, user_ids, context=context) + for user in users: + res.append((0, 0, { + 'wizard_id': wiz_id, + 'user_id': user.id, + 'user_login': user.login, + })) + return {'user_ids': res} + + + def change_password_button(self, cr, uid, id, context=None): + wizard = self.browse(cr, uid, id, context=context)[0] + user_ids = [] + for user in wizard.user_ids: + user_ids.append(user.id) + self.pool.get('change.password.user').change_password_button(cr, uid, user_ids, context=context) + return { + 'type': 'ir.actions.act_window_close', + } + +class change_password_user(osv.TransientModel): + """ + A model to configure users in the change password wizard + """ + + _name = 'change.password.user' + _description = 'Change Password Wizard User' + _columns = { + 'wizard_id': fields.many2one('change.password.wizard', string='Wizard', required=True), + 'user_id': fields.many2one('res.users', string='User', required=True), + 'user_login': fields.char('User Login', readonly=True), + 'new_passwd': fields.char('New Password'), + } + _defaults = { + 'new_passwd': '', + } + + def change_password_button(self, cr, uid, ids, context=None): + for user in self.browse(cr, uid, ids, context=context): + self.pool.get('res.users').write(cr, uid, user.user_id.id, {'password': user.new_passwd}) + diff --git a/openerp/addons/base/res/wizard/change_password_wizard_view.xml b/openerp/addons/base/res/wizard/change_password_wizard_view.xml new file mode 100644 index 00000000000..c5bd5c96901 --- /dev/null +++ b/openerp/addons/base/res/wizard/change_password_wizard_view.xml @@ -0,0 +1,44 @@ + + + + + + + + + + Change Password + change.password.wizard + + + +
+
+ +
+
+ + + + Change Password Users + change.password.user + + + + + + + + + +
+
diff --git a/openerp/addons/base/static/src/js/apps.js b/openerp/addons/base/static/src/js/apps.js new file mode 100644 index 00000000000..397f028c1fd --- /dev/null +++ b/openerp/addons/base/static/src/js/apps.js @@ -0,0 +1,117 @@ +openerp.base = function(instance) { + + instance.base.apps_remote = null; + instance.base.apps_client = null; + + instance.base.Apps = instance.web.Widget.extend({ + template: 'EmptyComponent', + remote_action_id: 'loempia.action_embed', + failback_action_id: 'base.open_module_tree', + + init: function(parent, action) { + this._super(parent, action); + var options = action.params || {}; + + if (options.apps_user) { + sessionStorage.setItem('apps.login', options.apps_user); + } + if (options.apps_access_token) { + sessionStorage.setItem('apps.access_token', options.apps_access_token); + } + + this.params = options; // NOTE read by embedded client action + }, + + get_client: function() { + // return the client via a deferred, resolved or rejected depending if the remote host is available or not. + var check_client_available = function(client) { + var d = $.Deferred(); + var i = new Image(); + i.onerror = function() { + d.reject(client); + }; + i.onload = function() { + client.session.session_bind(client.origin).then(function() { + // check if client can authenticate + client.authenticate().then( + function() { /* done */ + d.resolve(client); + }, function() { /* fail */ + if (client.login === 'anonymous') { + d.reject(client); + } else { + sessionStorage.removeItem('apps.login'); + sessionStorage.removeItem('apps.access_token'); + client.bind_crendentials(client.dbname, 'anonymous', 'anonymous'); + client.authenticate().then( + function() { /* done */ + d.resolve(client); + }, function() { /* fail */ + d.reject(client); + }); + } + }); + }); + + }; + i.src = _.str.sprintf('%s/web/static/src/img/sep-a.gif', client.origin); + return d.promise(); + }; + if (instance.base.apps_client) { + return check_client_available(instance.base.apps_client); + } else { + var ICP = new instance.web.Model('ir.config_parameter'); + return ICP.call('get_param', ['apps.server', 'https://apps.openerp.com/apps']).then(function(u) { + var link = $(_.str.sprintf('', u))[0]; + var host = _.str.sprintf('%s//%s', link.protocol, link.host); + var dbname = link.pathname; + if (dbname[0] === '/') { + dbname = dbname.substr(1); + } + var login = (sessionStorage ? sessionStorage.getItem('apps.login') : null) || 'anonymous'; + var passwd = (sessionStorage ? sessionStorage.getItem('apps.access_token') : null) || 'anonymous'; + if (_.isNull(instance.base.apps_remote)) { + instance.base.apps_remote = new openerp.init(); + } + var client = new instance.base.apps_remote.web.EmbeddedClient(null, host, dbname, login, passwd); + instance.base.apps_client = client; + return check_client_available(client); + }); + } + }, + + destroy: function() { + if (instance.base.apps_client) { + instance.base.apps_client.destroy(); + } + return this._super(); + }, + + start: function() { + var self = this; + return self.get_client(). + done(function(client) { + client.replace(self.$el). + done(function() { + client.$el.removeClass('openerp'); + client.do_action(self.remote_action_id); + }); + }). + fail(function(client) { + self.do_warn('Apps Server not reachable.', 'Showing local modules.', true); + self.rpc('/web/action/load', {action_id: self.failback_action_id}).done(function(action) { + self.do_action(action); + instance.webclient.menu.open_action(action.id); + }); + }); + }, + }); + + instance.base.AppsUpdates = instance.base.Apps.extend({ + remote_action_id: 'loempia.action_embed_updates' + }); + + instance.web.client_actions.add("apps", "instance.base.Apps"); + instance.web.client_actions.add("apps.updates", "instance.base.AppsUpdates"); + +}; diff --git a/openerp/cli/server.py b/openerp/cli/server.py index d97d4c81571..bc83b735624 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -207,10 +207,15 @@ def quit_on_signals(): pass config = openerp.tools.config + openerp.service.stop_services() + + if getattr(openerp, 'phoenix', False): + # like the phoenix, reborn from ashes... + openerp.service._reexec() + return + if config['pidfile']: os.unlink(config['pidfile']) - - openerp.service.stop_services() sys.exit(0) def configure_babel_localedata_path(): diff --git a/openerp/modules/__init__.py b/openerp/modules/__init__.py index 56265e353a2..feaf014f568 100644 --- a/openerp/modules/__init__.py +++ b/openerp/modules/__init__.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -32,7 +32,8 @@ from openerp.modules.module import \ load_information_from_description_file, \ get_module_resource, zip_directory, \ get_module_path, initialize_sys_path, \ - load_openerp_module, init_module_models + load_openerp_module, init_module_models, \ + adapt_version from openerp.modules.loading import load_modules diff --git a/openerp/modules/module.py b/openerp/modules/module.py index bb4ff481fb9..98955aff492 100644 --- a/openerp/modules/module.py +++ b/openerp/modules/module.py @@ -3,7 +3,7 @@ # # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). -# Copyright (C) 2010-2011 OpenERP s.a. (). +# Copyright (C) 2010-2012 OpenERP s.a. (). # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -329,7 +329,7 @@ def load_information_from_description_file(module): 'license': 'AGPL-3', 'name': False, 'post_load': None, - 'version': '0.0.0', + 'version': '1.0', 'web': False, 'website': '', 'sequence': 100, @@ -349,6 +349,7 @@ def load_information_from_description_file(module): # 'active' has been renamed 'auto_install' info['auto_install'] = info['active'] + info['version'] = adapt_version(info['version']) return info #TODO: refactor the logger in this file to follow the logging guidelines @@ -447,15 +448,22 @@ def get_modules(): def get_modules_with_version(): modules = get_modules() - res = {} + res = dict.fromkeys(modules, adapt_version('1.0')) for module in modules: try: info = load_information_from_description_file(module) - res[module] = "%s.%s" % (release.major_version, info['version']) - except Exception, e: + res[module] = info['version'] + except Exception: continue return res +def adapt_version(version): + serie = release.major_version + if version == serie or not version.startswith(serie + '.'): + version = '%s.%s' % (serie, version) + return version + + def get_test_modules(module, submodule, explode): """ Return a list of submodules containing tests. diff --git a/openerp/release.py b/openerp/release.py index 50d9b8ac760..e66d924906b 100644 --- a/openerp/release.py +++ b/openerp/release.py @@ -50,4 +50,6 @@ author = 'OpenERP S.A.' author_email = 'info@openerp.com' license = 'AGPL-3' +nt_service_name = "openerp-server-" + serie + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/service/__init__.py b/openerp/service/__init__.py index f8752732cdf..307ee4a6526 100644 --- a/openerp/service/__init__.py +++ b/openerp/service/__init__.py @@ -21,6 +21,10 @@ ############################################################################## import logging +import os +import signal +import subprocess +import sys import threading import time @@ -33,6 +37,7 @@ import wsgi_server import openerp.modules import openerp.netsvc import openerp.osv +from openerp.release import nt_service_name import openerp.tools #.apidoc title: RPC Services @@ -97,27 +102,58 @@ def stop_services(): _logger.info("Initiating shutdown") _logger.info("Hit CTRL-C again or send a second signal to force the shutdown.") - logging.shutdown() # Manually join() all threads before calling sys.exit() to allow a second signal # to trigger _force_quit() in case some non-daemon threads won't exit cleanly. # threading.Thread.join() should not mask signals (at least in python 2.5). me = threading.currentThread() + _logger.debug('current thread: %r', me) for thread in threading.enumerate(): + _logger.debug('process %r (%r)', thread, thread.isDaemon()) if thread != me and not thread.isDaemon() and thread.ident != main_thread_id: while thread.isAlive(): + _logger.debug('join and sleep') # Need a busyloop here as thread.join() masks signals # and would prevent the forced shutdown. thread.join(0.05) time.sleep(0.05) + _logger.debug('--') openerp.modules.registry.RegistryManager.delete_all() + logging.shutdown() def start_services_workers(): import openerp.service.workers openerp.multi_process = True - openerp.service.workers.Multicorn(openerp.service.wsgi_server.application).run() +def _reexec(): + """reexecute openerp-server process with (nearly) the same arguments""" + if openerp.tools.osutil.is_running_as_nt_service(): + subprocess.call('sc stop {0} && sc start {0}'.format(nt_service_name), shell=True) + exe = os.path.basename(sys.executable) + strip_args = ['-d', '-u'] + a = sys.argv[:] + args = [x for i, x in enumerate(a) if x not in strip_args and a[max(i - 1, 0)] not in strip_args] + if not args or args[0] != exe: + args.insert(0, exe) + os.execv(sys.executable, args) + +def restart_server(): + if openerp.multi_process: + raise NotImplementedError("Multicorn is not supported (but gunicorn was)") + pid = openerp.wsgi.core.arbiter_pid + os.kill(pid, signal.SIGHUP) + else: + if os.name == 'nt': + def reborn(): + stop_services() + _reexec() + + # run in a thread to let the current thread return response to the caller. + threading.Thread(target=reborn).start() + else: + openerp.phoenix = True + os.kill(os.getpid(), signal.SIGINT) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/service/web_services.py b/openerp/service/web_services.py index 5b88e0fd880..940ecdb23e8 100644 --- a/openerp/service/web_services.py +++ b/openerp/service/web_services.py @@ -54,7 +54,12 @@ from openerp import SUPERUSER_ID _logger = logging.getLogger(__name__) -RPC_VERSION_1 = {'server_version': '6.1', 'protocol_version': 1} +RPC_VERSION_1 = { + 'server_version': release.version, + 'server_version_info': release.version_info, + 'server_serie': release.serie, + 'protocol_version': 1, +} # This should be moved to openerp.modules.db, along side initialize(). def _initialize_db(serv, id, db_name, demo, lang, user_password): @@ -120,6 +125,12 @@ class db(netsvc.ExportService): db = sql_db.db_connect('postgres') cr = db.cursor() chosen_template = tools.config['db_template'] + cr.execute("""SELECT datname + FROM pg_database + WHERE datname = %s """, + (name,)) + if cr.fetchall(): + raise openerp.exceptions.Warning(" %s database already exists!" % name ) try: cr.autocommit(True) # avoid transaction block cr.execute("""CREATE DATABASE "%s" ENCODING 'unicode' TEMPLATE "%s" """ % (name, chosen_template)) diff --git a/openerp/service/wsgi_server.py b/openerp/service/wsgi_server.py index f6d7a0582f7..67436a1c0bf 100644 --- a/openerp/service/wsgi_server.py +++ b/openerp/service/wsgi_server.py @@ -442,5 +442,6 @@ def stop_service(): """ if httpd: httpd.shutdown() + openerp.netsvc.close_socket(httpd.socket) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/tests/test_mail.py b/openerp/tests/test_mail.py index a8c806a13d0..b3c11a13bfe 100644 --- a/openerp/tests/test_mail.py +++ b/openerp/tests/test_mail.py @@ -177,6 +177,10 @@ class TestCleaner(unittest2.TestCase): new_html = html_email_clean(False) self.assertEqual(new_html, False, 'html_email_cleaner did change a False in an other value.') + # Test6: Message with xml and doctype tags don't crash + new_html = html_email_clean(u'\n\n\n \n 404 - Not Found\n \n \n

404 - Not Found

\n \n\n') + self.assertNotIn('encoding', new_html, 'html_email_cleaner did not remove correctly encoding attributes') + class TestHtmlTools(unittest2.TestCase): """ Test some of our generic utility functions about html """ diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py index a54f99ba1ad..e6b471a26ba 100644 --- a/openerp/tools/mail.py +++ b/openerp/tools/mail.py @@ -130,11 +130,15 @@ def html_email_clean(html): dest += source[idx:] return dest - if not html: + if not html or not isinstance(html, basestring): return html html = ustr(html) + # 0. remove encoding attribute inside tags + doctype = re.compile(r'(<[^>]*\s)(encoding=(["\'][^"\']*?["\']|[^\s\n\r>]+)(\s[^>]*|/)?>)', re.IGNORECASE | re.DOTALL) + html = doctype.sub(r"", html) + # 1. -> \n, because otherwise the tree is obfuscated br_tags = re.compile(r'([<]\s*[bB][rR]\s*\/?[>])') html = _replace_matching_regex(br_tags, html, '__BR_TAG__') diff --git a/openerp/tools/osutil.py b/openerp/tools/osutil.py index 67c586ad008..b5cff6b2646 100644 --- a/openerp/tools/osutil.py +++ b/openerp/tools/osutil.py @@ -26,6 +26,12 @@ Some functions related to the os and os.path module import os from os.path import join as opj +if os.name == 'nt': + import ctypes + import win32service as ws + import win32serviceutil as wsu + + def listdir(dir, recursive=False): """Allow to recursively get the file listing""" dir = os.path.normpath(dir) @@ -56,6 +62,59 @@ def walksymlinks(top, topdown=True, onerror=None): yield dirpath, dirnames, filenames +if os.name != 'nt': + getppid = os.getppid + is_running_as_nt_service = lambda: False +else: + # based on http://mail.python.org/pipermail/python-win32/2007-June/006174.html + _TH32CS_SNAPPROCESS = 0x00000002 + class _PROCESSENTRY32(ctypes.Structure): + _fields_ = [("dwSize", ctypes.c_ulong), + ("cntUsage", ctypes.c_ulong), + ("th32ProcessID", ctypes.c_ulong), + ("th32DefaultHeapID", ctypes.c_ulong), + ("th32ModuleID", ctypes.c_ulong), + ("cntThreads", ctypes.c_ulong), + ("th32ParentProcessID", ctypes.c_ulong), + ("pcPriClassBase", ctypes.c_ulong), + ("dwFlags", ctypes.c_ulong), + ("szExeFile", ctypes.c_char * 260)] + + def getppid(): + CreateToolhelp32Snapshot = ctypes.windll.kernel32.CreateToolhelp32Snapshot + Process32First = ctypes.windll.kernel32.Process32First + Process32Next = ctypes.windll.kernel32.Process32Next + CloseHandle = ctypes.windll.kernel32.CloseHandle + hProcessSnap = CreateToolhelp32Snapshot(_TH32CS_SNAPPROCESS, 0) + current_pid = os.getpid() + try: + pe32 = _PROCESSENTRY32() + pe32.dwSize = ctypes.sizeof(_PROCESSENTRY32) + if not Process32First(hProcessSnap, ctypes.byref(pe32)): + raise OSError('Failed getting first process.') + while True: + if pe32.th32ProcessID == current_pid: + return pe32.th32ParentProcessID + if not Process32Next(hProcessSnap, ctypes.byref(pe32)): + return None + finally: + CloseHandle(hProcessSnap) + + from contextlib import contextmanager + from openerp.release import nt_service_name + + def is_running_as_nt_service(): + @contextmanager + def close_srv(srv): + try: + yield srv + finally: + ws.CloseServiceHandle(srv) + + with close_srv(ws.OpenSCManager(None, None, ws.SC_MANAGER_ALL_ACCESS)) as hscm: + with close_srv(wsu.SmartOpenService(hscm, nt_service_name, ws.SERVICE_ALL_ACCESS)) as hs: + info = ws.QueryServiceStatusEx(hs) + return info['ProcessId'] == getppid() if __name__ == '__main__': from pprint import pprint as pp diff --git a/win32/OpenERPServerService.py b/win32/OpenERPServerService.py index bf7c83e74a4..8b3c117c03d 100644 --- a/win32/OpenERPServerService.py +++ b/win32/OpenERPServerService.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2009 Tiny SPRL (). # @@ -15,14 +15,12 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## -# Win32 python extensions modules import win32serviceutil import win32service -import win32event import win32api import win32process import servicemanager @@ -30,35 +28,32 @@ import servicemanager import sys import subprocess import os -import thread + +try: + import meta +except ImportError: + if hasattr(sys, 'frozen'): + raise + from setup import generate_files + generate_files() + import meta # noqa class OpenERPServerService(win32serviceutil.ServiceFramework): # required info - _svc_name_ = "openerp-server-6.1" - _svc_display_name_ = "OpenERP Server 6.1" - # optionnal info - _svc_description_ = "OpenERP Server 6.1 service" + _svc_name_ = meta.nt_service_name + _svc_display_name_ = "%s %s" % (meta.description, meta.serie) def __init__(self, args): win32serviceutil.ServiceFramework.__init__(self, args) - # Create an event which we will use to wait on. - # The "service stop" request will set this event. - self.hWaitStop = win32event.CreateEvent(None, 0, 0, None) # a reference to the server's process self.terpprocess = None - # info if the service terminates correctly or if the server crashed - self.stopping = False - def SvcStop(self): # Before we do anything, tell the SCM we are starting the stop process. self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING) - # stop the running TERP Server: say it's a normal exit + # stop the running OpenERP Server: say it's a normal exit win32api.TerminateProcess(int(self.terpprocess._handle), 0) servicemanager.LogInfoMsg("OpenERP Server stopped correctly") - # And set my event. - win32event.SetEvent(self.hWaitStop) - def StartTERP(self): # The server finds now its configuration automatically on Windows @@ -69,29 +64,19 @@ class OpenERPServerService(win32serviceutil.ServiceFramework): server_path = os.path.join(server_dir, 'server', 'openerp-server.exe') self.terpprocess = subprocess.Popen([server_path], cwd=server_dir, creationflags=win32process.CREATE_NO_WINDOW) - - def StartControl(self,ws): - # this listens to the Service Manager's events - win32event.WaitForSingleObject(ws, win32event.INFINITE) - self.stopping = True - def SvcDoRun(self): - # Start OpenERP Server itself self.StartTERP() - # start the loop waiting for the Service Manager's stop signal - thread.start_new_thread(self.StartControl, (self.hWaitStop,)) - # Log a info message that the server is running servicemanager.LogInfoMsg("OpenERP Server up and running") - # verification if the server is really running, else quit with an error - self.terpprocess.wait() - if not self.stopping: - sys.exit("OpenERP Server check: server not running, check the logfile for more info") + # exit with same exit code as OpenERP process + sys.exit(self.terpprocess.wait()) +def option_handler(opts): + # configure the service to auto restart on failures... + subprocess.call(['sc', 'failure', meta.nt_service_name, 'reset=', '0', 'actions=', 'restart/0/restart/0/restart/0']) -if __name__=='__main__': +if __name__ == '__main__': # Do with the service whatever option is passed in the command line - win32serviceutil.HandleCommandLine(OpenERPServerService) + win32serviceutil.HandleCommandLine(OpenERPServerService, customOptionHandler=option_handler) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/win32/setup.py b/win32/setup.py index 2dfb8ef3493..0feedce01e0 100644 --- a/win32/setup.py +++ b/win32/setup.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- ############################################################################## -# +# # OpenERP, Open Source Management Solution # Copyright (C) 2004-2010 Tiny SPRL (). # @@ -15,7 +15,7 @@ # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . +# along with this program. If not, see . # ############################################################################## @@ -30,15 +30,46 @@ def datas(): r.append(("Microsoft.VC90.CRT", glob.glob('C:\Microsoft.VC90.CRT\*.*'))) return r -setup(service=["OpenERPServerService"], - options={"py2exe":{"excludes":["Tkconstants","Tkinter","tcl", - "_imagingtk","PIL._imagingtk", - "ImageTk", "PIL.ImageTk", - "FixTk"], - "skip_archive": 1, - "optimize": 2,}}, +meta = {} +execfile(os.path.join(os.path.dirname(__file__), '..', 'openerp', 'release.py'), meta) + +def generate_files(): + actions = { + 'start': ['stop', 'start'], + 'stop': ['stop'], + } + + files = [] + for action, steps in actions.items(): + fname = action + '.bat' + files.append(fname) + with open(fname, 'w') as fp: + fp.write('@PATH=%WINDIR%\system32;%WINDIR%;%WINDIR%\System32\Wbem;.\n') + for step in steps: + fp.write('@net %s %s\n' % (step, meta['nt_service_name'])) + + files.append('meta.py') + with open('meta.py', 'w') as fp: + for m in 'description serie nt_service_name'.split(): + fp.write("%s = %r\n" % (m, meta[m],)) + + return files + +excludes = "Tkconstants Tkinter tcl _imagingtk PIL._imagingtk ImageTk PIL.ImageTk FixTk".split() + +setup(service = ["OpenERPServerService"], + version = meta['version'], + license = meta['license'], + url = meta['url'], + author = meta['author'], + author_email = meta['author_email'], + data_files = generate_files(), + options = {"py2exe": { + "excludes": excludes, + "skip_archive": 1, + "optimize": 2, + }}, data_files=datas(), ) # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: - diff --git a/win32/start.bat b/win32/start.bat deleted file mode 100644 index ff3c49b1397..00000000000 --- a/win32/start.bat +++ /dev/null @@ -1,7 +0,0 @@ -@PATH=%WINDIR%\system32;%WINDIR%;%WINDIR%\System32\Wbem;. - -@net stop openerp-server-6.1 - -@net start openerp-server-6.1 - -cls diff --git a/win32/stop.bat b/win32/stop.bat deleted file mode 100644 index 76a35b7e91f..00000000000 --- a/win32/stop.bat +++ /dev/null @@ -1,5 +0,0 @@ -@PATH=%WINDIR%\system32;%WINDIR%;%WINDIR%\System32\Wbem;. - -@net stop openerp-server-6.1 - -cls