[Merge] Merge with main server.

bzr revid: mdi@tinyerp.com-20121128042307-b2ukazq07mdzgp02
This commit is contained in:
Divyesh Makwana (Open ERP) 2012-11-28 09:53:07 +05:30
commit 6b13002e04
13 changed files with 434 additions and 322 deletions

View File

@ -1,271 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
"""
OpenERP - Server
OpenERP is an ERP+CRM program for small and medium businesses.
The whole source code is distributed under the terms of the
GNU Public Licence.
(c) 2003-TODAY, Fabien Pinckaers - OpenERP SA
"""
import logging
import os
import signal
import sys
import threading
import traceback
import time
import openerp
__author__ = openerp.release.author
__version__ = openerp.release.version
# Also use the `openerp` logger for the main script.
_logger = logging.getLogger('openerp')
def check_root_user():
""" Exit if the process's user is 'root' (on POSIX system)."""
if os.name == 'posix':
import pwd
if pwd.getpwuid(os.getuid())[0] == 'root' :
sys.stderr.write("Running as user 'root' is a security risk, aborting.\n")
sys.exit(1)
def check_postgres_user():
""" Exit if the configured database user is 'postgres'.
This function assumes the configuration has been initialized.
"""
config = openerp.tools.config
if config['db_user'] == 'postgres':
sys.stderr.write("Using the database user 'postgres' is a security risk, aborting.")
sys.exit(1)
def report_configuration():
""" Log the server version and some configuration values.
This function assumes the configuration has been initialized.
"""
config = openerp.tools.config
_logger.info("OpenERP version %s", __version__)
for name, value in [('addons paths', config['addons_path']),
('database hostname', config['db_host'] or 'localhost'),
('database port', config['db_port'] or '5432'),
('database user', config['db_user'])]:
_logger.info("%s: %s", name, value)
def setup_pid_file():
""" Create a file with the process id written in it.
This function assumes the configuration has been initialized.
"""
config = openerp.tools.config
if config['pidfile']:
fd = open(config['pidfile'], 'w')
pidtext = "%d" % (os.getpid())
fd.write(pidtext)
fd.close()
def preload_registry(dbname):
""" Preload a registry, and start the cron."""
try:
db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=openerp.tools.config['init'] or openerp.tools.config['update'], pooljobs=False)
# jobs will start to be processed later, when openerp.cron.start_master_thread() is called by openerp.service.start_services()
registry.schedule_cron_jobs()
except Exception:
_logger.exception('Failed to initialize database `%s`.', dbname)
def run_test_file(dbname, test_file):
""" Preload a registry, possibly run a test file, and start the cron."""
try:
config = openerp.tools.config
db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False)
cr = db.cursor()
_logger.info('loading test file %s', test_file)
openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True)
cr.rollback()
cr.close()
except Exception:
_logger.exception('Failed to initialize database `%s` and run test file `%s`.', dbname, test_file)
def export_translation():
config = openerp.tools.config
dbname = config['db_name']
if config["language"]:
msg = "language %s" % (config["language"],)
else:
msg = "new language"
_logger.info('writing translation file for %s to %s', msg,
config["translate_out"])
fileformat = os.path.splitext(config["translate_out"])[-1][1:].lower()
buf = file(config["translate_out"], "w")
cr = openerp.pooler.get_db(dbname).cursor()
openerp.tools.trans_export(config["language"],
config["translate_modules"] or ["all"], buf, fileformat, cr)
cr.close()
buf.close()
_logger.info('translation file written successfully')
def import_translation():
config = openerp.tools.config
context = {'overwrite': config["overwrite_existing_translations"]}
dbname = config['db_name']
cr = openerp.pooler.get_db(dbname).cursor()
openerp.tools.trans_load( cr, config["translate_in"], config["language"],
context=context)
cr.commit()
cr.close()
# Variable keeping track of the number of calls to the signal handler defined
# below. This variable is monitored by ``quit_on_signals()``.
quit_signals_received = 0
def signal_handler(sig, frame):
""" Signal handler: exit ungracefully on the second handled signal.
:param sig: the signal number
:param frame: the interrupted stack frame or None
"""
global quit_signals_received
quit_signals_received += 1
if quit_signals_received > 1:
# logging.shutdown was already called at this point.
sys.stderr.write("Forced shutdown.\n")
os._exit(0)
def dumpstacks(sig, frame):
""" Signal handler: dump a stack trace for each existing thread."""
# code from http://stackoverflow.com/questions/132058/getting-stack-trace-from-a-running-python-application#answer-2569696
# modified for python 2.5 compatibility
threads_info = dict([(th.ident, {'name': th.name,
'uid': getattr(th,'uid','n/a')})
for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
thread_info = threads_info.get(threadId)
code.append("\n# Thread: %s (id:%s) (uid:%s)" % \
(thread_info and thread_info['name'] or 'n/a',
threadId,
thread_info and thread_info['uid'] or 'n/a'))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
_logger.info("\n".join(code))
def setup_signal_handlers():
""" Register the signal handler defined above. """
SIGNALS = map(lambda x: getattr(signal, "SIG%s" % x), "INT TERM".split())
if os.name == 'posix':
map(lambda sig: signal.signal(sig, signal_handler), SIGNALS)
signal.signal(signal.SIGQUIT, dumpstacks)
elif os.name == 'nt':
import win32api
win32api.SetConsoleCtrlHandler(lambda sig: signal_handler(sig, None), 1)
def quit_on_signals():
""" Wait for one or two signals then shutdown the server.
The first SIGINT or SIGTERM signal will initiate a graceful shutdown while
a second one if any will force an immediate exit.
"""
# Wait for a first signal to be handled. (time.sleep will be interrupted
# by the signal handler.) The try/except is for the win32 case.
try:
while quit_signals_received == 0:
time.sleep(60)
except KeyboardInterrupt:
pass
config = openerp.tools.config
if config['pidfile']:
os.unlink(config['pidfile'])
openerp.service.stop_services()
sys.exit(0)
def configure_babel_localedata_path():
# Workaround: py2exe and babel.
if hasattr(sys, 'frozen'):
import babel
babel.localedata._dirname = os.path.join(os.path.dirname(sys.executable), 'localedata')
def main():
os.environ["TZ"] = "UTC"
check_root_user()
openerp.tools.config.parse_config(sys.argv[1:])
check_postgres_user()
openerp.netsvc.init_logger()
report_configuration()
config = openerp.tools.config
configure_babel_localedata_path()
setup_signal_handlers()
if config["test_file"]:
run_test_file(config['db_name'], config['test_file'])
sys.exit(0)
if config["translate_out"]:
export_translation()
sys.exit(0)
if config["translate_in"]:
import_translation()
sys.exit(0)
if not config["stop_after_init"]:
setup_pid_file()
# Some module register themselves when they are loaded so we need the
# services to be running before loading any registry.
if config['workers']:
openerp.service.start_services_workers()
else:
openerp.service.start_services()
if config['db_name']:
for dbname in config['db_name'].split(','):
preload_registry(dbname)
if config["stop_after_init"]:
sys.exit(0)
_logger.info('OpenERP server is running, waiting for connections...')
quit_on_signals()
if __name__ == "__main__":
main()
openerp.cli.main()
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -26,6 +26,7 @@
SUPERUSER_ID = 1
import addons
import cli
import conf
import loglevels
import modules

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 6.0.0-rc1\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-11-24 02:51+0000\n"
"PO-Revision-Date: 2012-08-20 15:28+0000\n"
"Last-Translator: Bayuka <bayuka1988@gmail.com>\n"
"PO-Revision-Date: 2012-11-26 17:49+0000\n"
"Last-Translator: gobi <Unknown>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-11-25 05:29+0000\n"
"X-Generator: Launchpad (build 16293)\n"
"X-Launchpad-Export-Date: 2012-11-27 05:22+0000\n"
"X-Generator: Launchpad (build 16309)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -24,6 +24,10 @@ msgid ""
"================================================\n"
" "
msgstr ""
"\n"
"Чек бичих болон Чек хэвлэх модуль.\n"
"================================================\n"
" "
#. module: base
#: model:res.country,name:base.sh
@ -59,7 +63,7 @@ msgstr "Дэлгэцийн архитектур"
#. module: base
#: model:ir.module.module,summary:base.module_sale_stock
msgid "Quotation, Sale Orders, Delivery & Invoicing Control"
msgstr ""
msgstr "Үнийн санал, Борлуулалтын захиалга, Хүргэлт & Нэхэмжлэлийн хяналт"
#. module: base
#: selection:ir.sequence,implementation:0
@ -88,12 +92,12 @@ msgstr ""
#. module: base
#: model:ir.module.module,summary:base.module_point_of_sale
msgid "Touchscreen Interface for Shops"
msgstr ""
msgstr "Дэлгүүрт зориулагдсан маажих дэлгэц"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_in_hr_payroll
msgid "Indian Payroll"
msgstr ""
msgstr "Энэтхэг Цалин"
#. module: base
#: help:ir.cron,model:0
@ -121,6 +125,17 @@ msgid ""
" * Product Attributes\n"
" "
msgstr ""
"\n"
"Барааны маягт дээр үйлдвэрлэгч болон үзүүлэлтүүд нэмдэг модуль.\n"
"====================================================================\n"
"\n"
"Бараанд дараах зүйлсийг тодорхойлох боломжтой болно:\n"
"-----------------------------------------------\n"
" * Үйлдвэрлэгч\n"
" * Барааны Үйлдвэрлэгчийн өгсөн нэр\n"
" * Барааны Үйлдвэрлэгчийн өгсөн код\n"
" * Барааны үзүүлэлтүүд\n"
" "
#. module: base
#: field:ir.actions.client,params:0
@ -134,11 +149,14 @@ msgid ""
"The module adds google user in res user.\n"
"========================================\n"
msgstr ""
"\n"
"Энэ модуль нь res_user-т google хэрэглэгчийг нэмдэг.\n"
"========================================\n"
#. module: base
#: help:res.partner,employee:0
msgid "Check this box if this contact is an Employee."
msgstr ""
msgstr "Хэрэв холбогч нь ажилтан бол үүнийг тэмдэглэ."
#. module: base
#: help:ir.model.fields,domain:0
@ -168,7 +186,7 @@ msgstr "Ашиглах цонх"
#. module: base
#: field:ir.actions.report.xml,report_rml:0
msgid "Main Report File Path"
msgstr ""
msgstr "Тайлангийн Үндсэн Файлын Зам"
#. module: base
#: model:ir.module.module,shortdesc:base.module_sale_analytic_plans
@ -189,6 +207,14 @@ msgid ""
"revenue\n"
"reports."
msgstr ""
"\n"
"Зардал, Цагийн хуудсын бичилтээс нэхэмжлэлийг үүсгэдэг.\n"
"========================================================\n"
"\n"
"Өртөг (хүний нөөц, зардал, ...) дээр суурилан нэхэмжлэл үүсгэдэг модуль .\n"
"\n"
"Шинжилгээний данс дээр зарах үнийн хүснэгт үүсгэж орох ашгийн онолийн "
"тайланг үүсгэж болно."
#. module: base
#: model:ir.module.module,description:base.module_crm
@ -223,6 +249,33 @@ msgid ""
"* Planned Revenue by Stage and User (graph)\n"
"* Opportunities by Stage (graph)\n"
msgstr ""
"\n"
"OpenERP-н Захиалагчийн Харилцааны Менежмент (CRM)-н ерөнхий модуль\n"
"=====================================================\n"
"\n"
"Энэ модуль нь хүмүүсийн бүлэгүүд сэжим, боломж, уулзалт, утасны дуудлагыг "
"ухаалаг бөгөөд оновчтой зохион байгуулах боломжийг олгодог.\n"
"\n"
"Түүнчлэн харилцах, олж таних, эрэмбэлэх, оноох, шийдэх, мэдэгдэх гэх мэт "
"түлхүүр даалгавруудыг удирддаг.\n"
"\n"
"OpenERP нь бүх хэрэгүүд хэрэглэгч, захиалагч, нийлүүлэгчээр амжилттай "
"хөтлөгдөх баталгааг хангадаг. Автомат сануулга илгээх, хүсэлтийг дээд шат "
"рүү хүргэх, байгууллагын дүрэм дээр тулгуурласан маш олон төрлийн "
"үйлдлүүдийг гүйцэтгэх боломжтой. \n"
"\n"
"Системийн гайхалтай тал нь хэрэглэгчид ямар нэг нарийвчилсан ажил хийх "
"шаардлагагүй байдаг. CRM модуль нь имэйл болон OpenERP-г хооронд нь холбох "
"имэйл үүдтэй. Иймээс зөвхөн имэйл илгээх замаар сэжим үүсгэж боломж "
"олгодог.\n"
"\n"
"OpenERP нь талархлын мессеж илгээгээд имэйлийг харгалзах ажилтан руу илгээж "
"цаашид авах бүх арга хэмжээг авч зөв боловсруулалтыг хийлгэдэг.\n"
"\n"
"CRM-н хянах самбар дараах зүйлсийг агуулдаг:\n"
"-------------------------------\n"
"* Төлөвлөсөн орлого үеээр болон хэрэглэгчээр (graph)\n"
"* Боломж үеээр (график)\n"
#. module: base
#: code:addons/base/ir/ir_model.py:394
@ -266,7 +319,7 @@ msgstr "үүсгэгдсэн."
#. module: base
#: field:ir.actions.report.xml,report_xsl:0
msgid "XSL Path"
msgstr ""
msgstr "XSL зам"
#. module: base
#: model:ir.module.module,shortdesc:base.module_l10n_tr
@ -292,7 +345,7 @@ msgstr "Инуит хэл / ᐃᓄᒃᑎᑐᑦ"
#. module: base
#: model:res.groups,name:base.group_multi_currency
msgid "Multi Currencies"
msgstr ""
msgstr "Олон валютууд"
#. module: base
#: model:ir.module.module,description:base.module_l10n_cl
@ -315,7 +368,7 @@ msgstr "Борлуулалтын менежмент"
msgid ""
"The internal user that is in charge of communicating with this contact if "
"any."
msgstr ""
msgstr "Энэ холбогчтой харилцах дотоод хэрэглэгч (хэрэв байгаа бол)."
#. module: base
#: view:res.partner:0
@ -350,6 +403,15 @@ msgid ""
" * Commitment Date\n"
" * Effective Date\n"
msgstr ""
"\n"
"Борлуулалтын захиалгад огнооны нэмэлт мэдээлэл нэмдэг .\n"
"===================================================\n"
"\n"
"Борлуулалтын захиалгад дараах огноонуудыг нэмж болно:\n"
"-----------------------------------------------------------\n"
" * Хүссэн Огноо\n"
" * Амласан Огноо\n"
" * Зохистой Огноо\n"
#. module: base
#: help:ir.actions.act_window,res_id:0
@ -357,6 +419,8 @@ msgid ""
"Database ID of record to open in form view, when ``view_mode`` is set to "
"'form' only"
msgstr ""
"Форм харагдацийг нээх бичлэгийн өгөгдлийн баазын ID, зөвхөн ``view_mode`` нь "
"'form' гэж тохируулагдсан үед."
#. module: base
#: field:res.partner.address,name:0
@ -568,7 +632,7 @@ msgstr ""
#. module: base
#: view:workflow.transition:0
msgid "Workflow Transition"
msgstr ""
msgstr "Ажлын урсгалын шилжилт"
#. module: base
#: model:res.country,name:base.gf
@ -578,7 +642,7 @@ msgstr "Франц Гуана"
#. module: base
#: model:ir.module.module,summary:base.module_hr
msgid "Jobs, Departments, Employees Details"
msgstr ""
msgstr "Ажлууд, Хэлтсүүд, Ажилчдийн дэлгэрэнгүй"
#. module: base
#: model:ir.module.module,description:base.module_analytic

View File

@ -7,14 +7,14 @@ msgstr ""
"Project-Id-Version: OpenERP Server 5.0.4\n"
"Report-Msgid-Bugs-To: support@openerp.com\n"
"POT-Creation-Date: 2012-11-24 02:51+0000\n"
"PO-Revision-Date: 2012-11-25 09:34+0000\n"
"PO-Revision-Date: 2012-11-26 06:49+0000\n"
"Last-Translator: Joshua Jan(SHINEIT) <popkar77@gmail.com>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Launchpad-Export-Date: 2012-11-26 04:40+0000\n"
"X-Generator: Launchpad (build 16293)\n"
"X-Launchpad-Export-Date: 2012-11-27 05:22+0000\n"
"X-Generator: Launchpad (build 16309)\n"
#. module: base
#: model:ir.module.module,description:base.module_account_check_writing
@ -14970,7 +14970,7 @@ msgstr "系统更新"
#: 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内容"
#. module: base
#: help:ir.sequence,prefix:0
@ -14985,7 +14985,7 @@ msgstr "塞舌尔"
#. module: base
#: model:res.partner.category,name:base.res_partner_category_4
msgid "Gold"
msgstr ""
msgstr "黄金"
#. module: base
#: code:addons/base/res/res_company.py:159
@ -15012,7 +15012,7 @@ msgstr "一般信息"
#. module: base
#: field:ir.model.data,complete_name:0
msgid "Complete ID"
msgstr ""
msgstr "完整ID"
#. module: base
#: model:res.country,name:base.tc
@ -15063,7 +15063,7 @@ msgstr "切换公司警告"
msgid ""
"Helps you manage your manufacturing processes and generate reports on those "
"processes."
msgstr ""
msgstr "帮助您管理您的生产和其生成的报表。"
#. module: base
#: help:ir.sequence,number_increment:0
@ -15125,12 +15125,12 @@ msgstr "公司"
#. module: base
#: model:ir.module.module,shortdesc:base.module_purchase_requisition
msgid "Purchase Requisitions"
msgstr ""
msgstr "采购申请"
#. module: base
#: selection:ir.actions.act_window,target:0
msgid "Inline Edit"
msgstr ""
msgstr "行内编辑"
#. module: base
#: selection:ir.cron,interval_type:0
@ -15151,7 +15151,7 @@ msgstr "业务伙伴: "
#. module: base
#: view:res.partner:0
msgid "Is a Company?"
msgstr ""
msgstr "是一个公司?"
#. module: base
#: code:addons/base/res/res_company.py:159
@ -15173,7 +15173,7 @@ msgstr "创建对象"
#. module: base
#: model:res.country,name:base.ss
msgid "South Sudan"
msgstr ""
msgstr "苏丹南部"
#. module: base
#: field:ir.filters,context:0
@ -15206,7 +15206,7 @@ msgstr "潜在客户"
#. module: base
#: model:ir.module.module,shortdesc:base.module_stock_invoice_directly
msgid "Invoice Picking Directly"
msgstr ""
msgstr "根据装箱单开发票"
#. module: base
#: selection:base.language.install,lang:0

View File

@ -66,9 +66,11 @@
<field name="name" string="Record Rule"/>
<filter string="Global" icon="terp-stage" domain="[('global','=',True)]"/>
<separator/>
<filter string="Full Access" icon="terp-gtk-select-all" domain="[('perm_read','=',True),('perm_write','=',True),('perm_create','=',True),('perm_unlink','=',True)]"/>
<filter string="Read Access" icon="terp-stock_align_left_24" domain="[('perm_read','=',True)]"/>
<filter string="Write Access" icon="terp-tools" domain="[('perm_write','=',True)]"/>
<filter string="Full Access Right" domain="[('perm_read','=',True),('perm_write','=',True),('perm_create','=',True),('perm_unlink','=',True)]"/>
<filter string="Read Access Right" domain="[('perm_read','=',True)]"/>
<filter string="Write Access Right" domain="[('perm_write','=',True)]"/>
<filter string="Create Access Right" domain="[('perm_create','=',True)]"/>
<filter string="Delete Access Right" domain="[('perm_unlink','=',True)]"/>
<field name="model_id"/>
<field name="groups"/>
</search>

View File

@ -22,6 +22,9 @@
import logging
import time
from osv import osv, fields
from tools.translate import _
import openerp
_logger = logging.getLogger(__name__)
@ -98,6 +101,8 @@ class ir_sequence(openerp.osv.osv.osv):
There is no access rights check.
"""
if number_increment == 0:
raise osv.except_osv(_('Warning!'),_("Increment number must not be zero."))
assert isinstance(id, (int, long))
sql = "CREATE SEQUENCE ir_sequence_%03d INCREMENT BY %%s START WITH %%s" % id
cr.execute(sql, (number_increment, number_next))
@ -122,6 +127,8 @@ class ir_sequence(openerp.osv.osv.osv):
There is no access rights check.
"""
if number_increment == 0:
raise osv.except_osv(_('Warning!'),_("Increment number must not be zero."))
assert isinstance(id, (int, long))
cr.execute("""
ALTER SEQUENCE ir_sequence_%03d INCREMENT BY %%s RESTART WITH %%s

View File

@ -54,12 +54,12 @@
<record id="view_translation_tree" model="ir.ui.view">
<field name="model">ir.translation</field>
<field name="arch" type="xml">
<tree string="Translations" editable="bottom">
<field name="src" readonly="True"/>
<tree string="Translations" editable="top">
<field name="src"/>
<field name="value"/>
<field name="name" readonly="True"/>
<field name="lang" readonly="True"/>
<field name="type" readonly="True"/>
<field name="name"/>
<field name="lang"/>
<field name="type"/>
</tree>
</field>
</record>

View File

@ -2,7 +2,7 @@
<openerp>
<data>
<record model="ir.module.category" id="module_category_hidden">
<field name="name">Hidden</field>
<field name="name">Technical Settings</field>
<field name="sequence">0</field>
<field name="visible" eval="0" />
</record>

View File

@ -20,8 +20,8 @@
<field name="arch" type="xml">
<form string="Company" version="7.0">
<sheet>
<div class="oe_right oe_avatar">
<field name="logo" nolabel="1" widget="image"/>
<div>
<field name="logo" nolabel="1" widget="image" class="oe_avatar oe_left"/>
</div>
<div class="oe_right oe_button_box" name="button_box">
<button name="%(preview_report)d" string="Preview Header/Footer" type="action" icon="gtk-print" class="oe_inline oe_right"/>

View File

@ -508,23 +508,6 @@ class res_partner(osv.osv, format_address):
result[adr] = address_dict.get(adr, default_address)
return result
def gen_next_ref(self, cr, uid, ids):
if len(ids) != 1:
return True
# compute the next number ref
cr.execute("select ref from res_partner where ref is not null order by char_length(ref) desc, ref desc limit 1")
res = cr.dictfetchall()
ref = res and res[0]['ref'] or '0'
try:
nextref = int(ref)+1
except:
raise osv.except_osv(_('Warning'), _("Couldn't generate the next id because some partners have an alphabetic id !"))
# update the current partner
cr.execute("update res_partner set ref=%s where id=%s", (nextref, ids[0]))
return True
def view_header_get(self, cr, uid, view_id, view_type, context):
res = super(res_partner, self).view_header_get(cr, uid, view_id, view_type, context)
if res: return res

View File

@ -148,7 +148,7 @@
<group>
<group>
<label for="type" attrs="{'invisible': [('parent_id','=', False)]}"/>
<div attrs="{'invisible': [('parent_id','=', False)]}" invisible="1" name="div_type">
<div attrs="{'invisible': [('parent_id','=', False)]}" name="div_type">
<field class="oe_inline"
name="type"/>
<label for="use_parent_address" class="oe_edit_only"/>
@ -295,7 +295,7 @@
<filter string="Customers" name="customer" icon="terp-personal" domain="[('customer','=',1)]" help="Customer Partners"/>
<separator/>
<filter string="Suppliers" name="supplier" icon="terp-personal" domain="[('supplier','=',1)]" help="Supplier Partners"/>
<field name="category_id" string="Category" filter_domain="[('category_id','ilike', self)]"/>
<field name="category_id" string="Tag" filter_domain="[('category_id','ilike', self)]"/>
<field name="user_id"/>
<field name="parent_id" filter_domain="[('parent_id','child_of',[self])]"/>
<group expand="0" string="Group By...">
@ -527,7 +527,7 @@
<field name="help">Manage the partner categories in order to better classify them for tracking and analysis purposes. A partner may belong to several categories and categories have a hierarchy structure: a partner belonging to a category also belong to his parent category.</field>
</record>
<menuitem action="action_partner_category_form" id="menu_partner_category_form" name="Partner Categories" sequence="4" parent="menu_config_address_book" groups="base.group_no_one"/>
<menuitem action="action_partner_category_form" id="menu_partner_category_form" name="Partner Tags" sequence="4" parent="menu_config_address_book" groups="base.group_no_one"/>
</data>
</openerp>

44
openerp/cli/__init__.py Normal file
View File

@ -0,0 +1,44 @@
import logging
import sys
import openerp
_logger = logging.getLogger(__name__)
commands = {}
class CommandType(type):
def __init__(cls, name, bases, attrs):
super(CommandType, cls).__init__(name, bases, attrs)
name = getattr(cls, name, cls.__name__.lower())
cls.name = name
if name != 'command':
commands[name] = cls
class Command(object):
"""Subclass this class to define new openerp subcommands """
__metaclass__ = CommandType
def run(self, args):
pass
class Help(Command):
def run(self, args):
print "Available commands:\n"
for k, v in commands.items():
print " %s" % k
import server
def main():
args = sys.argv[1:]
command = "server"
if len(args) and not args[0].startswith("-"):
command = args[0]
args = args[1:]
if command in commands:
o = commands[command]()
o.run(args)
# vim:et:ts=4:sw=4:

275
openerp/cli/server.py Normal file
View File

@ -0,0 +1,275 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
#
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
"""
OpenERP - Server
OpenERP is an ERP+CRM program for small and medium businesses.
The whole source code is distributed under the terms of the
GNU Public Licence.
(c) 2003-TODAY, Fabien Pinckaers - OpenERP SA
"""
import logging
import os
import signal
import sys
import threading
import traceback
import time
import openerp
from . import Command
__author__ = openerp.release.author
__version__ = openerp.release.version
# Also use the `openerp` logger for the main script.
_logger = logging.getLogger('openerp')
def check_root_user():
""" Exit if the process's user is 'root' (on POSIX system)."""
if os.name == 'posix':
import pwd
if pwd.getpwuid(os.getuid())[0] == 'root' :
sys.stderr.write("Running as user 'root' is a security risk, aborting.\n")
sys.exit(1)
def check_postgres_user():
""" Exit if the configured database user is 'postgres'.
This function assumes the configuration has been initialized.
"""
config = openerp.tools.config
if config['db_user'] == 'postgres':
sys.stderr.write("Using the database user 'postgres' is a security risk, aborting.")
sys.exit(1)
def report_configuration():
""" Log the server version and some configuration values.
This function assumes the configuration has been initialized.
"""
config = openerp.tools.config
_logger.info("OpenERP version %s", __version__)
for name, value in [('addons paths', config['addons_path']),
('database hostname', config['db_host'] or 'localhost'),
('database port', config['db_port'] or '5432'),
('database user', config['db_user'])]:
_logger.info("%s: %s", name, value)
def setup_pid_file():
""" Create a file with the process id written in it.
This function assumes the configuration has been initialized.
"""
config = openerp.tools.config
if config['pidfile']:
fd = open(config['pidfile'], 'w')
pidtext = "%d" % (os.getpid())
fd.write(pidtext)
fd.close()
def preload_registry(dbname):
""" Preload a registry, and start the cron."""
try:
db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=openerp.tools.config['init'] or openerp.tools.config['update'], pooljobs=False)
# jobs will start to be processed later, when openerp.cron.start_master_thread() is called by openerp.service.start_services()
registry.schedule_cron_jobs()
except Exception:
_logger.exception('Failed to initialize database `%s`.', dbname)
def run_test_file(dbname, test_file):
""" Preload a registry, possibly run a test file, and start the cron."""
try:
config = openerp.tools.config
db, registry = openerp.pooler.get_db_and_pool(dbname, update_module=config['init'] or config['update'], pooljobs=False)
cr = db.cursor()
_logger.info('loading test file %s', test_file)
openerp.tools.convert_yaml_import(cr, 'base', file(test_file), 'test', {}, 'test', True)
cr.rollback()
cr.close()
except Exception:
_logger.exception('Failed to initialize database `%s` and run test file `%s`.', dbname, test_file)
def export_translation():
config = openerp.tools.config
dbname = config['db_name']
if config["language"]:
msg = "language %s" % (config["language"],)
else:
msg = "new language"
_logger.info('writing translation file for %s to %s', msg,
config["translate_out"])
fileformat = os.path.splitext(config["translate_out"])[-1][1:].lower()
buf = file(config["translate_out"], "w")
cr = openerp.pooler.get_db(dbname).cursor()
openerp.tools.trans_export(config["language"],
config["translate_modules"] or ["all"], buf, fileformat, cr)
cr.close()
buf.close()
_logger.info('translation file written successfully')
def import_translation():
config = openerp.tools.config
context = {'overwrite': config["overwrite_existing_translations"]}
dbname = config['db_name']
cr = openerp.pooler.get_db(dbname).cursor()
openerp.tools.trans_load( cr, config["translate_in"], config["language"],
context=context)
cr.commit()
cr.close()
# Variable keeping track of the number of calls to the signal handler defined
# below. This variable is monitored by ``quit_on_signals()``.
quit_signals_received = 0
def signal_handler(sig, frame):
""" Signal handler: exit ungracefully on the second handled signal.
:param sig: the signal number
:param frame: the interrupted stack frame or None
"""
global quit_signals_received
quit_signals_received += 1
if quit_signals_received > 1:
# logging.shutdown was already called at this point.
sys.stderr.write("Forced shutdown.\n")
os._exit(0)
def dumpstacks(sig, frame):
""" Signal handler: dump a stack trace for each existing thread."""
# code from http://stackoverflow.com/questions/132058/getting-stack-trace-from-a-running-python-application#answer-2569696
# modified for python 2.5 compatibility
threads_info = dict([(th.ident, {'name': th.name,
'uid': getattr(th,'uid','n/a')})
for th in threading.enumerate()])
code = []
for threadId, stack in sys._current_frames().items():
thread_info = threads_info.get(threadId)
code.append("\n# Thread: %s (id:%s) (uid:%s)" % \
(thread_info and thread_info['name'] or 'n/a',
threadId,
thread_info and thread_info['uid'] or 'n/a'))
for filename, lineno, name, line in traceback.extract_stack(stack):
code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
if line:
code.append(" %s" % (line.strip()))
_logger.info("\n".join(code))
def setup_signal_handlers():
""" Register the signal handler defined above. """
SIGNALS = map(lambda x: getattr(signal, "SIG%s" % x), "INT TERM".split())
if os.name == 'posix':
map(lambda sig: signal.signal(sig, signal_handler), SIGNALS)
signal.signal(signal.SIGQUIT, dumpstacks)
elif os.name == 'nt':
import win32api
win32api.SetConsoleCtrlHandler(lambda sig: signal_handler(sig, None), 1)
def quit_on_signals():
""" Wait for one or two signals then shutdown the server.
The first SIGINT or SIGTERM signal will initiate a graceful shutdown while
a second one if any will force an immediate exit.
"""
# Wait for a first signal to be handled. (time.sleep will be interrupted
# by the signal handler.) The try/except is for the win32 case.
try:
while quit_signals_received == 0:
time.sleep(60)
except KeyboardInterrupt:
pass
config = openerp.tools.config
if config['pidfile']:
os.unlink(config['pidfile'])
openerp.service.stop_services()
sys.exit(0)
def configure_babel_localedata_path():
# Workaround: py2exe and babel.
if hasattr(sys, 'frozen'):
import babel
babel.localedata._dirname = os.path.join(os.path.dirname(sys.executable), 'localedata')
def main(args):
os.environ["TZ"] = "UTC"
check_root_user()
openerp.tools.config.parse_config(args)
check_postgres_user()
openerp.netsvc.init_logger()
report_configuration()
config = openerp.tools.config
configure_babel_localedata_path()
setup_signal_handlers()
if config["test_file"]:
run_test_file(config['db_name'], config['test_file'])
sys.exit(0)
if config["translate_out"]:
export_translation()
sys.exit(0)
if config["translate_in"]:
import_translation()
sys.exit(0)
if not config["stop_after_init"]:
setup_pid_file()
# Some module register themselves when they are loaded so we need the
# services to be running before loading any registry.
if config['workers']:
openerp.service.start_services_workers()
else:
openerp.service.start_services()
if config['db_name']:
for dbname in config['db_name'].split(','):
preload_registry(dbname)
if config["stop_after_init"]:
sys.exit(0)
_logger.info('OpenERP server is running, waiting for connections...')
quit_on_signals()
class Server(Command):
def run(self, args):
main(args)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: